2017-10-23 13:57:01 +02:00
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimWellPltPlot.h"
#include "RiaApplication.h"
#include "RiaColorTables.h"
#include "RiaDateStringParser.h"
2017-11-08 16:35:58 +01:00
#include "RiaWellNameComparer.h"
2017-11-13 10:21:24 +01:00
2017-10-23 13:57:01 +02:00
#include "RifReaderEclipseRft.h"
2017-11-13 10:21:24 +01:00
#include "RigAccWellFlowCalculator.h"
2017-10-23 13:57:01 +02:00
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
2017-11-13 10:21:24 +01:00
#include "RigEclipseWellLogExtractor.h"
#include "RigMainGrid.h"
2017-10-23 13:57:01 +02:00
#include "RigSimWellData.h"
2017-11-13 10:21:24 +01:00
#include "RigWellLogExtractor.h"
2017-10-23 13:57:01 +02:00
#include "RigWellPath.h"
2017-11-13 10:21:24 +01:00
2017-10-23 13:57:01 +02:00
#include "RimEclipseCase.h"
#include "RimEclipseCaseCollection.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseResultDefinition.h"
2017-11-13 10:21:24 +01:00
#include "RimMainPlotCollection.h"
2017-10-23 13:57:01 +02:00
#include "RimOilField.h"
#include "RimProject.h"
2017-11-13 10:21:24 +01:00
#include "RimSummaryCurveAppearanceCalculator.h"
2017-10-23 13:57:01 +02:00
#include "RimTools.h"
2017-11-13 10:21:24 +01:00
#include "RimWellFlowRateCurve.h"
2017-10-23 13:57:01 +02:00
#include "RimWellLogExtractionCurve.h"
#include "RimWellLogFile.h"
#include "RimWellLogFileChannel.h"
#include "RimWellLogFileCurve.h"
#include "RimWellLogPlot.h"
2017-11-13 10:21:24 +01:00
#include "RimWellLogPlotCollection.h"
2017-10-23 13:57:01 +02:00
#include "RimWellLogRftCurve.h"
#include "RimWellLogTrack.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
2017-11-09 10:03:32 +01:00
#include "RimWellPlotTools.h"
2017-11-13 10:21:24 +01:00
2017-10-23 13:57:01 +02:00
#include "RiuWellPltPlot.h"
2017-11-13 10:21:24 +01:00
#include "cafPdmUiTreeOrdering.h"
2017-10-23 13:57:01 +02:00
#include "cafPdmUiTreeSelectionEditor.h"
2017-11-13 10:21:24 +01:00
#include "cafVecIjk.h"
2017-10-23 13:57:01 +02:00
#include <algorithm>
#include <iterator>
2017-11-13 10:21:24 +01:00
#include <tuple>
2017-11-15 16:17:55 +01:00
#include "QMessageBox"
2017-11-13 10:21:24 +01:00
2017-10-23 13:57:01 +02:00
2017-11-08 16:35:58 +01:00
2017-10-23 13:57:01 +02:00
CAF_PDM_SOURCE_INIT ( RimWellPltPlot , "WellPltPlot" );
2017-10-25 19:44:04 +02:00
namespace caf
{
2017-10-25 14:43:17 +02:00
template <>
2017-11-09 10:03:32 +01:00
void caf :: AppEnum < FlowType >:: setUp ()
2017-10-25 14:43:17 +02:00
{
2017-11-09 10:03:32 +01:00
addItem ( FLOW_TYPE_PHASE_SPLIT , "PHASE_SPLIT" , "Phase Split" );
2017-11-17 15:35:07 +01:00
addItem ( FLOW_TYPE_TOTAL , "TOTAL" , "Total Flow" );
setDefault ( FLOW_TYPE_PHASE_SPLIT );
2017-10-25 14:43:17 +02:00
}
template <>
2017-11-09 10:03:32 +01:00
void caf :: AppEnum < FlowPhase >:: setUp ()
2017-10-25 14:43:17 +02:00
{
2017-11-09 10:03:32 +01:00
addItem ( FLOW_PHASE_OIL , "PHASE_OIL" , "Oil" );
addItem ( FLOW_PHASE_GAS , "PHASE_GAS" , "Gas" );
addItem ( FLOW_PHASE_WATER , "PHASE_WATER" , "Water" );
2017-11-23 15:11:07 +01:00
addItem ( FLOW_PHASE_TOTAL , "PHASE_TOTAL" , "Total" );
2017-10-25 14:43:17 +02:00
}
2017-10-25 19:44:04 +02:00
}
2017-10-25 14:43:17 +02:00
2017-10-23 13:57:01 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-10-27 09:17:05 +02:00
const char RimWellPltPlot :: PLOT_NAME_QFORMAT_STRING [] = "PLT: %1" ;
2017-10-23 13:57:01 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPltPlot :: RimWellPltPlot ()
{
CAF_PDM_InitObject ( "Well Allocation Plot" , ":/WellAllocPlot16x16.png" , "" , "" );
2017-10-27 09:17:05 +02:00
CAF_PDM_InitField ( & m_userName , "PlotDescription" , QString ( "PLT Plot" ), "Name" , "" , "" , "" );
2017-10-23 13:57:01 +02:00
m_userName . uiCapability () -> setUiReadOnly ( true );
CAF_PDM_InitField ( & m_showPlotTitle , "ShowPlotTitle" , true , "Show Plot Title" , "" , "" , "" );
CAF_PDM_InitFieldNoDefault ( & m_wellLogPlot , "WellLog" , "WellLog" , "" , "" , "" );
m_wellLogPlot . uiCapability () -> setUiHidden ( true );
m_wellLogPlot = new RimWellLogPlot ();
2017-10-25 14:43:17 +02:00
m_wellLogPlot -> setDepthType ( RimWellLogPlot :: MEASURED_DEPTH );
2017-10-23 13:57:01 +02:00
2017-11-30 13:44:18 +01:00
CAF_PDM_InitFieldNoDefault ( & m_wellPathName , "WellName" , "Well Name" , "" , "" , "" );
2017-10-23 13:57:01 +02:00
2017-11-30 13:44:18 +01:00
CAF_PDM_InitFieldNoDefault ( & m_selectedSources , "SourcesInternal" , "Sources Internal" , "" , "" , "" );
2017-10-23 13:57:01 +02:00
m_selectedSources . uiCapability () -> setUiEditorTypeName ( caf :: PdmUiTreeSelectionEditor :: uiEditorTypeName ());
m_selectedSources . uiCapability () -> setUiLabelPosition ( caf :: PdmUiItemInfo :: HIDDEN );
m_selectedSources . uiCapability () -> setAutoAddingOptionFromValue ( false );
2017-10-27 09:38:24 +02:00
m_selectedSources . xmlCapability () -> disableIO ();
CAF_PDM_InitFieldNoDefault ( & m_selectedSourcesForIo , "Sources" , "Sources" , "" , "" , "" );
m_selectedSourcesForIo . uiCapability () -> setUiHidden ( true );
2017-10-23 13:57:01 +02:00
2017-11-30 13:44:18 +01:00
CAF_PDM_InitFieldNoDefault ( & m_selectedTimeSteps , "TimeSteps" , "Time Steps" , "" , "" , "" );
2017-10-23 13:57:01 +02:00
m_selectedTimeSteps . uiCapability () -> setUiEditorTypeName ( caf :: PdmUiTreeSelectionEditor :: uiEditorTypeName ());
m_selectedTimeSteps . uiCapability () -> setUiLabelPosition ( caf :: PdmUiItemInfo :: HIDDEN );
m_selectedTimeSteps . uiCapability () -> setAutoAddingOptionFromValue ( false );
2017-12-15 15:11:08 +01:00
CAF_PDM_InitField ( & m_useStandardConditionCurves , "UseStandardConditionCurves" , true , "Standard Volume" , "" , "" , "" );
CAF_PDM_InitField ( & m_useReservoirConditionCurves , "UseReservoirConditionCurves" , true , "Reservoir Volume" , "" , "" , "" );
2017-10-25 14:43:17 +02:00
CAF_PDM_InitFieldNoDefault ( & m_phases , "Phases" , "Phases" , "" , "" , "" );
m_phases . uiCapability () -> setUiEditorTypeName ( caf :: PdmUiTreeSelectionEditor :: uiEditorTypeName ());
2017-11-09 10:03:32 +01:00
m_phases = std :: vector < caf :: AppEnum < FlowPhase >> ({ FLOW_PHASE_OIL , FLOW_PHASE_GAS , FLOW_PHASE_WATER });
2017-11-23 15:11:07 +01:00
m_phases . uiCapability () -> setUiLabelPosition ( caf :: PdmUiItemInfo :: HIDDEN );
2017-10-25 14:43:17 +02:00
2017-10-23 13:57:01 +02:00
this -> setAsPlotMdiWindow ();
2017-10-27 09:38:24 +02:00
m_doInitAfterLoad = false ;
2017-11-13 08:56:22 +01:00
m_isOnLoad = true ;
2017-10-23 13:57:01 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPltPlot ::~ RimWellPltPlot ()
{
removeMdiWindowFromMdiArea ();
deleteViewWidget ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: deleteViewWidget ()
{
if ( m_wellLogPlotWidget )
{
m_wellLogPlotWidget -> deleteLater ();
m_wellLogPlotWidget = nullptr ;
}
}
2017-10-25 14:43:17 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: setPlotXAxisTitles ( RimWellLogTrack * plotTrack )
{
2017-11-15 16:17:55 +01:00
std :: set < RiaEclipseUnitTools :: UnitSystem > presentUnitSystems ;
for ( const RifDataSourceForRftPlt & source : m_selectedSources . v ())
2017-10-23 13:57:01 +02:00
{
2017-11-15 16:17:55 +01:00
if ( source . eclCase ()) presentUnitSystems . insert ( source . eclCase () -> eclipseCaseData () -> unitsType ());
if ( source . wellLogFile ())
{
if ( source . wellLogFile () -> wellLogFileData ())
{
// Todo: Handle different units in the relevant las channels
switch ( source . wellLogFile () -> wellLogFileData () -> depthUnit ())
{
case RiaDefines :: UNIT_METER : presentUnitSystems . insert ( RiaEclipseUnitTools :: UNITS_METRIC );
case RiaDefines :: UNIT_FEET : presentUnitSystems . insert ( RiaEclipseUnitTools :: UNITS_FIELD );
case RiaDefines :: UNIT_NONE : presentUnitSystems . insert ( RiaEclipseUnitTools :: UNITS_UNKNOWN );
}
}
}
2017-10-25 14:43:17 +02:00
}
2017-10-23 13:57:01 +02:00
2017-11-15 16:17:55 +01:00
if ( presentUnitSystems . size () > 1 ) { QMessageBox :: warning ( nullptr , "ResInsight PLT Plot" , "Inconsistent units in PLT plot" );}
2017-11-23 16:10:39 +01:00
if ( presentUnitSystems . size () <= 0 ) return ;
RiaEclipseUnitTools :: UnitSystem unitSet = * presentUnitSystems . begin ();
QString axisTitle ;
if ( m_useReservoirConditionCurves ) axisTitle += RimWellPlotTools :: flowPlotAxisTitle ( RimWellLogFile :: WELL_FLOW_COND_RESERVOIR , unitSet );
if ( m_useReservoirConditionCurves && m_useStandardConditionCurves ) axisTitle += " | " ;
if ( m_useStandardConditionCurves ) axisTitle += RimWellPlotTools :: flowPlotAxisTitle ( RimWellLogFile :: WELL_FLOW_COND_STANDARD , unitSet );
plotTrack -> setXAxisTitle ( axisTitle );
#if 0
2017-11-15 16:17:55 +01:00
QString unitText;
for ( auto unitSet: presentUnitSystems )
2017-10-23 13:57:01 +02:00
{
2017-11-15 16:17:55 +01:00
switch ( unitSet )
2017-10-23 13:57:01 +02:00
{
2017-11-15 16:17:55 +01:00
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:
unitText += "(unknown unit)";
break;
2017-10-25 14:43:17 +02:00
}
2017-10-23 13:57:01 +02:00
}
2017-11-15 16:17:55 +01:00
plotTrack->setXAxisTitle("Surface Flow Rate " + unitText);
2017-11-23 16:10:39 +01:00
#endif
2017-10-25 14:43:17 +02:00
}
2017-10-23 13:57:01 +02:00
2017-11-06 14:40:26 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-11-07 10:38:05 +01:00
void RimWellPltPlot :: updateFormationsOnPlot () const
2017-11-06 14:40:26 +01:00
{
2017-11-12 14:45:06 +01:00
if ( m_wellLogPlot -> trackCount () > 0 )
2017-11-06 14:40:26 +01:00
{
2017-11-12 14:45:06 +01:00
RimProject * proj = RiaApplication :: instance () -> project ();
RimWellPath * wellPath = proj -> wellPathByName ( m_wellPathName );
2017-11-06 14:40:26 +01:00
2017-11-12 14:45:06 +01:00
RimCase * formationNamesCase = m_wellLogPlot -> trackByIndex ( 0 ) -> formationNamesCase ();
2017-11-06 14:40:26 +01:00
2017-11-12 14:45:06 +01:00
if ( ! formationNamesCase )
{
/// Set default case. Todo : Use the first of the selected cases in the plot
std :: vector < RimCase *> cases ;
proj -> allCases ( cases );
2017-11-06 14:40:26 +01:00
2017-11-12 14:45:06 +01:00
if ( ! cases . empty () )
{
formationNamesCase = cases [ 0 ];
}
}
m_wellLogPlot -> trackByIndex ( 0 ) -> setAndUpdateWellPathFormationNamesData ( formationNamesCase , wellPath );
2017-11-06 14:40:26 +01:00
}
}
2017-10-23 13:57:01 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: updateWidgetTitleWindowTitle ()
{
updateMdiWindowTitle ();
if ( m_wellLogPlotWidget )
{
if ( m_showPlotTitle )
{
m_wellLogPlotWidget -> showTitle ( m_userName );
}
else
{
m_wellLogPlotWidget -> hideTitle ();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-11-15 17:08:09 +01:00
std :: set < RiaRftPltCurveDefinition > RimWellPltPlot :: selectedCurveDefs () const
2017-11-16 16:17:54 +01:00
{
2017-11-16 16:35:55 +01:00
return RimWellPlotTools :: curveDefsFromTimesteps ( RimWellPlotTools :: simWellName ( m_wellPathName ),
m_selectedTimeSteps . v (),
2017-12-07 16:24:28 +01:00
false ,
2017-11-16 16:35:55 +01:00
selectedSourcesExpanded ());
2017-11-16 16:17:54 +01:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-11-07 14:40:36 +01:00
class RigResultPointCalculator
{
public :
RigResultPointCalculator () {}
virtual ~ RigResultPointCalculator () {}
const std :: vector < cvf :: Vec3d >& pipeBranchCLCoords () { return m_pipeBranchCLCoords ; }
const std :: vector < RigWellResultPoint >& pipeBranchWellResultPoints () { return m_pipeBranchWellResultPoints ; }
const std :: vector < double >& pipeBranchMeasuredDepths () { return m_pipeBranchMeasuredDepths ; }
protected :
2017-11-08 16:35:58 +01:00
RigEclipseWellLogExtractor * findWellLogExtractor ( const QString & wellPathName ,
2017-11-07 14:40:36 +01:00
RimEclipseResultCase * eclCase )
{
RimProject * proj = RiaApplication :: instance () -> project ();
2017-11-08 16:35:58 +01:00
RimWellPath * wellPath = proj -> wellPathByName ( wellPathName );
2017-11-07 14:40:36 +01:00
RimWellLogPlotCollection * wellLogCollection = proj -> mainPlotCollection () -> wellLogPlotCollection ();
RigEclipseWellLogExtractor * eclExtractor = wellLogCollection -> findOrCreateExtractor ( wellPath , eclCase );
2017-10-23 13:57:01 +02:00
2017-11-07 14:40:36 +01:00
return eclExtractor ;
}
2017-11-06 22:23:54 +01:00
2017-11-07 14:40:36 +01:00
std :: vector < cvf :: Vec3d > m_pipeBranchCLCoords ;
std :: vector < RigWellResultPoint > m_pipeBranchWellResultPoints ;
std :: vector < double > m_pipeBranchMeasuredDepths ;
};
2017-11-06 22:23:54 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-11-07 14:40:36 +01:00
class RigRftResultPointCalculator : public RigResultPointCalculator
2017-11-06 22:23:54 +01:00
{
public :
2017-11-08 16:35:58 +01:00
RigRftResultPointCalculator ( const QString & wellPathName ,
2017-11-06 22:23:54 +01:00
RimEclipseResultCase * eclCase ,
QDateTime m_timeStep )
{
2017-11-09 10:03:32 +01:00
RifEclipseRftAddress gasRateAddress ( RimWellPlotTools :: simWellName ( wellPathName ), m_timeStep , RifEclipseRftAddress :: GRAT );
RifEclipseRftAddress oilRateAddress ( RimWellPlotTools :: simWellName ( wellPathName ), m_timeStep , RifEclipseRftAddress :: ORAT );
RifEclipseRftAddress watRateAddress ( RimWellPlotTools :: simWellName ( wellPathName ), m_timeStep , RifEclipseRftAddress :: WRAT );
2017-11-06 22:23:54 +01:00
std :: vector < caf :: VecIjk > rftIndices ;
eclCase -> rftReader () -> cellIndices ( gasRateAddress , & rftIndices );
if ( rftIndices . empty ()) eclCase -> rftReader () -> cellIndices ( oilRateAddress , & rftIndices );
if ( rftIndices . empty ()) eclCase -> rftReader () -> cellIndices ( watRateAddress , & rftIndices );
if ( rftIndices . empty ()) return ;
std :: vector < double > gasRates ;
std :: vector < double > oilRates ;
std :: vector < double > watRates ;
eclCase -> rftReader () -> values ( gasRateAddress , & gasRates );
eclCase -> rftReader () -> values ( oilRateAddress , & oilRates );
eclCase -> rftReader () -> values ( watRateAddress , & watRates );
std :: map < size_t , size_t > globCellIdxToIdxInRftFile ;
2017-11-07 14:40:36 +01:00
const RigMainGrid * mainGrid = eclCase -> eclipseCaseData () -> mainGrid ();
2017-11-06 22:23:54 +01:00
for ( size_t rftCellIdx = 0 ; rftCellIdx < rftIndices . size (); rftCellIdx ++ )
{
caf :: VecIjk ijkIndex = rftIndices [ rftCellIdx ];
size_t globalCellIndex = mainGrid -> cellIndexFromIJK ( ijkIndex . i (), ijkIndex . j (), ijkIndex . k ());
globCellIdxToIdxInRftFile [ globalCellIndex ] = rftCellIdx ;
}
2017-11-08 16:35:58 +01:00
RigEclipseWellLogExtractor * eclExtractor = findWellLogExtractor ( wellPathName , eclCase );
2017-11-07 14:40:36 +01:00
if ( ! eclExtractor ) return ;
2017-12-12 16:32:57 +01:00
std :: vector < WellPathCellIntersectionInfo > intersections = eclExtractor -> cellIntersectionInfosAlongWellPath ();
2017-11-07 14:40:36 +01:00
2017-11-06 22:23:54 +01:00
for ( size_t wpExIdx = 0 ; wpExIdx < intersections . size (); wpExIdx ++ )
{
size_t globCellIdx = intersections [ wpExIdx ]. globCellIndex ;
auto it = globCellIdxToIdxInRftFile . find ( globCellIdx );
2017-11-08 11:58:14 +01:00
if ( it == globCellIdxToIdxInRftFile . end ())
{
2017-12-04 18:58:52 +01:00
if ( ! m_pipeBranchWellResultPoints . empty () && wpExIdx == ( intersections . size () - 1 ))
2017-11-08 11:58:14 +01:00
{
m_pipeBranchWellResultPoints . pop_back ();
}
continue ;
}
2017-11-06 22:23:54 +01:00
m_pipeBranchCLCoords . push_back ( intersections [ wpExIdx ]. startPoint );
m_pipeBranchMeasuredDepths . push_back ( intersections [ wpExIdx ]. startMD );
m_pipeBranchCLCoords . push_back ( intersections [ wpExIdx ]. endPoint );
m_pipeBranchMeasuredDepths . push_back ( intersections [ wpExIdx ]. endMD );
RigWellResultPoint resPoint ;
2017-11-07 18:35:34 +01:00
resPoint . m_isOpen = true ;
2017-11-09 13:47:00 +01:00
resPoint . m_gridIndex = 0 ; // Always main grid
2017-11-06 22:23:54 +01:00
resPoint . m_gridCellIndex = globCellIdx ; // Shortcut, since we only have main grid results from RFT
2017-11-09 13:47:00 +01:00
resPoint . m_gasRate = RiaEclipseUnitTools :: convertSurfaceGasFlowRateToOilEquivalents ( eclCase -> eclipseCaseData () -> unitsType (),
gasRates [ it -> second ]);
resPoint . m_oilRate = oilRates [ it -> second ];
2017-11-06 22:23:54 +01:00
resPoint . m_waterRate = watRates [ it -> second ];
m_pipeBranchWellResultPoints . push_back ( resPoint );
2017-11-07 18:35:34 +01:00
if ( wpExIdx < intersections . size () - 1 )
{
m_pipeBranchWellResultPoints . push_back ( RigWellResultPoint ()); // Invalid res point describing the "line" between the cells
}
2017-11-06 22:23:54 +01:00
}
}
};
2017-11-07 14:40:36 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RigSimWellResultPointCalculator : public RigResultPointCalculator
{
public :
2017-11-08 16:35:58 +01:00
RigSimWellResultPointCalculator ( const QString & wellPathName ,
2017-11-07 14:40:36 +01:00
RimEclipseResultCase * eclCase ,
QDateTime m_timeStep )
{
// Find timestep index from qdatetime
const std :: vector < QDateTime > timeSteps = eclCase -> eclipseCaseData () -> results ( RiaDefines :: MATRIX_MODEL ) -> timeStepDates ();
size_t tsIdx = timeSteps . size ();
for ( tsIdx = 0 ; tsIdx < timeSteps . size (); ++ tsIdx ) { if ( timeSteps [ tsIdx ] == m_timeStep ) break ; }
if ( tsIdx >= timeSteps . size ()) return ;
// Build search map into simulation well data
std :: map < size_t , std :: pair < size_t , size_t > > globCellIdxToIdxInSimWellBranch ;
2017-11-09 10:03:32 +01:00
const RimWellPath * wellPath = RimWellPlotTools :: wellPathByWellPathNameOrSimWellName ( wellPathName );
2017-11-17 15:35:07 +01:00
const RigSimWellData * simWell = wellPath != nullptr ? eclCase -> eclipseCaseData () -> findSimWellData ( wellPath -> associatedSimulationWellName ()) : nullptr ;
2017-11-07 14:40:36 +01:00
if ( ! simWell ) return ;
if ( ! simWell -> hasWellResult ( tsIdx )) return ;
const RigWellResultFrame & resFrame = simWell -> wellResultFrame ( tsIdx );
const RigMainGrid * mainGrid = eclCase -> eclipseCaseData () -> mainGrid ();
for ( size_t brIdx = 0 ; brIdx < resFrame . m_wellResultBranches . size (); ++ brIdx )
{
const std :: vector < RigWellResultPoint >& branchResPoints = resFrame . m_wellResultBranches [ brIdx ]. m_branchResultPoints ;
for ( size_t wrpIdx = 0 ; wrpIdx < branchResPoints . size (); wrpIdx ++ )
{
const RigGridBase * grid = mainGrid -> gridByIndex ( branchResPoints [ wrpIdx ]. m_gridIndex );
size_t globalCellIndex = grid -> reservoirCellIndex ( branchResPoints [ wrpIdx ]. m_gridCellIndex );
globCellIdxToIdxInSimWellBranch [ globalCellIndex ] = std :: make_pair ( brIdx , wrpIdx );
}
}
2017-11-08 16:35:58 +01:00
RigEclipseWellLogExtractor * eclExtractor = findWellLogExtractor ( wellPathName , eclCase );
2017-11-07 14:40:36 +01:00
if ( ! eclExtractor ) return ;
2017-12-12 16:32:57 +01:00
std :: vector < WellPathCellIntersectionInfo > intersections = eclExtractor -> cellIntersectionInfosAlongWellPath ();
2017-11-07 14:40:36 +01:00
for ( size_t wpExIdx = 0 ; wpExIdx < intersections . size (); wpExIdx ++ )
{
size_t globCellIdx = intersections [ wpExIdx ]. globCellIndex ;
auto it = globCellIdxToIdxInSimWellBranch . find ( globCellIdx );
2017-11-08 11:58:14 +01:00
if ( it == globCellIdxToIdxInSimWellBranch . end ())
{
2017-12-04 18:58:52 +01:00
if ( ! m_pipeBranchWellResultPoints . empty () && wpExIdx == ( intersections . size () - 1 ))
2017-11-08 11:58:14 +01:00
{
m_pipeBranchWellResultPoints . pop_back ();
}
continue ;
}
2017-11-07 14:40:36 +01:00
m_pipeBranchCLCoords . push_back ( intersections [ wpExIdx ]. startPoint );
m_pipeBranchMeasuredDepths . push_back ( intersections [ wpExIdx ]. startMD );
m_pipeBranchCLCoords . push_back ( intersections [ wpExIdx ]. endPoint );
m_pipeBranchMeasuredDepths . push_back ( intersections [ wpExIdx ]. endMD );
const RigWellResultPoint & resPoint = resFrame . m_wellResultBranches [ it -> second . first ]. m_branchResultPoints [ it -> second . second ];
m_pipeBranchWellResultPoints . push_back ( resPoint );
2017-11-07 18:35:34 +01:00
if ( wpExIdx < intersections . size () - 1 )
{
m_pipeBranchWellResultPoints . push_back ( RigWellResultPoint ()); // Invalid res point describing the "line" between the cells
}
2017-11-07 14:40:36 +01:00
}
}
};
2017-11-06 22:23:54 +01:00
2017-10-23 13:57:01 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-10-31 12:49:14 +01:00
void RimWellPltPlot :: syncCurvesFromUiSelection ()
2017-10-23 13:57:01 +02:00
{
2017-10-31 12:49:14 +01:00
RimWellLogTrack * plotTrack = m_wellLogPlot -> trackByIndex ( 0 );
2017-11-15 17:08:09 +01:00
const std :: set < RiaRftPltCurveDefinition >& curveDefs = selectedCurveDefs ();
2017-10-23 13:57:01 +02:00
2017-10-25 14:43:17 +02:00
setPlotXAxisTitles ( plotTrack );
// Delete existing curves
2017-11-15 11:31:35 +01:00
plotTrack -> deleteAllCurves ();
2017-10-23 13:57:01 +02:00
2017-10-27 15:17:24 +02:00
int curveGroupId = 0 ;
2017-11-06 22:23:54 +01:00
RimProject * proj = RiaApplication :: instance () -> project ();
2017-11-09 10:03:32 +01:00
RimWellPath * wellPath = RimWellPlotTools :: wellPathByWellPathNameOrSimWellName ( m_wellPathName );
2017-11-06 22:23:54 +01:00
2017-11-23 15:11:07 +01:00
QString dateFormatString ;
{
std :: vector < QDateTime > allTimeSteps ;
for ( const RiaRftPltCurveDefinition & curveDefToAdd : curveDefs )
{
allTimeSteps . push_back ( curveDefToAdd . timeStep ());
}
dateFormatString = RimTools :: createTimeFormatStringFromDates ( allTimeSteps );
}
2017-10-25 14:43:17 +02:00
// Add curves
2017-11-15 17:08:09 +01:00
for ( const RiaRftPltCurveDefinition & curveDefToAdd : curveDefs )
2017-10-23 13:57:01 +02:00
{
2017-11-23 15:11:07 +01:00
std :: set < FlowPhase > selectedPhases = std :: set < FlowPhase > ( m_phases (). begin (), m_phases (). end ()) ;
2017-11-15 17:08:09 +01:00
RifDataSourceForRftPlt sourceDef = curveDefToAdd . address ();
QDateTime timeStep = curveDefToAdd . timeStep ();
2017-10-27 15:17:24 +02:00
2017-11-07 14:40:36 +01:00
std :: unique_ptr < RigResultPointCalculator > resultPointCalc ;
2017-11-12 23:46:12 +01:00
2017-11-08 11:22:16 +01:00
QString curveName ;
2017-12-05 09:45:41 +01:00
2017-11-12 23:46:12 +01:00
{
2017-11-23 15:11:07 +01:00
curveName += sourceDef . eclCase () ? sourceDef . eclCase () -> caseUserDescription () : "" ;
2017-11-12 23:46:12 +01:00
curveName += sourceDef . wellLogFile () ? sourceDef . wellLogFile () -> name () : "" ;
2017-11-13 11:10:27 +01:00
if ( sourceDef . sourceType () == RifDataSourceForRftPlt :: RFT ) curveName += ", RFT" ;
2017-11-23 15:11:07 +01:00
curveName += ", " + timeStep . toString ( dateFormatString );
2017-11-12 23:46:12 +01:00
}
2017-11-07 14:40:36 +01:00
2017-12-05 09:45:41 +01:00
RimEclipseResultCase * rimEclipseResultCase = dynamic_cast < RimEclipseResultCase *> ( sourceDef . eclCase ());
2017-11-13 11:10:27 +01:00
if ( sourceDef . sourceType () == RifDataSourceForRftPlt :: RFT )
2017-11-07 14:40:36 +01:00
{
2017-11-08 16:35:58 +01:00
resultPointCalc . reset ( new RigRftResultPointCalculator ( m_wellPathName ,
2017-12-05 09:45:41 +01:00
rimEclipseResultCase ,
2017-11-08 11:22:16 +01:00
timeStep ));
2017-11-07 14:40:36 +01:00
}
2017-11-13 11:10:27 +01:00
else if ( sourceDef . sourceType () == RifDataSourceForRftPlt :: GRID )
2017-11-07 14:40:36 +01:00
{
2017-11-08 16:35:58 +01:00
resultPointCalc . reset ( new RigSimWellResultPointCalculator ( m_wellPathName ,
2017-12-05 09:45:41 +01:00
rimEclipseResultCase ,
2017-11-08 11:22:16 +01:00
timeStep ));
2017-11-07 14:40:36 +01:00
}
2017-12-05 09:45:41 +01:00
RiaEclipseUnitTools :: UnitSystem unitSet = RiaEclipseUnitTools :: UNITS_UNKNOWN ;
if ( rimEclipseResultCase )
{
unitSet = rimEclipseResultCase -> eclipseCaseData () -> unitsType ();
}
2017-11-07 14:40:36 +01:00
if ( resultPointCalc != nullptr )
2017-11-06 22:23:54 +01:00
{
2017-11-07 14:40:36 +01:00
if ( resultPointCalc -> pipeBranchCLCoords (). size () )
2017-11-06 22:23:54 +01:00
{
2017-12-05 09:45:41 +01:00
2017-11-23 15:11:07 +01:00
if ( selectedPhases . count ( FLOW_PHASE_TOTAL )
&& m_useReservoirConditionCurves ()
&& sourceDef . sourceType () == RifDataSourceForRftPlt :: GRID )
{
RigAccWellFlowCalculator wfTotalAccumulator ( resultPointCalc -> pipeBranchCLCoords (),
resultPointCalc -> pipeBranchWellResultPoints (),
resultPointCalc -> pipeBranchMeasuredDepths (),
true );
const std :: vector < double >& depthValues = wfTotalAccumulator . pseudoLengthFromTop ( 0 );
2017-12-05 09:45:41 +01:00
QString curveUnitText = RimWellPlotTools :: flowUnitText ( RimWellLogFile :: WELL_FLOW_COND_RESERVOIR , unitSet );
2017-11-23 15:11:07 +01:00
const std :: vector < double > accFlow = wfTotalAccumulator . accumulatedTracerFlowPrPseudoLength ( RIG_FLOW_TOTAL_NAME , 0 );
2017-12-05 09:45:41 +01:00
addStackedCurve ( curveName + ", " + RIG_FLOW_TOTAL_NAME + " " + curveUnitText ,
2017-11-23 15:11:07 +01:00
depthValues ,
accFlow ,
plotTrack ,
cvf :: Color3f :: DARK_GRAY ,
curveGroupId ,
false );
curveGroupId ++ ;
}
if ( m_useStandardConditionCurves () )
2017-11-06 22:23:54 +01:00
{
2017-11-23 15:11:07 +01:00
RigAccWellFlowCalculator wfPhaseAccumulator ( resultPointCalc -> pipeBranchCLCoords (),
resultPointCalc -> pipeBranchWellResultPoints (),
resultPointCalc -> pipeBranchMeasuredDepths (),
false );
const std :: vector < double >& depthValues = wfPhaseAccumulator . pseudoLengthFromTop ( 0 );
std :: vector < QString > tracerNames = wfPhaseAccumulator . tracerNames ();
for ( const QString & tracerName : tracerNames )
2017-11-08 11:22:16 +01:00
{
2017-11-23 15:11:07 +01:00
auto color = tracerName == RIG_FLOW_OIL_NAME ? cvf :: Color3f :: DARK_GREEN :
tracerName == RIG_FLOW_GAS_NAME ? cvf :: Color3f :: DARK_RED :
tracerName == RIG_FLOW_WATER_NAME ? cvf :: Color3f :: BLUE :
cvf :: Color3f :: DARK_GRAY ;
if ( tracerName == RIG_FLOW_OIL_NAME && selectedPhases . count ( FLOW_PHASE_OIL )
|| tracerName == RIG_FLOW_GAS_NAME && selectedPhases . count ( FLOW_PHASE_GAS )
|| tracerName == RIG_FLOW_WATER_NAME && selectedPhases . count ( FLOW_PHASE_WATER ) )
{
2017-12-05 09:45:41 +01:00
FlowPhase flowPhase = FLOW_PHASE_NONE ;
if ( tracerName == RIG_FLOW_OIL_NAME ) flowPhase = FLOW_PHASE_OIL ;
else if ( tracerName == RIG_FLOW_GAS_NAME ) flowPhase = FLOW_PHASE_GAS ;
else if ( tracerName == RIG_FLOW_WATER_NAME ) flowPhase = FLOW_PHASE_WATER ;
QString curveUnitText = RimWellPlotTools :: curveUnitText ( RimWellLogFile :: WELL_FLOW_COND_STANDARD , unitSet , flowPhase );
2017-11-23 15:11:07 +01:00
const std :: vector < double > accFlow = wfPhaseAccumulator . accumulatedTracerFlowPrPseudoLength ( tracerName , 0 );
2017-12-05 09:45:41 +01:00
addStackedCurve ( curveName + ", " + tracerName + " " + curveUnitText ,
2017-11-23 15:11:07 +01:00
depthValues ,
accFlow ,
plotTrack ,
color ,
curveGroupId ,
false );
}
2017-11-08 11:22:16 +01:00
}
2017-11-06 22:23:54 +01:00
}
}
}
2017-11-13 11:10:27 +01:00
else if ( sourceDef . sourceType () == RifDataSourceForRftPlt :: OBSERVED )
2017-10-23 13:57:01 +02:00
{
2017-11-08 11:22:16 +01:00
RimWellLogFile * const wellLogFile = sourceDef . wellLogFile ();
2017-11-23 15:11:07 +01:00
if ( sourceDef . wellLogFile () && sourceDef . wellLogFile () -> wellLogFileData () )
2017-10-23 13:57:01 +02:00
{
2017-11-23 15:11:07 +01:00
RimWellLogFile :: WellFlowCondition flowCondition = sourceDef . wellLogFile () -> wellFlowRateCondition ();
2017-10-25 14:43:17 +02:00
2017-11-23 15:11:07 +01:00
if ( ( m_useStandardConditionCurves () && flowCondition == RimWellLogFile :: WELL_FLOW_COND_STANDARD )
|| ( m_useReservoirConditionCurves () && flowCondition == RimWellLogFile :: WELL_FLOW_COND_RESERVOIR ) )
2017-10-25 14:43:17 +02:00
{
2017-11-23 15:11:07 +01:00
using ChannelValNameIdxTuple = std :: tuple < double , QString , int > ;
RigWellLogFile * wellLogFileData = sourceDef . wellLogFile () -> wellLogFileData ();
QStringList channelNames = wellLogFileData -> wellLogChannelNames ();
std :: multiset < ChannelValNameIdxTuple > sortedChannels ;
2017-11-17 20:17:44 +01:00
std :: vector < std :: vector < double > > channelData ;
2017-11-23 15:11:07 +01:00
channelData . resize ( channelNames . size ());
for ( int chIdx = 0 ; chIdx < channelNames . size (); ++ chIdx )
2017-10-25 14:43:17 +02:00
{
2017-11-23 15:11:07 +01:00
QString channelName = channelNames [ chIdx ];
2017-11-17 20:17:44 +01:00
channelData [ chIdx ] = wellLogFileData -> values ( channelName );
2017-11-23 15:11:07 +01:00
if ( channelData [ chIdx ]. size () )
2017-11-17 20:17:44 +01:00
{
2017-11-23 15:11:07 +01:00
sortedChannels . insert ( ChannelValNameIdxTuple ( - fabs ( channelData [ chIdx ]. front ()), channelName , chIdx ));
2017-11-17 20:17:44 +01:00
}
}
std :: vector < double > depthValues = wellLogFileData -> depthValues ();
2017-12-05 09:45:41 +01:00
RiaEclipseUnitTools :: UnitSystem unitSystem = RiaEclipseUnitTools :: UNITS_UNKNOWN ;
{
RiaDefines :: DepthUnitType depthUnit = wellLogFileData -> depthUnit ();
if ( depthUnit == RiaDefines :: UNIT_FEET ) unitSystem = RiaEclipseUnitTools :: UNITS_FIELD ;
if ( depthUnit == RiaDefines :: UNIT_METER ) unitSystem = RiaEclipseUnitTools :: UNITS_METRIC ;
}
2017-11-17 20:17:44 +01:00
2017-11-23 15:11:07 +01:00
for ( const ChannelValNameIdxTuple & channelInfo : sortedChannels )
2017-11-17 20:17:44 +01:00
{
const auto & channelName = std :: get < 1 > ( channelInfo );
2017-11-23 15:11:07 +01:00
if ( selectedPhases . count ( RimWellPlotTools :: flowPhaseFromChannelName ( channelName )) > 0 )
2017-10-25 14:43:17 +02:00
{
2017-11-23 15:11:07 +01:00
auto color = RimWellPlotTools :: isOilFlowChannel ( channelName ) ? cvf :: Color3f :: DARK_GREEN :
RimWellPlotTools :: isGasFlowChannel ( channelName ) ? cvf :: Color3f :: DARK_RED :
2017-11-17 20:17:44 +01:00
RimWellPlotTools :: isWaterFlowChannel ( channelName ) ? cvf :: Color3f :: BLUE :
cvf :: Color3f :: DARK_GRAY ;
2017-11-08 11:22:16 +01:00
2017-12-05 09:45:41 +01:00
FlowPhase flowPhase = FLOW_PHASE_NONE ;
if ( RimWellPlotTools :: isOilFlowChannel ( channelName )) flowPhase = FLOW_PHASE_OIL ;
else if ( RimWellPlotTools :: isGasFlowChannel ( channelName )) flowPhase = FLOW_PHASE_GAS ;
else if ( RimWellPlotTools :: isWaterFlowChannel ( channelName )) flowPhase = FLOW_PHASE_WATER ;
2017-12-08 11:07:21 +01:00
QString curveUnitText = RimWellPlotTools :: curveUnitText ( flowCondition , unitSystem , flowPhase );
2017-11-23 15:11:07 +01:00
2017-12-08 11:07:21 +01:00
addStackedCurve ( curveName + ", " + channelName + " " + curveUnitText ,
2017-11-23 15:11:07 +01:00
depthValues ,
2017-11-17 20:17:44 +01:00
channelData [ std :: get < 2 > ( channelInfo )],
2017-11-23 15:11:07 +01:00
plotTrack ,
2017-11-08 11:22:16 +01:00
color ,
2017-11-23 15:11:07 +01:00
curveGroupId ,
2017-11-06 22:23:54 +01:00
true );
2017-11-23 15:11:07 +01:00
// Total flow channel will end up first, so just increment the group
// idx to make the rest of the phases group together
if ( RimWellPlotTools :: isTotalFlowChannel ( channelName ) ) curveGroupId ++ ;
2017-10-25 14:43:17 +02:00
}
}
}
2017-10-23 13:57:01 +02:00
}
}
2017-10-27 15:17:24 +02:00
curveGroupId ++ ;
2017-10-23 13:57:01 +02:00
}
2017-11-17 15:35:07 +01:00
2017-12-08 09:55:41 +01:00
updateWidgetTitleWindowTitle ();
2017-11-09 14:14:09 +01:00
m_wellLogPlot -> loadDataAndUpdate ();
2017-11-17 15:35:07 +01:00
m_wellLogPlot -> updateDepthZoom ();
plotTrack -> updateXZoom ();
2017-10-23 13:57:01 +02:00
}
2017-10-25 14:43:17 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-11-08 11:22:16 +01:00
void RimWellPltPlot :: addStackedCurve ( const QString & curveName ,
2017-10-25 14:43:17 +02:00
const std :: vector < double >& depthValues ,
const std :: vector < double >& accFlow ,
2017-10-27 15:17:24 +02:00
RimWellLogTrack * plotTrack ,
2017-11-08 11:22:16 +01:00
cvf :: Color3f color ,
2017-10-27 15:49:00 +02:00
int curveGroupId ,
bool doFillCurve )
2017-10-25 14:43:17 +02:00
{
RimWellFlowRateCurve * curve = new RimWellFlowRateCurve ;
2017-11-08 11:22:16 +01:00
curve -> setFlowValuesPrDepthValue ( curveName , depthValues , accFlow );
2017-10-25 14:43:17 +02:00
2017-10-27 15:17:24 +02:00
curve -> setColor ( color );
curve -> setGroupId ( curveGroupId );
2017-11-08 11:58:14 +01:00
2017-11-17 13:52:29 +01:00
if ( curveGroupId == 0 )
{
curve -> setDoFillCurve ( true );
curve -> setSymbol ( RimPlotCurve :: SYMBOL_NONE );
}
else
{
curve -> setDoFillCurve ( false );
curve -> setSymbol ( RimSummaryCurveAppearanceCalculator :: cycledSymbol ( curveGroupId ));
}
2017-10-25 14:43:17 +02:00
2017-11-17 13:52:29 +01:00
curve -> setSymbolSkipDinstance ( 10 );
plotTrack -> addCurve ( curve );
2017-10-25 14:43:17 +02:00
}
2017-10-23 13:57:01 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-11-15 16:17:55 +01:00
std :: vector < RifDataSourceForRftPlt > RimWellPltPlot :: selectedSourcesExpanded () const
2017-10-23 13:57:01 +02:00
{
2017-11-13 11:10:27 +01:00
std :: vector < RifDataSourceForRftPlt > sources ;
for ( const RifDataSourceForRftPlt & addr : m_selectedSources ())
2017-10-23 13:57:01 +02:00
{
2017-11-13 11:10:27 +01:00
if ( addr . sourceType () == RifDataSourceForRftPlt :: OBSERVED )
2017-10-23 13:57:01 +02:00
{
2017-11-09 10:03:32 +01:00
for ( RimWellLogFile * const wellLogFile : RimWellPlotTools :: wellLogFilesContainingFlow ( m_wellPathName ))
2017-10-23 13:57:01 +02:00
{
2017-11-13 11:10:27 +01:00
sources . push_back ( RifDataSourceForRftPlt ( RifDataSourceForRftPlt :: OBSERVED , wellLogFile ));
2017-10-23 13:57:01 +02:00
}
}
else
sources . push_back ( addr );
}
return sources ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget * RimWellPltPlot :: viewWidget ()
{
return m_wellLogPlotWidget ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: zoomAll ()
{
m_wellLogPlot () -> zoomAll ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogPlot * RimWellPltPlot :: wellLogPlot () const
{
return m_wellLogPlot ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: setCurrentWellName ( const QString & currWellName )
{
2017-11-08 16:35:58 +01:00
m_wellPathName = currWellName ;
2017-10-23 13:57:01 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellPltPlot :: currentWellName () const
{
2017-11-08 16:35:58 +01:00
return m_wellPathName ;
2017-10-23 13:57:01 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const char * RimWellPltPlot :: plotNameFormatString ()
{
return PLOT_NAME_QFORMAT_STRING ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList < caf :: PdmOptionItemInfo > RimWellPltPlot :: calculateValueOptions ( const caf :: PdmFieldHandle * fieldNeedingOptions , bool * useOptionsOnly )
{
QList < caf :: PdmOptionItemInfo > options ;
2017-11-09 10:03:32 +01:00
const QString simWellName = RimWellPlotTools :: simWellName ( m_wellPathName );
2017-10-23 13:57:01 +02:00
2017-11-08 16:35:58 +01:00
if ( fieldNeedingOptions == & m_wellPathName )
2017-10-23 13:57:01 +02:00
{
calculateValueOptionsForWells ( options );
}
else if ( fieldNeedingOptions == & m_selectedSources )
{
2017-11-13 11:10:27 +01:00
std :: set < RifDataSourceForRftPlt > optionAddresses ;
2017-10-31 15:41:28 +01:00
2017-11-09 10:03:32 +01:00
const std :: vector < RimEclipseResultCase *> rftCases = RimWellPlotTools :: rftCasesForWell ( simWellName );
2017-11-15 16:17:55 +01:00
std :: set < RifDataSourceForRftPlt > availableRftSources ;
for ( const auto & rftCase : rftCases )
2017-11-07 14:40:36 +01:00
{
2017-11-15 16:17:55 +01:00
std :: set < QDateTime > rftTimes = rftCase -> rftReader () -> availableTimeSteps ( simWellName , { RifEclipseRftAddress :: ORAT ,
RifEclipseRftAddress :: WRAT ,
RifEclipseRftAddress :: GRAT });
if ( rftTimes . size ())
{
availableRftSources . insert ( RifDataSourceForRftPlt ( RifDataSourceForRftPlt :: RFT , rftCase ));
}
2017-11-07 14:40:36 +01:00
}
2017-11-15 16:17:55 +01:00
if ( availableRftSources . size () )
2017-11-07 14:40:36 +01:00
{
2017-11-15 16:17:55 +01:00
options . push_back ( caf :: PdmOptionItemInfo :: createHeader ( RifDataSourceForRftPlt :: sourceTypeUiText ( RifDataSourceForRftPlt :: RFT ), true ));
for ( const auto & addr : availableRftSources )
{
auto item = caf :: PdmOptionItemInfo ( addr . eclCase () -> caseUserDescription (), QVariant :: fromValue ( addr ));
item . setLevel ( 1 );
options . push_back ( item );
}
2017-11-07 14:40:36 +01:00
}
2017-11-09 10:03:32 +01:00
const std :: vector < RimEclipseResultCase *> gridCases = RimWellPlotTools :: gridCasesForWell ( simWellName );
2017-11-07 14:40:36 +01:00
if ( gridCases . size () > 0 )
{
2017-11-13 11:10:27 +01:00
options . push_back ( caf :: PdmOptionItemInfo :: createHeader ( RifDataSourceForRftPlt :: sourceTypeUiText ( RifDataSourceForRftPlt :: GRID ), true ));
2017-11-07 14:40:36 +01:00
}
for ( const auto & gridCase : gridCases )
{
2017-11-13 11:10:27 +01:00
auto addr = RifDataSourceForRftPlt ( RifDataSourceForRftPlt :: GRID , gridCase );
2017-11-07 14:40:36 +01:00
auto item = caf :: PdmOptionItemInfo ( gridCase -> caseUserDescription (), QVariant :: fromValue ( addr ));
item . setLevel ( 1 );
options . push_back ( item );
}
2017-10-25 14:43:17 +02:00
2017-11-09 10:03:32 +01:00
if ( RimWellPlotTools :: wellLogFilesContainingFlow ( m_wellPathName ). size () > 0 )
2017-10-23 13:57:01 +02:00
{
2017-11-13 11:10:27 +01:00
options . push_back ( caf :: PdmOptionItemInfo :: createHeader ( RifDataSourceForRftPlt :: sourceTypeUiText ( RifDataSourceForRftPlt :: OBSERVED ), true ));
2017-10-23 13:57:01 +02:00
2017-11-13 11:10:27 +01:00
auto addr = RifDataSourceForRftPlt ( RifDataSourceForRftPlt :: OBSERVED );
2017-10-23 13:57:01 +02:00
auto item = caf :: PdmOptionItemInfo ( "Observed Data" , QVariant :: fromValue ( addr ));
item . setLevel ( 1 );
options . push_back ( item );
2017-10-31 15:41:28 +01:00
optionAddresses . insert ( addr );
2017-10-23 13:57:01 +02:00
}
}
else if ( fieldNeedingOptions == & m_selectedTimeSteps )
{
2017-11-16 16:35:55 +01:00
RimWellPlotTools :: calculateValueOptionsForTimeSteps ( RimWellPlotTools :: simWellName ( m_wellPathName ),
selectedSourcesExpanded (),
{ RifEclipseRftAddress :: ORAT ,
RifEclipseRftAddress :: WRAT ,
RifEclipseRftAddress :: GRAT },
options );
2017-10-23 13:57:01 +02:00
}
2017-11-23 15:11:07 +01:00
if ( fieldNeedingOptions == & m_phases )
2017-10-25 14:43:17 +02:00
{
2017-11-09 10:03:32 +01:00
options . push_back ( caf :: PdmOptionItemInfo ( "Oil" , FLOW_PHASE_OIL ));
options . push_back ( caf :: PdmOptionItemInfo ( "Gas" , FLOW_PHASE_GAS ));
options . push_back ( caf :: PdmOptionItemInfo ( "Water" , FLOW_PHASE_WATER ));
2017-11-23 15:11:07 +01:00
options . push_back ( caf :: PdmOptionItemInfo ( "Total" , FLOW_PHASE_TOTAL ));
2017-10-25 14:43:17 +02:00
}
2017-10-23 13:57:01 +02:00
return options ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: fieldChangedByUi ( const caf :: PdmFieldHandle * changedField , const QVariant & oldValue , const QVariant & newValue )
{
RimViewWindow :: fieldChangedByUi ( changedField , oldValue , newValue );
2017-11-08 16:35:58 +01:00
if ( changedField == & m_wellPathName )
2017-10-23 13:57:01 +02:00
{
2017-11-08 16:35:58 +01:00
setDescription ( QString ( plotNameFormatString ()). arg ( m_wellPathName ));
2017-10-23 13:57:01 +02:00
}
2017-11-09 13:36:14 +01:00
if ( changedField == & m_wellPathName )
2017-10-23 13:57:01 +02:00
{
RimWellLogTrack * const plotTrack = m_wellLogPlot -> trackByIndex ( 0 );
2017-11-15 11:31:35 +01:00
plotTrack -> deleteAllCurves ();
m_selectedSources . v (). clear ();
m_selectedTimeSteps . v (). clear ();
2017-11-12 21:22:12 +01:00
updateFormationsOnPlot ();
2017-10-23 13:57:01 +02:00
}
else if ( changedField == & m_selectedSources )
{
2017-12-14 12:53:50 +01:00
RimProject * project = RiaApplication :: instance () -> project ();
RimWellPath * wellPath = project -> wellPathByName ( m_wellPathName ());
if ( wellPath && ! wellPath -> wellPathGeometry ())
{
for ( RifDataSourceForRftPlt address : m_selectedSources ())
{
if ( address . sourceType () == RifDataSourceForRftPlt :: RFT || address . sourceType () == RifDataSourceForRftPlt :: GRID )
{
if ( ! wellPath -> wellPathGeometry ())
{
QString tmp = QString ( "Display of Measured Depth (MD) for Grid or RFT curves is not possible without a well log path, and the curve will be hidden in this mode. \n\n " );
QMessageBox :: warning ( nullptr , "Grid/RFT curve without MD" , tmp );
// Do not show multiple dialogs
break ;
}
}
}
}
2017-10-23 13:57:01 +02:00
}
if ( changedField == & m_selectedSources ||
changedField == & m_selectedTimeSteps )
{
2017-11-12 21:22:12 +01:00
updateFormationsOnPlot ();
2017-10-31 15:41:28 +01:00
syncSourcesIoFieldFromGuiField ();
2017-10-23 13:57:01 +02:00
syncCurvesFromUiSelection ();
}
2017-10-25 14:43:17 +02:00
2017-11-23 15:11:07 +01:00
if ( changedField == & m_useStandardConditionCurves
|| changedField == & m_useReservoirConditionCurves
|| changedField == & m_phases )
2017-10-25 14:43:17 +02:00
{
syncCurvesFromUiSelection ();
}
2017-10-23 13:57:01 +02:00
}
2017-11-13 10:21:24 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: defineUiTreeOrdering ( caf :: PdmUiTreeOrdering & uiTreeOrdering , QString uiConfigName )
{
uiTreeOrdering . skipRemainingChildren ( true );
}
2017-10-23 13:57:01 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimWellPltPlot :: snapshotWindowContent ()
{
QImage image ;
if ( m_wellLogPlotWidget )
{
QPixmap pix = QPixmap :: grabWidget ( m_wellLogPlotWidget );
image = pix . toImage ();
}
return image ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: defineUiOrdering ( QString uiConfigName , caf :: PdmUiOrdering & uiOrdering )
{
2017-11-09 10:03:32 +01:00
const QString simWellName = RimWellPlotTools :: simWellName ( m_wellPathName );
2017-10-23 13:57:01 +02:00
uiOrdering . add ( & m_userName );
2017-11-08 16:35:58 +01:00
uiOrdering . add ( & m_wellPathName );
2017-10-23 13:57:01 +02:00
caf :: PdmUiGroup * sourcesGroup = uiOrdering . addNewGroupWithKeyword ( "Sources" , "Sources" );
sourcesGroup -> add ( & m_selectedSources );
caf :: PdmUiGroup * timeStepsGroup = uiOrdering . addNewGroupWithKeyword ( "Time Steps" , "TimeSteps" );
timeStepsGroup -> add ( & m_selectedTimeSteps );
2017-11-23 15:11:07 +01:00
caf :: PdmUiGroup * flowGroup = uiOrdering . addNewGroupWithKeyword ( "Curve Selection" , "PhaseSelection" );
flowGroup -> add ( & m_useStandardConditionCurves );
flowGroup -> add ( & m_useReservoirConditionCurves );
2017-10-25 14:43:17 +02:00
2017-11-23 15:11:07 +01:00
flowGroup -> add ( & m_phases );
2017-10-23 13:57:01 +02:00
2017-11-06 16:07:29 +01:00
if ( m_wellLogPlot && m_wellLogPlot -> trackCount () > 0 )
{
RimWellLogTrack * track = m_wellLogPlot -> trackByIndex ( 0 );
2018-01-04 16:42:57 +01:00
track -> uiOrderingForRftPltFormations ( uiOrdering );
2017-11-06 16:07:29 +01:00
caf :: PdmUiGroup * legendAndAxisGroup = uiOrdering . addNewGroup ( "Legend and Axis" );
legendAndAxisGroup -> setCollapsedByDefault ( true );
m_wellLogPlot -> uiOrderingForPlot ( * legendAndAxisGroup );
track -> uiOrderingForVisibleXRange ( * legendAndAxisGroup );
m_wellLogPlot -> uiOrderingForVisibleDepthRange ( * legendAndAxisGroup );
}
2017-10-23 13:57:01 +02:00
uiOrdering . skipRemainingFields ( true );
}
2017-10-25 14:43:17 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: defineEditorAttribute ( const caf :: PdmFieldHandle * field , QString uiConfigName , caf :: PdmUiEditorAttribute * attribute )
{
if ( field == & m_phases )
{
caf :: PdmUiTreeSelectionEditorAttribute * attrib = dynamic_cast < caf :: PdmUiTreeSelectionEditorAttribute *> ( attribute );
attrib -> showTextFilter = false ;
attrib -> showToggleAllCheckbox = false ;
}
}
2017-10-27 09:38:24 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: initAfterRead ()
{
RimViewWindow :: initAfterRead ();
// Postpone init until data has been loaded
m_doInitAfterLoad = true ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: setupBeforeSave ()
{
2017-11-15 12:40:04 +01:00
syncSourcesIoFieldFromGuiField ();
2017-10-27 09:38:24 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: initAfterLoad ()
{
2017-11-15 12:40:04 +01:00
std :: vector < RifDataSourceForRftPlt > selectedSources ;
2017-11-13 11:16:36 +01:00
for ( RimDataSourceForRftPlt * addr : m_selectedSourcesForIo )
2017-10-27 09:38:24 +02:00
{
2017-11-15 12:40:04 +01:00
selectedSources . push_back ( addr -> address ());
2017-10-27 09:38:24 +02:00
}
2017-11-15 12:40:04 +01:00
m_selectedSources = selectedSources ;
2017-10-27 09:38:24 +02:00
}
2017-10-31 15:41:28 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: syncSourcesIoFieldFromGuiField ()
{
m_selectedSourcesForIo . clear ();
2017-11-15 12:40:04 +01:00
for ( const RifDataSourceForRftPlt & addr : m_selectedSources ())
2017-10-31 15:41:28 +01:00
{
2017-11-13 11:16:36 +01:00
m_selectedSourcesForIo . push_back ( new RimDataSourceForRftPlt ( addr ));
2017-10-31 15:41:28 +01:00
}
}
2017-10-23 13:57:01 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: calculateValueOptionsForWells ( QList < caf :: PdmOptionItemInfo >& options )
{
RimProject * proj = RiaApplication :: instance () -> project ();
if ( proj != nullptr )
{
// Observed wells
2017-11-08 16:35:58 +01:00
for ( const RimWellPath * const wellPath : proj -> allWellPaths ())
2017-10-23 13:57:01 +02:00
{
2017-12-14 11:22:44 +01:00
const QString wellName = wellPath -> name ();
2017-10-23 13:57:01 +02:00
2017-12-14 11:22:44 +01:00
if ( wellPath -> wellPathGeometry () || RimWellPlotTools :: hasFlowData ( wellPath ))
options . push_back ( caf :: PdmOptionItemInfo ( wellName , wellName ));
2017-10-23 13:57:01 +02:00
}
}
2017-11-06 14:20:43 +01:00
2017-11-15 16:17:55 +01:00
options . push_back ( caf :: PdmOptionItemInfo ( "None" , "" ));
2017-10-23 13:57:01 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPltPlot :: setDescription ( const QString & description )
{
m_userName = description ;
updateWidgetTitleWindowTitle ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellPltPlot :: description () const
{
return m_userName ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-10-31 12:49:14 +01:00
void RimWellPltPlot :: onLoadDataAndUpdate ()
2017-10-23 13:57:01 +02:00
{
2017-10-27 09:38:24 +02:00
if ( m_doInitAfterLoad )
{
initAfterLoad ();
m_doInitAfterLoad = false ;
}
2017-11-13 08:56:22 +01:00
if ( m_isOnLoad )
{
if ( m_wellLogPlot -> trackCount () > 0 )
{
m_wellLogPlot -> trackByIndex ( 0 ) -> setShowFormations ( true );
}
m_isOnLoad = false ;
}
2017-10-23 13:57:01 +02:00
updateMdiWindowVisibility ();
2017-11-12 21:22:12 +01:00
updateFormationsOnPlot ();
2017-10-27 09:38:24 +02:00
syncCurvesFromUiSelection ();
2017-10-23 13:57:01 +02:00
m_wellLogPlot -> loadDataAndUpdate ();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget * RimWellPltPlot :: createViewWidget ( QWidget * mainWindowParent )
{
m_wellLogPlotWidget = new RiuWellPltPlot ( this , mainWindowParent );
return m_wellLogPlotWidget ;
}