mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-01 03:37:15 -06:00
906 lines
36 KiB
C++
906 lines
36 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 "RiuRelativePermeabilityPlotPanel.h"
|
|
|
|
#include "RigFlowDiagSolverInterface.h"
|
|
|
|
#include "RiaCurveDataTools.h"
|
|
#include "RiaEclipseUnitTools.h"
|
|
#include "RiaPlotDefines.h"
|
|
#include "RiaResultNames.h"
|
|
#include "RiuDockedQwtPlot.h"
|
|
#include "RiuGuiTheme.h"
|
|
#include "RiuPlotCurveSymbol.h"
|
|
#include "RiuQwtPlotTools.h"
|
|
#include "RiuQwtSymbol.h"
|
|
#include "RiuRelativePermeabilityPlotUpdater.h"
|
|
#include "RiuTextDialog.h"
|
|
|
|
#include "cvfAssert.h"
|
|
|
|
#include "qwt_legend.h"
|
|
#include "qwt_plot.h"
|
|
#include "qwt_plot_curve.h"
|
|
#include "qwt_plot_marker.h"
|
|
#include "qwt_scale_engine.h"
|
|
#include "qwt_text.h"
|
|
|
|
#include <QButtonGroup>
|
|
#include <QCheckBox>
|
|
#include <QContextMenuEvent>
|
|
#include <QGridLayout>
|
|
#include <QGroupBox>
|
|
#include <QHBoxLayout>
|
|
#include <QMenu>
|
|
#include <QPushButton>
|
|
#include <QVBoxLayout>
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
//==================================================================================================
|
|
//
|
|
//
|
|
//
|
|
//==================================================================================================
|
|
class RelPermQwtPlot : public RiuDockedQwtPlot
|
|
{
|
|
public:
|
|
RelPermQwtPlot( QWidget* parent )
|
|
: RiuDockedQwtPlot( parent )
|
|
{
|
|
}
|
|
QSize sizeHint() const override { return QSize( 100, 100 ); }
|
|
QSize minimumSizeHint() const override { return QSize( 0, 0 ); }
|
|
};
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class RiuRelativePermeabilityPlotPanel
|
|
///
|
|
///
|
|
///
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RiuRelativePermeabilityPlotPanel::RiuRelativePermeabilityPlotPanel( QWidget* parent )
|
|
: QWidget( parent )
|
|
, m_unitSystem( RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN )
|
|
, m_swat( HUGE_VAL )
|
|
, m_sgas( HUGE_VAL )
|
|
, m_plotUpdater( new RiuRelativePermeabilityPlotUpdater( this ) )
|
|
, m_qwtPlot( nullptr )
|
|
, m_selectedCurvesButtonGroup( nullptr )
|
|
, m_groupBox( nullptr )
|
|
, m_logarithmicScaleKrAxisCheckBox( nullptr )
|
|
, m_showUnscaledCheckBox( nullptr )
|
|
, m_showScaledCheckBox( nullptr )
|
|
, m_fixedXAxisCheckBox( nullptr )
|
|
, m_fixedLeftYAxisCheckBox( nullptr )
|
|
|
|
{
|
|
m_qwtPlot = new RelPermQwtPlot( this );
|
|
m_qwtPlot->setProperty( "qss-class", "RelPermPlot" );
|
|
|
|
setPlotDefaults( m_qwtPlot );
|
|
applyFontSizes( false );
|
|
|
|
m_selectedCurvesButtonGroup = new QButtonGroup( this );
|
|
m_selectedCurvesButtonGroup->setExclusive( false );
|
|
|
|
m_selectedCurvesButtonGroup->addButton( new QCheckBox( "KRW" ), RigFlowDiagSolverInterface::RelPermCurve::KRW );
|
|
m_selectedCurvesButtonGroup->addButton( new QCheckBox( "KRG" ), RigFlowDiagSolverInterface::RelPermCurve::KRG );
|
|
m_selectedCurvesButtonGroup->addButton( new QCheckBox( "KROW" ), RigFlowDiagSolverInterface::RelPermCurve::KROW );
|
|
m_selectedCurvesButtonGroup->addButton( new QCheckBox( "KROG" ), RigFlowDiagSolverInterface::RelPermCurve::KROG );
|
|
m_selectedCurvesButtonGroup->addButton( new QCheckBox( "PCOW" ), RigFlowDiagSolverInterface::RelPermCurve::PCOW );
|
|
m_selectedCurvesButtonGroup->addButton( new QCheckBox( "PCOG" ), RigFlowDiagSolverInterface::RelPermCurve::PCOG );
|
|
|
|
m_groupBox = new QGroupBox( "Curves" );
|
|
QGridLayout* groupBoxLayout = new QGridLayout;
|
|
m_groupBox->setLayout( groupBoxLayout );
|
|
|
|
QList<QAbstractButton*> checkButtonList = m_selectedCurvesButtonGroup->buttons();
|
|
for ( int i = 0; i < checkButtonList.size(); i++ )
|
|
{
|
|
checkButtonList[i]->setChecked( true );
|
|
groupBoxLayout->addWidget( checkButtonList[i], i / 2, i % 2 );
|
|
}
|
|
|
|
m_logarithmicScaleKrAxisCheckBox = new QCheckBox( "Log Scale Kr Axis" );
|
|
m_showUnscaledCheckBox = new QCheckBox( "Show Unscaled" );
|
|
m_showScaledCheckBox = new QCheckBox( "Show Scaled" );
|
|
m_fixedXAxisCheckBox = new QCheckBox( "Fixed [0, 1] X-axis" );
|
|
m_fixedLeftYAxisCheckBox = new QCheckBox( "Fixed [0, 1] Kr-axis" );
|
|
|
|
m_fixedXAxisCheckBox->setChecked( true );
|
|
m_fixedLeftYAxisCheckBox->setChecked( true );
|
|
m_showScaledCheckBox->setChecked( true );
|
|
|
|
QCheckBox* showCurveSelection = new QCheckBox( "Show Curve Selection" );
|
|
showCurveSelection->setCheckState( Qt::Unchecked );
|
|
connect( showCurveSelection, SIGNAL( stateChanged( int ) ), SLOT( slotShowCurveSelectionWidgets( int ) ) );
|
|
|
|
QVBoxLayout* leftLayout = new QVBoxLayout;
|
|
leftLayout->addWidget( showCurveSelection );
|
|
leftLayout->addWidget( m_groupBox );
|
|
leftLayout->addWidget( m_logarithmicScaleKrAxisCheckBox );
|
|
leftLayout->addWidget( m_showScaledCheckBox );
|
|
leftLayout->addWidget( m_showUnscaledCheckBox );
|
|
leftLayout->addWidget( m_fixedXAxisCheckBox );
|
|
leftLayout->addWidget( m_fixedLeftYAxisCheckBox );
|
|
leftLayout->addStretch( 1 );
|
|
|
|
QHBoxLayout* mainLayout = new QHBoxLayout();
|
|
mainLayout->addLayout( leftLayout );
|
|
mainLayout->addWidget( m_qwtPlot );
|
|
mainLayout->setContentsMargins( 5, 0, 0, 0 );
|
|
|
|
setLayout( mainLayout );
|
|
|
|
connect( m_selectedCurvesButtonGroup, SIGNAL( idClicked( int ) ), SLOT( slotButtonInButtonGroupClicked( int ) ) );
|
|
connect( m_logarithmicScaleKrAxisCheckBox, SIGNAL( stateChanged( int ) ), SLOT( slotSomeCheckBoxStateChanged( int ) ) );
|
|
connect( m_showUnscaledCheckBox, SIGNAL( stateChanged( int ) ), SLOT( slotSomeCheckBoxStateChanged( int ) ) );
|
|
connect( m_showScaledCheckBox, SIGNAL( stateChanged( int ) ), SLOT( slotSomeCheckBoxStateChanged( int ) ) );
|
|
connect( m_fixedXAxisCheckBox, SIGNAL( stateChanged( int ) ), SLOT( slotSomeCheckBoxStateChanged( int ) ) );
|
|
connect( m_fixedLeftYAxisCheckBox, SIGNAL( stateChanged( int ) ), SLOT( slotSomeCheckBoxStateChanged( int ) ) );
|
|
|
|
slotShowCurveSelectionWidgets( showCurveSelection->checkState() );
|
|
|
|
plotUiSelectedCurves();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RiuRelativePermeabilityPlotPanel::~RiuRelativePermeabilityPlotPanel()
|
|
{
|
|
}
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::setPlotDefaults( QwtPlot* plot )
|
|
{
|
|
RiuQwtPlotTools::setCommonPlotBehaviour( plot );
|
|
|
|
{
|
|
QwtText plotTitle = plot->title();
|
|
QFont titleFont = plotTitle.font();
|
|
titleFont.setPointSize( 10 );
|
|
plotTitle.setFont( titleFont );
|
|
plot->setTitle( plotTitle );
|
|
}
|
|
|
|
plot->setAxesCount( QwtAxis::XBottom, 1 );
|
|
plot->setAxesCount( QwtAxis::YLeft, 1 );
|
|
|
|
plot->setAxisMaxMinor( QwtAxis::XBottom, 2 );
|
|
plot->setAxisMaxMinor( QwtAxis::YLeft, 3 );
|
|
|
|
QwtLegend* legend = new QwtLegend( plot );
|
|
plot->insertLegend( legend, QwtPlot::BottomLegend );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::setPlotData( RiaDefines::EclipseUnitSystem unitSystem,
|
|
const std::vector<RigFlowDiagSolverInterface::RelPermCurve>& relPermCurves,
|
|
double swat,
|
|
double sgas,
|
|
const QString& caseName,
|
|
const QString& cellReferenceText )
|
|
{
|
|
// cvf::Trace::show("Set RelPerm plot data");
|
|
|
|
m_unitSystem = unitSystem;
|
|
m_allCurvesArr = relPermCurves;
|
|
m_swat = swat;
|
|
m_sgas = sgas;
|
|
m_caseName = caseName;
|
|
m_cellReferenceText = cellReferenceText;
|
|
|
|
plotUiSelectedCurves();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::clearPlot()
|
|
{
|
|
// cvf::Trace::show("Clear RelPerm plot data");
|
|
|
|
if ( m_allCurvesArr.empty() && m_cellReferenceText.isEmpty() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_unitSystem = RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
|
m_allCurvesArr.clear();
|
|
m_swat = HUGE_VAL;
|
|
m_sgas = HUGE_VAL;
|
|
m_caseName.clear();
|
|
m_cellReferenceText.clear();
|
|
|
|
plotCurvesInQwt( m_unitSystem, m_allCurvesArr, m_swat, m_sgas, m_cellReferenceText, false, true, true, m_qwtPlot, &m_myPlotMarkers, false, false );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RiuRelativePermeabilityPlotUpdater* RiuRelativePermeabilityPlotPanel::plotUpdater()
|
|
{
|
|
return m_plotUpdater.get();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::applyFontSizes( bool replot /*= true*/ )
|
|
{
|
|
m_qwtPlot->applyFontSizes( replot );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::plotUiSelectedCurves()
|
|
{
|
|
std::vector<RigFlowDiagSolverInterface::RelPermCurve> selectedCurves = gatherUiSelectedCurves();
|
|
|
|
const bool useLogScale = m_logarithmicScaleKrAxisCheckBox->isChecked();
|
|
const bool fixedXAxis = m_fixedXAxisCheckBox->isChecked();
|
|
const bool fixedYAxis = m_fixedLeftYAxisCheckBox->isChecked();
|
|
plotCurvesInQwt( m_unitSystem,
|
|
selectedCurves,
|
|
m_swat,
|
|
m_sgas,
|
|
m_cellReferenceText,
|
|
useLogScale,
|
|
fixedXAxis,
|
|
fixedYAxis,
|
|
m_qwtPlot,
|
|
&m_myPlotMarkers,
|
|
m_showScaledCheckBox->isChecked(),
|
|
m_showUnscaledCheckBox->isChecked() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Add a transparent curve to make tooltip available on given points.
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::addTransparentCurve( QwtPlot* plot,
|
|
const std::vector<QPointF>& points,
|
|
const std::vector<WhichYAxis>& axes,
|
|
bool logScaleLeftAxis )
|
|
{
|
|
QwtPlotCurve* curveLeftAxis = new QwtPlotCurve();
|
|
QwtPlotCurve* curveRightAxis = new QwtPlotCurve();
|
|
|
|
QVector<QPointF> pointsOnLeftAxis;
|
|
QVector<QPointF> pointsOnRightAxis;
|
|
|
|
// Each point is defined by either left or right axis
|
|
CVF_ASSERT( points.size() == axes.size() );
|
|
|
|
for ( size_t i = 0; i < points.size(); i++ )
|
|
{
|
|
if ( !RiaCurveDataTools::isValidValue( points[i].y(), logScaleLeftAxis ) ) continue;
|
|
|
|
if ( axes[i] == LEFT_YAXIS )
|
|
{
|
|
pointsOnLeftAxis.push_back( points[i] );
|
|
}
|
|
else
|
|
{
|
|
pointsOnRightAxis.push_back( points[i] );
|
|
}
|
|
}
|
|
|
|
curveLeftAxis->setSamples( pointsOnLeftAxis );
|
|
curveRightAxis->setSamples( pointsOnRightAxis );
|
|
|
|
curveLeftAxis->setYAxis( QwtAxis::YLeft );
|
|
curveRightAxis->setYAxis( QwtAxis::YRight );
|
|
|
|
curveLeftAxis->setStyle( QwtPlotCurve::NoCurve );
|
|
curveRightAxis->setStyle( QwtPlotCurve::NoCurve );
|
|
|
|
curveLeftAxis->setLegendAttribute( QwtPlotCurve::LegendNoAttribute );
|
|
curveRightAxis->setLegendAttribute( QwtPlotCurve::LegendNoAttribute );
|
|
|
|
curveLeftAxis->attach( plot );
|
|
curveRightAxis->attach( plot );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::plotCurvesInQwt( RiaDefines::EclipseUnitSystem unitSystem,
|
|
const std::vector<RigFlowDiagSolverInterface::RelPermCurve>& curveArr,
|
|
double swat,
|
|
double sgas,
|
|
QString cellReferenceText,
|
|
bool logScaleLeftAxis,
|
|
bool fixedXAxis,
|
|
bool fixedLeftYAxis,
|
|
QwtPlot* plot,
|
|
std::vector<QwtPlotMarker*>* myPlotMarkers,
|
|
bool showScaled,
|
|
bool showUnscaled )
|
|
{
|
|
bool skipUnscaledLegends = showScaled && showUnscaled;
|
|
|
|
plot->detachItems( QwtPlotItem::Rtti_PlotCurve );
|
|
|
|
// Workaround for detaching only plot markers that we have added
|
|
// Needed as long as the curve point tracker is also using plot markers for its marking
|
|
// plot->detachItems(QwtPlotItem::Rtti_PlotMarker);
|
|
for ( QwtPlotMarker* marker : *myPlotMarkers )
|
|
{
|
|
marker->detach();
|
|
delete marker;
|
|
}
|
|
myPlotMarkers->clear();
|
|
|
|
std::vector<QPointF> points;
|
|
std::vector<WhichYAxis> axes;
|
|
|
|
const QColor waterColor = RiuGuiTheme::getColorByVariableName( "curveColorWater" );
|
|
const QColor gasColor = RiuGuiTheme::getColorByVariableName( "curveColorGas" );
|
|
|
|
bool shouldEnableRightYAxis = false;
|
|
|
|
for ( size_t i = 0; i < curveArr.size(); i++ )
|
|
{
|
|
const RigFlowDiagSolverInterface::RelPermCurve& curve = curveArr[i];
|
|
|
|
const auto unscaledCurve = ( curve.epsMode == RigFlowDiagSolverInterface::RelPermCurve::EPS_OFF );
|
|
|
|
// Which axis should this curve be plotted on
|
|
WhichYAxis plotOnWhichYAxis = LEFT_YAXIS;
|
|
if ( curve.ident == RigFlowDiagSolverInterface::RelPermCurve::PCOW || curve.ident == RigFlowDiagSolverInterface::RelPermCurve::PCOG )
|
|
{
|
|
plotOnWhichYAxis = RIGHT_YAXIS;
|
|
}
|
|
|
|
QwtPlotCurve* qwtCurve = new QwtPlotCurve( curve.name.c_str() );
|
|
|
|
CVF_ASSERT( curve.saturationVals.size() == curve.yVals.size() );
|
|
qwtCurve->setSamples( curve.saturationVals.data(), curve.yVals.data(), static_cast<int>( curve.saturationVals.size() ) );
|
|
|
|
qwtCurve->setTitle( curve.name.c_str() );
|
|
|
|
qwtCurve->setStyle( QwtPlotCurve::Lines );
|
|
|
|
Qt::PenStyle penStyle = Qt::SolidLine;
|
|
switch ( curve.ident )
|
|
{
|
|
case RigFlowDiagSolverInterface::RelPermCurve::KRW:
|
|
qwtCurve->setTitle( "KRW" );
|
|
break;
|
|
case RigFlowDiagSolverInterface::RelPermCurve::KROW:
|
|
qwtCurve->setTitle( "KROW" );
|
|
break;
|
|
case RigFlowDiagSolverInterface::RelPermCurve::PCOW:
|
|
qwtCurve->setTitle( "PCOW" );
|
|
penStyle = Qt::DashLine;
|
|
break;
|
|
case RigFlowDiagSolverInterface::RelPermCurve::KRG:
|
|
qwtCurve->setTitle( "KRG" );
|
|
break;
|
|
case RigFlowDiagSolverInterface::RelPermCurve::KROG:
|
|
qwtCurve->setTitle( "KROG" );
|
|
break;
|
|
case RigFlowDiagSolverInterface::RelPermCurve::PCOG:
|
|
qwtCurve->setTitle( "PCOG" );
|
|
penStyle = Qt::DashLine;
|
|
break;
|
|
}
|
|
|
|
const QPen curvePen( QBrush(), 1, penStyle );
|
|
qwtCurve->setPen( curvePen );
|
|
|
|
auto* curveSymbol = unscaledCurve ? new RiuQwtSymbol( RiuPlotCurveSymbol::SYMBOL_CROSS )
|
|
: new RiuQwtSymbol( RiuPlotCurveSymbol::SYMBOL_ELLIPSE );
|
|
curveSymbol->setSize( 6, 6 );
|
|
curveSymbol->setBrush( Qt::NoBrush );
|
|
qwtCurve->setSymbol( curveSymbol );
|
|
|
|
qwtCurve->setLegendAttribute( QwtPlotCurve::LegendShowLine, true );
|
|
qwtCurve->setLegendAttribute( QwtPlotCurve::LegendShowSymbol, false );
|
|
qwtCurve->setLegendAttribute( QwtPlotCurve::LegendShowBrush, true );
|
|
|
|
const bool showLegend = !( unscaledCurve && skipUnscaledLegends );
|
|
qwtCurve->setItemAttribute( QwtPlotItem::Legend, showLegend );
|
|
|
|
qwtCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
|
|
|
|
if ( plotOnWhichYAxis == RIGHT_YAXIS )
|
|
{
|
|
qwtCurve->setYAxis( { QwtAxis::YRight, 0 } );
|
|
shouldEnableRightYAxis = true;
|
|
}
|
|
|
|
qwtCurve->attach( plot );
|
|
|
|
RiuGuiTheme::styleQwtItem( qwtCurve );
|
|
|
|
// Add markers to indicate where SWAT and/or SGAS saturation intersects the respective curves
|
|
// Note that if we're using log scale we must guard against non-positive values
|
|
if ( swat != HUGE_VAL )
|
|
{
|
|
if ( curve.ident == RigFlowDiagSolverInterface::RelPermCurve::KRW || curve.ident == RigFlowDiagSolverInterface::RelPermCurve::KROW ||
|
|
curve.ident == RigFlowDiagSolverInterface::RelPermCurve::PCOW )
|
|
{
|
|
addCurveConstSaturationIntersectionMarker( curve, swat, waterColor, plotOnWhichYAxis, plot, myPlotMarkers, &points, &axes );
|
|
}
|
|
}
|
|
if ( sgas != HUGE_VAL )
|
|
{
|
|
if ( curve.ident == RigFlowDiagSolverInterface::RelPermCurve::KRG || curve.ident == RigFlowDiagSolverInterface::RelPermCurve::KROG ||
|
|
curve.ident == RigFlowDiagSolverInterface::RelPermCurve::PCOG )
|
|
{
|
|
addCurveConstSaturationIntersectionMarker( curve, sgas, gasColor, plotOnWhichYAxis, plot, myPlotMarkers, &points, &axes );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( shouldEnableRightYAxis )
|
|
{
|
|
plot->setAxesCount( QwtAxis::YRight, 1 );
|
|
plot->setAxisVisible( QwtAxis::YRight, true );
|
|
}
|
|
else
|
|
{
|
|
plot->setAxesCount( QwtAxis::YRight, 0 );
|
|
plot->setAxisVisible( QwtAxis::YRight, false );
|
|
}
|
|
|
|
addTransparentCurve( plot, points, axes, logScaleLeftAxis );
|
|
|
|
// Add vertical marker lines to indicate cell SWAT and/or SGAS saturations
|
|
if ( swat != HUGE_VAL )
|
|
{
|
|
addVerticalSaturationMarkerLine( swat, RiaResultNames::swat(), waterColor, plot, myPlotMarkers );
|
|
}
|
|
if ( sgas != HUGE_VAL )
|
|
{
|
|
addVerticalSaturationMarkerLine( sgas, RiaResultNames::sgas(), gasColor, plot, myPlotMarkers );
|
|
}
|
|
|
|
if ( logScaleLeftAxis )
|
|
{
|
|
if ( !dynamic_cast<QwtLogScaleEngine*>( plot->axisScaleEngine( QwtAxis::YLeft ) ) )
|
|
{
|
|
plot->setAxisScaleEngine( QwtAxis::YLeft, new QwtLogScaleEngine );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !dynamic_cast<QwtLinearScaleEngine*>( plot->axisScaleEngine( QwtAxis::YLeft ) ) )
|
|
{
|
|
plot->setAxisScaleEngine( QwtAxis::YLeft, new QwtLinearScaleEngine );
|
|
}
|
|
}
|
|
|
|
if ( fixedXAxis )
|
|
{
|
|
plot->setAxisScale( QwtAxis::XBottom, 0.0, 1.0 );
|
|
plot->setAxisAutoScale( QwtAxis::XBottom, false );
|
|
}
|
|
else
|
|
{
|
|
plot->setAxisAutoScale( QwtAxis::XBottom, true );
|
|
}
|
|
|
|
if ( fixedLeftYAxis )
|
|
{
|
|
if ( logScaleLeftAxis )
|
|
{
|
|
plot->setAxisScale( QwtAxis::YLeft, 1.0e-6, 1.0 );
|
|
}
|
|
else
|
|
{
|
|
plot->setAxisScale( QwtAxis::YLeft, 0.0, 1.0 );
|
|
}
|
|
plot->setAxisAutoScale( QwtAxis::YLeft, false );
|
|
}
|
|
else
|
|
{
|
|
plot->setAxisAutoScale( QwtAxis::YLeft, true );
|
|
}
|
|
|
|
if ( showScaled )
|
|
{
|
|
QwtPlotCurve* curve = getLegendCurve( "Scaled", true /*scaled*/ );
|
|
curve->attach( plot );
|
|
}
|
|
|
|
if ( showUnscaled )
|
|
{
|
|
QwtPlotCurve* curve = getLegendCurve( "Unscaled", false /*scaled*/ );
|
|
curve->attach( plot );
|
|
}
|
|
|
|
QString titleStr = "Relative Permeability";
|
|
if ( !cellReferenceText.isEmpty() )
|
|
{
|
|
titleStr += ", " + cellReferenceText;
|
|
}
|
|
plot->setTitle( titleStr );
|
|
|
|
plot->setAxisTitle( QwtAxis::XBottom, determineXAxisTitleFromCurveCollection( curveArr ) );
|
|
plot->setAxisTitle( QwtAxis::YLeft, "Kr" );
|
|
plot->setAxisTitle( QwtAxis::YRight, QString( "Pc [%1]" ).arg( RiaEclipseUnitTools::unitStringPressure( unitSystem ) ) );
|
|
plot->replot();
|
|
}
|
|
|
|
QwtPlotCurve* RiuRelativePermeabilityPlotPanel::getLegendCurve( QString title, bool scaled )
|
|
{
|
|
QwtPlotCurve* curve = new QwtPlotCurve( title );
|
|
|
|
curve->setTitle( title );
|
|
|
|
curve->setStyle( QwtPlotCurve::Lines );
|
|
|
|
const QPen curvePen( QBrush(), 1, Qt::SolidLine );
|
|
curve->setPen( curvePen );
|
|
|
|
auto* curveSymbol = scaled ? new RiuQwtSymbol( RiuPlotCurveSymbol::SYMBOL_ELLIPSE ) : new RiuQwtSymbol( RiuPlotCurveSymbol::SYMBOL_CROSS );
|
|
curveSymbol->setSize( 6, 6 );
|
|
curveSymbol->setBrush( QBrush() );
|
|
curve->setSymbol( curveSymbol );
|
|
|
|
curve->setLegendAttribute( QwtPlotCurve::LegendShowLine, true );
|
|
curve->setLegendAttribute( QwtPlotCurve::LegendShowSymbol, true );
|
|
curve->setLegendAttribute( QwtPlotCurve::LegendShowBrush, false );
|
|
curve->setItemAttribute( QwtPlotItem::Legend, true );
|
|
|
|
return curve;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RiuRelativePermeabilityPlotPanel::determineXAxisTitleFromCurveCollection( const std::vector<RigFlowDiagSolverInterface::RelPermCurve>& curveArr )
|
|
{
|
|
bool sawWater = false;
|
|
bool sawGas = false;
|
|
|
|
for ( RigFlowDiagSolverInterface::RelPermCurve curve : curveArr )
|
|
{
|
|
switch ( curve.ident )
|
|
{
|
|
case RigFlowDiagSolverInterface::RelPermCurve::KRW:
|
|
sawWater = true;
|
|
break;
|
|
case RigFlowDiagSolverInterface::RelPermCurve::KROW:
|
|
sawWater = true;
|
|
break;
|
|
case RigFlowDiagSolverInterface::RelPermCurve::PCOW:
|
|
sawWater = true;
|
|
break;
|
|
|
|
case RigFlowDiagSolverInterface::RelPermCurve::KRG:
|
|
sawGas = true;
|
|
break;
|
|
case RigFlowDiagSolverInterface::RelPermCurve::KROG:
|
|
sawGas = true;
|
|
break;
|
|
case RigFlowDiagSolverInterface::RelPermCurve::PCOG:
|
|
sawGas = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
QString title = "";
|
|
if ( sawWater && sawGas )
|
|
title = "Water/Gas ";
|
|
else if ( sawWater )
|
|
title = "Water ";
|
|
else if ( sawGas )
|
|
title = "Gas ";
|
|
|
|
title += "Saturation";
|
|
|
|
return title;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Add a vertical labeled marker line at the specified saturation value
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::addVerticalSaturationMarkerLine( double saturationValue,
|
|
QString label,
|
|
QColor color,
|
|
QwtPlot* plot,
|
|
std::vector<QwtPlotMarker*>* myPlotMarkers )
|
|
{
|
|
QwtPlotMarker* lineMarker = new QwtPlotMarker;
|
|
lineMarker->setXValue( saturationValue );
|
|
lineMarker->setLineStyle( QwtPlotMarker::VLine );
|
|
lineMarker->setLinePen( QPen( color, 1, Qt::DotLine ) );
|
|
lineMarker->setLabel( label );
|
|
lineMarker->setLabelAlignment( Qt::AlignTop | Qt::AlignRight );
|
|
lineMarker->setLabelOrientation( Qt::Vertical );
|
|
|
|
lineMarker->attach( plot );
|
|
myPlotMarkers->push_back( lineMarker );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Add a marker at the intersection of the passed curve and the constant saturation value
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::addCurveConstSaturationIntersectionMarker( const RigFlowDiagSolverInterface::RelPermCurve& curve,
|
|
double saturationValue,
|
|
QColor markerColor,
|
|
WhichYAxis whichYAxis,
|
|
QwtPlot* plot,
|
|
std::vector<QwtPlotMarker*>* myPlotMarkers,
|
|
std::vector<QPointF>* points,
|
|
std::vector<WhichYAxis>* axes )
|
|
{
|
|
const double yVal = interpolatedCurveYValue( curve.saturationVals, curve.yVals, saturationValue );
|
|
if ( yVal != HUGE_VAL )
|
|
{
|
|
QwtPlotMarker* pointMarker = new QwtPlotMarker;
|
|
pointMarker->setValue( saturationValue, yVal );
|
|
|
|
QwtSymbol* symbol = new QwtSymbol( QwtSymbol::Ellipse );
|
|
symbol->setSize( 13, 13 );
|
|
symbol->setPen( QPen( markerColor, 2 ) );
|
|
symbol->setBrush( Qt::NoBrush );
|
|
pointMarker->setSymbol( symbol );
|
|
pointMarker->attach( plot );
|
|
|
|
if ( whichYAxis == RIGHT_YAXIS )
|
|
{
|
|
pointMarker->setYAxis( QwtAxis::YRight );
|
|
}
|
|
|
|
myPlotMarkers->push_back( pointMarker );
|
|
axes->push_back( whichYAxis );
|
|
points->push_back( QPointF( saturationValue, yVal ) );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Assumes that all the x-values are ordered in increasing order
|
|
//--------------------------------------------------------------------------------------------------
|
|
double RiuRelativePermeabilityPlotPanel::interpolatedCurveYValue( const std::vector<double>& xVals, const std::vector<double>& yVals, double x )
|
|
{
|
|
if ( xVals.empty() ) return HUGE_VAL;
|
|
if ( x < xVals.front() ) return HUGE_VAL;
|
|
if ( x > xVals.back() ) return HUGE_VAL;
|
|
|
|
// Find first element greater or equal to the passed x-value
|
|
std::vector<double>::const_iterator it = std::upper_bound( xVals.begin(), xVals.end(), x );
|
|
|
|
// Due to checks above, we should never come up empty, but to safeguard against NaNs etc
|
|
if ( it == xVals.end() )
|
|
{
|
|
return HUGE_VAL;
|
|
}
|
|
|
|
// Corner case - exact match on first element
|
|
if ( it == xVals.begin() )
|
|
{
|
|
return yVals.front();
|
|
}
|
|
|
|
const size_t idx1 = it - xVals.begin();
|
|
CVF_ASSERT( idx1 > 0 );
|
|
const size_t idx0 = idx1 - 1;
|
|
|
|
const double x0 = xVals[idx0];
|
|
const double y0 = yVals[idx0];
|
|
const double x1 = xVals[idx1];
|
|
const double y1 = yVals[idx1];
|
|
CVF_ASSERT( x1 > x0 );
|
|
|
|
const double t = ( x1 - x0 ) > 0 ? ( x - x0 ) / ( x1 - x0 ) : 0;
|
|
const double y = y0 * ( 1.0 - t ) + y1 * t;
|
|
|
|
return y;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<RigFlowDiagSolverInterface::RelPermCurve> RiuRelativePermeabilityPlotPanel::gatherUiSelectedCurves() const
|
|
{
|
|
std::vector<RigFlowDiagSolverInterface::RelPermCurve> selectedCurves;
|
|
|
|
// Determine which curves to actually plot based on selection in GUI
|
|
const bool showScaled = m_showScaledCheckBox->isChecked();
|
|
const bool showUnscaled = m_showUnscaledCheckBox->isChecked();
|
|
|
|
for ( size_t i = 0; i < m_allCurvesArr.size(); i++ )
|
|
{
|
|
const RigFlowDiagSolverInterface::RelPermCurve::Ident curveIdent = m_allCurvesArr[i].ident;
|
|
const RigFlowDiagSolverInterface::RelPermCurve::EpsMode curveEpsMode = m_allCurvesArr[i].epsMode;
|
|
|
|
if ( m_selectedCurvesButtonGroup->button( curveIdent ) && m_selectedCurvesButtonGroup->button( curveIdent )->isChecked() )
|
|
{
|
|
if ( ( ( curveEpsMode == RigFlowDiagSolverInterface::RelPermCurve::EPS_ON ) && showScaled ) ||
|
|
( ( curveEpsMode == RigFlowDiagSolverInterface::RelPermCurve::EPS_OFF ) && showUnscaled ) )
|
|
{
|
|
selectedCurves.push_back( m_allCurvesArr[i] );
|
|
}
|
|
}
|
|
}
|
|
|
|
return selectedCurves;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RiuRelativePermeabilityPlotPanel::asciiDataForUiSelectedCurves() const
|
|
{
|
|
std::vector<RigFlowDiagSolverInterface::RelPermCurve> selectedCurves = gatherUiSelectedCurves();
|
|
|
|
QString outTxt;
|
|
|
|
// Info header
|
|
outTxt += m_caseName + ", " + m_cellReferenceText + "\n";
|
|
|
|
// Column headers
|
|
for ( size_t icurve = 0; icurve < selectedCurves.size(); icurve++ )
|
|
{
|
|
if ( icurve > 0 ) outTxt += "\t";
|
|
|
|
const RigFlowDiagSolverInterface::RelPermCurve& curve = selectedCurves[icurve];
|
|
outTxt += "Saturation";
|
|
outTxt += "\t";
|
|
outTxt += curve.name.c_str();
|
|
}
|
|
|
|
// Table data
|
|
size_t sampleIndex = 0;
|
|
bool iterationContributedData = true;
|
|
while ( iterationContributedData )
|
|
{
|
|
iterationContributedData = false;
|
|
|
|
QString lineStr = "\n";
|
|
|
|
for ( size_t icurve = 0; icurve < selectedCurves.size(); icurve++ )
|
|
{
|
|
if ( icurve > 0 ) lineStr += "\t";
|
|
|
|
const RigFlowDiagSolverInterface::RelPermCurve& curve = selectedCurves[icurve];
|
|
if ( sampleIndex < curve.saturationVals.size() && sampleIndex < curve.yVals.size() )
|
|
{
|
|
lineStr += QString::number( curve.saturationVals[sampleIndex], 'g', 6 );
|
|
lineStr += "\t";
|
|
lineStr += QString::number( curve.yVals[sampleIndex], 'g', 6 );
|
|
|
|
iterationContributedData = true;
|
|
}
|
|
else
|
|
{
|
|
lineStr += "\t";
|
|
}
|
|
}
|
|
|
|
if ( iterationContributedData )
|
|
{
|
|
outTxt += lineStr;
|
|
}
|
|
|
|
sampleIndex++;
|
|
}
|
|
|
|
return outTxt;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::contextMenuEvent( QContextMenuEvent* event )
|
|
{
|
|
QMenu menu;
|
|
|
|
const int curveCount = m_qwtPlot->itemList( QwtPlotItem::Rtti_PlotCurve ).count();
|
|
|
|
QAction* act = menu.addAction( "Show Plot Data", this, SLOT( slotCurrentPlotDataInTextDialog() ) );
|
|
act->setEnabled( curveCount > 0 );
|
|
|
|
menu.exec( event->globalPos() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::slotCurrentPlotDataInTextDialog()
|
|
{
|
|
QString outTxt = asciiDataForUiSelectedCurves();
|
|
|
|
RiuTextDialog* textDialog = new RiuTextDialog( this );
|
|
textDialog->setMinimumSize( 400, 600 );
|
|
textDialog->setWindowTitle( "Relative Permeability Data" );
|
|
textDialog->setText( outTxt );
|
|
textDialog->show();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::slotShowCurveSelectionWidgets( int state )
|
|
{
|
|
bool setVisible = ( state != Qt::CheckState::Unchecked );
|
|
|
|
m_groupBox->setVisible( setVisible );
|
|
m_showUnscaledCheckBox->setVisible( setVisible );
|
|
m_showScaledCheckBox->setVisible( setVisible );
|
|
m_logarithmicScaleKrAxisCheckBox->setVisible( setVisible );
|
|
m_fixedXAxisCheckBox->setVisible( setVisible );
|
|
m_fixedLeftYAxisCheckBox->setVisible( setVisible );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::slotButtonInButtonGroupClicked( int )
|
|
{
|
|
plotUiSelectedCurves();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::slotSomeCheckBoxStateChanged( int )
|
|
{
|
|
plotUiSelectedCurves();
|
|
}
|
|
|
|
//==================================================================================================
|
|
//
|
|
//
|
|
//
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RiuRelativePermeabilityPlotPanel::ValueRange::ValueRange()
|
|
: min( HUGE_VAL )
|
|
, max( -HUGE_VAL )
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RiuRelativePermeabilityPlotPanel::ValueRange::add( const ValueRange& range )
|
|
{
|
|
if ( range.max >= range.min )
|
|
{
|
|
if ( range.max > max )
|
|
{
|
|
max = range.max;
|
|
}
|
|
if ( range.min < min )
|
|
{
|
|
min = range.min;
|
|
}
|
|
}
|
|
}
|