mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-08 23:23:01 -06:00
0c90f67dcc
* Refactor interface to PdmObjectHandle and PdmFieldHandle Return objects instead of passing in structures as parameters * Add nodiscard to several functions * Remove redundant this-> * Rename to ptrReferencedObjectsByType
1434 lines
53 KiB
C++
1434 lines
53 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2017 Statoil ASA
|
|
//
|
|
// ResInsight is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RimWellLogRftCurve.h"
|
|
|
|
#include "RiaColorTables.h"
|
|
#include "RiaColorTools.h"
|
|
#include "RiaDefines.h"
|
|
#include "RiaEclipseUnitTools.h"
|
|
#include "RiaQDateTimeTools.h"
|
|
#include "RiaResultNames.h"
|
|
#include "RiaRftDefines.h"
|
|
#include "RiaSimWellBranchTools.h"
|
|
#include "RiaStatisticsTools.h"
|
|
#include "RiaSummaryTools.h"
|
|
#include "RiaTextStringTools.h"
|
|
|
|
#include "RifEclipseRftAddress.h"
|
|
#include "RifReaderEclipseRft.h"
|
|
|
|
#include "RigEclipseCaseData.h"
|
|
#include "RigEclipseWellLogExtractor.h"
|
|
#include "RigMainGrid.h"
|
|
#include "RigWellLogCurveData.h"
|
|
#include "RigWellPath.h"
|
|
#include "RigWellPathGeometryTools.h"
|
|
#include "RigWellPathIntersectionTools.h"
|
|
|
|
#include "RimDepthTrackPlot.h"
|
|
#include "RimEclipseResultCase.h"
|
|
#include "RimFileSummaryCase.h"
|
|
#include "RimMainPlotCollection.h"
|
|
#include "RimObservedFmuRftData.h"
|
|
#include "RimPressureDepthData.h"
|
|
#include "RimProject.h"
|
|
#include "RimRftTools.h"
|
|
#include "RimSummaryCase.h"
|
|
#include "RimSummaryCaseCollection.h"
|
|
#include "RimTools.h"
|
|
#include "RimWellLogPlot.h"
|
|
#include "RimWellLogPlotCollection.h"
|
|
#include "RimWellLogTrack.h"
|
|
#include "RimWellPath.h"
|
|
#include "RimWellPlotTools.h"
|
|
#include "RimWellRftPlot.h"
|
|
|
|
#include "RiuQwtPlotCurve.h"
|
|
#include "RiuQwtPlotWidget.h"
|
|
|
|
#include "cafPdmObject.h"
|
|
#include "cafVecIjk.h"
|
|
#include "cvfAssert.h"
|
|
|
|
#include <qwt_plot.h>
|
|
|
|
#include <QString>
|
|
|
|
#include <numeric>
|
|
#include <vector>
|
|
|
|
namespace caf
|
|
{
|
|
template <>
|
|
void caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::setUp()
|
|
{
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::NONE, "NONE", "None" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::TVD, "DEPTH", "Depth" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::PRESSURE, "PRESSURE", "Pressure" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::SWAT, RiaResultNames::swat(), "Water Saturation" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::SOIL, RiaResultNames::soil(), "Oil Saturation" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::SGAS, RiaResultNames::sgas(), "Gas Saturation" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::WRAT, "WRAT", "Water Flow" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::ORAT, "ORAT", "Oil Flow" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::GRAT, "GRAT", "Gas flow" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::MD, "MD", "Measured Depth" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P10, "PRESSURE_P10", "P10: Pressure" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P50, "PRESSURE_P50", "P50: Pressure" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_P90, "PRESSURE_P90", "P90: Pressure" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_MEAN, "PRESSURE_MEAN", "Mean: Pressure" );
|
|
addItem( RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_ERROR, "PRESSURE_ERROR", "Error: Pressure" );
|
|
setDefault( RifEclipseRftAddress::RftWellLogChannelType::NONE );
|
|
}
|
|
} // namespace caf
|
|
|
|
namespace caf
|
|
{
|
|
template <>
|
|
void caf::AppEnum<RimWellLogRftCurve::RftDataType>::setUp()
|
|
{
|
|
addItem( RimWellLogRftCurve::RftDataType::RFT_DATA, "RFT_DATA", "RFT" );
|
|
addItem( RimWellLogRftCurve::RftDataType::RFT_SEGMENT_DATA, "RFT_SEGMENT_DATA", "RFT Segment" );
|
|
setDefault( RimWellLogRftCurve::RftDataType::RFT_DATA );
|
|
}
|
|
} // namespace caf
|
|
|
|
CAF_PDM_SOURCE_INIT( RimWellLogRftCurve, "WellLogRftCurve" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RiaDefines::PhaseType RimWellLogRftCurve::phaseType() const
|
|
{
|
|
if ( m_rftDataType() == RimWellLogRftCurve::RftDataType::RFT_DATA )
|
|
{
|
|
if ( m_wellLogChannelName() == RifEclipseRftAddress::RftWellLogChannelType::SWAT ||
|
|
m_wellLogChannelName() == RifEclipseRftAddress::RftWellLogChannelType::WRAT )
|
|
{
|
|
return RiaDefines::PhaseType::WATER_PHASE;
|
|
}
|
|
|
|
if ( m_wellLogChannelName() == RifEclipseRftAddress::RftWellLogChannelType::SGAS ||
|
|
m_wellLogChannelName() == RifEclipseRftAddress::RftWellLogChannelType::GRAT )
|
|
{
|
|
return RiaDefines::PhaseType::GAS_PHASE;
|
|
}
|
|
|
|
if ( m_wellLogChannelName() == RifEclipseRftAddress::RftWellLogChannelType::SOIL ||
|
|
m_wellLogChannelName() == RifEclipseRftAddress::RftWellLogChannelType::ORAT )
|
|
{
|
|
return RiaDefines::PhaseType::OIL_PHASE;
|
|
}
|
|
}
|
|
else if ( m_rftDataType() == RimWellLogRftCurve::RftDataType::RFT_SEGMENT_DATA )
|
|
{
|
|
if ( m_segmentResultName().startsWith( "SEGO" ) ) return RiaDefines::PhaseType::OIL_PHASE;
|
|
if ( m_segmentResultName().startsWith( "SEGW" ) ) return RiaDefines::PhaseType::WATER_PHASE;
|
|
if ( m_segmentResultName().startsWith( "SEGG" ) ) return RiaDefines::PhaseType::GAS_PHASE;
|
|
}
|
|
|
|
return RiaDefines::PhaseType::PHASE_NOT_APPLICABLE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
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_summaryCase, "CurveSummaryCase", "Summary Case" );
|
|
m_summaryCase.uiCapability()->setUiTreeChildrenHidden( true );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_ensemble, "CurveEnsemble", "Ensemble" );
|
|
m_ensemble.uiCapability()->setUiTreeChildrenHidden( true );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_observedFmuRftData, "ObservedFmuRftData", "Observed FMU RFT Data" );
|
|
m_observedFmuRftData.uiCapability()->setUiTreeChildrenHidden( true );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_pressureDepthData, "PressureDepthData", "Pressure Depth Data" );
|
|
m_pressureDepthData.uiCapability()->setUiTreeChildrenHidden( true );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_timeStep, "TimeStep", "Time Step" );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_wellName, "WellName", "Well Name" );
|
|
CAF_PDM_InitField( &m_branchIndex, "BranchIndex", 0, "Branch Index" );
|
|
CAF_PDM_InitField( &m_branchDetection,
|
|
"BranchDetection",
|
|
true,
|
|
"Branch Detection",
|
|
"",
|
|
"Compute branches based on how simulation well cells are organized",
|
|
"" );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_wellLogChannelName, "WellLogChannelName", "Well Property" );
|
|
CAF_PDM_InitFieldNoDefault( &m_rftDataType, "RftDataType", "Data Type" );
|
|
|
|
CAF_PDM_InitField( &m_segmentResultName, "SegmentResultName", RiaResultNames::undefinedResultName(), "Result Name" );
|
|
CAF_PDM_InitField( &m_segmentBranchIndex, "SegmentBranchIndex", -1, "Branch" );
|
|
CAF_PDM_InitFieldNoDefault( &m_segmentBranchType, "SegmentBranchType", "Completion" );
|
|
|
|
CAF_PDM_InitField( &m_scaleFactor, "ScaleFactor", 1.0, "Scale Factor" );
|
|
|
|
CAF_PDM_InitField( &m_curveColorByPhase, "CurveColorByPhase", false, "Color by Phase" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimWellLogRftCurve::~RimWellLogRftCurve()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setWellName( const QString& wellName )
|
|
{
|
|
m_wellName = wellName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimWellLogRftCurve::wellName() const
|
|
{
|
|
return m_wellName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimWellLogRftCurve::wellLogChannelUiName() const
|
|
{
|
|
return m_wellLogChannelName().text();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimWellLogRftCurve::wellLogChannelUnits() const
|
|
{
|
|
return RiaWellLogUnitTools<double>::noUnitString();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setTimeStep( const QDateTime& dateTime )
|
|
{
|
|
m_timeStep = dateTime;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QDateTime RimWellLogRftCurve::timeStep() const
|
|
{
|
|
return m_timeStep();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setSegmentBranchIndex( int branchIndex )
|
|
{
|
|
m_segmentBranchIndex = branchIndex;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setSegmentBranchType( RiaDefines::RftBranchType branchType )
|
|
{
|
|
m_segmentBranchType = branchType;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setEclipseResultCase( RimEclipseResultCase* eclipseResultCase )
|
|
{
|
|
m_eclipseResultCase = eclipseResultCase;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEclipseResultCase* RimWellLogRftCurve::eclipseResultCase() const
|
|
{
|
|
return m_eclipseResultCase;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setSummaryCase( RimSummaryCase* summaryCase )
|
|
{
|
|
m_summaryCase = summaryCase;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimSummaryCase* RimWellLogRftCurve::summaryCase() const
|
|
{
|
|
return m_summaryCase;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setEnsemble( RimSummaryCaseCollection* ensemble )
|
|
{
|
|
m_ensemble = ensemble;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimSummaryCaseCollection* RimWellLogRftCurve::ensemble() const
|
|
{
|
|
return m_ensemble;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setObservedFmuRftData( RimObservedFmuRftData* observedFmuRftData )
|
|
{
|
|
m_observedFmuRftData = observedFmuRftData;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimObservedFmuRftData* RimWellLogRftCurve::observedFmuRftData() const
|
|
{
|
|
return m_observedFmuRftData;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setPressureDepthData( RimPressureDepthData* observedFmuRftData )
|
|
{
|
|
m_pressureDepthData = observedFmuRftData;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimPressureDepthData* RimWellLogRftCurve::pressureDepthData() const
|
|
{
|
|
return m_pressureDepthData;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setRftAddress( RifEclipseRftAddress address )
|
|
{
|
|
m_timeStep = address.timeStep();
|
|
m_wellName = address.wellName();
|
|
m_wellLogChannelName = address.wellLogChannel();
|
|
|
|
if ( address.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::SEGMENT_VALUES )
|
|
{
|
|
m_rftDataType = RftDataType::RFT_SEGMENT_DATA;
|
|
m_segmentResultName = address.segmentResultName();
|
|
m_segmentBranchIndex = address.segmentBranchIndex();
|
|
m_segmentBranchType = address.segmentBranchType();
|
|
}
|
|
else
|
|
{
|
|
m_rftDataType = RftDataType::RFT_DATA;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RifEclipseRftAddress RimWellLogRftCurve::rftAddress() const
|
|
{
|
|
if ( m_rftDataType == RftDataType::RFT_SEGMENT_DATA )
|
|
{
|
|
return RifEclipseRftAddress::createBranchSegmentAddress( m_wellName,
|
|
m_timeStep,
|
|
m_segmentResultName(),
|
|
m_segmentBranchIndex(),
|
|
m_segmentBranchType() );
|
|
}
|
|
|
|
return RifEclipseRftAddress::createAddress( m_wellName, m_timeStep, m_wellLogChannelName() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setDefaultAddress( QString wellName )
|
|
{
|
|
RifReaderRftInterface* reader = rftReader();
|
|
if ( !reader ) return;
|
|
|
|
bool wellNameHasRftData = false;
|
|
std::set<QString> wellNames = reader->wellNames();
|
|
for ( const QString& wellNameWithRft : wellNames )
|
|
{
|
|
if ( wellName == wellNameWithRft )
|
|
{
|
|
wellNameHasRftData = true;
|
|
m_wellName = wellName;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !wellNameHasRftData )
|
|
{
|
|
m_wellLogChannelName = RifEclipseRftAddress::RftWellLogChannelType::NONE;
|
|
m_timeStep = QDateTime();
|
|
return;
|
|
}
|
|
|
|
m_wellLogChannelName = RifEclipseRftAddress::RftWellLogChannelType::PRESSURE;
|
|
|
|
std::set<QDateTime> timeSteps = reader->availableTimeSteps( m_wellName, m_wellLogChannelName() );
|
|
if ( !timeSteps.empty() )
|
|
{
|
|
m_timeStep = *( timeSteps.begin() );
|
|
}
|
|
else
|
|
{
|
|
m_timeStep = QDateTime();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::updateWellChannelNameAndTimeStep()
|
|
{
|
|
if ( !m_timeStep().isValid() || m_wellLogChannelName() == RifEclipseRftAddress::RftWellLogChannelType::NONE )
|
|
{
|
|
setDefaultAddress( m_wellName );
|
|
return;
|
|
}
|
|
|
|
RifReaderRftInterface* reader = rftReader();
|
|
if ( !reader ) return;
|
|
|
|
std::set<RifEclipseRftAddress::RftWellLogChannelType> channelNames = reader->availableWellLogChannels( m_wellName );
|
|
|
|
if ( channelNames.empty() )
|
|
{
|
|
m_wellLogChannelName = RifEclipseRftAddress::RftWellLogChannelType::NONE;
|
|
}
|
|
else if ( !channelNames.count( m_wellLogChannelName() ) )
|
|
{
|
|
m_wellLogChannelName = RifEclipseRftAddress::RftWellLogChannelType::PRESSURE;
|
|
}
|
|
|
|
std::set<QDateTime> timeSteps = reader->availableTimeSteps( m_wellName, m_wellLogChannelName() );
|
|
|
|
if ( timeSteps.empty() )
|
|
{
|
|
m_timeStep = QDateTime();
|
|
}
|
|
else if ( !timeSteps.count( m_timeStep() ) )
|
|
{
|
|
m_timeStep = *( timeSteps.begin() );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setSimWellBranchData( bool branchDetection, int branchIndex )
|
|
{
|
|
m_branchDetection = branchDetection;
|
|
m_branchIndex = branchIndex;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::enableColorFromResultName( bool enable )
|
|
{
|
|
m_curveColorByPhase = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::assignColorFromResultName( const QString& resultName )
|
|
{
|
|
cvf::Color3f color = cvf::Color3f::BLACK;
|
|
|
|
if ( resultName.startsWith( "SEGO" ) || resultName.startsWith( "CONO" ) || resultName.startsWith( "SOIL" ) )
|
|
{
|
|
color = RiaColorTables::summaryCurveGreenPaletteColors().cycledColor3f( 0 );
|
|
}
|
|
else if ( resultName.startsWith( "SEGW" ) || resultName.startsWith( "CONW" ) || resultName.startsWith( "SWAT" ) )
|
|
{
|
|
color = RiaColorTables::summaryCurveBluePaletteColors().cycledColor3f( 0 );
|
|
}
|
|
else if ( resultName.startsWith( "SEGG" ) || resultName.startsWith( "CONG" ) || resultName.startsWith( "SGAS" ) )
|
|
{
|
|
color = RiaColorTables::summaryCurveRedPaletteColors().cycledColor3f( 0 );
|
|
}
|
|
|
|
// Do nothing if not phase is identified
|
|
if ( color == cvf::Color3f::BLACK ) return;
|
|
|
|
float scalingFactor = 0.5;
|
|
auto fillColor = RiaColorTools::makeLighter( color, scalingFactor );
|
|
setColor( color );
|
|
setFillColor( fillColor );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::setScaleFactor( double factor )
|
|
{
|
|
m_scaleFactor = factor;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::map<QString, QString> RimWellLogRftCurve::createCurveNameKeyValueMap() const
|
|
{
|
|
std::map<QString, QString> variableValueMap;
|
|
|
|
if ( !wellName().isEmpty() )
|
|
{
|
|
variableValueMap[RiaDefines::namingVariableWell()] = wellName();
|
|
}
|
|
|
|
variableValueMap[RiaDefines::namingVariableResultType()] = "RFT";
|
|
|
|
QString caseText;
|
|
if ( m_eclipseResultCase )
|
|
{
|
|
caseText = m_eclipseResultCase->caseUserDescription();
|
|
}
|
|
else if ( m_summaryCase && m_ensemble ) // Summary RFT curves have both ensemble and summary set
|
|
{
|
|
caseText = QString( "%1, %2" ).arg( m_ensemble->name() ).arg( m_summaryCase->displayCaseName() );
|
|
}
|
|
else if ( m_ensemble )
|
|
{
|
|
caseText = m_ensemble->name();
|
|
}
|
|
else if ( m_summaryCase )
|
|
{
|
|
caseText = m_summaryCase->displayCaseName();
|
|
}
|
|
else if ( m_observedFmuRftData )
|
|
{
|
|
caseText = m_observedFmuRftData->name();
|
|
}
|
|
|
|
if ( !caseText.isEmpty() )
|
|
{
|
|
variableValueMap[RiaDefines::namingVariableCase()] = caseText;
|
|
}
|
|
|
|
if ( m_rftDataType() == RftDataType::RFT_DATA )
|
|
{
|
|
if ( wellLogChannelUiName() !=
|
|
caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::text( RifEclipseRftAddress::RftWellLogChannelType::NONE ) )
|
|
{
|
|
RifEclipseRftAddress::RftWellLogChannelType channelNameEnum =
|
|
caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::fromText( wellLogChannelUiName() );
|
|
QString channelName = caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::uiText( channelNameEnum );
|
|
|
|
variableValueMap[RiaDefines::namingVariableResultName()] = channelName;
|
|
}
|
|
}
|
|
else if ( m_rftDataType() == RftDataType::RFT_SEGMENT_DATA )
|
|
{
|
|
variableValueMap[RiaDefines::namingVariableResultName()] = m_segmentResultName;
|
|
|
|
QString branchText = QString( "Branch %1" ).arg( m_segmentBranchIndex() );
|
|
|
|
variableValueMap[RiaDefines::namingVariableWellBranch()] = branchText;
|
|
|
|
if ( isSegmentResult( m_segmentResultName() ) )
|
|
{
|
|
variableValueMap[RiaDefines::namingVariableResultType()] = m_segmentBranchType().uiText();
|
|
}
|
|
else
|
|
{
|
|
variableValueMap[RiaDefines::namingVariableResultType()] = "Reservoir";
|
|
}
|
|
}
|
|
|
|
if ( !m_timeStep().isNull() )
|
|
{
|
|
variableValueMap[RiaDefines::namingVariableTime()] = m_timeStep().toString( RiaQDateTimeTools::dateFormatString() );
|
|
}
|
|
|
|
return variableValueMap;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimWellLogRftCurve::createCurveAutoName()
|
|
{
|
|
QStringList curveNameSubStrings;
|
|
|
|
for ( const auto& [key, value] : createCurveNameKeyValueMap() )
|
|
{
|
|
curveNameSubStrings.push_back( value );
|
|
}
|
|
|
|
return curveNameSubStrings.join( ", " );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimWellLogRftCurve::createCurveNameFromTemplate( const QString& templateText )
|
|
{
|
|
auto name = RiaTextStringTools::replaceTemplateTextWithValues( templateText, createCurveNameKeyValueMap() );
|
|
|
|
if ( m_scaleFactor() != 1.0 )
|
|
{
|
|
int exponent = std::log10( m_scaleFactor() );
|
|
auto text = QString( "x1e%1" ).arg( QString::number( exponent ) );
|
|
|
|
name += QString( " [%1]" ).arg( text );
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QStringList RimWellLogRftCurve::supportedCurveNameVariables() const
|
|
{
|
|
return { RiaDefines::namingVariableWell(),
|
|
RiaDefines::namingVariableResultName(),
|
|
RiaDefines::namingVariableResultType(),
|
|
RiaDefines::namingVariableCase(),
|
|
RiaDefines::namingVariableWellBranch(),
|
|
RiaDefines::namingVariableTime() };
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
|
{
|
|
if ( m_curveColorByPhase && m_rftDataType() == RimWellLogRftCurve::RftDataType::RFT_SEGMENT_DATA )
|
|
{
|
|
assignColorFromResultName( m_segmentResultName );
|
|
}
|
|
|
|
this->RimPlotCurve::updateCurvePresentation( updateParentPlot );
|
|
|
|
DerivedMDSource derivedMDSource = DerivedMDSource::NO_SOURCE;
|
|
|
|
if ( m_autoCheckStateBasedOnCurveData() || isChecked() )
|
|
{
|
|
auto wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
|
|
|
|
auto* rftPlot = dynamic_cast<RimWellRftPlot*>( wellLogPlot );
|
|
bool showErrorBarsInObservedData = rftPlot ? rftPlot->showErrorBarsForObservedData() : false;
|
|
m_showErrorBars = showErrorBarsInObservedData;
|
|
|
|
std::vector<double> measuredDepthVector = measuredDepthValues();
|
|
std::vector<double> tvDepthVector = tvDepthValues();
|
|
std::vector<double> values = xValues();
|
|
std::vector<double> errors = errorValues();
|
|
std::vector<QString> perPointLabels;
|
|
|
|
auto anyValidValuesPresent = []( const std::vector<double>& values ) -> bool
|
|
{
|
|
for ( const auto& v : values )
|
|
{
|
|
if ( RiaStatisticsTools::isValidNumber<double>( v ) ) return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
if ( !anyValidValuesPresent( values ) || ( values.size() != tvDepthVector.size() ) )
|
|
{
|
|
clearCurveData();
|
|
this->detach( true );
|
|
return;
|
|
}
|
|
|
|
RiaDefines::EclipseUnitSystem unitSystem = RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
|
if ( m_eclipseResultCase )
|
|
{
|
|
// TODO: If no grid data, but only RFT data is loaded, we do not have any way to
|
|
// detect unit
|
|
if ( m_eclipseResultCase->eclipseCaseData() )
|
|
{
|
|
unitSystem = m_eclipseResultCase->eclipseCaseData()->unitsType();
|
|
}
|
|
}
|
|
else if ( m_summaryCase )
|
|
{
|
|
unitSystem = m_summaryCase->unitsSystem();
|
|
}
|
|
else if ( m_ensemble )
|
|
{
|
|
unitSystem = m_ensemble->unitSystem();
|
|
}
|
|
else if ( m_observedFmuRftData )
|
|
{
|
|
// TODO: Read unit system somewhere for FMU RFT Data
|
|
unitSystem = RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
|
perPointLabels = this->perPointLabels();
|
|
}
|
|
else if ( m_pressureDepthData )
|
|
{
|
|
// TODO: Read unit system for pressure data
|
|
unitSystem = RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
|
// perPointLabels = this->perPointLabels();
|
|
}
|
|
else
|
|
{
|
|
CVF_ASSERT( false && "Need to have either an eclipse result case, a summary case or an ensemble" );
|
|
}
|
|
|
|
if ( tvDepthVector.size() != measuredDepthVector.size() )
|
|
{
|
|
if ( deriveMeasuredDepthValuesFromWellPath( tvDepthVector, measuredDepthVector ) )
|
|
{
|
|
derivedMDSource = DerivedMDSource::WELL_PATH;
|
|
}
|
|
else if ( deriveMeasuredDepthFromObservedData( tvDepthVector, measuredDepthVector ) )
|
|
{
|
|
derivedMDSource = DerivedMDSource::OBSERVED_DATA;
|
|
}
|
|
}
|
|
|
|
if ( tvDepthVector.size() != measuredDepthVector.size() )
|
|
{
|
|
derivedMDSource = DerivedMDSource::NO_SOURCE;
|
|
measuredDepthVector = tvDepthVector;
|
|
}
|
|
|
|
RimProject* proj = RimProject::current();
|
|
RimWellPath* wellPath = proj->wellPathByName( m_wellName );
|
|
|
|
double rkbDiff = 0.0;
|
|
if ( wellPath && wellPath->wellPathGeometry() )
|
|
{
|
|
rkbDiff = wellPath->wellPathGeometry()->rkbDiff();
|
|
}
|
|
|
|
bool useLogarithmicScale = false;
|
|
this->setPropertyValuesWithMdAndTVD( values,
|
|
measuredDepthVector,
|
|
tvDepthVector,
|
|
rkbDiff,
|
|
RiaDefines::fromEclipseUnit( unitSystem ),
|
|
false,
|
|
useLogarithmicScale );
|
|
|
|
RiaDefines::DepthUnitType displayUnit = RiaDefines::DepthUnitType::UNIT_METER;
|
|
if ( wellLogPlot )
|
|
{
|
|
displayUnit = wellLogPlot->depthUnit();
|
|
}
|
|
|
|
if ( m_plotCurve )
|
|
{
|
|
if ( wellLogPlot->depthType() == RiaDefines::DepthTypeEnum::MEASURED_DEPTH )
|
|
{
|
|
m_plotCurve->setPerPointLabels( perPointLabels );
|
|
|
|
auto propertyValues = this->curveData()->propertyValuesByIntervals();
|
|
auto depthValues = this->curveData()->depthValuesByIntervals( RiaDefines::DepthTypeEnum::MEASURED_DEPTH, displayUnit );
|
|
|
|
if ( !errors.empty() )
|
|
{
|
|
setPropertyAndDepthsAndErrors( propertyValues, depthValues, errors );
|
|
}
|
|
else
|
|
{
|
|
setPropertyAndDepthValuesToPlotCurve( propertyValues, depthValues );
|
|
}
|
|
|
|
m_plotCurve->setLineSegmentStartStopIndices( this->curveData()->polylineStartStopIndices() );
|
|
|
|
auto wellLogTrack = firstAncestorOrThisOfTypeAsserted<RimWellLogTrack>();
|
|
|
|
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();
|
|
}
|
|
|
|
viewer->setAxisTitleText( wellLogPlot->depthAxis(), text );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_plotCurve->setPerPointLabels( perPointLabels );
|
|
|
|
auto propertyValues = this->curveData()->propertyValuesByIntervals();
|
|
auto depthValues = this->curveData()->depthValuesByIntervals( RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH, displayUnit );
|
|
bool useLogarithmicScale = false;
|
|
|
|
if ( !errors.empty() )
|
|
{
|
|
setPropertyAndDepthsAndErrors( propertyValues, depthValues, errors );
|
|
}
|
|
else
|
|
{
|
|
if ( isVerticalCurve() )
|
|
{
|
|
m_plotCurve->setSamplesFromXValuesAndYValues( propertyValues, depthValues, useLogarithmicScale );
|
|
}
|
|
else
|
|
{
|
|
m_plotCurve->setSamplesFromXValuesAndYValues( depthValues, propertyValues, useLogarithmicScale );
|
|
}
|
|
}
|
|
}
|
|
|
|
m_plotCurve->setLineSegmentStartStopIndices( this->curveData()->polylineStartStopIndices() );
|
|
}
|
|
|
|
if ( updateParentPlot )
|
|
{
|
|
updateZoomInParentPlot();
|
|
}
|
|
|
|
if ( m_parentPlot )
|
|
{
|
|
m_parentPlot->replot();
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogRftCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
|
{
|
|
RimPlotCurve::updateFieldUiState();
|
|
|
|
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Curve Data" );
|
|
curveDataGroup->add( &m_eclipseResultCase );
|
|
curveDataGroup->add( &m_summaryCase );
|
|
curveDataGroup->add( &m_wellName );
|
|
curveDataGroup->add( &m_timeStep );
|
|
curveDataGroup->add( &m_rftDataType );
|
|
curveDataGroup->add( &m_scaleFactor );
|
|
|
|
caf::PdmUiGroup* automationGroup = uiOrdering.addNewGroup( "Automation" );
|
|
automationGroup->setCollapsedByDefault();
|
|
automationGroup->add( &m_autoCheckStateBasedOnCurveData );
|
|
|
|
if ( m_rftDataType() == RimWellLogRftCurve::RftDataType::RFT_DATA )
|
|
{
|
|
curveDataGroup->add( &m_wellLogChannelName );
|
|
|
|
RiaSimWellBranchTools::appendSimWellBranchFieldsIfRequiredFromWellName( curveDataGroup, m_wellName, m_branchDetection, m_branchIndex );
|
|
}
|
|
else
|
|
{
|
|
curveDataGroup->add( &m_segmentResultName );
|
|
curveDataGroup->add( &m_segmentBranchType );
|
|
curveDataGroup->add( &m_segmentBranchIndex );
|
|
curveDataGroup->add( &m_curveColorByPhase );
|
|
}
|
|
|
|
RimStackablePlotCurve::defaultUiOrdering( uiOrdering );
|
|
|
|
uiOrdering.skipRemainingFields();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
|
{
|
|
QList<caf::PdmOptionItemInfo> options;
|
|
|
|
options = RimWellLogCurve::calculateValueOptions( fieldNeedingOptions );
|
|
|
|
if ( !options.empty() ) return options;
|
|
|
|
RifReaderRftInterface* reader = rftReader();
|
|
if ( fieldNeedingOptions == &m_eclipseResultCase )
|
|
{
|
|
RimTools::caseOptionItems( &options );
|
|
|
|
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_summaryCase )
|
|
{
|
|
options = RiaSummaryTools::optionsForSummaryCases( RimProject::current()->allSummaryCases() );
|
|
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_wellName )
|
|
{
|
|
options = RimRftTools::wellNameOptions( reader );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_wellLogChannelName )
|
|
{
|
|
options = RimRftTools::wellLogChannelsOptions( reader, m_wellName() );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_timeStep )
|
|
{
|
|
if ( m_rftDataType == RimWellLogRftCurve::RftDataType::RFT_SEGMENT_DATA )
|
|
options = RimRftTools::segmentTimeStepOptions( reader, m_wellName );
|
|
else
|
|
options = RimRftTools::timeStepOptions( reader, m_wellName, m_wellLogChannelName() );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_branchIndex )
|
|
{
|
|
auto simulationWellBranches =
|
|
RiaSimWellBranchTools::simulationWellBranches( RimWellPlotTools::simWellName( m_wellName ), m_branchDetection );
|
|
|
|
options = RiaSimWellBranchTools::valueOptionsForBranchIndexField( simulationWellBranches );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_segmentResultName )
|
|
{
|
|
options = RimRftTools::segmentResultNameOptions( reader, m_wellName(), m_timeStep() );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_segmentBranchIndex )
|
|
{
|
|
options = RimRftTools::segmentBranchIndexOptions( reader, m_wellName(), m_timeStep(), m_segmentBranchType() );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_scaleFactor )
|
|
{
|
|
for ( int exp = -12; exp <= 12; exp += 3 )
|
|
{
|
|
QString uiText = exp == 0 ? "1" : QString( "10 ^ %1" ).arg( exp );
|
|
double value = std::pow( 10, exp );
|
|
|
|
options.push_back( caf::PdmOptionItemInfo( uiText, value ) );
|
|
}
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
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 )
|
|
{
|
|
m_timeStep = QDateTime();
|
|
m_wellName = "";
|
|
m_wellLogChannelName = RifEclipseRftAddress::RftWellLogChannelType::NONE;
|
|
|
|
loadData = true;
|
|
}
|
|
else if ( changedField == &m_wellName )
|
|
{
|
|
m_branchIndex = 0;
|
|
|
|
updateWellChannelNameAndTimeStep();
|
|
loadData = true;
|
|
}
|
|
else if ( changedField == &m_branchDetection || changedField == &m_branchIndex )
|
|
{
|
|
QString simWellName = RimWellPlotTools::simWellName( m_wellName );
|
|
|
|
m_branchIndex = RiaSimWellBranchTools::clampBranchIndex( simWellName, m_branchIndex, m_branchDetection );
|
|
|
|
updateWellChannelNameAndTimeStep();
|
|
loadData = true;
|
|
}
|
|
else if ( changedField == &m_wellLogChannelName )
|
|
{
|
|
if ( m_wellLogChannelName == RifEclipseRftAddress::RftWellLogChannelType::NONE )
|
|
{
|
|
m_timeStep = QDateTime();
|
|
}
|
|
loadData = true;
|
|
}
|
|
else if ( changedField == &m_timeStep || changedField == &m_segmentResultName || changedField == &m_segmentBranchIndex ||
|
|
changedField == &m_rftDataType || changedField == &m_segmentBranchType || m_scaleFactor )
|
|
{
|
|
loadData = true;
|
|
}
|
|
|
|
if ( changedField == &m_rftDataType )
|
|
{
|
|
if ( m_rftDataType() == RftDataType::RFT_SEGMENT_DATA )
|
|
{
|
|
auto fileSummaryCase = dynamic_cast<RimFileSummaryCase*>( m_summaryCase() );
|
|
if ( fileSummaryCase ) fileSummaryCase->searchForWseglinkAndRecreateRftReader();
|
|
}
|
|
}
|
|
|
|
if ( loadData ) this->loadDataAndUpdate( true );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<QString> RimWellLogRftCurve::perPointLabels() const
|
|
{
|
|
if ( m_observedFmuRftData() )
|
|
{
|
|
auto address = RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::PRESSURE );
|
|
return m_observedFmuRftData()->labels( address );
|
|
}
|
|
return {};
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
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();
|
|
}
|
|
|
|
if ( m_ensemble() )
|
|
{
|
|
return m_ensemble()->rftStatisticsReader();
|
|
}
|
|
|
|
if ( m_observedFmuRftData() )
|
|
{
|
|
return m_observedFmuRftData()->rftReader();
|
|
}
|
|
|
|
if ( m_pressureDepthData() )
|
|
{
|
|
return m_pressureDepthData()->rftReader();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
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 )
|
|
{
|
|
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 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;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<double> RimWellLogRftCurve::xValues()
|
|
{
|
|
RifReaderRftInterface* reader = rftReader();
|
|
if ( !reader ) return {};
|
|
|
|
std::vector<double> values;
|
|
|
|
if ( m_rftDataType() == RftDataType::RFT_SEGMENT_DATA )
|
|
{
|
|
auto depthAddress = RifEclipseRftAddress::createBranchSegmentAddress( m_wellName(),
|
|
m_timeStep,
|
|
m_segmentResultName(),
|
|
segmentBranchIndex(),
|
|
m_segmentBranchType() );
|
|
|
|
reader->values( depthAddress, &values );
|
|
}
|
|
else
|
|
{
|
|
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 )
|
|
{
|
|
for ( auto& val : values )
|
|
{
|
|
val *= m_scaleFactor();
|
|
}
|
|
}
|
|
|
|
return values;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<double> RimWellLogRftCurve::errorValues()
|
|
{
|
|
RifReaderRftInterface* reader = rftReader();
|
|
std::vector<double> errorValues;
|
|
|
|
if ( reader && m_rftDataType() == RftDataType::RFT_DATA )
|
|
{
|
|
RifEclipseRftAddress errorAddress =
|
|
RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::PRESSURE_ERROR );
|
|
reader->values( errorAddress, &errorValues );
|
|
}
|
|
|
|
return errorValues;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<double> RimWellLogRftCurve::tvDepthValues()
|
|
{
|
|
RifReaderRftInterface* reader = rftReader();
|
|
std::vector<double> values;
|
|
|
|
if ( !reader ) return values;
|
|
|
|
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;
|
|
}
|
|
|
|
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()
|
|
{
|
|
if ( m_rftDataType() == RftDataType::RFT_SEGMENT_DATA )
|
|
{
|
|
RifReaderRftInterface* reader = rftReader();
|
|
if ( reader )
|
|
{
|
|
return RimRftTools::seglenstValues( reader, m_wellName(), m_timeStep, segmentBranchIndex(), m_segmentBranchType() );
|
|
}
|
|
return {};
|
|
}
|
|
|
|
if ( m_observedFmuRftData && !m_ensemble && !m_summaryCase )
|
|
{
|
|
RifReaderRftInterface* reader = rftReader();
|
|
std::vector<double> values;
|
|
|
|
if ( !reader ) return values;
|
|
|
|
RifEclipseRftAddress depthAddress =
|
|
RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::MD );
|
|
reader->values( depthAddress, &values );
|
|
return values;
|
|
}
|
|
|
|
if ( m_pressureDepthData && !m_ensemble && !m_summaryCase )
|
|
{
|
|
// Pressure depth data does not have MD
|
|
return {};
|
|
}
|
|
|
|
std::vector<double> measuredDepthForCells;
|
|
|
|
RigEclipseWellLogExtractor* eclExtractor = extractor();
|
|
|
|
if ( !eclExtractor ) return measuredDepthForCells;
|
|
|
|
std::vector<double> measuredDepthForIntersections = eclExtractor->cellIntersectionMDs();
|
|
|
|
if ( measuredDepthForIntersections.empty() )
|
|
{
|
|
return measuredDepthForCells;
|
|
}
|
|
|
|
std::vector<size_t> globCellIndices = eclExtractor->intersectedCellsGlobIdx();
|
|
|
|
for ( size_t i = 0; i < globCellIndices.size() - 1; i = i + 2 )
|
|
{
|
|
double sum = measuredDepthForIntersections[i] + measuredDepthForIntersections[i + 1];
|
|
|
|
measuredDepthForCells.push_back( sum / 2.0 );
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimWellLogRftCurve::deriveMeasuredDepthFromObservedData( const std::vector<double>& tvDepthValues, std::vector<double>& derivedMDValues )
|
|
{
|
|
if ( m_observedFmuRftData )
|
|
{
|
|
RifReaderRftInterface* reader = m_observedFmuRftData->rftReader();
|
|
if ( reader )
|
|
{
|
|
std::vector<double> tvdValuesOfObservedData;
|
|
std::vector<double> mdValuesOfObservedData;
|
|
|
|
RifEclipseRftAddress tvdAddress =
|
|
RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::TVD );
|
|
RifEclipseRftAddress mdAddress =
|
|
RifEclipseRftAddress::createAddress( m_wellName(), m_timeStep, RifEclipseRftAddress::RftWellLogChannelType::MD );
|
|
|
|
reader->values( tvdAddress, &tvdValuesOfObservedData );
|
|
reader->values( mdAddress, &mdValuesOfObservedData );
|
|
|
|
// We are not able to estimate MD/TVD relationship for less than two samples
|
|
if ( tvdValuesOfObservedData.size() < 2 ) return false;
|
|
|
|
derivedMDValues = RigWellPathGeometryTools::interpolateMdFromTvd( mdValuesOfObservedData, tvdValuesOfObservedData, tvDepthValues );
|
|
CVF_ASSERT( derivedMDValues.size() == tvDepthValues.size() );
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
int RimWellLogRftCurve::segmentBranchIndex() const
|
|
{
|
|
return m_segmentBranchIndex();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimWellLogRftCurve::isSegmentResult( const QString& resultName )
|
|
{
|
|
return resultName.startsWith( "SEG" );
|
|
}
|