mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-01 03:37:15 -06:00
806 lines
30 KiB
C++
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();
|
|
}
|