ResInsight/ApplicationCode/ProjectDataModel/Flow/RimWellAllocationPlot.cpp

878 lines
35 KiB
C++
Raw Normal View History

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil ASA
2019-09-06 06:17:36 -05:00
//
// 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.
2019-09-06 06:17:36 -05:00
//
// 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.
2019-09-06 06:17:36 -05:00
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimWellAllocationPlot.h"
#include "RiaApplication.h"
#include "RigAccWellFlowCalculator.h"
#include "RigEclipseCaseData.h"
#include "RigFlowDiagResultAddress.h"
#include "RigFlowDiagResults.h"
2019-09-06 06:17:36 -05:00
#include "RigSimWellData.h"
#include "RigSimulationWellCenterLineCalculator.h"
#include "RigSimulationWellCoordsAndMD.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseView.h"
#include "RimFlowDiagSolution.h"
#include "RimProject.h"
#include "RimSimWellInView.h"
2019-09-06 06:17:36 -05:00
#include "RimSimWellInViewCollection.h"
#include "RimTofAccumulatedPhaseFractionsPlot.h"
#include "RimTotalWellAllocationPlot.h"
#include "RimWellAllocationPlotLegend.h"
#include "RimWellFlowRateCurve.h"
#include "RimWellLogPlot.h"
#include "RimWellLogTrack.h"
#include "RimWellLogFile.h"
#include "RimWellPlotTools.h"
2018-04-26 23:28:08 -05:00
#include "RiuPlotMainWindow.h"
#include "RiuQwtPlotWidget.h"
#include "RiuWellAllocationPlot.h"
2019-09-06 06:17:36 -05:00
CAF_PDM_SOURCE_INIT( RimWellAllocationPlot, "WellAllocationPlot" );
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
namespace caf
{
2019-09-06 06:17:36 -05:00
template <>
void AppEnum<RimWellAllocationPlot::FlowType>::setUp()
{
2019-09-06 06:17:36 -05:00
addItem( RimWellAllocationPlot::ACCUMULATED, "ACCUMULATED", "Accumulated" );
addItem( RimWellAllocationPlot::INFLOW, "INFLOW", "Inflow Rates" );
setDefault( RimWellAllocationPlot::ACCUMULATED );
}
2019-09-06 06:17:36 -05:00
} // namespace caf
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
RimWellAllocationPlot::RimWellAllocationPlot()
{
2019-09-06 06:17:36 -05:00
CAF_PDM_InitObject( "Well Allocation Plot", ":/WellAllocPlot16x16.png", "", "" );
CAF_PDM_InitField( &m_userName, "PlotDescription", QString( "Flow Diagnostics Plot" ), "Name", "", "", "" );
m_userName.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitField( &m_showPlotTitle, "ShowPlotTitle", true, "Show Plot Title", "", "", "" );
2019-09-06 06:17:36 -05:00
CAF_PDM_InitField( &m_branchDetection,
"BranchDetection",
true,
"Branch Detection",
"",
"Compute branches based on how simulation well cells are organized",
"" );
CAF_PDM_InitFieldNoDefault( &m_case, "CurveCase", "Case", "", "", "" );
m_case.uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitField( &m_timeStep, "PlotTimeStep", 0, "Time Step", "", "", "" );
CAF_PDM_InitField( &m_wellName, "WellName", QString( "None" ), "Well", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_flowDiagSolution, "FlowDiagSolution", "Plot Type", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_flowType, "FlowType", "Flow Type", "", "", "" );
CAF_PDM_InitField( &m_groupSmallContributions, "GroupSmallContributions", true, "Group Small Contributions", "", "", "" );
CAF_PDM_InitField( &m_smallContributionsThreshold, "SmallContributionsThreshold", 0.005, "Threshold", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_accumulatedWellFlowPlot, "AccumulatedWellFlowPlot", "Accumulated Well Flow", "", "", "" );
m_accumulatedWellFlowPlot.uiCapability()->setUiHidden( true );
m_accumulatedWellFlowPlot = new RimWellLogPlot;
m_accumulatedWellFlowPlot->setDepthUnit( RiaDefines::UNIT_NONE );
m_accumulatedWellFlowPlot->setDepthType( RimWellLogPlot::CONNECTION_NUMBER );
m_accumulatedWellFlowPlot->setLegendsVisible( false );
m_accumulatedWellFlowPlot->uiCapability()->setUiIconFromResourceString( ":/WellFlowPlot16x16.png" );
2019-09-06 06:17:36 -05:00
CAF_PDM_InitFieldNoDefault( &m_totalWellAllocationPlot, "TotalWellFlowPlot", "Total Well Flow", "", "", "" );
m_totalWellAllocationPlot.uiCapability()->setUiHidden( true );
m_totalWellAllocationPlot = new RimTotalWellAllocationPlot;
2019-09-06 06:17:36 -05:00
CAF_PDM_InitFieldNoDefault( &m_wellAllocationPlotLegend, "WellAllocLegend", "Legend", "", "", "" );
m_wellAllocationPlotLegend.uiCapability()->setUiHidden( true );
m_wellAllocationPlotLegend = new RimWellAllocationPlotLegend;
2019-09-06 06:17:36 -05:00
CAF_PDM_InitFieldNoDefault( &m_tofAccumulatedPhaseFractionsPlot,
"TofAccumulatedPhaseFractionsPlot",
"TOF Accumulated Phase Fractions",
"",
"",
"" );
m_tofAccumulatedPhaseFractionsPlot.uiCapability()->setUiHidden( true );
m_tofAccumulatedPhaseFractionsPlot = new RimTofAccumulatedPhaseFractionsPlot;
this->setAsPlotMdiWindow();
m_accumulatedWellFlowPlot->setAvailableDepthUnits( {} );
m_accumulatedWellFlowPlot->setAvailableDepthTypes(
{RimWellLogPlot::CONNECTION_NUMBER, RimWellLogPlot::TRUE_VERTICAL_DEPTH, RimWellLogPlot::PSEUDO_LENGTH} );
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
RimWellAllocationPlot::~RimWellAllocationPlot()
{
removeMdiWindowFromMdiArea();
2019-09-06 06:17:36 -05:00
delete m_accumulatedWellFlowPlot();
delete m_totalWellAllocationPlot();
delete m_tofAccumulatedPhaseFractionsPlot();
deleteViewWidget();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
void RimWellAllocationPlot::setFromSimulationWell( RimSimWellInView* simWell )
{
RimEclipseView* eclView;
2019-09-06 06:17:36 -05:00
simWell->firstAncestorOrThisOfType( eclView );
RimEclipseResultCase* eclCase;
2019-09-06 06:17:36 -05:00
simWell->firstAncestorOrThisOfType( eclCase );
2019-09-06 06:17:36 -05:00
m_case = eclCase;
m_wellName = simWell->simWellData()->m_wellName;
m_timeStep = eclView->currentTimeStep();
// Use the active flow diag solutions, or the first one as default
m_flowDiagSolution = eclView->cellResult()->flowDiagSolution();
if ( !m_flowDiagSolution )
{
m_flowDiagSolution = m_case->defaultFlowDiagSolution();
}
onLoadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellAllocationPlot::deleteViewWidget()
{
if ( m_wellAllocationPlotWidget )
{
m_wellAllocationPlotWidget->deleteLater();
m_wellAllocationPlotWidget = nullptr;
}
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
void RimWellAllocationPlot::updateFromWell()
{
// Delete existing tracks
{
std::vector<RimWellLogTrack*> tracks;
accumulatedWellFlowPlot()->descendantsIncludingThisOfType( tracks );
2019-09-06 06:17:36 -05:00
for ( RimWellLogTrack* t : tracks )
{
accumulatedWellFlowPlot()->removePlot( t );
delete t;
}
}
CVF_ASSERT( accumulatedWellFlowPlot()->plotCount() == 0 );
QString description;
2019-09-06 06:17:36 -05:00
if ( m_flowType() == ACCUMULATED ) description = "Accumulated Flow";
if ( m_flowType() == INFLOW ) description = "Inflow Rates";
accumulatedWellFlowPlot()->setDescription( description + " (" + m_wellName + ")" );
2019-09-06 06:17:36 -05:00
if ( !m_case ) return;
2019-09-06 06:17:36 -05:00
const RigSimWellData* simWellData = m_case->eclipseCaseData()->findSimWellData( m_wellName );
2019-09-06 06:17:36 -05:00
if ( !simWellData ) return;
2019-09-06 06:17:36 -05:00
// Set up the Accumulated Well Flow Calculator
2019-09-06 06:17:36 -05:00
std::vector<std::vector<cvf::Vec3d>> pipeBranchesCLCoords;
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds;
2019-09-06 06:17:36 -05:00
RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellFrame( m_case->eclipseCaseData(),
simWellData,
m_timeStep,
m_branchDetection,
true,
pipeBranchesCLCoords,
pipeBranchesCellIds );
2019-09-06 06:17:36 -05:00
std::map<QString, const std::vector<double>*> tracerFractionCellValues = findRelevantTracerCellFractions(
simWellData );
std::unique_ptr<RigAccWellFlowCalculator> wfCalculator;
double smallContributionThreshold = 0.0;
2019-09-06 06:17:36 -05:00
if ( m_groupSmallContributions() ) smallContributionThreshold = m_smallContributionsThreshold;
if ( tracerFractionCellValues.size() )
{
2019-09-06 06:17:36 -05:00
bool isProducer = ( simWellData->wellProductionType( m_timeStep ) == RigWellResultFrame::PRODUCER ||
simWellData->wellProductionType( m_timeStep ) ==
RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE );
RigEclCellIndexCalculator cellIdxCalc( m_case->eclipseCaseData()->mainGrid(),
m_case->eclipseCaseData()->activeCellInfo( RiaDefines::MATRIX_MODEL ) );
wfCalculator.reset( new RigAccWellFlowCalculator( pipeBranchesCLCoords,
pipeBranchesCellIds,
tracerFractionCellValues,
cellIdxCalc,
smallContributionThreshold,
isProducer ) );
}
2019-09-06 06:17:36 -05:00
else
{
2019-09-06 06:17:36 -05:00
if ( pipeBranchesCLCoords.size() > 0 )
{
2019-09-06 06:17:36 -05:00
wfCalculator.reset(
new RigAccWellFlowCalculator( pipeBranchesCLCoords, pipeBranchesCellIds, smallContributionThreshold ) );
}
}
auto depthType = accumulatedWellFlowPlot()->depthType();
2019-09-06 06:17:36 -05:00
if ( depthType == RimWellLogPlot::MEASURED_DEPTH ) return;
// Create tracks and curves from the calculated data
size_t branchCount = pipeBranchesCLCoords.size();
2019-09-06 06:17:36 -05:00
for ( size_t brIdx = 0; brIdx < branchCount; ++brIdx )
{
// Skip Tiny dummy branches
2019-09-06 06:17:36 -05:00
if ( pipeBranchesCellIds[brIdx].size() <= 3 ) continue;
RimWellLogTrack* plotTrack = new RimWellLogTrack();
2019-09-06 06:17:36 -05:00
plotTrack->setDescription( QString( "Branch %1" ).arg( brIdx + 1 ) );
plotTrack->setFormationsForCaseWithSimWellOnly( true );
plotTrack->setFormationBranchIndex( (int)brIdx );
accumulatedWellFlowPlot()->addPlot( plotTrack );
2019-09-06 06:17:36 -05:00
const std::vector<double>& depthValues = depthType == RimWellLogPlot::CONNECTION_NUMBER
? wfCalculator->connectionNumbersFromTop( brIdx )
: depthType == RimWellLogPlot::PSEUDO_LENGTH
? wfCalculator->pseudoLengthFromTop( brIdx )
: depthType == RimWellLogPlot::TRUE_VERTICAL_DEPTH
? wfCalculator->trueVerticalDepth( brIdx )
: std::vector<double>();
{
std::vector<QString> tracerNames = wfCalculator->tracerNames();
2019-09-06 06:17:36 -05:00
for ( const QString& tracerName : tracerNames )
{
const std::vector<double>* accFlow = nullptr;
2019-09-06 06:17:36 -05:00
if ( depthType == RimWellLogPlot::CONNECTION_NUMBER )
{
2019-09-06 06:17:36 -05:00
accFlow = &( m_flowType == ACCUMULATED
? wfCalculator->accumulatedTracerFlowPrConnection( tracerName, brIdx )
: wfCalculator->tracerFlowPrConnection( tracerName, brIdx ) );
}
2019-09-06 06:17:36 -05:00
else if ( depthType == RimWellLogPlot::PSEUDO_LENGTH || depthType == RimWellLogPlot::TRUE_VERTICAL_DEPTH )
{
2019-09-06 06:17:36 -05:00
accFlow = &( m_flowType == ACCUMULATED
? wfCalculator->accumulatedTracerFlowPrPseudoLength( tracerName, brIdx )
: wfCalculator->tracerFlowPrPseudoLength( tracerName, brIdx ) );
}
2019-09-06 06:17:36 -05:00
if ( accFlow )
2018-12-21 05:31:42 -06:00
{
2019-09-06 06:17:36 -05:00
addStackedCurve( tracerName, depthValues, *accFlow, plotTrack );
2018-12-21 05:31:42 -06:00
// TODO: THIs is the data to be plotted...
}
}
}
2019-09-06 06:17:36 -05:00
updateWellFlowPlotXAxisTitle( plotTrack );
}
2019-09-06 06:17:36 -05:00
QString wellStatusText = QString( "(%1)" ).arg(
RimWellAllocationPlot::wellStatusTextForTimeStep( m_wellName, m_case, m_timeStep ) );
2019-09-06 06:17:36 -05:00
QString flowTypeText = m_flowDiagSolution() ? "Well Allocation" : "Well Flow";
setDescription( flowTypeText + ": " + m_wellName + " " + wellStatusText + ", " +
m_case->timeStepStrings()[m_timeStep] + " (" + m_case->caseUserDescription() + ")" );
/// Pie chart
m_totalWellAllocationPlot->clearSlices();
if ( m_wellAllocationPlotWidget ) m_wellAllocationPlotWidget->clearLegend();
2019-09-06 06:17:36 -05:00
if ( wfCalculator )
{
2019-09-06 06:17:36 -05:00
std::vector<std::pair<QString, double>> totalTracerFractions = wfCalculator->totalTracerFractions();
for ( const auto& tracerVal : totalTracerFractions )
{
cvf::Color3f color;
2019-09-06 06:17:36 -05:00
if ( m_flowDiagSolution )
color = m_flowDiagSolution->tracerColor( tracerVal.first );
else
2019-09-06 06:17:36 -05:00
color = getTracerColor( tracerVal.first );
2019-09-06 06:17:36 -05:00
double tracerPercent = 100 * tracerVal.second;
2019-09-06 06:17:36 -05:00
m_totalWellAllocationPlot->addSlice( tracerVal.first, color, tracerPercent );
if ( m_wellAllocationPlotWidget )
m_wellAllocationPlotWidget->addLegendItem( tracerVal.first, color, tracerPercent );
}
}
if ( m_wellAllocationPlotWidget )
m_wellAllocationPlotWidget->showLegend( m_wellAllocationPlotLegend->isShowingLegend() );
m_totalWellAllocationPlot->updateConnectedEditors();
accumulatedWellFlowPlot()->updateConnectedEditors();
m_tofAccumulatedPhaseFractionsPlot->reloadFromWell();
m_tofAccumulatedPhaseFractionsPlot->updateConnectedEditors();
if ( m_wellAllocationPlotWidget ) m_wellAllocationPlotWidget->updateGeometry();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
std::map<QString, const std::vector<double>*>
RimWellAllocationPlot::findRelevantTracerCellFractions( const RigSimWellData* simWellData )
{
2019-09-06 06:17:36 -05:00
std::map<QString, const std::vector<double>*> tracerCellFractionValues;
2019-09-06 06:17:36 -05:00
if ( m_flowDiagSolution && simWellData->hasWellResult( m_timeStep ) )
{
RimFlowDiagSolution::TracerStatusType requestedTracerType = RimFlowDiagSolution::UNDEFINED;
2019-09-06 06:17:36 -05:00
const RigWellResultFrame::WellProductionType prodType = simWellData->wellProductionType( m_timeStep );
if ( prodType == RigWellResultFrame::PRODUCER || prodType == RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE )
{
requestedTracerType = RimFlowDiagSolution::INJECTOR;
}
2019-09-06 06:17:36 -05:00
else
{
requestedTracerType = RimFlowDiagSolution::PRODUCER;
}
std::vector<QString> tracerNames = m_flowDiagSolution->tracerNames();
for ( const QString& tracerName : tracerNames )
{
2019-09-06 06:17:36 -05:00
if ( m_flowDiagSolution->tracerStatusInTimeStep( tracerName, m_timeStep ) == requestedTracerType )
{
2019-09-06 06:17:36 -05:00
RigFlowDiagResultAddress resAddr( RIG_FLD_CELL_FRACTION_RESNAME,
RigFlowDiagResultAddress::PHASE_ALL,
tracerName.toStdString() );
const std::vector<double>* tracerCellFractions = m_flowDiagSolution->flowDiagResults()
->resultValues( resAddr, m_timeStep );
if ( tracerCellFractions ) tracerCellFractionValues[tracerName] = tracerCellFractions;
}
}
}
return tracerCellFractionValues;
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
void RimWellAllocationPlot::updateWellFlowPlotXAxisTitle( RimWellLogTrack* plotTrack )
{
2019-09-06 06:17:36 -05:00
RiaEclipseUnitTools::UnitSystem unitSet = m_case->eclipseCaseData()->unitsType();
RimWellLogFile::WellFlowCondition condition = m_flowDiagSolution ? RimWellLogFile::WELL_FLOW_COND_RESERVOIR
: RimWellLogFile::WELL_FLOW_COND_STANDARD;
2019-09-06 06:17:36 -05:00
QString axisTitle = RimWellPlotTools::flowPlotAxisTitle( condition, unitSet );
plotTrack->setXAxisTitle( axisTitle );
2019-09-06 06:17:36 -05:00
#if 0
if (m_flowDiagSolution)
{
QString unitText;
switch ( unitSet )
{
case RiaEclipseUnitTools::UNITS_METRIC:
unitText = "[m<sup>3</sup>/day]";
break;
case RiaEclipseUnitTools::UNITS_FIELD:
unitText = "[Brl/day]";
break;
case RiaEclipseUnitTools::UNITS_LAB:
unitText = "[cm<sup>3</sup>/hr]";
break;
default:
break;
}
plotTrack->setXAxisTitle("Reservoir Flow Rate " + unitText);
}
else
{
QString unitText;
switch ( unitSet )
{
case RiaEclipseUnitTools::UNITS_METRIC:
unitText = "[Liquid Sm<sup>3</sup>/day], [Gas kSm<sup>3</sup>/day]";
break;
case RiaEclipseUnitTools::UNITS_FIELD:
unitText = "[Liquid BBL/day], [Gas BOE/day]";
break;
case RiaEclipseUnitTools::UNITS_LAB:
unitText = "[cm<sup>3</sup>/hr]";
break;
default:
break;
}
plotTrack->setXAxisTitle("Surface Flow Rate " + unitText);
}
#endif
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
void RimWellAllocationPlot::addStackedCurve( const QString& tracerName,
const std::vector<double>& depthValues,
const std::vector<double>& accFlow,
RimWellLogTrack* plotTrack )
{
RimWellFlowRateCurve* curve = new RimWellFlowRateCurve;
2019-09-06 06:17:36 -05:00
curve->setFlowValuesPrDepthValue( tracerName, depthValues, accFlow );
if ( m_flowDiagSolution )
{
2019-09-06 06:17:36 -05:00
curve->setColor( m_flowDiagSolution->tracerColor( tracerName ) );
}
else
{
2019-09-06 06:17:36 -05:00
curve->setColor( getTracerColor( tracerName ) );
}
2019-09-06 06:17:36 -05:00
plotTrack->addCurve( curve );
2019-09-06 06:17:36 -05:00
curve->loadDataAndUpdate( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellAllocationPlot::updateWidgetTitleWindowTitle()
{
updateMdiWindowTitle();
if ( m_wellAllocationPlotWidget )
{
if ( m_showPlotTitle )
{
m_wellAllocationPlotWidget->showTitle( m_userName );
}
else
{
m_wellAllocationPlotWidget->hideTitle();
}
}
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
QString RimWellAllocationPlot::wellStatusTextForTimeStep( const QString& wellName,
const RimEclipseResultCase* eclipseResultCase,
size_t timeStep )
{
QString statusText = "Undefined";
2019-09-06 06:17:36 -05:00
if ( eclipseResultCase )
{
2019-09-06 06:17:36 -05:00
const RigSimWellData* simWellData = eclipseResultCase->eclipseCaseData()->findSimWellData( wellName );
2019-09-06 06:17:36 -05:00
if ( simWellData )
{
2019-09-06 06:17:36 -05:00
if ( simWellData->hasWellResult( timeStep ) )
{
2019-09-06 06:17:36 -05:00
const RigWellResultFrame& wellResultFrame = simWellData->wellResultFrame( timeStep );
RigWellResultFrame::WellProductionType prodType = wellResultFrame.m_productionType;
2019-09-06 06:17:36 -05:00
switch ( prodType )
{
2019-09-06 06:17:36 -05:00
case RigWellResultFrame::PRODUCER:
statusText = "Producer";
break;
case RigWellResultFrame::OIL_INJECTOR:
statusText = "Oil Injector";
break;
case RigWellResultFrame::GAS_INJECTOR:
statusText = "Gas Injector";
break;
case RigWellResultFrame::WATER_INJECTOR:
statusText = "Water Injector";
break;
case RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE:
break;
default:
break;
}
}
}
}
return statusText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimWellAllocationPlot::viewWidget()
{
return m_wellAllocationPlotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellAllocationPlot::zoomAll()
{
m_accumulatedWellFlowPlot()->zoomAll();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogPlot* RimWellAllocationPlot::accumulatedWellFlowPlot()
{
return m_accumulatedWellFlowPlot();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
RimTotalWellAllocationPlot* RimWellAllocationPlot::totalWellFlowPlot()
{
return m_totalWellAllocationPlot();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
RimTofAccumulatedPhaseFractionsPlot* RimWellAllocationPlot::tofAccumulatedPhaseFractionsPlot()
{
return m_tofAccumulatedPhaseFractionsPlot();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
caf::PdmObject* RimWellAllocationPlot::plotLegend()
{
return m_wellAllocationPlotLegend;
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
RimEclipseResultCase* RimWellAllocationPlot::rimCase()
{
return m_case();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
int RimWellAllocationPlot::timeStep()
{
return m_timeStep();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
QList<caf::PdmOptionItemInfo>
RimWellAllocationPlot::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options;
2019-09-06 06:17:36 -05:00
if ( fieldNeedingOptions == &m_wellName )
{
std::set<QString> sortedWellNames = this->findSortedWellNames();
2019-09-06 06:17:36 -05:00
caf::QIconProvider simWellIcon( ":/Well.png" );
for ( const QString& wname : sortedWellNames )
{
2019-09-06 06:17:36 -05:00
options.push_back( caf::PdmOptionItemInfo( wname, wname, false, simWellIcon ) );
}
2019-09-06 06:17:36 -05:00
if ( options.size() == 0 )
{
2019-09-06 06:17:36 -05:00
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
}
}
2019-09-06 06:17:36 -05:00
else if ( fieldNeedingOptions == &m_timeStep )
{
QStringList timeStepNames;
2019-09-06 06:17:36 -05:00
if ( m_case && m_case->eclipseCaseData() )
{
timeStepNames = m_case->timeStepStrings();
}
2019-09-06 06:17:36 -05:00
for ( int i = 0; i < timeStepNames.size(); i++ )
{
2019-09-06 06:17:36 -05:00
options.push_back( caf::PdmOptionItemInfo( timeStepNames[i], i ) );
}
}
2019-09-06 06:17:36 -05:00
else if ( fieldNeedingOptions == &m_case )
{
RimProject* proj = nullptr;
2019-09-06 06:17:36 -05:00
this->firstAncestorOrThisOfType( proj );
if ( proj )
{
std::vector<RimEclipseResultCase*> cases;
2019-09-06 06:17:36 -05:00
proj->descendantsIncludingThisOfType( cases );
2019-09-06 06:17:36 -05:00
for ( RimEclipseResultCase* c : cases )
{
2019-09-06 06:17:36 -05:00
options.push_back( caf::PdmOptionItemInfo( c->caseUserDescription(), c, false, c->uiIconProvider() ) );
}
}
}
2019-09-06 06:17:36 -05:00
else if ( fieldNeedingOptions == &m_flowDiagSolution )
{
2019-09-06 06:17:36 -05:00
if ( m_case )
{
2019-09-06 06:17:36 -05:00
// std::vector<RimFlowDiagSolution*> flowSols = m_case->flowDiagSolutions();
// options.push_back(caf::PdmOptionItemInfo("None", nullptr));
2019-09-06 06:17:36 -05:00
// for (RimFlowDiagSolution* flowSol : flowSols)
//{
// options.push_back(caf::PdmOptionItemInfo(flowSol->userDescription(), flowSol, false, flowSol->uiIcon()));
//}
2019-09-06 06:17:36 -05:00
RimFlowDiagSolution* defaultFlowSolution = m_case->defaultFlowDiagSolution();
options.push_back( caf::PdmOptionItemInfo( "Well Flow", nullptr ) );
if ( defaultFlowSolution )
{
2019-09-06 06:17:36 -05:00
options.push_back( caf::PdmOptionItemInfo( "Allocation", defaultFlowSolution ) );
}
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
QString RimWellAllocationPlot::wellName() const
{
return m_wellName();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
void RimWellAllocationPlot::removeFromMdiAreaAndDeleteViewWidget()
{
removeMdiWindowFromMdiArea();
deleteViewWidget();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
void RimWellAllocationPlot::showPlotLegend( bool doShow )
{
if ( m_wellAllocationPlotWidget ) m_wellAllocationPlotWidget->showLegend( doShow );
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
void RimWellAllocationPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
2019-09-06 06:17:36 -05:00
RimViewWindow::fieldChangedByUi( changedField, oldValue, newValue );
if ( changedField == &m_userName || changedField == &m_showPlotTitle )
{
updateWidgetTitleWindowTitle();
}
else if ( changedField == &m_case )
{
if ( m_flowDiagSolution && m_case )
{
m_flowDiagSolution = m_case->defaultFlowDiagSolution();
}
else
{
m_flowDiagSolution = nullptr;
}
2019-09-06 06:17:36 -05:00
if ( !m_case )
m_timeStep = 0;
else if ( m_timeStep >= static_cast<int>( m_case->timeStepDates().size() ) )
{
2019-09-06 06:17:36 -05:00
m_timeStep = std::max( 0, ( (int)m_case->timeStepDates().size() ) - 1 );
}
std::set<QString> sortedWellNames = findSortedWellNames();
2019-09-06 06:17:36 -05:00
if ( !sortedWellNames.size() )
m_wellName = "";
else if ( sortedWellNames.count( m_wellName() ) == 0 )
{
m_wellName = *sortedWellNames.begin();
}
onLoadDataAndUpdate();
}
2019-09-06 06:17:36 -05:00
else if ( changedField == &m_wellName || changedField == &m_timeStep || changedField == &m_flowDiagSolution ||
changedField == &m_groupSmallContributions || changedField == &m_smallContributionsThreshold ||
changedField == &m_flowType || changedField == &m_branchDetection )
{
onLoadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
std::set<QString> RimWellAllocationPlot::findSortedWellNames()
{
std::set<QString> sortedWellNames;
if ( m_case && m_case->eclipseCaseData() )
{
const cvf::Collection<RigSimWellData>& simWellData = m_case->eclipseCaseData()->wellResults();
for ( size_t wIdx = 0; wIdx < simWellData.size(); ++wIdx )
{
2019-09-06 06:17:36 -05:00
sortedWellNames.insert( simWellData[wIdx]->m_wellName );
}
}
return sortedWellNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimWellAllocationPlot::snapshotWindowContent()
{
QImage image;
if ( m_wellAllocationPlotWidget )
{
QPixmap pix = m_wellAllocationPlotWidget->grab();
image = pix.toImage();
}
return image;
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
void RimWellAllocationPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_userName );
uiOrdering.add( &m_showPlotTitle );
2019-09-06 06:17:36 -05:00
caf::PdmUiGroup& dataGroup = *uiOrdering.addNewGroup( "Plot Data" );
dataGroup.add( &m_case );
dataGroup.add( &m_timeStep );
dataGroup.add( &m_wellName );
dataGroup.add( &m_branchDetection );
caf::PdmUiGroup& optionGroup = *uiOrdering.addNewGroup( "Options" );
optionGroup.add( &m_flowDiagSolution );
optionGroup.add( &m_flowType );
optionGroup.add( &m_groupSmallContributions );
optionGroup.add( &m_smallContributionsThreshold );
m_smallContributionsThreshold.uiCapability()->setUiReadOnly( !m_groupSmallContributions() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellAllocationPlot::setDescription( const QString& description )
{
m_userName = description;
updateWidgetTitleWindowTitle();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
QString RimWellAllocationPlot::description() const
{
return m_userName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellAllocationPlot::onLoadDataAndUpdate()
{
updateMdiWindowVisibility();
updateFromWell();
m_accumulatedWellFlowPlot->loadDataAndUpdate();
updateFormationNamesData();
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
QWidget* RimWellAllocationPlot::createViewWidget( QWidget* mainWindowParent )
{
m_wellAllocationPlotWidget = new RiuWellAllocationPlot( this, mainWindowParent );
return m_wellAllocationPlotWidget;
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
cvf::Color3f RimWellAllocationPlot::getTracerColor( const QString& tracerName )
{
2019-09-06 06:17:36 -05:00
if ( tracerName == RIG_FLOW_OIL_NAME ) return cvf::Color3f::DARK_GREEN;
if ( tracerName == RIG_FLOW_GAS_NAME ) return cvf::Color3f::DARK_RED;
if ( tracerName == RIG_FLOW_WATER_NAME ) return cvf::Color3f::BLUE;
return cvf::Color3f::DARK_GRAY;
}
//--------------------------------------------------------------------------------------------------
2019-09-06 06:17:36 -05:00
///
//--------------------------------------------------------------------------------------------------
void RimWellAllocationPlot::updateFormationNamesData() const
{
for ( size_t i = 0; i < m_accumulatedWellFlowPlot->plotCount(); ++i )
{
RimWellLogTrack* track = dynamic_cast<RimWellLogTrack*>( m_accumulatedWellFlowPlot->plotByIndex( i ) );
CAF_ASSERT( track );
if ( track )
{
track->setAndUpdateSimWellFormationNamesData( m_case, m_wellName );
}
}
}