ResInsight/ApplicationLibCode/UserInterface/RiuPvtPlotPanel.cpp

806 lines
30 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 "RiuPvtPlotPanel.h"
#include "RiuDockedQwtPlot.h"
#include "RiuGuiTheme.h"
#include "RiuPvtPlotUpdater.h"
#include "RiaEclipseUnitTools.h"
#include "RigFlowDiagSolverInterface.h"
#include "cvfAssert.h"
#include "cvfMath.h"
#include "qwt_legend.h"
#include "qwt_picker_machine.h"
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include "qwt_plot_grid.h"
#include "qwt_plot_layout.h"
#include "qwt_plot_marker.h"
#include "qwt_plot_picker.h"
#include "qwt_symbol.h"
#include "qwt_text.h"
#include <QComboBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QVBoxLayout>
#include <QWidget>
//==================================================================================================
//
//
//
//==================================================================================================
class PvtQwtPlot : public RiuDockedQwtPlot
{
public:
PvtQwtPlot( QWidget* parent )
: RiuDockedQwtPlot( parent )
{
}
QSize sizeHint() const override { return QSize( 100, 100 ); }
QSize minimumSizeHint() const override { return QSize( 0, 0 ); }
};
//==================================================================================================
//
//
//
//==================================================================================================
class RiuPvtQwtPicker : public QwtPicker
{
public:
RiuPvtQwtPicker( QwtPlot* plot, RiuPvtTrackerTextProvider* trackerTextProvider )
: QwtPicker( QwtPicker::NoRubberBand, QwtPicker::AlwaysOn, plot->canvas() )
, m_trackerTextProvider( trackerTextProvider )
{
setStateMachine( new QwtPickerTrackerMachine );
}
QwtText trackerText( const QPoint& ) const override
{
QwtText text( m_trackerTextProvider->trackerText() );
text.setRenderFlags( Qt::AlignLeft );
return text;
}
private:
const RiuPvtTrackerTextProvider* m_trackerTextProvider;
};
//==================================================================================================
///
/// \class RiuPvtPlotWidget
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPvtPlotWidget::RiuPvtPlotWidget( RiuPvtPlotPanel* parent )
: QWidget( parent )
, m_trackerPlotMarker( nullptr )
{
m_qwtPlot = new PvtQwtPlot( this );
m_qwtPlot->setProperty( "qss-class", "PvtPlot" );
setPlotDefaults( m_qwtPlot );
applyFontSizes( false );
QHBoxLayout* layout = new QHBoxLayout();
layout->addWidget( m_qwtPlot );
layout->setSpacing( 0 );
layout->setContentsMargins( 0, 0, 0, 0 );
setLayout( layout );
m_qwtPicker = new RiuPvtQwtPicker( m_qwtPlot, this );
RiuGuiTheme::styleQwtItem( m_qwtPicker );
connect( m_qwtPicker, SIGNAL( activated( bool ) ), this, SLOT( slotPickerActivated( bool ) ) );
connect( m_qwtPicker, SIGNAL( moved( const QPoint& ) ), this, SLOT( slotPickerPointChanged( const QPoint& ) ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotWidget::setPlotDefaults( QwtPlot* plot )
{
plot->setAutoFillBackground( true );
QFrame* canvasFrame = dynamic_cast<QFrame*>( plot->canvas() );
if ( canvasFrame )
{
canvasFrame->setFrameShape( QFrame::NoFrame );
}
// Grid
{
QwtPlotGrid* grid = new QwtPlotGrid;
grid->attach( plot );
RiuGuiTheme::styleQwtItem( grid );
}
// Axis number font
{
QFont axisFont = plot->axisFont( QwtAxis::XBottom );
axisFont.setPointSize( 8 );
plot->setAxisFont( QwtAxis::XBottom, axisFont );
plot->setAxisFont( QwtAxis::YLeft, axisFont );
}
// Axis title font
{
QwtText axisTitle = plot->axisTitle( QwtAxis::XBottom );
QFont axisTitleFont = axisTitle.font();
axisTitleFont.setPointSize( 8 );
axisTitleFont.setBold( false );
axisTitle.setFont( axisTitleFont );
axisTitle.setRenderFlags( Qt::AlignRight );
plot->setAxisTitle( QwtAxis::XBottom, axisTitle );
plot->setAxisTitle( QwtAxis::YLeft, axisTitle );
}
// Title font
{
QwtText plotTitle = plot->title();
QFont titleFont = plotTitle.font();
titleFont.setPointSize( 12 );
plotTitle.setFont( titleFont );
plot->setTitle( plotTitle );
}
plot->setAxisMaxMinor( QwtAxis::XBottom, 2 );
plot->setAxisMaxMinor( QwtAxis::YLeft, 3 );
plot->plotLayout()->setAlignCanvasToScales( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotWidget::plotCurves( RiaDefines::EclipseUnitSystem unitSystem,
const std::vector<RigFlowDiagSolverInterface::PvtCurve>& curveArr,
double pressure,
double pointMarkerYValue,
const QString& pointMarkerLabel,
const QString& plotTitle,
const QString& yAxisTitle )
{
m_qwtPlot->detachItems( QwtPlotItem::Rtti_PlotCurve );
m_qwtPlot->detachItems( QwtPlotItem::Rtti_PlotMarker );
m_qwtCurveArr.clear();
m_pvtCurveArr.clear();
m_trackerPlotMarker = nullptr;
// Construct an auxiliary curve that connects the first point in all the input curves as a visual aid
// This should only be shown when the phase being plotted is oil
// Will not be added to our array of qwt curves since we do not expect the user to interact with it
{
std::vector<double> xVals;
std::vector<double> yVals;
for ( size_t i = 0; i < curveArr.size(); i++ )
{
const RigFlowDiagSolverInterface::PvtCurve& curve = curveArr[i];
if ( curve.phase == RigFlowDiagSolverInterface::PvtCurve::OIL && !curve.pressureVals.empty() && !curve.yVals.empty() )
{
xVals.push_back( curve.pressureVals[0] );
yVals.push_back( curve.yVals[0] );
}
}
if ( xVals.size() > 1 )
{
QwtPlotCurve* qwtCurve = new QwtPlotCurve( "Auxiliary" );
qwtCurve->setSamples( xVals.data(), yVals.data(), static_cast<int>( xVals.size() ) );
qwtCurve->setStyle( QwtPlotCurve::Lines );
qwtCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
qwtCurve->attach( m_qwtPlot );
RiuGuiTheme::styleQwtItem( qwtCurve );
}
}
// Add the primary curves
for ( size_t i = 0; i < curveArr.size(); i++ )
{
const RigFlowDiagSolverInterface::PvtCurve& curve = curveArr[i];
QwtPlotCurve* qwtCurve = new QwtPlotCurve();
QwtSymbol* curveSymbol = new QwtSymbol( QwtSymbol::Ellipse );
CVF_ASSERT( curve.pressureVals.size() == curve.yVals.size() );
qwtCurve->setSamples( curve.pressureVals.data(), curve.yVals.data(), static_cast<int>( curve.pressureVals.size() ) );
qwtCurve->setStyle( QwtPlotCurve::Lines );
if ( curve.phase == RigFlowDiagSolverInterface::PvtCurve::GAS )
{
qwtCurve->setTitle( "Gas" );
}
else if ( curve.phase == RigFlowDiagSolverInterface::PvtCurve::OIL )
{
qwtCurve->setTitle( "Oil" );
}
else
{
qwtCurve->setTitle( "Undefined" );
}
qwtCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
curveSymbol->setSize( 6, 6 );
curveSymbol->setBrush( Qt::NoBrush );
qwtCurve->setSymbol( curveSymbol );
qwtCurve->attach( m_qwtPlot );
RiuGuiTheme::styleQwtItem( qwtCurve );
m_qwtCurveArr.push_back( qwtCurve );
}
m_pvtCurveArr = curveArr;
CVF_ASSERT( m_pvtCurveArr.size() == m_qwtCurveArr.size() );
// Add vertical marker line to indicate cell pressure
if ( pressure != HUGE_VAL )
{
QwtPlotMarker* lineMarker = new QwtPlotMarker;
QPen pen;
pen.setStyle( Qt::DashLine );
lineMarker->setLinePen( pen );
lineMarker->setXValue( pressure );
lineMarker->setLineStyle( QwtPlotMarker::VLine );
lineMarker->setLabel( QString( "PRESSURE" ) );
lineMarker->setLabelAlignment( Qt::AlignTop | Qt::AlignRight );
lineMarker->setLabelOrientation( Qt::Vertical );
lineMarker->attach( m_qwtPlot );
RiuGuiTheme::styleQwtItem( lineMarker );
}
// Then point marker
if ( pressure != HUGE_VAL && pointMarkerYValue != HUGE_VAL )
{
QwtPlotMarker* pointMarker = new QwtPlotMarker;
pointMarker->setValue( pressure, pointMarkerYValue );
QwtSymbol* symbol = new QwtSymbol( QwtSymbol::Ellipse );
symbol->setSize( 13, 13 );
QPen pen;
pen.setWidth( 2 );
symbol->setPen( pen );
symbol->setBrush( Qt::NoBrush );
pointMarker->setSymbol( symbol );
if ( !pointMarkerLabel.isEmpty() )
{
QwtText text( pointMarkerLabel );
text.setRenderFlags( Qt::AlignLeft );
text.setColor( RiuGuiTheme::getColorByVariableName( "textColor" ) );
pointMarker->setLabel( text );
pointMarker->setLabelAlignment( Qt::AlignTop | Qt::AlignRight );
}
pointMarker->attach( m_qwtPlot );
RiuGuiTheme::styleQwtItem( pointMarker );
}
m_qwtPlot->setTitle( plotTitle );
m_qwtPlot->setAxisTitle( QwtAxis::XBottom, QString( "Pressure [%1]" ).arg( RiaEclipseUnitTools::unitStringPressure( unitSystem ) ) );
m_qwtPlot->setAxisTitle( QwtAxis::YLeft, yAxisTitle );
updateTrackerPlotMarkerAndLabelFromPicker();
m_qwtPlot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotWidget::applyFontSizes( bool replot )
{
m_qwtPlot->applyFontSizes( replot );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotWidget::updateTrackerPlotMarkerAndLabelFromPicker()
{
bool hasValidSamplePoint = false;
QPointF samplePoint;
QString mixRatioText = "";
double mixRat = HUGE_VAL;
if ( m_qwtPicker && m_qwtPicker->isActive() )
{
const QPoint trackerPos = m_qwtPicker->trackerPosition();
int pointSampleIdx = -1;
const QwtPlotCurve* closestQwtCurve = closestCurveSample( trackerPos, &pointSampleIdx );
if ( closestQwtCurve && pointSampleIdx >= 0 )
{
samplePoint = closestQwtCurve->sample( pointSampleIdx );
hasValidSamplePoint = true;
size_t curveIdx = indexOfQwtCurve( closestQwtCurve );
if ( curveIdx < m_pvtCurveArr.size() )
{
const RigFlowDiagSolverInterface::PvtCurve& pvtCurve = m_pvtCurveArr[curveIdx];
if ( static_cast<size_t>( pointSampleIdx ) < pvtCurve.mixRatVals.size() )
{
mixRat = pvtCurve.mixRatVals[pointSampleIdx];
// The text is Rs or Rv depending on phase
mixRatioText = ( pvtCurve.phase == RigFlowDiagSolverInterface::PvtCurve::GAS ) ? "Rv" : "Rs";
}
}
}
}
m_trackerLabel = "";
bool needsReplot = false;
if ( hasValidSamplePoint )
{
if ( !m_trackerPlotMarker )
{
m_trackerPlotMarker = new QwtPlotMarker;
m_trackerPlotMarker->setTitle( QString( "TrackedPoint" ) );
QwtSymbol* symbol = new QwtSymbol( QwtSymbol::Ellipse );
symbol->setSize( 13, 13 );
symbol->setBrush( Qt::NoBrush );
m_trackerPlotMarker->setSymbol( symbol );
m_trackerPlotMarker->attach( m_qwtPlot );
RiuGuiTheme::styleQwtItem( m_trackerPlotMarker );
needsReplot = true;
}
if ( m_trackerPlotMarker->value() != samplePoint )
{
m_trackerPlotMarker->setValue( samplePoint );
needsReplot = true;
}
m_trackerLabel = QString( "%1 (%2)" ).arg( samplePoint.y() ).arg( samplePoint.x() );
if ( mixRat != HUGE_VAL )
{
m_trackerLabel += QString( "\n%1 = %2" ).arg( mixRatioText ).arg( mixRat );
}
}
else
{
if ( m_trackerPlotMarker )
{
m_trackerPlotMarker->detach();
delete m_trackerPlotMarker;
m_trackerPlotMarker = nullptr;
needsReplot = true;
}
}
if ( needsReplot )
{
m_qwtPlot->replot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QwtPlotCurve* RiuPvtPlotWidget::closestCurveSample( const QPoint& cursorPosition, int* closestSampleIndex ) const
{
// Construct a set containing the relevant qwt curves to consider
// These are the curves that have a corresponding Pvt source curve
std::set<const QwtPlotCurve*> relevantQwtCurvesSet( m_qwtCurveArr.begin(), m_qwtCurveArr.end() );
if ( closestSampleIndex ) *closestSampleIndex = -1;
const QwtPlotCurve* closestCurve = nullptr;
double distMin = HUGE_VAL;
int closestPointSampleIndex = -1;
const QwtPlotItemList& itemList = m_qwtPlot->itemList();
for ( QwtPlotItemIterator it = itemList.begin(); it != itemList.end(); it++ )
{
if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve )
{
const QwtPlotCurve* curve = static_cast<const QwtPlotCurve*>( *it );
if ( relevantQwtCurvesSet.find( curve ) != relevantQwtCurvesSet.end() )
{
double dist = HUGE_VAL;
int candidateSampleIndex = curve->closestPoint( cursorPosition, &dist );
if ( dist < distMin )
{
closestCurve = curve;
closestPointSampleIndex = candidateSampleIndex;
distMin = dist;
}
}
}
}
if ( closestCurve && closestPointSampleIndex >= 0 && distMin < 50 )
{
if ( closestSampleIndex ) *closestSampleIndex = closestPointSampleIndex;
return closestCurve;
}
else
{
return nullptr;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RiuPvtPlotWidget::indexOfQwtCurve( const QwtPlotCurve* qwtCurve ) const
{
for ( size_t i = 0; i < m_qwtCurveArr.size(); i++ )
{
if ( m_qwtCurveArr[i] == qwtCurve )
{
return i;
}
}
return cvf::UNDEFINED_SIZE_T;
}
//--------------------------------------------------------------------------------------------------
/// Implements the RiuPvtTrackerTextProvider interface
//--------------------------------------------------------------------------------------------------
QString RiuPvtPlotWidget::trackerText() const
{
return m_trackerLabel;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotWidget::slotPickerPointChanged( const QPoint& pt )
{
updateTrackerPlotMarkerAndLabelFromPicker();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotWidget::slotPickerActivated( bool on )
{
updateTrackerPlotMarkerAndLabelFromPicker();
}
//==================================================================================================
///
/// \class RiuPvtPlotPanel
///
///
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPvtPlotPanel::RiuPvtPlotPanel( QWidget* parent )
: QWidget( parent )
, m_unitSystem( RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN )
, m_plotUpdater( new RiuPvtPlotUpdater( this ) )
{
m_phaseComboBox = new QComboBox( this );
m_phaseComboBox->setEditable( false );
m_phaseComboBox->addItem( "Oil", QVariant( RigFlowDiagSolverInterface::PvtCurve::OIL ) );
m_phaseComboBox->addItem( "Gas", QVariant( RigFlowDiagSolverInterface::PvtCurve::GAS ) );
m_titleLabel = new QLabel( "", this );
m_titleLabel->setAlignment( Qt::AlignHCenter );
QFont font = m_titleLabel->font();
font.setPointSize( 10 );
font.setBold( true );
m_titleLabel->setFont( font );
QHBoxLayout* topLayout = new QHBoxLayout();
topLayout->addWidget( new QLabel( "Phase:" ) );
topLayout->addWidget( m_phaseComboBox );
topLayout->addWidget( m_titleLabel, 1 );
topLayout->setContentsMargins( 5, 5, 0, 0 );
m_fvfPlot = new RiuPvtPlotWidget( this );
m_viscosityPlot = new RiuPvtPlotWidget( this );
QHBoxLayout* plotLayout = new QHBoxLayout();
plotLayout->addWidget( m_fvfPlot );
plotLayout->addWidget( m_viscosityPlot );
plotLayout->setSpacing( 0 );
plotLayout->setContentsMargins( 0, 0, 0, 0 );
QVBoxLayout* mainLayout = new QVBoxLayout();
mainLayout->addLayout( topLayout );
mainLayout->addLayout( plotLayout );
mainLayout->setContentsMargins( 0, 0, 0, 0 );
setLayout( mainLayout );
connect( m_phaseComboBox, SIGNAL( currentIndexChanged( int ) ), SLOT( slotPhaseComboCurrentIndexChanged( int ) ) );
plotUiSelectedCurves();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPvtPlotPanel::~RiuPvtPlotPanel()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotPanel::setPlotData( RiaDefines::EclipseUnitSystem unitSystem,
const std::vector<RigFlowDiagSolverInterface::PvtCurve>& fvfCurveArr,
const std::vector<RigFlowDiagSolverInterface::PvtCurve>& viscosityCurveArr,
const FvfDynProps& fvfDynProps,
const ViscosityDynProps& viscosityDynProps,
const CellValues& cellValues,
const QString& cellReferenceText )
{
// cvf::Trace::show("RiuPvtPlotPanel::setPlotData()");
m_unitSystem = unitSystem;
m_allFvfCurvesArr = fvfCurveArr;
m_allViscosityCurvesArr = viscosityCurveArr;
m_fvfDynProps = fvfDynProps;
m_viscosityDynProps = viscosityDynProps;
m_cellValues = cellValues;
m_cellReferenceText = cellReferenceText;
plotUiSelectedCurves();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotPanel::clearPlot()
{
// cvf::Trace::show("RiuPvtPlotPanel::clearPlot()");
if ( m_allFvfCurvesArr.empty() && m_allViscosityCurvesArr.empty() && m_cellReferenceText.isEmpty() )
{
return;
}
m_unitSystem = RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
m_allFvfCurvesArr.clear();
m_allViscosityCurvesArr.clear();
m_fvfDynProps = FvfDynProps();
m_viscosityDynProps = ViscosityDynProps();
m_cellValues = CellValues();
m_cellReferenceText.clear();
plotUiSelectedCurves();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPvtPlotUpdater* RiuPvtPlotPanel::plotUpdater()
{
return m_plotUpdater.get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotPanel::applyFontSizes( bool replot )
{
if ( m_fvfPlot ) m_fvfPlot->applyFontSizes( replot );
if ( m_viscosityPlot ) m_viscosityPlot->applyFontSizes( replot );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotPanel::plotUiSelectedCurves()
{
// Determine which curves (phase) to actually plot based on selection in GUI
const int currComboIdx = m_phaseComboBox->currentIndex();
const RigFlowDiagSolverInterface::PvtCurve::Phase phaseToPlot =
static_cast<RigFlowDiagSolverInterface::PvtCurve::Phase>( m_phaseComboBox->itemData( currComboIdx ).toInt() );
QString phaseString = "";
if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::GAS )
{
phaseString = "Gas ";
}
else if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::OIL )
{
phaseString = "Oil ";
}
// FVF plot
{
RigFlowDiagSolverInterface::PvtCurve::Ident curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Unknown;
double pointMarkerFvfValue = HUGE_VAL;
QString pointMarkerLabel = "";
if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::GAS )
{
curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Bg;
pointMarkerFvfValue = m_fvfDynProps.bg;
pointMarkerLabel = QString( "%1 (%2)" ).arg( pointMarkerFvfValue ).arg( m_cellValues.pressure );
if ( m_cellValues.rv != HUGE_VAL )
{
pointMarkerLabel += QString( "\nRv = %1" ).arg( m_cellValues.rv );
}
}
else if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::OIL )
{
curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Bo;
pointMarkerFvfValue = m_fvfDynProps.bo;
pointMarkerLabel = QString( "%1 (%2)" ).arg( pointMarkerFvfValue ).arg( m_cellValues.pressure );
if ( m_cellValues.rs != HUGE_VAL )
{
pointMarkerLabel += QString( "\nRs = %1" ).arg( m_cellValues.rs );
}
}
std::vector<RigFlowDiagSolverInterface::PvtCurve> selectedFvfCurves;
for ( RigFlowDiagSolverInterface::PvtCurve curve : m_allFvfCurvesArr )
{
if ( curve.ident == curveIdentToPlot )
{
selectedFvfCurves.push_back( curve );
}
}
const QString plotTitle = QString( "%1 Formation Volume Factor" ).arg( phaseString );
const QString yAxisTitle =
QString( "%1 Formation Volume Factor [%2]" ).arg( phaseString ).arg( unitLabelFromCurveIdent( m_unitSystem, curveIdentToPlot ) );
m_fvfPlot->plotCurves( m_unitSystem, selectedFvfCurves, m_cellValues.pressure, pointMarkerFvfValue, pointMarkerLabel, plotTitle, yAxisTitle );
}
// Viscosity plot
{
RigFlowDiagSolverInterface::PvtCurve::Ident curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Unknown;
double pointMarkerViscosityValue = HUGE_VAL;
QString pointMarkerLabel = "";
if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::GAS )
{
curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Visc_g;
pointMarkerViscosityValue = m_viscosityDynProps.mu_g;
pointMarkerLabel = QString( "%1 (%2)" ).arg( pointMarkerViscosityValue ).arg( m_cellValues.pressure );
if ( m_cellValues.rv != HUGE_VAL )
{
pointMarkerLabel += QString( "\nRv = %1" ).arg( m_cellValues.rv );
}
}
else if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::OIL )
{
curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Visc_o;
pointMarkerViscosityValue = m_viscosityDynProps.mu_o;
pointMarkerLabel = QString( "%1 (%2)" ).arg( pointMarkerViscosityValue ).arg( m_cellValues.pressure );
if ( m_cellValues.rs != HUGE_VAL )
{
pointMarkerLabel += QString( "\nRs = %1" ).arg( m_cellValues.rs );
}
}
std::vector<RigFlowDiagSolverInterface::PvtCurve> selectedViscosityCurves;
for ( RigFlowDiagSolverInterface::PvtCurve curve : m_allViscosityCurvesArr )
{
if ( curve.ident == curveIdentToPlot )
{
selectedViscosityCurves.push_back( curve );
}
}
const QString plotTitle = QString( "%1 Viscosity" ).arg( phaseString );
const QString yAxisTitle =
QString( "%1 Viscosity [%2]" ).arg( phaseString ).arg( unitLabelFromCurveIdent( m_unitSystem, curveIdentToPlot ) );
m_viscosityPlot->plotCurves( m_unitSystem,
selectedViscosityCurves,
m_cellValues.pressure,
pointMarkerViscosityValue,
pointMarkerLabel,
plotTitle,
yAxisTitle );
}
// Update the label on top in our panel
QString titleStr = "PVT";
if ( !m_cellReferenceText.isEmpty() )
{
titleStr += ", " + m_cellReferenceText;
}
m_titleLabel->setText( titleStr );
}
//--------------------------------------------------------------------------------------------------
/// Static helper to get unit labels
//--------------------------------------------------------------------------------------------------
QString RiuPvtPlotPanel::unitLabelFromCurveIdent( RiaDefines::EclipseUnitSystem unitSystem,
RigFlowDiagSolverInterface::PvtCurve::Ident curveIdent )
{
if ( curveIdent == RigFlowDiagSolverInterface::PvtCurve::Bo )
{
switch ( unitSystem )
{
case RiaDefines::EclipseUnitSystem::UNITS_METRIC:
return "rm3/sm3";
case RiaDefines::EclipseUnitSystem::UNITS_FIELD:
return "rb/stb";
case RiaDefines::EclipseUnitSystem::UNITS_LAB:
return "rcc/scc";
default:
return "";
}
}
else if ( curveIdent == RigFlowDiagSolverInterface::PvtCurve::Bg )
{
switch ( unitSystem )
{
case RiaDefines::EclipseUnitSystem::UNITS_METRIC:
return "rm3/sm3";
case RiaDefines::EclipseUnitSystem::UNITS_FIELD:
return "rb/Mscf";
case RiaDefines::EclipseUnitSystem::UNITS_LAB:
return "rcc/scc";
default:
return "";
}
}
else if ( curveIdent == RigFlowDiagSolverInterface::PvtCurve::Visc_o || curveIdent == RigFlowDiagSolverInterface::PvtCurve::Visc_g )
{
switch ( unitSystem )
{
case RiaDefines::EclipseUnitSystem::UNITS_METRIC:
return "cP";
case RiaDefines::EclipseUnitSystem::UNITS_FIELD:
return "cP";
case RiaDefines::EclipseUnitSystem::UNITS_LAB:
return "cP";
default:
return "";
}
}
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuPvtPlotPanel::slotPhaseComboCurrentIndexChanged( int )
{
plotUiSelectedCurves();
}