///////////////////////////////////////////////////////////////////////////////// // // 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 // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RimWellFlowRateCurve.h" #include "WellLogCommands/RicWellLogPlotCurveFeatureImpl.h" #include "RigWellLogCurveData.h" #include "RimWellAllocationPlot.h" #include "RimWellLogPlot.h" #include "RimWellLogTrack.h" #include "RiuQwtPlotCurve.h" #include "qwt_plot.h" #include "cvfMath.h" #include //================================================================================================== /// /// //================================================================================================== CAF_PDM_SOURCE_INIT( RimWellFlowRateCurve, "WellFlowRateCurve" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWellFlowRateCurve::RimWellFlowRateCurve() { CAF_PDM_InitObject( "Flow Rate Curve", "", "", "" ); m_groupId = 0; m_doFillCurve = true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWellFlowRateCurve::~RimWellFlowRateCurve() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimEclipseResultCase* RimWellFlowRateCurve::rimCase() { RimWellAllocationPlot* wap = wellAllocationPlot(); if ( wap ) { return wap->rimCase(); } return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RimWellFlowRateCurve::timeStep() { RimWellAllocationPlot* wap = wellAllocationPlot(); if ( wap ) { return wap->timeStep(); } return -1; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimWellFlowRateCurve::wellName() const { QString name; RimWellAllocationPlot* wap = wellAllocationPlot(); if ( wap ) { name = wap->wellName(); } else { name = "Undefined"; } return name; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimWellFlowRateCurve::wellLogChannelUiName() const { return "AccumulatedFlowRate"; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimWellFlowRateCurve::wellLogChannelUnits() const { return RiaWellLogUnitTools::noUnitString(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellFlowRateCurve::setGroupId( int groupId ) { m_groupId = groupId; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RimWellFlowRateCurve::groupId() const { return m_groupId; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellFlowRateCurve::setDoFillCurve( bool doFill ) { m_doFillCurve = doFill; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimWellFlowRateCurve::createCurveAutoName() { return m_curveAutoName; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellFlowRateCurve::onLoadDataAndUpdate( bool updateParentPlot ) { this->RimPlotCurve::updateCurvePresentation( updateParentPlot ); if ( isCurveVisible() ) { m_qwtPlotCurve->setTitle( createCurveAutoName() ); updateStackedPlotData(); updateZoomInParentPlot(); if ( m_parentQwtPlot ) m_parentQwtPlot->replot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellFlowRateCurve::updateCurveAppearance() { RimWellLogCurve::updateCurveAppearance(); bool isLastCurveInGroup = false; { RimWellLogTrack* wellLogTrack; firstAncestorOrThisOfTypeAsserted( wellLogTrack ); std::map> stackedCurveGroups = wellLogTrack->visibleStackedCurves(); const std::vector& curveGroup = stackedCurveGroups[this->m_groupId]; isLastCurveInGroup = ( curveGroup.back() == this ); } if ( isUsingConnectionNumberDepthType() ) { m_qwtPlotCurve->setStyle( QwtPlotCurve::Steps ); } if ( m_doFillCurve || isLastCurveInGroup ) // Fill the last curve in group with a transparent color to "tie" the // group together { QColor curveQColor = QColor( m_curveColor.value().rByte(), m_curveColor.value().gByte(), m_curveColor.value().bByte() ); QColor fillColor = curveQColor; QColor lineColor = curveQColor.darker(); if ( !m_doFillCurve && isLastCurveInGroup ) { fillColor = QColor( 24, 16, 10, 50 ); lineColor = curveQColor; } QLinearGradient gradient; gradient.setCoordinateMode( QGradient::StretchToDeviceMode ); gradient.setColorAt( 0, fillColor.darker( 110 ) ); gradient.setColorAt( 0.15, fillColor ); gradient.setColorAt( 0.25, fillColor ); gradient.setColorAt( 0.4, fillColor.darker( 110 ) ); gradient.setColorAt( 0.6, fillColor ); gradient.setColorAt( 0.8, fillColor.darker( 110 ) ); gradient.setColorAt( 1, fillColor ); m_qwtPlotCurve->setBrush( gradient ); QPen curvePen = m_qwtPlotCurve->pen(); curvePen.setColor( lineColor ); m_qwtPlotCurve->setPen( curvePen ); m_qwtPlotCurve->setOrientation( Qt::Horizontal ); m_qwtPlotCurve->setBaseline( 0.0 ); m_qwtPlotCurve->setCurveAttribute( QwtPlotCurve::Inverted, true ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellFlowRateCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { uiOrdering.add( &m_curveName ); m_curveName.uiCapability()->setUiReadOnly( true ); uiOrdering.add( &m_curveColor ); m_curveColor.uiCapability()->setUiReadOnly( true ); uiOrdering.skipRemainingFields(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellFlowRateCurve::updateStackedPlotData() { RimWellLogPlot* wellLogPlot; firstAncestorOrThisOfTypeAsserted( wellLogPlot ); RimWellLogTrack* wellLogTrack; firstAncestorOrThisOfTypeAsserted( wellLogTrack ); RimWellLogPlot::DepthTypeEnum depthType = wellLogPlot->depthType(); RiaDefines::DepthUnitType displayUnit = wellLogPlot->depthUnit(); if ( depthType == RiaDefines::DepthTypeEnum::CONNECTION_NUMBER ) { displayUnit = RiaDefines::DepthUnitType::UNIT_NONE; } std::vector depthValues; std::vector stackedValues; std::vector> polyLineStartStopIndices; // Z-position of curve, to draw them in correct order double zPos = -10000.0 + 100.0 * static_cast( groupId() ); // Starting way behind the grid (z == 0) at -10000 giving room for 100 groups with 100 curves each before getting // above the grid { std::map> stackedCurveGroups = wellLogTrack->visibleStackedCurves(); std::vector stackedCurves; if ( stackedCurveGroups.count( groupId() ) > 0 ) { stackedCurves = stackedCurveGroups[groupId()]; } std::vector allDepthValues = curveData()->depths( depthType ); if ( allDepthValues.empty() ) return; std::vector allStackedValues( allDepthValues.size() ); for ( RimWellFlowRateCurve* stCurve : stackedCurves ) { std::vector allValues = stCurve->curveData()->xValues(); for ( size_t i = 0; i < allValues.size(); ++i ) { if ( allValues[i] != HUGE_VAL ) { allStackedValues[i] += allValues[i]; } } if ( stCurve == this ) break; zPos -= 1.0; } RigWellLogCurveData tempCurveData; tempCurveData.setValuesAndDepths( allStackedValues, allDepthValues, depthType, 0.0, displayUnit, false ); depthValues = tempCurveData.depthPlotValues( depthType, displayUnit ); stackedValues = tempCurveData.xPlotValues(); polyLineStartStopIndices = tempCurveData.polylineStartStopIndices(); } auto minmax_it = std::minmax_element( stackedValues.begin(), stackedValues.end() ); this->setOverrideCurveDataXRange( *( minmax_it.first ), *( minmax_it.second ) ); m_qwtPlotCurve->setSamples( stackedValues.data(), depthValues.data(), static_cast( depthValues.size() ) ); m_qwtPlotCurve->setLineSegmentStartStopIndices( polyLineStartStopIndices ); m_qwtPlotCurve->setZ( zPos ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimWellFlowRateCurve::isUsingConnectionNumberDepthType() const { RimWellLogPlot* wellLogPlot; firstAncestorOrThisOfType( wellLogPlot ); if ( wellLogPlot && wellLogPlot->depthType() == RiaDefines::DepthTypeEnum::CONNECTION_NUMBER ) { return true; } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWellAllocationPlot* RimWellFlowRateCurve::wellAllocationPlot() const { RimWellAllocationPlot* wap = nullptr; this->firstAncestorOrThisOfType( wap ); return wap; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWellFlowRateCurve::setFlowValuesPrDepthValue( const QString& curveName, RiaDefines::DepthTypeEnum depthType, const std::vector& depthValues, const std::vector& flowRates ) { this->setValuesAndDepths( flowRates, depthValues, depthType, 0.0, RiaDefines::DepthUnitType::UNIT_NONE, false ); m_curveAutoName = curveName; }