From 16215585be3eae596533d89300a1553496e02d97 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 24 Jun 2024 14:20:54 +0200 Subject: [PATCH] Refactoring to prepare for renaming of RimSummaryCaseCollection Move functions into RimSummaryEnsembleTools Use enum class instead of plain enum --- .../RicCreateRftPlotsFeature.cpp | 4 +- .../RimAbstractCorrelationPlot.cpp | 3 +- .../RimCorrelationPlotCollection.cpp | 4 +- .../Flow/RimWellPlotTools.cpp | 288 +++++++-------- .../ProjectDataModel/Flow/RimWellPlotTools.h | 144 +++----- .../ProjectDataModel/Flow/RimWellPltPlot.cpp | 56 +-- .../ProjectDataModel/Flow/RimWellPltPlot.h | 7 +- .../ProjectDataModel/Flow/RimWellRftPlot.cpp | 11 +- .../Summary/CMakeLists_files.cmake | 2 + .../Summary/RimSummaryCaseCollection.cpp | 328 +----------------- .../Summary/RimSummaryCaseCollection.h | 15 +- .../Summary/RimSummaryEnsembleTools.cpp | 325 +++++++++++++++++ .../Summary/RimSummaryEnsembleTools.h | 40 +++ .../RimSummaryCaseCollection-Test.cpp | 6 +- 14 files changed, 633 insertions(+), 600 deletions(-) create mode 100644 ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsembleTools.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsembleTools.h diff --git a/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.cpp b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.cpp index 19e4bf81a1..41e729f3d8 100644 --- a/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.cpp +++ b/ApplicationLibCode/Commands/WellLogCommands/RicCreateRftPlotsFeature.cpp @@ -28,9 +28,9 @@ #include "RimRftPlotCollection.h" #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" +#include "RimSummaryEnsembleTools.h" #include "RimWellLogPlotNameConfig.h" #include "RimWellLogTrack.h" -#include "RimWellPlotTools.h" #include "RimWellRftPlot.h" #include "RiuPlotMainWindowTools.h" @@ -58,7 +58,7 @@ void RicCreateRftPlotsFeature::onActionTriggered( bool isChecked ) auto dataSource = sourcePlot->dataSource(); if ( auto summaryCollection = std::get_if( &dataSource ) ) { - wellsWithRftData = ( *summaryCollection )->wellsWithRftData(); + wellsWithRftData = RimSummaryEnsembleTools::wellsWithRftData( ( *summaryCollection )->allSummaryCases() ); } else if ( auto summaryCase = std::get_if( &dataSource ) ) { diff --git a/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimAbstractCorrelationPlot.cpp b/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimAbstractCorrelationPlot.cpp index fbea61f87b..f657e90da0 100644 --- a/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimAbstractCorrelationPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimAbstractCorrelationPlot.cpp @@ -32,6 +32,7 @@ #include "RimSummaryAddress.h" #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" +#include "RimSummaryEnsembleTools.h" #include "RiuContextMenuLauncher.h" #include "RiuPlotMainWindowTools.h" @@ -465,7 +466,7 @@ std::set RimAbstractCorrelationPlot::ensembleParameters() for ( RimSummaryCaseCollection* ensemble : analyserOfSelectedCurveDefs->m_ensembles ) { - std::vector parameters = ensemble->alphabeticEnsembleParameters(); + std::vector parameters = RimSummaryEnsembleTools::alphabeticEnsembleParameters( ensemble->allSummaryCases() ); ensembleParms.insert( parameters.begin(), parameters.end() ); } return ensembleParms; diff --git a/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimCorrelationPlotCollection.cpp b/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimCorrelationPlotCollection.cpp index 6408faac80..9f31a77c5a 100644 --- a/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimCorrelationPlotCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/CorrelationPlots/RimCorrelationPlotCollection.cpp @@ -26,6 +26,7 @@ #include "RimParameterResultCrossPlot.h" #include "RimProject.h" #include "RimSummaryCaseCollection.h" +#include "RimSummaryEnsembleTools.h" CAF_PDM_SOURCE_INIT( RimCorrelationPlotCollection, "CorrelationPlotCollection" ); @@ -247,7 +248,8 @@ void RimCorrelationPlotCollection::applyFirstEnsembleFieldAddressesToPlot( RimAb auto crossPlot = dynamic_cast( plot ); if ( crossPlot ) { - crossPlot->setEnsembleParameter( ensembles.front()->alphabeticEnsembleParameters().front().name ); + crossPlot->setEnsembleParameter( + RimSummaryEnsembleTools::alphabeticEnsembleParameters( ensembles.front()->allSummaryCases() ).front().name ); } } } diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.cpp index 992c75894c..1943183b6a 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.cpp @@ -19,9 +19,6 @@ #include "RimWellPlotTools.h" #include "RiaQDateTimeTools.h" -#include "RiaWellNameComparer.h" - -#include "RifReaderEclipseRft.h" #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" @@ -37,6 +34,7 @@ #include "RimProject.h" #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" +#include "RimSummaryEnsembleTools.h" #include "RimWellLogChannel.h" #include "RimWellLogExtractionCurve.h" #include "RimWellLogLasFile.h" @@ -47,17 +45,42 @@ #include +namespace RimWellPlotTools +{ + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const std::set RimWellPlotTools::PRESSURE_DATA_NAMES = { "PRESSURE", "PRES_FORM" }; +const std::set PRESSURE_DATA_NAMES = { "PRESSURE", "PRES_FORM" }; -const std::set RimWellPlotTools::OIL_CHANNEL_NAMES = { "QOZT", "QOIL", "^.*\\D_QOIL" }; -const std::set RimWellPlotTools::GAS_CHANNEL_NAMES = { "QGZT", "QGAS", "^.*\\D_QGAS" }; -const std::set RimWellPlotTools::WATER_CHANNEL_NAMES = { "QWZT", "QWAT", "^.*\\D_QWAT" }; -const std::set RimWellPlotTools::TOTAL_CHANNEL_NAMES = { "QTZT", "QTOT", "^.*\\D_QTOT" }; +const std::set OIL_CHANNEL_NAMES = { "QOZT", "QOIL", "^.*\\D_QOIL" }; +const std::set GAS_CHANNEL_NAMES = { "QGZT", "QGAS", "^.*\\D_QGAS" }; +const std::set WATER_CHANNEL_NAMES = { "QWZT", "QWAT", "^.*\\D_QWAT" }; +const std::set TOTAL_CHANNEL_NAMES = { "QTZT", "QTOT", "^.*\\D_QTOT" }; -std::set RimWellPlotTools::FLOW_DATA_NAMES = {}; +std::set FLOW_DATA_NAMES = {}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool tryMatchChannelName( const std::set& channelNames, const QString& channelNameToMatch ) +{ + auto itr = std::find_if( channelNames.begin(), + channelNames.end(), + [&]( const QString& channelName ) + { + if ( channelName.startsWith( '^' ) ) + { + std::regex pattern( channelName.toStdString() ); + return std::regex_match( channelNameToMatch.toStdString(), pattern ); + } + else + { + return (bool)channelName.contains( channelNameToMatch, Qt::CaseInsensitive ); + } + } ); + return itr != channelNames.end(); +} //-------------------------------------------------------------------------------------------------- /// @@ -68,17 +91,29 @@ public: StaticFieldsInitializer() { // Init static list - RimWellPlotTools::FLOW_DATA_NAMES.insert( RimWellPlotTools::OIL_CHANNEL_NAMES.begin(), RimWellPlotTools::OIL_CHANNEL_NAMES.end() ); - RimWellPlotTools::FLOW_DATA_NAMES.insert( RimWellPlotTools::GAS_CHANNEL_NAMES.begin(), RimWellPlotTools::GAS_CHANNEL_NAMES.end() ); - RimWellPlotTools::FLOW_DATA_NAMES.insert( RimWellPlotTools::WATER_CHANNEL_NAMES.begin(), RimWellPlotTools::WATER_CHANNEL_NAMES.end() ); - RimWellPlotTools::FLOW_DATA_NAMES.insert( RimWellPlotTools::TOTAL_CHANNEL_NAMES.begin(), RimWellPlotTools::TOTAL_CHANNEL_NAMES.end() ); + FLOW_DATA_NAMES.insert( OIL_CHANNEL_NAMES.begin(), OIL_CHANNEL_NAMES.end() ); + FLOW_DATA_NAMES.insert( GAS_CHANNEL_NAMES.begin(), GAS_CHANNEL_NAMES.end() ); + FLOW_DATA_NAMES.insert( WATER_CHANNEL_NAMES.begin(), WATER_CHANNEL_NAMES.end() ); + FLOW_DATA_NAMES.insert( TOTAL_CHANNEL_NAMES.begin(), TOTAL_CHANNEL_NAMES.end() ); } } staticFieldsInitializer; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::hasPressureData( const RimWellLogFile* wellLogFile ) +bool isPressureChannel( RimWellLogChannel* channel ) +{ + for ( const auto& pressureDataName : PRESSURE_DATA_NAMES ) + { + if ( QString::compare( channel->name(), pressureDataName, Qt::CaseInsensitive ) == 0 ) return true; + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool hasPressureData( const RimWellLogFile* wellLogFile ) { for ( RimWellLogChannel* const wellLogChannel : wellLogFile->wellLogChannels() ) { @@ -90,7 +125,7 @@ bool RimWellPlotTools::hasPressureData( const RimWellLogFile* wellLogFile ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::hasPressureData( RimWellPath* wellPath ) +bool hasPressureData( RimWellPath* wellPath ) { for ( RimWellLogFile* const wellLogFile : wellPath->wellLogFiles() ) { @@ -105,7 +140,7 @@ bool RimWellPlotTools::hasPressureData( RimWellPath* wellPath ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::pair RimWellPlotTools::pressureResultDataInfo( const RigEclipseCaseData* eclipseCaseData ) +std::pair pressureResultDataInfo( const RigEclipseCaseData* eclipseCaseData ) { if ( eclipseCaseData != nullptr ) { @@ -125,26 +160,23 @@ std::pair RimWellPlotTools::pressureResultData //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::isPressureChannel( RimWellLogChannel* channel ) +bool hasPressureData( RimEclipseResultCase* gridCase ) { - for ( const auto& pressureDataName : PRESSURE_DATA_NAMES ) - { - if ( QString::compare( channel->name(), pressureDataName, Qt::CaseInsensitive ) == 0 ) return true; - } - return false; + return pressureResultDataInfo( gridCase->eclipseCaseData() ).first.isValid(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::hasPressureData( RimEclipseResultCase* gridCase ) +bool isFlowChannel( RimWellLogChannel* channel ) { - return pressureResultDataInfo( gridCase->eclipseCaseData() ).first.isValid(); + return tryMatchChannelName( FLOW_DATA_NAMES, channel->name() ); } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::hasFlowData( const RimWellLog* wellLog ) +bool hasFlowData( const RimWellLog* wellLog ) { for ( RimWellLogChannel* const wellLogChannel : wellLog->wellLogChannels() ) { @@ -156,7 +188,7 @@ bool RimWellPlotTools::hasFlowData( const RimWellLog* wellLog ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::hasFlowData( const RimWellPath* wellPath ) +bool hasFlowData( const RimWellPath* wellPath ) { for ( RimWellLogFile* const wellLogFile : wellPath->wellLogFiles() ) { @@ -171,7 +203,7 @@ bool RimWellPlotTools::hasFlowData( const RimWellPath* wellPath ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::hasAssociatedWellPath( const QString& wellName ) +bool hasAssociatedWellPath( const QString& wellName ) { RimProject* proj = RimProject::current(); RimWellPath* wellPath = proj->wellPathByName( wellName ); @@ -182,15 +214,7 @@ bool RimWellPlotTools::hasAssociatedWellPath( const QString& wellName ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::isFlowChannel( RimWellLogChannel* channel ) -{ - return tryMatchChannelName( FLOW_DATA_NAMES, channel->name() ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::isOilFlowChannel( const QString& channelName ) +bool isOilFlowChannel( const QString& channelName ) { return tryMatchChannelName( OIL_CHANNEL_NAMES, channelName ); } @@ -198,7 +222,7 @@ bool RimWellPlotTools::isOilFlowChannel( const QString& channelName ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::isGasFlowChannel( const QString& channelName ) +bool isGasFlowChannel( const QString& channelName ) { return tryMatchChannelName( GAS_CHANNEL_NAMES, channelName ); } @@ -206,7 +230,7 @@ bool RimWellPlotTools::isGasFlowChannel( const QString& channelName ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::isWaterFlowChannel( const QString& channelName ) +bool isWaterFlowChannel( const QString& channelName ) { return tryMatchChannelName( WATER_CHANNEL_NAMES, channelName ); } @@ -214,7 +238,7 @@ bool RimWellPlotTools::isWaterFlowChannel( const QString& channelName ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::isTotalFlowChannel( const QString& channelName ) +bool isTotalFlowChannel( const QString& channelName ) { return tryMatchChannelName( TOTAL_CHANNEL_NAMES, channelName ); } @@ -222,7 +246,7 @@ bool RimWellPlotTools::isTotalFlowChannel( const QString& channelName ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::hasFlowData( RimEclipseResultCase* gridCase ) +bool hasFlowData( RimEclipseResultCase* gridCase ) { const RigEclipseCaseData* const eclipseCaseData = gridCase->eclipseCaseData(); @@ -240,20 +264,20 @@ bool RimWellPlotTools::hasFlowData( RimEclipseResultCase* gridCase ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -FlowPhase RimWellPlotTools::flowPhaseFromChannelName( const QString& channelName ) +FlowPhase flowPhaseFromChannelName( const QString& channelName ) { - if ( tryMatchChannelName( OIL_CHANNEL_NAMES, channelName ) ) return FLOW_PHASE_OIL; - if ( tryMatchChannelName( GAS_CHANNEL_NAMES, channelName ) ) return FLOW_PHASE_GAS; - if ( tryMatchChannelName( WATER_CHANNEL_NAMES, channelName ) ) return FLOW_PHASE_WATER; - if ( tryMatchChannelName( TOTAL_CHANNEL_NAMES, channelName ) ) return FLOW_PHASE_TOTAL; - return FLOW_PHASE_NONE; + if ( tryMatchChannelName( OIL_CHANNEL_NAMES, channelName ) ) return FlowPhase::FLOW_PHASE_OIL; + if ( tryMatchChannelName( GAS_CHANNEL_NAMES, channelName ) ) return FlowPhase::FLOW_PHASE_GAS; + if ( tryMatchChannelName( WATER_CHANNEL_NAMES, channelName ) ) return FlowPhase::FLOW_PHASE_WATER; + if ( tryMatchChannelName( TOTAL_CHANNEL_NAMES, channelName ) ) return FlowPhase::FLOW_PHASE_TOTAL; + return FlowPhase::FLOW_PHASE_NONE; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellPlotTools::addTimeStepsToMap( std::map>& destMap, - const std::map>& timeStepsToAdd ) +void addTimeStepsToMap( std::map>& destMap, + const std::map>& timeStepsToAdd ) { for ( const auto& timeStepPair : timeStepsToAdd ) { @@ -268,7 +292,7 @@ void RimWellPlotTools::addTimeStepsToMap( std::map RimWellPlotTools::wellLogFilesContainingPressure( const QString& wellPathNameOrSimWellName ) +std::vector wellLogFilesContainingPressure( const QString& wellPathNameOrSimWellName ) { std::vector wellLogFiles; const RimProject* const project = RimProject::current(); @@ -297,7 +321,7 @@ std::vector RimWellPlotTools::wellLogFilesContainingPressure( c //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellLogChannel* RimWellPlotTools::getPressureChannelFromWellFile( const RimWellLogFile* wellLogFile ) +RimWellLogChannel* getPressureChannelFromWellFile( const RimWellLogFile* wellLogFile ) { if ( wellLogFile != nullptr ) { @@ -315,7 +339,7 @@ RimWellLogChannel* RimWellPlotTools::getPressureChannelFromWellFile( const RimWe //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::wellLogFilesContainingFlow( const QString& wellPathName ) +std::vector wellLogFilesContainingFlow( const QString& wellPathName ) { std::vector wellLogFiles; const RimProject* const project = RimProject::current(); @@ -342,7 +366,7 @@ std::vector RimWellPlotTools::wellLogFilesContainingFlow( const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPath* RimWellPlotTools::wellPathFromWellLogFile( const RimWellLogFile* wellLogFile ) +RimWellPath* wellPathFromWellLogFile( const RimWellLogFile* wellLogFile ) { RimProject* const project = RimProject::current(); for ( const auto& oilField : project->oilFields ) @@ -365,7 +389,7 @@ RimWellPath* RimWellPlotTools::wellPathFromWellLogFile( const RimWellLogFile* we //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::gridCasesForWell( const QString& simWellName ) +std::vector gridCasesForWell( const QString& simWellName ) { std::vector cases; const RimProject* project = RimProject::current(); @@ -387,7 +411,7 @@ std::vector RimWellPlotTools::gridCasesForWell( const QSt //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::rftCasesForWell( const QString& simWellName ) +std::vector rftCasesForWell( const QString& simWellName ) { std::vector cases; const RimProject* project = RimProject::current(); @@ -407,7 +431,25 @@ std::vector RimWellPlotTools::rftCasesForWell( const QStr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::rftEnsemblesForWell( const QString& simWellName ) +std::set rftTimeStepsForWell( const std::vector& summaryCases, const QString& wellName ) +{ + std::set allTimeSteps; + for ( RimSummaryCase* summaryCase : summaryCases ) + { + RifReaderRftInterface* reader = summaryCase->rftReader(); + if ( reader ) + { + std::set timeStep = reader->availableTimeSteps( wellName ); + allTimeSteps.insert( timeStep.begin(), timeStep.end() ); + } + } + return allTimeSteps; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector rftEnsemblesForWell( const QString& simWellName ) { const RimProject* project = RimProject::current(); @@ -417,7 +459,8 @@ std::vector RimWellPlotTools::rftEnsemblesForWell( co for ( RimSummaryCaseCollection* summaryCaseColl : allSummaryCaseCollections ) { - if ( summaryCaseColl && summaryCaseColl->isEnsemble() && !summaryCaseColl->rftTimeStepsForWell( simWellName ).empty() ) + if ( summaryCaseColl && summaryCaseColl->isEnsemble() && + !rftTimeStepsForWell( summaryCaseColl->allSummaryCases(), simWellName ).empty() ) { rftEnsembles.push_back( summaryCaseColl ); } @@ -428,7 +471,7 @@ std::vector RimWellPlotTools::rftEnsemblesForWell( co //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::rftEnsembles() +std::vector rftEnsembles() { const RimProject* project = RimProject::current(); @@ -438,7 +481,8 @@ std::vector RimWellPlotTools::rftEnsembles() for ( RimSummaryCaseCollection* summaryCaseColl : allSummaryCaseCollections ) { - if ( summaryCaseColl && summaryCaseColl->isEnsemble() && !summaryCaseColl->wellsWithRftData().empty() ) + if ( summaryCaseColl && summaryCaseColl->isEnsemble() && + !RimSummaryEnsembleTools::wellsWithRftData( summaryCaseColl->allSummaryCases() ).empty() ) { rftEnsembles.push_back( summaryCaseColl ); } @@ -449,7 +493,7 @@ std::vector RimWellPlotTools::rftEnsembles() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::observedFmuRftDataForWell( const QString& simWellName ) +std::vector observedFmuRftDataForWell( const QString& simWellName ) { std::vector observedDataForWell; std::vector allObservedData = observedFmuRftData(); @@ -466,7 +510,7 @@ std::vector RimWellPlotTools::observedFmuRftDataForWell( //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::observedFmuRftData() +std::vector observedFmuRftData() { const RimProject* project = RimProject::current(); RimObservedDataCollection* observedDataCollection = project->activeOilField() ? project->activeOilField()->observedDataCollection() @@ -482,7 +526,7 @@ std::vector RimWellPlotTools::observedFmuRftData() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::pressureDepthDataForWell( const QString& simWellName ) +std::vector pressureDepthDataForWell( const QString& simWellName ) { std::vector observedDataForWell; std::vector allObservedData = pressureDepthData(); @@ -499,7 +543,7 @@ std::vector RimWellPlotTools::pressureDepthDataForWell( c //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::pressureDepthData() +std::vector pressureDepthData() { const RimProject* project = RimProject::current(); RimObservedDataCollection* observedDataCollection = project->activeOilField() ? project->activeOilField()->observedDataCollection() @@ -515,7 +559,7 @@ std::vector RimWellPlotTools::pressureDepthData() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::map> RimWellPlotTools::timeStepsMapFromGridCase( RimEclipseCase* gridCase ) +std::map> timeStepsMapFromGridCase( RimEclipseCase* gridCase ) { const RigEclipseCaseData* const eclipseCaseData = gridCase->eclipseCaseData(); std::pair resultDataInfo = pressureResultDataInfo( eclipseCaseData ); @@ -539,8 +583,7 @@ std::map> RimWellPlotTools::timeStep //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::set RimWellPlotTools::findMatchingOrAdjacentTimeSteps( const std::set& baseTimeLine, - const std::set& availableTimeSteps ) +std::set findMatchingOrAdjacentTimeSteps( const std::set& baseTimeLine, const std::set& availableTimeSteps ) { std::set resultTimeSteps; for ( const QDateTime& baseTimeStep : baseTimeLine ) @@ -572,7 +615,7 @@ std::set RimWellPlotTools::findMatchingOrAdjacentTimeSteps( const std //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::set RimWellPlotTools::availableSimWellTimesteps( RimEclipseCase* eclCase, const QString& simWellName, bool addFirstReportTimestep ) +std::set availableSimWellTimesteps( RimEclipseCase* eclCase, const QString& simWellName, bool addFirstReportTimestep ) { if ( !eclCase || !eclCase->eclipseCaseData() ) return {}; @@ -600,7 +643,7 @@ std::set RimWellPlotTools::availableSimWellTimesteps( RimEclipseCase* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RifReaderRftInterface* RimWellPlotTools::rftReaderInterface( RimEclipseCase* eclipseCase ) +RifReaderRftInterface* rftReaderInterface( RimEclipseCase* eclipseCase ) { auto eclResCase = dynamic_cast( eclipseCase ); @@ -612,7 +655,7 @@ RifReaderRftInterface* RimWellPlotTools::rftReaderInterface( RimEclipseCase* ecl //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiaRftPltCurveDefinition RimWellPlotTools::curveDefFromCurve( const RimWellLogCurve* curve ) +RiaRftPltCurveDefinition curveDefFromCurve( const RimWellLogCurve* curve ) { const RimWellLogRftCurve* rftCurve = dynamic_cast( curve ); const RimWellLogExtractionCurve* gridCurve = dynamic_cast( curve ); @@ -696,7 +739,7 @@ RiaRftPltCurveDefinition RimWellPlotTools::curveDefFromCurve( const RimWellLogCu //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimWellPath* RimWellPlotTools::wellPathByWellPathNameOrSimWellName( const QString& wellPathNameOrSimwellName ) +RimWellPath* wellPathByWellPathNameOrSimWellName( const QString& wellPathNameOrSimwellName ) { RimProject* proj = RimProject::current(); RimWellPath* wellPath = proj->wellPathByName( wellPathNameOrSimwellName ); @@ -707,12 +750,12 @@ RimWellPath* RimWellPlotTools::wellPathByWellPathNameOrSimWellName( const QStrin //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimWellPlotTools::wellPathsContainingFlow() +std::vector wellPathsContainingFlow() { std::vector wellPaths; for ( RimWellPath* wellPath : RimProject::current()->allWellPaths() ) { - if ( wellPath->wellPathGeometry() || RimWellPlotTools::hasFlowData( wellPath ) ) wellPaths.push_back( wellPath ); + if ( wellPath->wellPathGeometry() || hasFlowData( wellPath ) ) wellPaths.push_back( wellPath ); } return wellPaths; @@ -721,7 +764,7 @@ std::vector RimWellPlotTools::wellPathsContainingFlow() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellPlotTools::simWellName( const QString& wellPathNameOrSimWellName ) +QString simWellName( const QString& wellPathNameOrSimWellName ) { RimWellPath* wellPath = wellPathByWellPathNameOrSimWellName( wellPathNameOrSimWellName ); return wellPath != nullptr ? wellPath->associatedSimulationWellName() : wellPathNameOrSimWellName; @@ -730,34 +773,11 @@ QString RimWellPlotTools::simWellName( const QString& wellPathNameOrSimWellName //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimWellPlotTools::tryMatchChannelName( const std::set& channelNames, const QString& channelNameToMatch ) -{ - auto itr = std::find_if( channelNames.begin(), - channelNames.end(), - [&]( const QString& channelName ) - { - if ( channelName.startsWith( '^' ) ) - { - std::regex pattern( channelName.toStdString() ); - return std::regex_match( channelNameToMatch.toStdString(), pattern ); - } - else - { - return (bool)channelName.contains( channelNameToMatch, Qt::CaseInsensitive ); - } - } ); - return itr != channelNames.end(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::set - RimWellPlotTools::curveDefsFromTimesteps( const QString& wellPathNameOrSimWellName, - const std::vector& selectedTimeSteps, - bool firstSimWellTimeStepIsValid, - const std::vector& selectedSourcesExpanded, - const std::set& interestingRFTResults ) +std::set curveDefsFromTimesteps( const QString& wellPathNameOrSimWellName, + const std::vector& selectedTimeSteps, + bool firstSimWellTimeStepIsValid, + const std::vector& selectedSourcesExpanded, + const std::set& interestingRFTResults ) { std::set curveDefs; @@ -781,8 +801,7 @@ std::set } else if ( addr.sourceType() == RifDataSourceForRftPlt::SourceType::GRID_MODEL_CELL_DATA && addr.eclCase() ) { - std::set timeSteps = - RimWellPlotTools::availableSimWellTimesteps( addr.eclCase(), simWellName, firstSimWellTimeStepIsValid ); + std::set timeSteps = availableSimWellTimesteps( addr.eclCase(), simWellName, firstSimWellTimeStepIsValid ); for ( const QDateTime& time : timeSteps ) { @@ -852,7 +871,7 @@ std::set // Add statistics curves if ( addr.sourceType() == RifDataSourceForRftPlt::SourceType::ENSEMBLE_RFT ) { - std::set statTimeSteps = addr.ensemble()->rftTimeStepsForWell( wellPathNameOrSimWellName ); + std::set statTimeSteps = rftTimeStepsForWell( addr.ensemble()->allSummaryCases(), wellPathNameOrSimWellName ); for ( const QDateTime& time : statTimeSteps ) { if ( selectedTimeStepSet.count( time ) ) @@ -885,19 +904,19 @@ std::set //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellPlotTools::flowPlotAxisTitle( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ) +QString flowPlotAxisTitle( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ) { QString axisTitle; if ( condition == RimWellLogLasFile::WELL_FLOW_COND_RESERVOIR ) { - QString unitText = RimWellPlotTools::flowUnitText( condition, unitSystem ); + QString unitText = flowUnitText( condition, unitSystem ); axisTitle = "Reservoir Flow Rate " + unitText; } else { - QString unitText = RimWellPlotTools::flowUnitText( condition, unitSystem ); + QString unitText = flowUnitText( condition, unitSystem ); axisTitle = "Surface Flow Rate " + unitText; } @@ -933,7 +952,7 @@ QString flowConditionReservoirUnitText( RiaDefines::EclipseUnitSystem unitSystem //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellPlotTools::flowUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ) +QString flowUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ) { QString unitText; @@ -965,19 +984,19 @@ QString RimWellPlotTools::flowUnitText( RimWellLogLasFile::WellFlowCondition con //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellPlotTools::flowVolumePlotAxisTitle( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ) +QString flowVolumePlotAxisTitle( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ) { QString axisTitle; if ( condition == RimWellLogLasFile::WELL_FLOW_COND_RESERVOIR ) { - QString unitText = RimWellPlotTools::flowVolumeUnitText( condition, unitSystem ); + QString unitText = flowVolumeUnitText( condition, unitSystem ); axisTitle = "Reservoir Flow Volume " + unitText; } else { - QString unitText = RimWellPlotTools::flowVolumeUnitText( condition, unitSystem ); + QString unitText = flowVolumeUnitText( condition, unitSystem ); axisTitle = "Surface Flow Volume " + unitText; } @@ -1013,7 +1032,7 @@ QString flowVolumeConditionReservoirUnitText( RiaDefines::EclipseUnitSystem unit //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellPlotTools::flowVolumeUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ) +QString flowVolumeUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ) { QString unitText; @@ -1045,9 +1064,7 @@ QString RimWellPlotTools::flowVolumeUnitText( RimWellLogLasFile::WellFlowConditi //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RimWellPlotTools::curveUnitText( RimWellLogLasFile::WellFlowCondition condition, - RiaDefines::EclipseUnitSystem unitSystem, - FlowPhase flowPhase ) +QString curveUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem, FlowPhase flowPhase ) { QString unitText; @@ -1062,11 +1079,11 @@ QString RimWellPlotTools::curveUnitText( RimWellLogLasFile::WellFlowCondition co case RiaDefines::EclipseUnitSystem::UNITS_METRIC: switch ( flowPhase ) { - case FLOW_PHASE_GAS: + case FlowPhase::FLOW_PHASE_GAS: unitText = "[kSm3/day]"; break; - case FLOW_PHASE_WATER: // Intentionally fall through, water and oil have same unit - case FLOW_PHASE_OIL: + case FlowPhase::FLOW_PHASE_WATER: // Intentionally fall through, water and oil have same unit + case FlowPhase::FLOW_PHASE_OIL: unitText = "[Sm3/day]"; break; default: @@ -1078,11 +1095,11 @@ QString RimWellPlotTools::curveUnitText( RimWellLogLasFile::WellFlowCondition co case RiaDefines::EclipseUnitSystem::UNITS_FIELD: switch ( flowPhase ) { - case FLOW_PHASE_GAS: + case FlowPhase::FLOW_PHASE_GAS: unitText = "[BOE/day]"; break; - case FLOW_PHASE_WATER: // Intentionally fall through, water and oil have same unit - case FLOW_PHASE_OIL: + case FlowPhase::FLOW_PHASE_WATER: // Intentionally fall through, water and oil have same unit + case FlowPhase::FLOW_PHASE_OIL: unitText = "[BBL/day]"; break; default: @@ -1105,9 +1122,9 @@ QString RimWellPlotTools::curveUnitText( RimWellLogLasFile::WellFlowCondition co /// //-------------------------------------------------------------------------------------------------- std::map> - RimWellPlotTools::calculateRelevantTimeStepsFromCases( const QString& wellPathNameOrSimWellName, - const std::vector& selSources, - const std::set& interestingRFTResults ) + calculateRelevantTimeStepsFromCases( const QString& wellPathNameOrSimWellName, + const std::vector& selSources, + const std::set& interestingRFTResults ) { bool addFirstTimestep = ( interestingRFTResults.count( RifEclipseRftAddress::RftWellLogChannelType::PRESSURE ) == 1 ); @@ -1208,8 +1225,7 @@ std::map> { if ( source.sourceType() == RifDataSourceForRftPlt::SourceType::GRID_MODEL_CELL_DATA && source.eclCase() ) { - std::set wellTimeSteps = - RimWellPlotTools::availableSimWellTimesteps( source.eclCase(), simWellName, addFirstTimestep ); + std::set wellTimeSteps = availableSimWellTimesteps( source.eclCase(), simWellName, addFirstTimestep ); for ( const QDateTime& date : wellTimeSteps ) { @@ -1246,7 +1262,7 @@ std::map> { if ( source.sourceType() == RifDataSourceForRftPlt::SourceType::ENSEMBLE_RFT && source.ensemble() ) { - std::set wellTimeSteps = source.ensemble()->rftTimeStepsForWell( wellPathNameOrSimWellName ); + std::set wellTimeSteps = rftTimeStepsForWell( source.ensemble()->allSummaryCases(), wellPathNameOrSimWellName ); for ( const QDateTime& date : wellTimeSteps ) { @@ -1302,12 +1318,10 @@ std::map> for ( const auto& dateSourceSetPair : ensembleTimeStepsWithSources ) ensembleRftTimeSteps.insert( dateSourceSetPair.first ); - std::set filteredRftTimeSteps = RimWellPlotTools::findMatchingOrAdjacentTimeSteps( baseTimeSteps, rftTimeSteps ); - std::set filteredGridTimeSteps = RimWellPlotTools::findMatchingOrAdjacentTimeSteps( baseTimeSteps, gridTimeSteps ); - std::set filteredEnsembleRftTimeSteps = - RimWellPlotTools::findMatchingOrAdjacentTimeSteps( baseTimeSteps, ensembleRftTimeSteps ); - std::set filteredSummaryRftTimeSteps = - RimWellPlotTools::findMatchingOrAdjacentTimeSteps( baseTimeSteps, summaryRftTimeSteps ); + std::set filteredRftTimeSteps = findMatchingOrAdjacentTimeSteps( baseTimeSteps, rftTimeSteps ); + std::set filteredGridTimeSteps = findMatchingOrAdjacentTimeSteps( baseTimeSteps, gridTimeSteps ); + std::set filteredEnsembleRftTimeSteps = findMatchingOrAdjacentTimeSteps( baseTimeSteps, ensembleRftTimeSteps ); + std::set filteredSummaryRftTimeSteps = findMatchingOrAdjacentTimeSteps( baseTimeSteps, summaryRftTimeSteps ); if ( addFirstTimestep && !gridTimeSteps.empty() ) { @@ -1364,10 +1378,10 @@ std::map> //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellPlotTools::calculateValueOptionsForTimeSteps( const QString& wellPathNameOrSimWellName, - const std::vector& selSources, - const std::set& interestingRFTResults, - QList& options ) +void calculateValueOptionsForTimeSteps( const QString& wellPathNameOrSimWellName, + const std::vector& selSources, + const std::set& interestingRFTResults, + QList& options ) { auto timestepsToShowWithSources = calculateRelevantTimeStepsFromCases( wellPathNameOrSimWellName, selSources, interestingRFTResults ); @@ -1424,3 +1438,5 @@ void RimWellPlotTools::calculateValueOptionsForTimeSteps( const QString& options.push_back( caf::PdmOptionItemInfo( optionText, timeStepPair.first ) ); } } + +} // namespace RimWellPlotTools diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.h b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.h index ced86c8550..f6f4f8d9f7 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.h +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.h @@ -21,13 +21,10 @@ #include "RiaDefines.h" #include "RiaRftPltCurveDefinition.h" -#include "RifDataSourceForRftPltQMetaType.h" #include "RifEclipseRftAddress.h" #include "RimWellLogLasFile.h" -#include - #include #include @@ -45,15 +42,15 @@ class RigEclipseCaseData; class RigEclipseResultAddress; class RifReaderRftInterface; -//================================================================================================== -/// -//================================================================================================== -enum FlowType +namespace RimWellPlotTools +{ + +enum class FlowType { FLOW_TYPE_PHASE_SPLIT, FLOW_TYPE_TOTAL }; -enum FlowPhase +enum class FlowPhase { FLOW_PHASE_NONE, FLOW_PHASE_OIL, @@ -62,100 +59,61 @@ enum FlowPhase FLOW_PHASE_TOTAL }; -//================================================================================================== -/// -//================================================================================================== -class RimWellPlotTools -{ -public: - // PLT Only - static bool isOilFlowChannel( const QString& channelName ); - static bool isGasFlowChannel( const QString& channelName ); - static bool isWaterFlowChannel( const QString& channelName ); - static bool isTotalFlowChannel( const QString& channelName ); - static FlowPhase flowPhaseFromChannelName( const QString& channelName ); +bool isOilFlowChannel( const QString& channelName ); +bool isGasFlowChannel( const QString& channelName ); +bool isWaterFlowChannel( const QString& channelName ); +bool isTotalFlowChannel( const QString& channelName ); +FlowPhase flowPhaseFromChannelName( const QString& channelName ); - static std::vector wellLogFilesContainingFlow( const QString& wellName ); - static RimWellPath* wellPathByWellPathNameOrSimWellName( const QString& wellPathNameOrSimwellName ); - static std::vector wellPathsContainingFlow(); +std::vector wellLogFilesContainingFlow( const QString& wellName ); +RimWellPath* wellPathByWellPathNameOrSimWellName( const QString& wellPathNameOrSimwellName ); +std::vector wellPathsContainingFlow(); - // RFT Only -private: - static std::pair pressureResultDataInfo( const RigEclipseCaseData* eclipseCaseData ); +void addTimeStepsToMap( std::map>& destMap, + const std::map>& timeStepsToAdd ); +std::vector wellLogFilesContainingPressure( const QString& wellPathNameOrSimWellName ); +RimWellLogChannel* getPressureChannelFromWellFile( const RimWellLogFile* wellLogFile ); +RimWellPath* wellPathFromWellLogFile( const RimWellLogFile* wellLogFile ); +std::map> timeStepsMapFromGridCase( RimEclipseCase* gridCase ); +RiaRftPltCurveDefinition curveDefFromCurve( const RimWellLogCurve* curve ); -public: - static void addTimeStepsToMap( std::map>& destMap, - const std::map>& timeStepsToAdd ); - static std::vector wellLogFilesContainingPressure( const QString& wellPathNameOrSimWellName ); - static RimWellLogChannel* getPressureChannelFromWellFile( const RimWellLogFile* wellLogFile ); - static RimWellPath* wellPathFromWellLogFile( const RimWellLogFile* wellLogFile ); - static std::map> timeStepsMapFromGridCase( RimEclipseCase* gridCase ); - static RiaRftPltCurveDefinition curveDefFromCurve( const RimWellLogCurve* curve ); +bool hasFlowData( const RimWellLog* wellLog ); +bool hasAssociatedWellPath( const QString& wellName ); - // others - static bool hasFlowData( const RimWellLog* wellLog ); - static bool hasAssociatedWellPath( const QString& wellName ); +std::vector gridCasesForWell( const QString& simWellName ); +std::vector rftCasesForWell( const QString& simWellName ); +std::vector rftEnsemblesForWell( const QString& simWellName ); +std::vector rftEnsembles(); +std::vector observedFmuRftDataForWell( const QString& simWellName ); +std::vector observedFmuRftData(); +QString simWellName( const QString& wellPathNameOrSimWellName ); - // Both - static std::vector gridCasesForWell( const QString& simWellName ); - static std::vector rftCasesForWell( const QString& simWellName ); - static std::vector rftEnsemblesForWell( const QString& simWellName ); - static std::vector rftEnsembles(); - static std::vector observedFmuRftDataForWell( const QString& simWellName ); - static std::vector observedFmuRftData(); - static QString simWellName( const QString& wellPathNameOrSimWellName ); +std::map> + calculateRelevantTimeStepsFromCases( const QString& wellPathNameOrSimWellName, + const std::vector& selSources, + const std::set& interestingRFTResults ); - static std::map> - calculateRelevantTimeStepsFromCases( const QString& wellPathNameOrSimWellName, - const std::vector& selSources, - const std::set& interestingRFTResults ); +void calculateValueOptionsForTimeSteps( const QString& wellPathNameOrSimWellName, + const std::vector& selSources, + const std::set& interestingRFTResults, + QList& options ); - static void calculateValueOptionsForTimeSteps( const QString& wellPathNameOrSimWellName, - const std::vector& selSources, - const std::set& interestingRFTResults, - QList& options ); +std::set curveDefsFromTimesteps( const QString& wellPathNameOrSimWellName, + const std::vector& selectedTimeStepVector, + bool firstReportTimeStepIsValid, + const std::vector& selectedSourcesExpanded, + const std::set& interestingRFTResults ); - static std::set - curveDefsFromTimesteps( const QString& wellPathNameOrSimWellName, - const std::vector& selectedTimeStepVector, - bool firstReportTimeStepIsValid, - const std::vector& selectedSourcesExpanded, - const std::set& interestingRFTResults ); +QString flowPlotAxisTitle( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ); +QString flowUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ); +QString flowVolumePlotAxisTitle( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ); +QString flowVolumeUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ); - static QString flowPlotAxisTitle( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ); - static QString flowUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ); - static QString flowVolumePlotAxisTitle( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ); - static QString flowVolumeUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem ); +QString curveUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem, FlowPhase flowPhase ); - static QString - curveUnitText( RimWellLogLasFile::WellFlowCondition condition, RiaDefines::EclipseUnitSystem unitSystem, FlowPhase flowPhase ); +bool hasFlowData( const RimWellPath* wellPath ); - static bool hasFlowData( const RimWellPath* wellPath ); +std::vector pressureDepthData(); +std::vector pressureDepthDataForWell( const QString& simWellName ); - static std::vector pressureDepthData(); - static std::vector pressureDepthDataForWell( const QString& simWellName ); - -private: - friend class StaticFieldsInitializer; - static const std::set PRESSURE_DATA_NAMES; - - static const std::set OIL_CHANNEL_NAMES; - static const std::set GAS_CHANNEL_NAMES; - static const std::set WATER_CHANNEL_NAMES; - static const std::set TOTAL_CHANNEL_NAMES; - - static std::set FLOW_DATA_NAMES; - - static bool hasPressureData( const RimWellLogFile* wellLogFile ); - static bool isPressureChannel( RimWellLogChannel* channel ); - static bool hasPressureData( RimEclipseResultCase* gridCase ); - static bool hasPressureData( RimWellPath* wellPath ); - static bool hasFlowData( RimEclipseResultCase* gridCase ); - static bool isFlowChannel( RimWellLogChannel* channel ); - static bool tryMatchChannelName( const std::set& channelNames, const QString& channelNameToMatch ); - static std::set findMatchingOrAdjacentTimeSteps( const std::set& baseTimeLine, - const std::set& availableTimeSteps ); - static std::set availableSimWellTimesteps( RimEclipseCase* eclCase, const QString& simWellName, bool addFirstReportTimeStep ); - - static RifReaderRftInterface* rftReaderInterface( RimEclipseCase* eclipseCase ); -}; +}; // namespace RimWellPlotTools diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPltPlot.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPltPlot.cpp index e7588ff0db..81aba6b70e 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPltPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPltPlot.cpp @@ -74,20 +74,20 @@ CAF_PDM_SOURCE_INIT( RimWellPltPlot, "WellPltPlot" ); namespace caf { template <> -void caf::AppEnum::setUp() +void caf::AppEnum::setUp() { - addItem( FLOW_TYPE_PHASE_SPLIT, "PHASE_SPLIT", "Phase Split" ); - addItem( FLOW_TYPE_TOTAL, "TOTAL", "Total Flow" ); - setDefault( FLOW_TYPE_PHASE_SPLIT ); + addItem( RimWellPlotTools::FlowType::FLOW_TYPE_PHASE_SPLIT, "PHASE_SPLIT", "Phase Split" ); + addItem( RimWellPlotTools::FlowType::FLOW_TYPE_TOTAL, "TOTAL", "Total Flow" ); + setDefault( RimWellPlotTools::FlowType::FLOW_TYPE_PHASE_SPLIT ); } template <> -void caf::AppEnum::setUp() +void caf::AppEnum::setUp() { - addItem( FLOW_PHASE_OIL, "PHASE_OIL", "Oil" ); - addItem( FLOW_PHASE_GAS, "PHASE_GAS", "Gas" ); - addItem( FLOW_PHASE_WATER, "PHASE_WATER", "Water" ); - addItem( FLOW_PHASE_TOTAL, "PHASE_TOTAL", "Total" ); + addItem( RimWellPlotTools::FlowPhase::FLOW_PHASE_OIL, "PHASE_OIL", "Oil" ); + addItem( RimWellPlotTools::FlowPhase::FLOW_PHASE_GAS, "PHASE_GAS", "Gas" ); + addItem( RimWellPlotTools::FlowPhase::FLOW_PHASE_WATER, "PHASE_WATER", "Water" ); + addItem( RimWellPlotTools::FlowPhase::FLOW_PHASE_TOTAL, "PHASE_TOTAL", "Total" ); } } // namespace caf @@ -127,7 +127,9 @@ RimWellPltPlot::RimWellPltPlot() CAF_PDM_InitFieldNoDefault( &m_phases, "Phases", "Phases" ); m_phases.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); - m_phases = std::vector>( { FLOW_PHASE_OIL, FLOW_PHASE_GAS, FLOW_PHASE_WATER } ); + m_phases = std::vector>( { RimWellPlotTools::FlowPhase::FLOW_PHASE_OIL, + RimWellPlotTools::FlowPhase::FLOW_PHASE_GAS, + RimWellPlotTools::FlowPhase::FLOW_PHASE_WATER } ); m_phases.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN ); m_nameConfig->setCustomName( "PLT Plot" ); @@ -484,7 +486,7 @@ void RimWellPltPlot::syncCurvesFromUiSelection() // Add curves for ( const RiaRftPltCurveDefinition& curveDefToAdd : curveDefs ) { - std::set selectedPhases = std::set( m_phases().begin(), m_phases().end() ); + std::set selectedPhases = std::set( m_phases().begin(), m_phases().end() ); RifDataSourceForRftPlt sourceDef = curveDefToAdd.address(); QDateTime timeStep = curveDefToAdd.timeStep(); @@ -522,7 +524,7 @@ void RimWellPltPlot::syncCurvesFromUiSelection() { if ( !resultPointCalc->pipeBranchCLCoords().empty() ) { - if ( selectedPhases.count( FLOW_PHASE_TOTAL ) && m_useReservoirConditionCurves() && + if ( selectedPhases.count( RimWellPlotTools::FlowPhase::FLOW_PHASE_TOTAL ) && m_useReservoirConditionCurves() && sourceDef.sourceType() == RifDataSourceForRftPlt::SourceType::GRID_MODEL_CELL_DATA ) { RigAccWellFlowCalculator wfTotalAccumulator( resultPointCalc->pipeBranchCLCoords(), @@ -561,17 +563,17 @@ void RimWellPltPlot::syncCurvesFromUiSelection() : 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 ) ) ) + if ( ( tracerName == RIG_FLOW_OIL_NAME && selectedPhases.count( RimWellPlotTools::FlowPhase::FLOW_PHASE_OIL ) ) || + ( tracerName == RIG_FLOW_GAS_NAME && selectedPhases.count( RimWellPlotTools::FlowPhase::FLOW_PHASE_GAS ) ) || + ( tracerName == RIG_FLOW_WATER_NAME && selectedPhases.count( RimWellPlotTools::FlowPhase::FLOW_PHASE_WATER ) ) ) { - FlowPhase flowPhase = FLOW_PHASE_NONE; + RimWellPlotTools::FlowPhase flowPhase = RimWellPlotTools::FlowPhase::FLOW_PHASE_NONE; if ( tracerName == RIG_FLOW_OIL_NAME ) - flowPhase = FLOW_PHASE_OIL; + flowPhase = RimWellPlotTools::FlowPhase::FLOW_PHASE_OIL; else if ( tracerName == RIG_FLOW_GAS_NAME ) - flowPhase = FLOW_PHASE_GAS; + flowPhase = RimWellPlotTools::FlowPhase::FLOW_PHASE_GAS; else if ( tracerName == RIG_FLOW_WATER_NAME ) - flowPhase = FLOW_PHASE_WATER; + flowPhase = RimWellPlotTools::FlowPhase::FLOW_PHASE_WATER; QString curveUnitText = RimWellPlotTools::curveUnitText( RimWellLogLasFile::WELL_FLOW_COND_STANDARD, unitSet, flowPhase ); @@ -631,13 +633,13 @@ void RimWellPltPlot::syncCurvesFromUiSelection() : RimWellPlotTools::isWaterFlowChannel( channelName ) ? cvf::Color3f::BLUE : cvf::Color3f::DARK_GRAY; - FlowPhase flowPhase = FLOW_PHASE_NONE; + RimWellPlotTools::FlowPhase flowPhase = RimWellPlotTools::FlowPhase::FLOW_PHASE_NONE; if ( RimWellPlotTools::isOilFlowChannel( channelName ) ) - flowPhase = FLOW_PHASE_OIL; + flowPhase = RimWellPlotTools::FlowPhase::FLOW_PHASE_OIL; else if ( RimWellPlotTools::isGasFlowChannel( channelName ) ) - flowPhase = FLOW_PHASE_GAS; + flowPhase = RimWellPlotTools::FlowPhase::FLOW_PHASE_GAS; else if ( RimWellPlotTools::isWaterFlowChannel( channelName ) ) - flowPhase = FLOW_PHASE_WATER; + flowPhase = RimWellPlotTools::FlowPhase::FLOW_PHASE_WATER; QString curveUnitText = RimWellPlotTools::curveUnitText( flowCondition, unitSystem, flowPhase ); addStackedCurve( curveName + ", " + channelName + " " + curveUnitText, @@ -801,10 +803,10 @@ QList RimWellPltPlot::calculateValueOptions( const caf:: if ( fieldNeedingOptions == &m_phases ) { - 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 ) ); - options.push_back( caf::PdmOptionItemInfo( "Total", FLOW_PHASE_TOTAL ) ); + options.push_back( caf::PdmOptionItemInfo( "Oil", RimWellPlotTools::FlowPhase::FLOW_PHASE_OIL ) ); + options.push_back( caf::PdmOptionItemInfo( "Gas", RimWellPlotTools::FlowPhase::FLOW_PHASE_GAS ) ); + options.push_back( caf::PdmOptionItemInfo( "Water", RimWellPlotTools::FlowPhase::FLOW_PHASE_WATER ) ); + options.push_back( caf::PdmOptionItemInfo( "Total", RimWellPlotTools::FlowPhase::FLOW_PHASE_TOTAL ) ); } return options; diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPltPlot.h b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPltPlot.h index 5764394a9e..251acabb58 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPltPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPltPlot.h @@ -118,9 +118,10 @@ private: caf::PdmChildField m_wellLogPlot_OBSOLETE; - caf::PdmField m_useStandardConditionCurves; - caf::PdmField m_useReservoirConditionCurves; - caf::PdmField>> m_phases; + caf::PdmField m_useStandardConditionCurves; + caf::PdmField m_useReservoirConditionCurves; + + caf::PdmField>> m_phases; bool m_doInitAfterLoad; bool m_isOnLoad; diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp index 7dd9d4d7b1..d2b78676d3 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp @@ -20,7 +20,6 @@ #include "RiaColorTables.h" #include "RiaColorTools.h" -#include "RiaDateStringParser.h" #include "RiaPlotDefines.h" #include "RiaSimWellBranchTools.h" #include "RiaSummaryTools.h" @@ -29,22 +28,18 @@ #include "RigCaseCellResultsData.h" #include "RigEclipseCaseData.h" -#include "RigSimWellData.h" -#include "RigWellPath.h" #include "RimEclipseCase.h" -#include "RimEclipseCaseCollection.h" #include "RimEclipseResultCase.h" -#include "RimEclipseResultDefinition.h" #include "RimEnsembleCurveSetColorManager.h" #include "RimObservedFmuRftData.h" -#include "RimOilField.h" #include "RimPressureDepthData.h" #include "RimProject.h" #include "RimRegularLegendConfig.h" #include "RimReloadCaseTools.h" #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" +#include "RimSummaryEnsembleTools.h" #include "RimTools.h" #include "RimWellLogChannel.h" #include "RimWellLogExtractionCurve.h" @@ -57,11 +52,9 @@ #include "RimWellPath.h" #include "RimWellPathCollection.h" #include "RimWellPlotTools.h" -#include "RimWellPltPlot.h" #include "RimWellRftEnsembleCurveSet.h" #include "RiuAbstractLegendFrame.h" -#include "RiuAbstractOverlayContentFrame.h" #include "RiuDraggableOverlayFrame.h" #include "RiuQwtPlotCurveDefines.h" #include "RiuQwtPlotWidget.h" @@ -1161,7 +1154,7 @@ std::map RimWellRftPlot::findWellSources() { for ( RimSummaryCaseCollection* summaryCaseColl : rftEnsembles ) { - std::set wellsWithRftData = summaryCaseColl->wellsWithRftData(); + std::set wellsWithRftData = RimSummaryEnsembleTools::wellsWithRftData( summaryCaseColl->allSummaryCases() ); for ( const QString& wellName : wellsWithRftData ) { wellNames[wellName].push_back( "Ensemble" ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/Summary/CMakeLists_files.cmake index 9d6f352605..fbcf8fb25c 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/Summary/CMakeLists_files.cmake @@ -54,6 +54,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimSummaryRegressionAnalysisCurve.h ${CMAKE_CURRENT_LIST_DIR}/RimSummaryAddressSelector.h ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCrossPlotStatisticsCase.h + ${CMAKE_CURRENT_LIST_DIR}/RimSummaryEnsembleTools.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -112,6 +113,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimSummaryRegressionAnalysisCurve.cpp ${CMAKE_CURRENT_LIST_DIR}/RimSummaryAddressSelector.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCrossPlotStatisticsCase.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimSummaryEnsembleTools.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp index ea0dce891f..e53fa8085f 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp @@ -24,7 +24,6 @@ #include "RiaStatisticsTools.h" #include "RiaSummaryAddressAnalyzer.h" -#include "RifReaderRftInterface.h" #include "RifSummaryReaderInterface.h" #include "RimDerivedEnsembleCaseCollection.h" @@ -32,6 +31,7 @@ #include "RimProject.h" #include "RimSummaryAddressCollection.h" #include "RimSummaryCase.h" +#include "RimSummaryEnsembleTools.h" #include "cafPdmFieldScriptingCapability.h" #include "cafPdmObjectScriptingCapability.h" @@ -43,56 +43,6 @@ CAF_PDM_SOURCE_INIT( RimSummaryCaseCollection, "SummaryCaseSubCollection" ); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryCaseCollection::sortByBinnedVariation( std::vector& parameterVector ) -{ - double minStdDev = std::numeric_limits::infinity(); - double maxStdDev = 0.0; - for ( const auto& paramPair : parameterVector ) - { - double stdDev = paramPair.normalizedStdDeviation(); - if ( stdDev != 0.0 ) - { - minStdDev = std::min( minStdDev, stdDev ); - maxStdDev = std::max( maxStdDev, stdDev ); - } - } - if ( ( maxStdDev - minStdDev ) <= 0.0 ) - { - return; - } - - double delta = ( maxStdDev - minStdDev ) / (float)( RigEnsembleParameter::NR_OF_VARIATION_BINS ); - - std::vector bins; - bins.push_back( 0.0 ); - for ( int i = 0; i < RigEnsembleParameter::NR_OF_VARIATION_BINS - 1; ++i ) - { - bins.push_back( minStdDev + ( i + 1 ) * delta ); - } - - for ( RigEnsembleParameter& nameParamPair : parameterVector ) - { - int binNumber = -1; - for ( double bin : bins ) - { - if ( nameParamPair.normalizedStdDeviation() > bin ) - { - binNumber++; - } - } - nameParamPair.variationBin = binNumber; - } - - // Sort by variation bin (highest first) but keep name as sorting parameter when parameters have the same variation - // index - std::stable_sort( parameterVector.begin(), - parameterVector.end(), - []( const RigEnsembleParameter& lhs, const RigEnsembleParameter& rhs ) { return lhs.variationBin > rhs.variationBin; } ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -360,42 +310,6 @@ std::set RimSummaryCaseCollection::ensembleTimeSteps() const return allTimeSteps; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::set RimSummaryCaseCollection::wellsWithRftData() const -{ - std::set allWellNames; - for ( RimSummaryCase* summaryCase : m_cases ) - { - RifReaderRftInterface* reader = summaryCase->rftReader(); - if ( reader ) - { - std::set wellNames = reader->wellNames(); - allWellNames.insert( wellNames.begin(), wellNames.end() ); - } - } - return allWellNames; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::set RimSummaryCaseCollection::rftTimeStepsForWell( const QString& wellName ) const -{ - std::set allTimeSteps; - for ( RimSummaryCase* summaryCase : m_cases ) - { - RifReaderRftInterface* reader = summaryCase->rftReader(); - if ( reader ) - { - std::set timeStep = reader->availableTimeSteps( wellName ); - allTimeSteps.insert( timeStep.begin(), timeStep.end() ); - } - } - return allTimeSteps; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -403,45 +317,24 @@ std::vector RimSummaryCaseCollection::variationSortedEnsem { if ( m_cachedSortedEnsembleParameters.empty() ) { - std::set paramSet; - for ( RimSummaryCase* rimCase : allSummaryCases() ) - { - if ( rimCase->caseRealizationParameters() != nullptr ) - { - auto ps = rimCase->caseRealizationParameters()->parameters(); - for ( const auto& p : ps ) - { - paramSet.insert( p.first ); - } - } - } - - m_cachedSortedEnsembleParameters.reserve( paramSet.size() ); - for ( const QString& parameterName : paramSet ) - { - auto ensembleParameter = createEnsembleParameter( parameterName ); - m_cachedSortedEnsembleParameters.push_back( ensembleParameter ); - } - RimSummaryCaseCollection::sortByBinnedVariation( m_cachedSortedEnsembleParameters ); + m_cachedSortedEnsembleParameters = RimSummaryEnsembleTools::createVariationSortedEnsembleParameters( allSummaryCases() ); } if ( !excludeNoVariation ) { return m_cachedSortedEnsembleParameters; } - else + + const double epsilon = 1e-9; + std::vector parametersWithVariation; + for ( const auto& p : m_cachedSortedEnsembleParameters ) { - const double epsilon = 1e-9; - std::vector parametersWithVariation; - for ( const auto& p : m_cachedSortedEnsembleParameters ) + if ( std::abs( p.normalizedStdDeviation() ) > epsilon ) { - if ( std::abs( p.normalizedStdDeviation() ) > epsilon ) - { - parametersWithVariation.push_back( p ); - } + parametersWithVariation.push_back( p ); } - return parametersWithVariation; } + return parametersWithVariation; } //-------------------------------------------------------------------------------------------------- @@ -595,144 +488,19 @@ std::vector> return correlationsForChosenTimeSteps[0]; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimSummaryCaseCollection::alphabeticEnsembleParameters() const -{ - std::set paramSet; - for ( RimSummaryCase* rimCase : allSummaryCases() ) - { - if ( rimCase->caseRealizationParameters() != nullptr ) - { - auto ps = rimCase->caseRealizationParameters()->parameters(); - for ( auto p : ps ) - { - paramSet.insert( p.first ); - } - } - } - - std::vector sortedEnsembleParameters; - sortedEnsembleParameters.reserve( paramSet.size() ); - for ( const QString& parameterName : paramSet ) - { - sortedEnsembleParameters.push_back( createEnsembleParameter( parameterName ) ); - } - return sortedEnsembleParameters; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigEnsembleParameter RimSummaryCaseCollection::ensembleParameter( const QString& paramName ) const { - if ( !isEnsemble() || paramName.isEmpty() ) return RigEnsembleParameter(); + if ( !isEnsemble() || paramName.isEmpty() ) return {}; - const std::vector& ensembleParams = variationSortedEnsembleParameters(); - - for ( const RigEnsembleParameter& ensParam : ensembleParams ) + for ( const RigEnsembleParameter& ensParam : variationSortedEnsembleParameters() ) { if ( ensParam.name == paramName ) return ensParam; } - return RigEnsembleParameter(); -} - -RigEnsembleParameter RimSummaryCaseCollection::createEnsembleParameter( const QString& paramName ) const -{ - RigEnsembleParameter eParam; - eParam.name = paramName; - - size_t numericValuesCount = 0; - size_t textValuesCount = 0; - - auto summaryCases = allSummaryCases(); - // Make sure the values list exactly matches the case count - // And use an invalid value (infinity) for invalid cases. - eParam.values.resize( summaryCases.size(), std::numeric_limits::infinity() ); - - // Prepare case realization params, and check types - for ( size_t caseIdx = 0; caseIdx < summaryCases.size(); ++caseIdx ) - { - auto rimCase = summaryCases[caseIdx]; - - auto crp = rimCase->caseRealizationParameters(); - if ( !crp ) continue; - - auto value = crp->parameterValue( paramName ); - if ( !value.isValid() ) continue; - - if ( value.isNumeric() ) - { - double numVal = value.numericValue(); - eParam.values[caseIdx] = QVariant( numVal ); - if ( numVal < eParam.minValue ) eParam.minValue = numVal; - if ( numVal > eParam.maxValue ) eParam.maxValue = numVal; - numericValuesCount++; - } - else if ( value.isText() ) - { - eParam.values[caseIdx] = QVariant( value.textValue() ); - textValuesCount++; - } - } - - if ( numericValuesCount && !textValuesCount ) - { - eParam.type = RigEnsembleParameter::TYPE_NUMERIC; - } - else if ( textValuesCount && !numericValuesCount ) - { - eParam.type = RigEnsembleParameter::TYPE_TEXT; - } - if ( numericValuesCount && textValuesCount ) - { - // A mix of types have been added to parameter values - if ( numericValuesCount > textValuesCount ) - { - // Use numeric type - for ( auto& val : eParam.values ) - { - if ( val.type() == QVariant::String ) - { - val.setValue( std::numeric_limits::infinity() ); - } - } - eParam.type = RigEnsembleParameter::TYPE_NUMERIC; - } - else - { - // Use text type - for ( auto& val : eParam.values ) - { - if ( val.type() == QVariant::Double ) - { - val.setValue( QString::number( val.value() ) ); - } - } - eParam.type = RigEnsembleParameter::TYPE_TEXT; - eParam.minValue = std::numeric_limits::infinity(); - eParam.maxValue = -std::numeric_limits::infinity(); - } - } - - if ( eParam.isText() ) - { - // Remove duplicate texts - std::set valueSet; - for ( const auto& val : eParam.values ) - { - valueSet.insert( val.toString() ); - } - eParam.values.clear(); - for ( const auto& val : valueSet ) - { - eParam.values.push_back( QVariant( val ) ); - } - } - - return eParam; + return {}; } //-------------------------------------------------------------------------------------------------- @@ -740,72 +508,7 @@ RigEnsembleParameter RimSummaryCaseCollection::createEnsembleParameter( const QS //-------------------------------------------------------------------------------------------------- void RimSummaryCaseCollection::calculateEnsembleParametersIntersectionHash() { - clearEnsembleParametersHashes(); - - // Find ensemble parameters intersection - std::set paramNames; - auto sumCases = allSummaryCases(); - - for ( size_t i = 0; i < sumCases.size(); i++ ) - { - auto crp = sumCases[i]->caseRealizationParameters(); - if ( !crp ) continue; - - auto caseParamNames = crp->parameterNames(); - - if ( i == 0 ) - paramNames = caseParamNames; - else - { - std::set newIntersection; - std::set_intersection( paramNames.begin(), - paramNames.end(), - caseParamNames.begin(), - caseParamNames.end(), - std::inserter( newIntersection, newIntersection.end() ) ); - - if ( paramNames.size() != newIntersection.size() ) paramNames = newIntersection; - } - } - - for ( auto sumCase : sumCases ) - { - auto crp = sumCase->caseRealizationParameters(); - if ( crp ) crp->calculateParametersHash( paramNames ); - } - - // Find common addess count - for ( const auto sumCase : sumCases ) - { - const auto reader = sumCase->summaryReader(); - if ( !reader ) continue; - auto currAddrCount = reader->allResultAddresses().size(); - - if ( m_commonAddressCount == 0 ) - { - m_commonAddressCount = currAddrCount; - } - else - { - if ( currAddrCount != m_commonAddressCount ) - { - m_commonAddressCount = 0; - break; - } - } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimSummaryCaseCollection::clearEnsembleParametersHashes() -{ - for ( auto sumCase : allSummaryCases() ) - { - auto crp = sumCase->caseRealizationParameters(); - if ( crp ) crp->clearParametersHash(); - } + m_commonAddressCount = RimSummaryEnsembleTools::calculateEnsembleParametersIntersectionHash( allSummaryCases() ); } //-------------------------------------------------------------------------------------------------- @@ -997,8 +700,9 @@ std::pair RimSummaryCaseCollection::minMax( const RifEclipseSumm //-------------------------------------------------------------------------------------------------- QString RimSummaryCaseCollection::nameAndItemCount() const { - size_t itemCount = m_cases.size(); - if ( itemCount > 20 ) + size_t itemCount = m_cases.size(); + const size_t itemCountThreshold = 20; + if ( itemCount > itemCountThreshold ) { return QString( "%1 (%2)" ).arg( m_name() ).arg( itemCount ); } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h index b2798c954e..02ce930e10 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h @@ -69,11 +69,9 @@ public: virtual std::set ensembleSummaryAddresses() const; virtual std::set ensembleTimeSteps() const; - std::set wellsWithRftData() const; - std::set rftTimeStepsForWell( const QString& wellName ) const; - void setEnsembleId( int ensembleId ); - int ensembleId() const; - bool hasEnsembleParameters() const; + void setEnsembleId( int ensembleId ); + int ensembleId() const; + bool hasEnsembleParameters() const; std::vector variationSortedEnsembleParameters( bool excludeNoVariation = false ) const; std::vector> correlationSortedEnsembleParameters( const RifEclipseSummaryAddress& address ) const; @@ -87,11 +85,8 @@ public: std::vector> parameterCorrelationsAllTimeSteps( const RifEclipseSummaryAddress& address, const std::vector& selectedParameters = {} ) const; - std::vector alphabeticEnsembleParameters() const; - RigEnsembleParameter ensembleParameter( const QString& paramName ) const; void calculateEnsembleParametersIntersectionHash(); - void clearEnsembleParametersHashes(); void loadDataAndUpdate(); @@ -111,10 +106,6 @@ public: std::pair minMax( const RifEclipseSummaryAddress& address ); private: - RigEnsembleParameter createEnsembleParameter( const QString& paramName ) const; - static void sortByBinnedVariation( std::vector& parameterVector ); - friend class RimSummaryCaseCollection_TESTER; - caf::PdmFieldHandle* userDescriptionField() override; QString nameAndItemCount() const; void updateIcon(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsembleTools.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsembleTools.cpp new file mode 100644 index 0000000000..79aa1734fa --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsembleTools.cpp @@ -0,0 +1,325 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor 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 "RimSummaryEnsembleTools.h" + +#include "RifReaderRftInterface.h" +#include "RifSummaryReaderInterface.h" + +#include "RigEnsembleParameter.h" + +#include "RimSummaryCase.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RimSummaryEnsembleTools::wellsWithRftData( const std::vector& summaryCases ) +{ + std::set allWellNames; + for ( auto summaryCase : summaryCases ) + { + if ( auto reader = summaryCase->rftReader() ) + { + std::set wellNames = reader->wellNames(); + allWellNames.insert( wellNames.begin(), wellNames.end() ); + } + } + return allWellNames; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigEnsembleParameter RimSummaryEnsembleTools::createEnsembleParameter( const std::vector& summaryCases, + const QString& paramName ) +{ + RigEnsembleParameter eParam; + eParam.name = paramName; + + size_t numericValuesCount = 0; + size_t textValuesCount = 0; + + // Make sure the values list exactly matches the case count + // And use an invalid value (infinity) for invalid cases. + eParam.values.resize( summaryCases.size(), std::numeric_limits::infinity() ); + + // Prepare case realization params, and check types + for ( size_t caseIdx = 0; caseIdx < summaryCases.size(); ++caseIdx ) + { + auto rimCase = summaryCases[caseIdx]; + + auto crp = rimCase->caseRealizationParameters(); + if ( !crp ) continue; + + auto value = crp->parameterValue( paramName ); + if ( !value.isValid() ) continue; + + if ( value.isNumeric() ) + { + double numVal = value.numericValue(); + eParam.values[caseIdx] = QVariant( numVal ); + if ( numVal < eParam.minValue ) eParam.minValue = numVal; + if ( numVal > eParam.maxValue ) eParam.maxValue = numVal; + numericValuesCount++; + } + else if ( value.isText() ) + { + eParam.values[caseIdx] = QVariant( value.textValue() ); + textValuesCount++; + } + } + + if ( numericValuesCount && !textValuesCount ) + { + eParam.type = RigEnsembleParameter::TYPE_NUMERIC; + } + else if ( textValuesCount && !numericValuesCount ) + { + eParam.type = RigEnsembleParameter::TYPE_TEXT; + } + if ( numericValuesCount && textValuesCount ) + { + // A mix of types have been added to parameter values + if ( numericValuesCount > textValuesCount ) + { + // Use numeric type + for ( auto& val : eParam.values ) + { + if ( val.type() == QVariant::String ) + { + val.setValue( std::numeric_limits::infinity() ); + } + } + eParam.type = RigEnsembleParameter::TYPE_NUMERIC; + } + else + { + // Use text type + for ( auto& val : eParam.values ) + { + if ( val.type() == QVariant::Double ) + { + val.setValue( QString::number( val.value() ) ); + } + } + eParam.type = RigEnsembleParameter::TYPE_TEXT; + eParam.minValue = std::numeric_limits::infinity(); + eParam.maxValue = -std::numeric_limits::infinity(); + } + } + + if ( eParam.isText() ) + { + // Remove duplicate texts + std::set valueSet; + for ( const auto& val : eParam.values ) + { + valueSet.insert( val.toString() ); + } + eParam.values.clear(); + for ( const auto& val : valueSet ) + { + eParam.values.push_back( QVariant( val ) ); + } + } + + return eParam; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryEnsembleTools::sortByBinnedVariation( std::vector& parameterVector ) +{ + double minStdDev = std::numeric_limits::infinity(); + double maxStdDev = 0.0; + for ( const auto& paramPair : parameterVector ) + { + double stdDev = paramPair.normalizedStdDeviation(); + if ( stdDev != 0.0 ) + { + minStdDev = std::min( minStdDev, stdDev ); + maxStdDev = std::max( maxStdDev, stdDev ); + } + } + if ( ( maxStdDev - minStdDev ) <= 0.0 ) + { + return; + } + + double delta = ( maxStdDev - minStdDev ) / (float)( RigEnsembleParameter::NR_OF_VARIATION_BINS ); + + std::vector bins; + bins.push_back( 0.0 ); + for ( int i = 0; i < RigEnsembleParameter::NR_OF_VARIATION_BINS - 1; ++i ) + { + bins.push_back( minStdDev + ( i + 1 ) * delta ); + } + + for ( RigEnsembleParameter& nameParamPair : parameterVector ) + { + int binNumber = -1; + for ( double bin : bins ) + { + if ( nameParamPair.normalizedStdDeviation() > bin ) + { + binNumber++; + } + } + nameParamPair.variationBin = binNumber; + } + + // Sort by variation bin (highest first) but keep name as sorting parameter when parameters have the same variation + // index + std::stable_sort( parameterVector.begin(), + parameterVector.end(), + []( const RigEnsembleParameter& lhs, const RigEnsembleParameter& rhs ) { return lhs.variationBin > rhs.variationBin; } ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimSummaryEnsembleTools::alphabeticEnsembleParameters( const std::vector& summaryCases ) +{ + std::set paramSet; + for ( RimSummaryCase* rimCase : summaryCases ) + { + if ( rimCase->caseRealizationParameters() != nullptr ) + { + auto ps = rimCase->caseRealizationParameters()->parameters(); + for ( auto p : ps ) + { + paramSet.insert( p.first ); + } + } + } + + std::vector sortedEnsembleParameters; + sortedEnsembleParameters.reserve( paramSet.size() ); + for ( const QString& parameterName : paramSet ) + { + sortedEnsembleParameters.push_back( RimSummaryEnsembleTools::createEnsembleParameter( summaryCases, parameterName ) ); + } + return sortedEnsembleParameters; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector + RimSummaryEnsembleTools::createVariationSortedEnsembleParameters( const std::vector& summaryCases ) +{ + std::set paramSet; + for ( RimSummaryCase* rimCase : summaryCases ) + { + if ( rimCase->caseRealizationParameters() != nullptr ) + { + auto ps = rimCase->caseRealizationParameters()->parameters(); + for ( const auto& p : ps ) + { + paramSet.insert( p.first ); + } + } + } + std::vector parameters; + parameters.reserve( paramSet.size() ); + for ( const QString& parameterName : paramSet ) + { + auto ensembleParameter = RimSummaryEnsembleTools::createEnsembleParameter( summaryCases, parameterName ); + parameters.push_back( ensembleParameter ); + } + RimSummaryEnsembleTools::sortByBinnedVariation( parameters ); + + return parameters; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void clearEnsembleParametersHashes( const std::vector& summaryCases ) +{ + for ( auto sumCase : summaryCases ) + { + auto crp = sumCase->caseRealizationParameters(); + if ( crp ) crp->clearParametersHash(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RimSummaryEnsembleTools::calculateEnsembleParametersIntersectionHash( const std::vector& summaryCases ) +{ + clearEnsembleParametersHashes( summaryCases ); + + // Find ensemble parameters intersection + std::set paramNames; + + for ( size_t i = 0; i < summaryCases.size(); i++ ) + { + auto crp = summaryCases[i]->caseRealizationParameters(); + if ( !crp ) continue; + + auto caseParamNames = crp->parameterNames(); + + if ( i == 0 ) + paramNames = caseParamNames; + else + { + std::set newIntersection; + std::set_intersection( paramNames.begin(), + paramNames.end(), + caseParamNames.begin(), + caseParamNames.end(), + std::inserter( newIntersection, newIntersection.end() ) ); + + if ( paramNames.size() != newIntersection.size() ) paramNames = newIntersection; + } + } + + for ( auto sumCase : summaryCases ) + { + auto crp = sumCase->caseRealizationParameters(); + if ( crp ) crp->calculateParametersHash( paramNames ); + } + + size_t commonAddressCount = 0; + + // Find common addess count + for ( const auto sumCase : summaryCases ) + { + const auto reader = sumCase->summaryReader(); + if ( !reader ) continue; + auto currAddrCount = reader->allResultAddresses().size(); + + if ( commonAddressCount == 0 ) + { + commonAddressCount = currAddrCount; + } + else + { + if ( currAddrCount != commonAddressCount ) + { + commonAddressCount = 0; + break; + } + } + } + + return commonAddressCount; +} diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsembleTools.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsembleTools.h new file mode 100644 index 0000000000..9439ad74a4 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsembleTools.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor 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. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +#include +#include + +class RimSummaryCase; +class RigEnsembleParameter; + +namespace RimSummaryEnsembleTools +{ +std::set wellsWithRftData( const std::vector& summaryCases ); + +RigEnsembleParameter createEnsembleParameter( const std::vector& summaryCases, const QString& paramName ); +void sortByBinnedVariation( std::vector& parameterVector ); +std::vector alphabeticEnsembleParameters( const std::vector& summaryCases ); +std::vector createVariationSortedEnsembleParameters( const std::vector& summaryCases ); + +size_t calculateEnsembleParametersIntersectionHash( const std::vector& summaryCases ); + +} // namespace RimSummaryEnsembleTools diff --git a/ApplicationLibCode/UnitTests/RimSummaryCaseCollection-Test.cpp b/ApplicationLibCode/UnitTests/RimSummaryCaseCollection-Test.cpp index 798c6f164a..84943ba3d9 100644 --- a/ApplicationLibCode/UnitTests/RimSummaryCaseCollection-Test.cpp +++ b/ApplicationLibCode/UnitTests/RimSummaryCaseCollection-Test.cpp @@ -1,12 +1,10 @@ #include "gtest/gtest.h" #include "RigEnsembleParameter.h" -#include "RimSummaryCaseCollection.h" +#include "RimSummaryEnsembleTools.h" #include -#include - class RimSummaryCaseCollection_TESTER { public: @@ -74,7 +72,7 @@ void RimSummaryCaseCollection_TESTER::test1() } size_t previousSize = parameters.size(); - RimSummaryCaseCollection::sortByBinnedVariation( parameters ); + RimSummaryEnsembleTools::sortByBinnedVariation( parameters ); size_t currentSize = parameters.size(); EXPECT_EQ( previousSize, currentSize );