mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Add RimVfpTableData used to represent connection to file and data
Extract data management from RimVfpPlot. Use pointer from RimVfpPlot to RimVfpTableData.
This commit is contained in:
parent
b8391e6f92
commit
ff9b13163a
@ -95,6 +95,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCalculationExpressionsFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicImportWellLogCsvFileFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewViewForGridEnsembleFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewVfpPlotFeature.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@ -193,6 +194,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCalculationExpressionsFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicImportWellLogCsvFileFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewViewForGridEnsembleFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewVfpPlotFeature.cpp
|
||||
)
|
||||
|
||||
if(RESINSIGHT_USE_QT_CHARTS)
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "RimWellPathFractureCollection.h"
|
||||
|
||||
#include "cafPdmUiItem.h"
|
||||
#include "cafPdmUiObjectHandle.h"
|
||||
#include "cafSelectionManager.h"
|
||||
|
||||
#include <QAction>
|
||||
@ -115,6 +116,14 @@ bool RicDeleteSubItemsFeature::hasDeletableSubItems( caf::PdmUiItem* uiItem )
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto collection = dynamic_cast<RimPlotCollection*>( uiItem );
|
||||
if ( collection && collection->plotCount() > 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -227,5 +236,18 @@ void RicDeleteSubItemsFeature::deleteSubItems( bool onlyDeleteUnchecked )
|
||||
if ( proj ) proj->reloadCompletionTypeResultsInAllViews();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto collection = dynamic_cast<RimPlotCollection*>( item );
|
||||
if ( collection )
|
||||
{
|
||||
collection->deleteAllPlots();
|
||||
|
||||
if ( auto objHandle = dynamic_cast<caf::PdmUiObjectHandle*>( item ) )
|
||||
{
|
||||
objHandle->updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "RimMainPlotCollection.h"
|
||||
|
||||
#include "VerticalFlowPerformance/RimVfpDataCollection.h"
|
||||
#include "VerticalFlowPerformance/RimVfpDeck.h"
|
||||
#include "VerticalFlowPerformance/RimVfpPlot.h"
|
||||
#include "VerticalFlowPerformance/RimVfpPlotCollection.h"
|
||||
@ -38,15 +39,6 @@
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicImportVfpDataFeature, "RicImportVfpDataFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicImportVfpDataFeature::isCommandEnabled() const
|
||||
{
|
||||
auto plotColl = caf::firstAncestorOfTypeFromSelectedObject<RimVfpPlotCollection>();
|
||||
return ( plotColl != nullptr );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -83,47 +75,17 @@ void RicImportVfpDataFeature::onActionTriggered( bool isChecked )
|
||||
std::vector<RimVfpPlot*> vfpPlots;
|
||||
std::vector<RimVfpDeck*> vfpDecks;
|
||||
|
||||
auto vfpDataColl = RimVfpDataCollection::instance();
|
||||
|
||||
for ( const auto& fileName : fileNames )
|
||||
{
|
||||
if ( fileName.contains( ".DATA" ) )
|
||||
{
|
||||
auto vfpDeck = vfpPlotColl->addDeck( fileName );
|
||||
vfpDecks.push_back( vfpDeck );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto vfpPlot = new RimVfpPlot();
|
||||
vfpPlot->setFileName( fileName );
|
||||
vfpPlotColl->addPlot( vfpPlot );
|
||||
|
||||
vfpPlots.push_back( vfpPlot );
|
||||
}
|
||||
auto vfpDataSource = vfpDataColl->appendTableDataObject( fileName );
|
||||
auto firstPlot = vfpPlotColl->createAndAppendPlots( vfpDataSource );
|
||||
vfpDataColl->updateAllRequiredEditors();
|
||||
RiuPlotMainWindowTools::onObjectAppended( firstPlot, firstPlot );
|
||||
}
|
||||
|
||||
vfpPlotColl->updateConnectedEditors();
|
||||
|
||||
for ( auto deck : vfpDecks )
|
||||
{
|
||||
deck->loadDataAndUpdate();
|
||||
deck->updateConnectedEditors();
|
||||
}
|
||||
|
||||
for ( auto plot : vfpPlots )
|
||||
{
|
||||
plot->loadDataAndUpdate();
|
||||
}
|
||||
|
||||
RiuPlotMainWindowTools::showPlotMainWindow();
|
||||
|
||||
if ( !vfpPlots.empty() )
|
||||
{
|
||||
RiuPlotMainWindowTools::onObjectAppended( vfpPlots.front() );
|
||||
}
|
||||
|
||||
if ( !vfpDecks.empty() )
|
||||
{
|
||||
RiuPlotMainWindowTools::onObjectAppended( vfpDecks.front() );
|
||||
}
|
||||
vfpPlotColl->updateAllRequiredEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -28,7 +28,6 @@ class RicImportVfpDataFeature : public caf::CmdFeature
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
private:
|
||||
bool isCommandEnabled() const override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
};
|
||||
|
59
ApplicationLibCode/Commands/RicNewVfpPlotFeature.cpp
Normal file
59
ApplicationLibCode/Commands/RicNewVfpPlotFeature.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RicNewVfpPlotFeature.h"
|
||||
|
||||
#include "RimMainPlotCollection.h"
|
||||
|
||||
#include "VerticalFlowPerformance/RimVfpDataCollection.h"
|
||||
#include "VerticalFlowPerformance/RimVfpPlotCollection.h"
|
||||
#include "VerticalFlowPerformance/RimVfpTableData.h"
|
||||
|
||||
#include "cafSelectionManagerTools.h"
|
||||
|
||||
#include "RiuPlotMainWindowTools.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicNewVfpPlotFeature, "RicNewVfpPlotFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewVfpPlotFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
RimVfpPlotCollection* vfpPlotColl = RimMainPlotCollection::current()->vfpPlotCollection();
|
||||
if ( !vfpPlotColl ) return;
|
||||
|
||||
auto selectedTableData = caf::selectedObjectsByTypeStrict<RimVfpTableData*>();
|
||||
for ( auto tableData : selectedTableData )
|
||||
{
|
||||
RimVfpPlot* firstPlot = vfpPlotColl->createAndAppendPlots( tableData );
|
||||
vfpPlotColl->updateConnectedEditors();
|
||||
RiuPlotMainWindowTools::onObjectAppended( firstPlot, firstPlot );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewVfpPlotFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
actionToSetup->setText( "Create VFP Plot" );
|
||||
actionToSetup->setIcon( QIcon( ":/VfpPlot.svg" ) );
|
||||
}
|
33
ApplicationLibCode/Commands/RicNewVfpPlotFeature.h
Normal file
33
ApplicationLibCode/Commands/RicNewVfpPlotFeature.h
Normal file
@ -0,0 +1,33 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafCmdFeature.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicNewVfpPlotFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
private:
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
};
|
@ -44,10 +44,7 @@ bool RicDeleteSubPlotFeature::isCommandEnabled() const
|
||||
{
|
||||
if ( RicWellLogPlotCurveFeatureImpl::parentWellAllocationPlot() ) return false;
|
||||
|
||||
std::vector<RimPlot*> selection;
|
||||
getSelection( selection );
|
||||
|
||||
return ( !selection.empty() );
|
||||
return isAnyDeletablePlotSelected();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -150,3 +147,23 @@ void RicDeleteSubPlotFeature::getSelection( std::vector<RimPlot*>& selection ) c
|
||||
caf::SelectionManager::instance()->objectsByType( &selection );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicDeleteSubPlotFeature::isAnyDeletablePlotSelected() const
|
||||
{
|
||||
std::vector<RimPlot*> selection;
|
||||
getSelection( selection );
|
||||
|
||||
for ( RimPlot* plot : selection )
|
||||
{
|
||||
if ( !plot ) continue;
|
||||
|
||||
RimMultiPlot* multiPlot = plot->firstAncestorOrThisOfType<RimMultiPlot>();
|
||||
RimWellLogPlot* wellLogPlot = plot->firstAncestorOrThisOfType<RimWellLogPlot>();
|
||||
if ( multiPlot || wellLogPlot ) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -39,4 +39,5 @@ protected:
|
||||
|
||||
private:
|
||||
void getSelection( std::vector<RimPlot*>& selection ) const;
|
||||
bool isAnyDeletablePlotSelected() const;
|
||||
};
|
||||
|
@ -85,94 +85,6 @@ Opm::VFPProdTable createProductionTable( const Opm::DeckKeyword& keyword )
|
||||
return { keyword, gaslift_opt_active, unitSystem };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<Opm::VFPInjTable> extractVfpInjectionTables( const std::string& filename )
|
||||
{
|
||||
std::vector<Opm::VFPInjTable> tables;
|
||||
|
||||
try
|
||||
{
|
||||
Opm::Parser parser( false );
|
||||
const ::Opm::ParserKeywords::VFPINJ kw1;
|
||||
const ::Opm::ParserKeywords::VFPIDIMS kw2;
|
||||
|
||||
parser.addParserKeyword( kw1 );
|
||||
parser.addParserKeyword( kw2 );
|
||||
|
||||
auto deck = parser.parseFile( filename );
|
||||
|
||||
std::string keyword = ::Opm::ParserKeywords::VFPINJ::keywordName;
|
||||
auto keywordList = deck.getKeywordList( keyword );
|
||||
for ( auto kw : keywordList )
|
||||
{
|
||||
auto table = createInjectionTable( *kw );
|
||||
tables.push_back( table );
|
||||
}
|
||||
}
|
||||
catch ( Opm::OpmInputError& e )
|
||||
{
|
||||
QString text = QString( "Error detected when parsing '%1'. Imported data might be missing or incomplete.\n%2" )
|
||||
.arg( QString::fromStdString( filename ) )
|
||||
.arg( QString::fromStdString( e.what() ) );
|
||||
|
||||
RiaLogging::warning( text );
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
QString text =
|
||||
QString( "Error detected when parsing '%1'. Imported data might be missing or incomplete." ).arg( QString::fromStdString( filename ) );
|
||||
|
||||
RiaLogging::warning( text );
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<Opm::VFPProdTable> extractVfpProductionTables( const std::string& filename )
|
||||
{
|
||||
std::vector<Opm::VFPProdTable> tables;
|
||||
|
||||
try
|
||||
{
|
||||
Opm::Parser parser( false );
|
||||
const ::Opm::ParserKeywords::VFPPROD kw1;
|
||||
|
||||
parser.addParserKeyword( kw1 );
|
||||
|
||||
auto deck = parser.parseFile( filename );
|
||||
|
||||
std::string keyword = ::Opm::ParserKeywords::VFPPROD::keywordName;
|
||||
auto keywordList = deck.getKeywordList( keyword );
|
||||
for ( auto kw : keywordList )
|
||||
{
|
||||
auto table = createProductionTable( *kw );
|
||||
tables.push_back( table );
|
||||
}
|
||||
}
|
||||
catch ( Opm::OpmInputError& e )
|
||||
{
|
||||
QString text = QString( "Error detected when parsing '%1'. Imported data might be missing or incomplete.\n%2" )
|
||||
.arg( QString::fromStdString( filename ) )
|
||||
.arg( QString::fromStdString( e.what() ) );
|
||||
|
||||
RiaLogging::warning( text );
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
QString text =
|
||||
QString( "Error detected when parsing '%1'. Imported data might be missing or incomplete." ).arg( QString::fromStdString( filename ) );
|
||||
|
||||
RiaLogging::warning( text );
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -30,8 +30,6 @@
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
namespace RiaOpmParserTools
|
||||
{
|
||||
std::vector<Opm::VFPInjTable> extractVfpInjectionTables( const std::string& filename );
|
||||
std::vector<Opm::VFPProdTable> extractVfpProductionTables( const std::string& filename );
|
||||
|
||||
std::pair<std::vector<Opm::VFPProdTable>, std::vector<Opm::VFPInjTable>> extractVfpTablesFromDataFile( const std::string& dataDeckFilename );
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "RimWellPathCollection.h"
|
||||
|
||||
#include "Polygons/RimPolygonCollection.h"
|
||||
#include "VerticalFlowPerformance/RimVfpDataCollection.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimOilField, "ResInsightOilField" );
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -93,6 +94,9 @@ RimOilField::RimOilField()
|
||||
ensembleWellLogsCollection = new RimEnsembleWellLogsCollection();
|
||||
polygonCollection = new RimPolygonCollection();
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &vfpDataCollection, "VfpDataCollection", "VFP Data" );
|
||||
vfpDataCollection = new RimVfpDataCollection();
|
||||
|
||||
m_fractureTemplateCollection_OBSOLETE = new RimFractureTemplateCollection;
|
||||
m_fractureTemplateCollection_OBSOLETE.xmlCapability()->setIOWritable( false );
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ class RimEnsembleWellLogsCollection;
|
||||
class RimPolygonCollection;
|
||||
class RimEclipseViewCollection;
|
||||
class RimEclipseContourMapViewCollection;
|
||||
class RimVfpDataCollection;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
@ -79,6 +80,7 @@ public:
|
||||
caf::PdmChildField<RimEnsembleWellLogsCollection*> ensembleWellLogsCollection;
|
||||
caf::PdmChildField<RimPolygonCollection*> polygonCollection;
|
||||
caf::PdmChildField<RimEclipseContourMapViewCollection*> eclipseContourMapCollection;
|
||||
caf::PdmChildField<RimVfpDataCollection*> vfpDataCollection;
|
||||
|
||||
protected:
|
||||
void initAfterRead() override;
|
||||
|
@ -99,6 +99,8 @@
|
||||
#include "RimWellLogPlotCollection.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPathCollection.h"
|
||||
|
||||
#include "VerticalFlowPerformance/RimVfpDataCollection.h"
|
||||
#include "VerticalFlowPerformance/RimVfpPlotCollection.h"
|
||||
|
||||
#include "Tools/RiaVariableMapper.h"
|
||||
@ -1458,6 +1460,10 @@ void RimProject::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, Q
|
||||
{
|
||||
uiTreeOrdering.add( oilField->ensembleWellLogsCollection() );
|
||||
}
|
||||
if ( oilField->vfpDataCollection() )
|
||||
{
|
||||
uiTreeOrdering.add( oilField->vfpDataCollection() );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( uiConfigName == "PlotWindow.Scripts" || uiConfigName == "MainWindow.Scripts" )
|
||||
|
@ -1396,17 +1396,10 @@ void RimSummaryCurve::updateTimeAnnotations()
|
||||
void RimSummaryCurve::updateLegendEntryVisibilityNoPlotUpdate()
|
||||
{
|
||||
if ( !m_plotCurve ) return;
|
||||
|
||||
auto ensembleCurveSet = firstAncestorOrThisOfType<RimEnsembleCurveSet>();
|
||||
if ( ensembleCurveSet )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ( !firstAncestorOrThisOfType<RimEnsembleCurveSet>() ) return;
|
||||
|
||||
bool showLegendInPlot = m_showLegend();
|
||||
|
||||
auto summaryPlot = firstAncestorOrThisOfType<RimSummaryPlot>();
|
||||
if ( summaryPlot )
|
||||
if ( auto summaryPlot = firstAncestorOrThisOfType<RimSummaryPlot>() )
|
||||
{
|
||||
bool anyCalculated = false;
|
||||
for ( const auto c : summaryPlot->summaryCurves() )
|
||||
|
@ -3,6 +3,8 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpDeck.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpPlotCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpTableData.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpDataCollection.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@ -10,6 +12,8 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpDefines.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpPlot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpPlotCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpTableData.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimVfpDataCollection.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
@ -0,0 +1,73 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimVfpDataCollection.h"
|
||||
|
||||
#include "RimOilField.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimVfpPlotCollection.h"
|
||||
#include "RimVfpTableData.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimVfpDataCollection, "RimVfpDataCollection" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDataCollection::RimVfpDataCollection()
|
||||
{
|
||||
CAF_PDM_InitObject( "VFP Data", ":/VfpPlotCollection.svg" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_vfpTableData, "VfpPlots", "Vertical Flow Performance Data" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDataCollection* RimVfpDataCollection::instance()
|
||||
{
|
||||
return RimProject::current()->activeOilField()->vfpDataCollection();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpTableData* RimVfpDataCollection::appendTableDataObject( const QString& fileName )
|
||||
{
|
||||
auto* vfpTableData = new RimVfpTableData();
|
||||
vfpTableData->setFileName( fileName );
|
||||
|
||||
m_vfpTableData.push_back( vfpTableData );
|
||||
|
||||
return vfpTableData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimVfpTableData*> RimVfpDataCollection::vfpTableData() const
|
||||
{
|
||||
return m_vfpTableData.childrenByType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpDataCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
|
||||
{
|
||||
RimVfpPlotCollection::addImportItems( menuBuilder );
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
class RimVfpTableData;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimVfpDataCollection : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimVfpDataCollection();
|
||||
|
||||
static RimVfpDataCollection* instance();
|
||||
|
||||
RimVfpTableData* appendTableDataObject( const QString& fileName );
|
||||
std::vector<RimVfpTableData*> vfpTableData() const;
|
||||
|
||||
private:
|
||||
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
|
||||
|
||||
private:
|
||||
caf::PdmChildArrayField<RimVfpTableData*> m_vfpTableData;
|
||||
};
|
@ -18,14 +18,14 @@
|
||||
|
||||
#include "RimVfpDeck.h"
|
||||
|
||||
#include "RiaOpmParserTools.h"
|
||||
#include "RigVfpTables.h"
|
||||
|
||||
#include "RimVfpDataCollection.h"
|
||||
#include "RimVfpPlotCollection.h"
|
||||
#include "RimVfpTableData.h"
|
||||
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimVfpDeck, "RimVfpDeck" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -35,7 +35,7 @@ RimVfpDeck::RimVfpDeck()
|
||||
{
|
||||
CAF_PDM_InitObject( "VFP Plot", ":/VfpPlot.svg" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_filePath, "FilePath", "File Path" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_vfpTableData, "VfpTableData", "VFP Data Source" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_vfpPlotCollection, "VfpPlotCollection", "Plot Collection" );
|
||||
m_vfpPlotCollection = new RimVfpPlotCollection();
|
||||
|
||||
@ -45,9 +45,9 @@ RimVfpDeck::RimVfpDeck()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpDeck::setFileName( const QString& filename )
|
||||
void RimVfpDeck::setDataSource( RimVfpTableData* tableData )
|
||||
{
|
||||
m_filePath = filename;
|
||||
m_vfpTableData = tableData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -57,50 +57,40 @@ void RimVfpDeck::loadDataAndUpdate()
|
||||
{
|
||||
updateObjectName();
|
||||
|
||||
auto createRimVfpPlot = [&]() -> RimVfpPlot*
|
||||
{
|
||||
auto plot = new RimVfpPlot();
|
||||
plot->setFileName( m_filePath().path() );
|
||||
return plot;
|
||||
};
|
||||
|
||||
std::vector<RimVfpPlot*> currentPlots = m_vfpPlotCollection->plots();
|
||||
|
||||
auto [vfpProdTables, vfpInjTables] = RiaOpmParserTools::extractVfpTablesFromDataFile( m_filePath().path().toStdString() );
|
||||
for ( const auto& prodTable : vfpProdTables )
|
||||
if ( m_vfpTableData )
|
||||
{
|
||||
RimVfpPlot* plot = m_vfpPlotCollection->plotForTableNumber( prodTable.getTableNum() );
|
||||
if ( !plot )
|
||||
{
|
||||
plot = createRimVfpPlot();
|
||||
m_vfpPlotCollection->addPlot( plot );
|
||||
}
|
||||
else
|
||||
{
|
||||
std::erase( currentPlots, plot );
|
||||
}
|
||||
plot->setProductionTable( prodTable );
|
||||
plot->setDataIsImportedExternally( true );
|
||||
plot->setDeletable( false );
|
||||
plot->loadDataAndUpdate();
|
||||
}
|
||||
m_vfpTableData->ensureDataIsImported();
|
||||
|
||||
for ( const auto& injTable : vfpInjTables )
|
||||
{
|
||||
RimVfpPlot* plot = m_vfpPlotCollection->plotForTableNumber( injTable.getTableNum() );
|
||||
if ( !plot )
|
||||
if ( m_vfpTableData->vfpTables() )
|
||||
{
|
||||
plot = createRimVfpPlot();
|
||||
m_vfpPlotCollection->addPlot( plot );
|
||||
auto tables = m_vfpTableData->vfpTables();
|
||||
|
||||
auto allTableNumbers = tables->productionTableNumbers();
|
||||
auto injTableNumbers = tables->injectionTableNumbers();
|
||||
allTableNumbers.insert( allTableNumbers.end(), injTableNumbers.begin(), injTableNumbers.end() );
|
||||
|
||||
for ( const auto& number : allTableNumbers )
|
||||
{
|
||||
RimVfpPlot* plot = m_vfpPlotCollection->plotForTableNumber( number );
|
||||
if ( !plot )
|
||||
{
|
||||
plot = new RimVfpPlot();
|
||||
plot->setDataSource( m_vfpTableData );
|
||||
plot->setTableNumber( number );
|
||||
plot->initializeObject();
|
||||
|
||||
m_vfpPlotCollection->addPlot( plot );
|
||||
}
|
||||
else
|
||||
{
|
||||
std::erase( currentPlots, plot );
|
||||
}
|
||||
plot->setDeletable( false );
|
||||
plot->loadDataAndUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::erase( currentPlots, plot );
|
||||
}
|
||||
plot->setInjectionTable( injTable );
|
||||
plot->setDataIsImportedExternally( true );
|
||||
plot->setDeletable( false );
|
||||
plot->loadDataAndUpdate();
|
||||
}
|
||||
|
||||
for ( auto plotToDelete : currentPlots )
|
||||
@ -109,6 +99,15 @@ void RimVfpDeck::loadDataAndUpdate()
|
||||
delete plotToDelete;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimVfpPlot*> RimVfpDeck::plots() const
|
||||
{
|
||||
return m_vfpPlotCollection->plots();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -127,13 +126,30 @@ void RimVfpDeck::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, Q
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpDeck::updateObjectName()
|
||||
{
|
||||
QString name = "VFP Plots";
|
||||
QString name = "VFP Deck";
|
||||
|
||||
QFileInfo fileInfo( m_filePath().path() );
|
||||
auto fileName = fileInfo.fileName();
|
||||
if ( !fileName.isEmpty() )
|
||||
if ( m_vfpTableData )
|
||||
{
|
||||
name += " - " + fileName;
|
||||
name = m_vfpTableData->name();
|
||||
}
|
||||
|
||||
setName( name );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimVfpDeck::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
if ( fieldNeedingOptions == &m_vfpTableData )
|
||||
{
|
||||
RimVfpDataCollection* vfpDataCollection = RimVfpDataCollection::instance();
|
||||
for ( auto table : vfpDataCollection->vfpTableData() )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( table->name(), table ) );
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
@ -21,8 +21,11 @@
|
||||
#include "RimNamedObject.h"
|
||||
|
||||
#include "cafFilePath.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
class RimVfpPlotCollection;
|
||||
class RimVfpTableData;
|
||||
class RimVfpPlot;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// RimVfpDeck parses a deck file (*.DATA) containing VFP data and creates a collection of VFP plots.
|
||||
@ -34,14 +37,17 @@ class RimVfpDeck : public RimNamedObject
|
||||
public:
|
||||
RimVfpDeck();
|
||||
|
||||
void setFileName( const QString& filename );
|
||||
void setDataSource( RimVfpTableData* tableData );
|
||||
void loadDataAndUpdate();
|
||||
|
||||
private:
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
void updateObjectName();
|
||||
std::vector<RimVfpPlot*> plots() const;
|
||||
|
||||
private:
|
||||
caf::PdmField<caf::FilePath> m_filePath;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
void updateObjectName();
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimVfpTableData*> m_vfpTableData;
|
||||
caf::PdmChildField<RimVfpPlotCollection*> m_vfpPlotCollection;
|
||||
};
|
||||
|
@ -19,22 +19,27 @@
|
||||
#include "RimVfpPlot.h"
|
||||
|
||||
#include "RiaColorTables.h"
|
||||
#include "RiaColorTools.h"
|
||||
#include "RiaEclipseUnitTools.h"
|
||||
#include "RiaOpmParserTools.h"
|
||||
|
||||
#include "RigVfpTables.h"
|
||||
|
||||
#include "RimPlotAxisProperties.h"
|
||||
#include "RimPlotCurve.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimVfpDataCollection.h"
|
||||
#include "RimVfpDefines.h"
|
||||
#include "RimVfpTableData.h"
|
||||
#include "Tools/RimPlotAxisTools.h"
|
||||
|
||||
#include "RiuContextMenuLauncher.h"
|
||||
#include "RiuPlotCurve.h"
|
||||
#include "RiuPlotWidget.h"
|
||||
#include "RiuQwtCurvePointTracker.h"
|
||||
#include "RiuQwtPlotCurveDefines.h"
|
||||
#include "RiuQwtPlotWheelZoomer.h"
|
||||
#include "RiuQwtPlotWidget.h"
|
||||
|
||||
#include "RiuQwtCurvePointTracker.h"
|
||||
#include "RiuQwtPlotWidget.h"
|
||||
#include "RiuQwtPlotZoomer.h"
|
||||
|
||||
#include "cafPdmUiComboBoxEditor.h"
|
||||
@ -51,39 +56,6 @@
|
||||
//
|
||||
//==================================================================================================
|
||||
|
||||
class VfpPlotData
|
||||
{
|
||||
public:
|
||||
void setXAxisTitle( const QString& xAxisTitle ) { m_xAxisTitle = xAxisTitle; }
|
||||
void setYAxisTitle( const QString& yAxisTitle ) { m_yAxisTitle = yAxisTitle; }
|
||||
|
||||
const QString& xAxisTitle() const { return m_xAxisTitle; }
|
||||
const QString& yAxisTitle() const { return m_yAxisTitle; }
|
||||
|
||||
void appendCurve( const QString& curveTitle, const std::vector<double>& xData, const std::vector<double>& yData )
|
||||
{
|
||||
m_curveTitles.push_back( curveTitle );
|
||||
m_xData.push_back( xData );
|
||||
m_yData.push_back( yData );
|
||||
}
|
||||
|
||||
const QString& curveTitle( size_t idx ) const { return m_curveTitles[idx]; }
|
||||
|
||||
size_t size() const { return m_xData.size(); }
|
||||
|
||||
size_t curveSize( size_t idx ) const { return m_xData[idx].size(); }
|
||||
|
||||
const std::vector<double>& xData( size_t idx ) const { return m_xData[idx]; }
|
||||
const std::vector<double>& yData( size_t idx ) const { return m_yData[idx]; }
|
||||
|
||||
private:
|
||||
QString m_xAxisTitle;
|
||||
QString m_yAxisTitle;
|
||||
std::vector<QString> m_curveTitles;
|
||||
std::vector<std::vector<double>> m_xData;
|
||||
std::vector<std::vector<double>> m_yData;
|
||||
};
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimVfpPlot, "VfpPlot" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -97,7 +69,10 @@ RimVfpPlot::RimVfpPlot()
|
||||
CAF_PDM_InitField( &m_plotTitle, "PlotTitle", QString( "VFP Plot" ), "Plot Title" );
|
||||
m_plotTitle.uiCapability()->setUiHidden( true );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_filePath, "FilePath", "File Path" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_filePath_OBSOLETE, "FilePath", "File Path" );
|
||||
m_filePath_OBSOLETE.xmlCapability()->setIOWritable( false );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_vfpTableData, "VfpTableData", "VFP Data Source" );
|
||||
|
||||
caf::AppEnum<RimVfpDefines::TableType> defaultTableType = RimVfpDefines::TableType::INJECTION;
|
||||
CAF_PDM_InitField( &m_tableType, "TableType", defaultTableType, "Table Type" );
|
||||
@ -156,6 +131,8 @@ RimVfpPlot::RimVfpPlot()
|
||||
connectAxisSignals( m_xAxisProperties() );
|
||||
connectAxisSignals( m_yAxisProperties() );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_plotCurves, "PlotCurves", "Curves" );
|
||||
|
||||
m_showWindow = true;
|
||||
m_showPlotLegends = true;
|
||||
m_dataIsImportedExternally = false;
|
||||
@ -163,6 +140,8 @@ RimVfpPlot::RimVfpPlot()
|
||||
setAsPlotMdiWindow();
|
||||
|
||||
setDeletable( true );
|
||||
|
||||
m_vfpTables = std::make_unique<RigVfpTables>();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -177,9 +156,43 @@ RimVfpPlot::~RimVfpPlot()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::setFileName( const QString& filename )
|
||||
void RimVfpPlot::setDataSource( RimVfpTableData* vfpTableData )
|
||||
{
|
||||
m_filePath = filename;
|
||||
m_vfpTableData = vfpTableData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::setTableNumber( int tableNumber )
|
||||
{
|
||||
m_tableNumber = tableNumber;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::initializeObject()
|
||||
{
|
||||
if ( !vfpTables() ) return;
|
||||
|
||||
auto tableNumber = m_tableNumber();
|
||||
|
||||
// Always use the available table number if only one table is available
|
||||
auto prodTableNumbers = vfpTables()->productionTableNumbers();
|
||||
auto injTableNumbers = vfpTables()->injectionTableNumbers();
|
||||
|
||||
if ( prodTableNumbers.size() == 1 && injTableNumbers.empty() )
|
||||
{
|
||||
tableNumber = prodTableNumbers.front();
|
||||
}
|
||||
else if ( injTableNumbers.size() == 1 && prodTableNumbers.empty() )
|
||||
{
|
||||
tableNumber = injTableNumbers.front();
|
||||
}
|
||||
|
||||
auto table = vfpTables()->getTableInitialData( tableNumber );
|
||||
initializeFromInitData( table );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -260,72 +273,35 @@ void RimVfpPlot::updateLegend()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimVfpPlot::asciiDataForPlotExport() const
|
||||
{
|
||||
QString filePath = m_filePath.v().path();
|
||||
if ( !filePath.isEmpty() )
|
||||
if ( !vfpTables() ) return {};
|
||||
|
||||
auto tableText = vfpTables()->asciiDataForTable( m_tableNumber(),
|
||||
m_primaryVariable(),
|
||||
m_familyVariable(),
|
||||
m_interpolatedVariable(),
|
||||
m_flowingPhase(),
|
||||
tableSelection() );
|
||||
|
||||
QString wellName;
|
||||
|
||||
if ( m_vfpTableData )
|
||||
{
|
||||
QFileInfo fi( filePath );
|
||||
QString wellName = fi.baseName();
|
||||
|
||||
VfpPlotData plotData;
|
||||
if ( m_tableType() == RimVfpDefines::TableType::PRODUCTION )
|
||||
wellName = m_vfpTableData->name();
|
||||
}
|
||||
else
|
||||
{
|
||||
QString filePath = m_filePath_OBSOLETE.v().path();
|
||||
if ( !filePath.isEmpty() )
|
||||
{
|
||||
if ( m_prodTable )
|
||||
{
|
||||
populatePlotData( *m_prodTable, m_primaryVariable(), m_familyVariable(), m_interpolatedVariable(), m_flowingPhase(), plotData );
|
||||
}
|
||||
QFileInfo fi( filePath );
|
||||
QString wellName = fi.baseName();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_injectionTable )
|
||||
{
|
||||
populatePlotData( *m_injectionTable, m_interpolatedVariable(), m_flowingPhase(), plotData );
|
||||
}
|
||||
}
|
||||
|
||||
QString plotTitle =
|
||||
generatePlotTitle( wellName, m_tableNumber(), m_tableType(), m_interpolatedVariable(), m_primaryVariable(), m_familyVariable() );
|
||||
|
||||
QString dataText;
|
||||
|
||||
if ( plotData.size() > 0 )
|
||||
{
|
||||
// The curves should have same dimensions
|
||||
const size_t curveSize = plotData.curveSize( 0 );
|
||||
|
||||
// Generate the headers for the columns
|
||||
// First column is the primary variable
|
||||
QString columnTitleLine( plotData.xAxisTitle() );
|
||||
|
||||
// Then one column per "family"
|
||||
for ( size_t s = 0; s < plotData.size(); s++ )
|
||||
{
|
||||
columnTitleLine.append( QString( "\t%1" ).arg( plotData.curveTitle( s ) ) );
|
||||
}
|
||||
columnTitleLine.append( "\n" );
|
||||
|
||||
dataText.append( columnTitleLine );
|
||||
|
||||
// Add the rows: one row per primary variable value
|
||||
for ( size_t idx = 0; idx < curveSize; idx++ )
|
||||
{
|
||||
QString line;
|
||||
|
||||
// First item on each line is the primary variable
|
||||
line.append( QString( "%1" ).arg( plotData.xData( 0 )[idx] ) );
|
||||
|
||||
for ( size_t s = 0; s < plotData.size(); s++ )
|
||||
{
|
||||
line.append( QString( "\t%1" ).arg( plotData.yData( s )[idx] ) );
|
||||
}
|
||||
dataText.append( line );
|
||||
dataText.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
return QString( "%1\n\n%2" ).arg( plotTitle ).arg( dataText );
|
||||
}
|
||||
|
||||
return {};
|
||||
QString plotTitle =
|
||||
generatePlotTitle( wellName, m_tableNumber(), m_tableType(), m_interpolatedVariable(), m_primaryVariable(), m_familyVariable() );
|
||||
|
||||
return QString( "%1\n\n%2" ).arg( plotTitle ).arg( tableText );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -333,6 +309,13 @@ QString RimVfpPlot::asciiDataForPlotExport() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::reattachAllCurves()
|
||||
{
|
||||
for ( auto curve : m_plotCurves() )
|
||||
{
|
||||
if ( curve->isChecked() )
|
||||
{
|
||||
curve->setParentPlotNoReplot( m_plotWidget );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -340,6 +323,10 @@ void RimVfpPlot::reattachAllCurves()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::detachAllCurves()
|
||||
{
|
||||
for ( auto curve : m_plotCurves() )
|
||||
{
|
||||
curve->detach();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -385,24 +372,6 @@ void RimVfpPlot::zoomAll()
|
||||
updatePlotWidgetFromAxisRanges();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::setProductionTable( const Opm::VFPProdTable& table )
|
||||
{
|
||||
m_prodTable = std::make_unique<Opm::VFPProdTable>( table );
|
||||
m_injectionTable.reset();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::setInjectionTable( const Opm::VFPInjTable& table )
|
||||
{
|
||||
m_prodTable.reset();
|
||||
m_injectionTable = std::make_unique<Opm::VFPInjTable>( table );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -422,8 +391,12 @@ int RimVfpPlot::tableNumber() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::doRemoveFromCollection()
|
||||
void RimVfpPlot::onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& updatedObjects )
|
||||
{
|
||||
detachAllCurves();
|
||||
reattachAllCurves();
|
||||
|
||||
m_plotWidget->scheduleReplot();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -500,57 +473,22 @@ void RimVfpPlot::onLoadDataAndUpdate()
|
||||
return;
|
||||
}
|
||||
|
||||
m_plotWidget->detachItems( RiuPlotWidget::PlotItemType::CURVE );
|
||||
|
||||
updateLegend();
|
||||
|
||||
QString wellName;
|
||||
|
||||
if ( !m_dataIsImportedExternally )
|
||||
if ( vfpTables() )
|
||||
{
|
||||
QString filePath = m_filePath.v().path();
|
||||
if ( !filePath.isEmpty() )
|
||||
{
|
||||
QFileInfo fi( filePath );
|
||||
wellName = fi.baseName();
|
||||
wellName = m_vfpTableData->baseFileName();
|
||||
|
||||
// Try to read the file as an prod table first (most common)
|
||||
const std::vector<Opm::VFPProdTable> tables = RiaOpmParserTools::extractVfpProductionTables( filePath.toStdString() );
|
||||
if ( !tables.empty() )
|
||||
{
|
||||
setProductionTable( tables[0] );
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::vector<Opm::VFPInjTable> tables = RiaOpmParserTools::extractVfpInjectionTables( filePath.toStdString() );
|
||||
if ( !tables.empty() )
|
||||
{
|
||||
setInjectionTable( tables[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto vfpPlotData = vfpTables()->populatePlotData( m_tableNumber(),
|
||||
m_primaryVariable(),
|
||||
m_familyVariable(),
|
||||
m_interpolatedVariable(),
|
||||
m_flowingPhase(),
|
||||
tableSelection() );
|
||||
|
||||
if ( m_prodTable )
|
||||
{
|
||||
auto table = *m_prodTable;
|
||||
m_tableType = RimVfpDefines::TableType::PRODUCTION;
|
||||
m_tableNumber = table.getTableNum();
|
||||
m_referenceDepth = table.getDatumDepth();
|
||||
m_flowingPhase = getFlowingPhaseType( table );
|
||||
m_flowingGasFraction = getFlowingGasFractionType( table );
|
||||
m_flowingWaterFraction = getFlowingWaterFractionType( table );
|
||||
populatePlotWidgetWithCurveData( m_plotWidget, table, m_primaryVariable(), m_familyVariable() );
|
||||
}
|
||||
else if ( m_injectionTable )
|
||||
{
|
||||
auto table = *m_injectionTable;
|
||||
|
||||
m_tableType = RimVfpDefines::TableType::INJECTION;
|
||||
m_tableNumber = table.getTableNum();
|
||||
m_referenceDepth = table.getDatumDepth();
|
||||
m_flowingPhase = getFlowingPhaseType( table );
|
||||
populatePlotWidgetWithCurveData( m_plotWidget, table );
|
||||
populatePlotWidgetWithPlotData( m_plotWidget, vfpPlotData );
|
||||
}
|
||||
|
||||
updatePlotTitle(
|
||||
@ -559,85 +497,18 @@ void RimVfpPlot::onLoadDataAndUpdate()
|
||||
m_plotWidget->setAxisTitleEnabled( RiuPlotAxis::defaultBottom(), true );
|
||||
m_plotWidget->setAxisTitleEnabled( RiuPlotAxis::defaultLeft(), true );
|
||||
|
||||
reattachAllCurves();
|
||||
|
||||
updatePlotWidgetFromAxisRanges();
|
||||
|
||||
m_plotWidget->scheduleReplot();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::populatePlotWidgetWithCurveData( RiuPlotWidget* plotWidget, const Opm::VFPInjTable& table )
|
||||
{
|
||||
VfpPlotData plotData;
|
||||
populatePlotData( table, m_interpolatedVariable(), m_flowingPhase(), plotData );
|
||||
populatePlotWidgetWithPlotData( plotWidget, plotData );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::populatePlotData( const Opm::VFPInjTable& table,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
VfpPlotData& plotData )
|
||||
{
|
||||
QString xAxisTitle = axisTitle( RimVfpDefines::ProductionVariableType::FLOW_RATE, flowingPhase );
|
||||
plotData.setXAxisTitle( xAxisTitle );
|
||||
|
||||
QString yAxisTitle = QString( "%1 %2" ).arg( caf::AppEnum<RimVfpDefines::InterpolatedVariableType>::uiText( interpolatedVariable ),
|
||||
getDisplayUnitWithBracket( RimVfpDefines::ProductionVariableType::THP ) );
|
||||
plotData.setYAxisTitle( yAxisTitle );
|
||||
|
||||
std::vector<double> thpValues = table.getTHPAxis();
|
||||
|
||||
for ( size_t thp = 0; thp < thpValues.size(); thp++ )
|
||||
{
|
||||
size_t numValues = table.getFloAxis().size();
|
||||
std::vector<double> xVals = table.getFloAxis();
|
||||
std::vector<double> yVals( numValues, 0.0 );
|
||||
for ( size_t y = 0; y < numValues; y++ )
|
||||
{
|
||||
yVals[y] = table( thp, y );
|
||||
if ( interpolatedVariable == RimVfpDefines::InterpolatedVariableType::BHP_THP_DIFF )
|
||||
{
|
||||
yVals[y] -= thpValues[thp];
|
||||
}
|
||||
}
|
||||
|
||||
double value = convertToDisplayUnit( thpValues[thp], RimVfpDefines::ProductionVariableType::THP );
|
||||
QString unit = getDisplayUnit( RimVfpDefines::ProductionVariableType::THP );
|
||||
QString title = QString( "%1 [%2]: %3" )
|
||||
.arg( caf::AppEnum<RimVfpDefines::ProductionVariableType>::uiText( RimVfpDefines::ProductionVariableType::THP ) )
|
||||
.arg( unit )
|
||||
.arg( value );
|
||||
|
||||
convertToDisplayUnit( yVals, RimVfpDefines::ProductionVariableType::THP );
|
||||
convertToDisplayUnit( xVals, RimVfpDefines::ProductionVariableType::FLOW_RATE );
|
||||
|
||||
plotData.appendCurve( title, xVals, yVals );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::populatePlotWidgetWithCurveData( RiuPlotWidget* plotWidget,
|
||||
const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable )
|
||||
{
|
||||
VfpPlotData plotData;
|
||||
populatePlotData( table, primaryVariable, familyVariable, m_interpolatedVariable(), m_flowingPhase(), plotData );
|
||||
populatePlotWidgetWithPlotData( plotWidget, plotData );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::populatePlotWidgetWithPlotData( RiuPlotWidget* plotWidget, const VfpPlotData& plotData )
|
||||
{
|
||||
plotWidget->detachItems( RiuPlotWidget::PlotItemType::CURVE );
|
||||
plotWidget->setAxisScale( RiuPlotAxis::defaultBottom(), 0, 1 );
|
||||
plotWidget->setAxisScale( RiuPlotAxis::defaultLeft(), 0, 1 );
|
||||
plotWidget->setAxisAutoScale( RiuPlotAxis::defaultBottom(), true );
|
||||
@ -645,25 +516,45 @@ void RimVfpPlot::populatePlotWidgetWithPlotData( RiuPlotWidget* plotWidget, cons
|
||||
plotWidget->setAxisTitleText( RiuPlotAxis::defaultBottom(), plotData.xAxisTitle() );
|
||||
plotWidget->setAxisTitleText( RiuPlotAxis::defaultLeft(), plotData.yAxisTitle() );
|
||||
|
||||
if ( m_plotCurves.size() != plotData.size() )
|
||||
{
|
||||
detachAllCurves();
|
||||
m_plotCurves.deleteChildren();
|
||||
|
||||
for ( auto idx = 0u; idx < plotData.size(); idx++ )
|
||||
{
|
||||
QColor qtClr = RiaColorTables::summaryCurveDefaultPaletteColors().cycledQColor( idx );
|
||||
|
||||
auto curve = new RimPlotCurve();
|
||||
|
||||
curve->setLineStyle( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID );
|
||||
curve->setLineThickness( 2 );
|
||||
curve->setColor( RiaColorTools::fromQColorTo3f( qtClr ) );
|
||||
curve->setSymbol( RiuPlotCurveSymbol::SYMBOL_ELLIPSE );
|
||||
curve->setSymbolSize( 6 );
|
||||
|
||||
m_plotCurves.push_back( curve );
|
||||
}
|
||||
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
auto plotCurves = m_plotCurves.childrenByType();
|
||||
|
||||
for ( auto idx = 0u; idx < plotData.size(); idx++ )
|
||||
{
|
||||
QColor qtClr = RiaColorTables::summaryCurveDefaultPaletteColors().cycledQColor( idx );
|
||||
RiuPlotCurve* curve = m_plotWidget->createPlotCurve( nullptr, plotData.curveTitle( idx ) );
|
||||
auto curve = plotCurves[idx];
|
||||
if ( !curve ) continue;
|
||||
|
||||
curve->setAppearance( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID,
|
||||
RiuQwtPlotCurveDefines::CurveInterpolationEnum::INTERPOLATION_POINT_TO_POINT,
|
||||
2,
|
||||
qtClr );
|
||||
|
||||
RiuPlotCurveSymbol* symbol = curve->createSymbol( RiuPlotCurveSymbol::PointSymbolEnum::SYMBOL_ELLIPSE );
|
||||
symbol->setColor( qtClr );
|
||||
symbol->setSize( 6, 6 );
|
||||
curve->setSymbol( symbol );
|
||||
|
||||
bool useLogarithmicScale = false;
|
||||
curve->setSamplesFromXValuesAndYValues( plotData.xData( idx ), plotData.yData( idx ), useLogarithmicScale );
|
||||
curve->attachToPlot( plotWidget );
|
||||
curve->showInPlot();
|
||||
curve->setCustomName( plotData.curveTitle( idx ) );
|
||||
curve->setParentPlotNoReplot( plotWidget );
|
||||
if ( curve->plotCurve() )
|
||||
{
|
||||
bool useLogarithmicScale = false;
|
||||
curve->plotCurve()->setSamplesFromXValuesAndYValues( plotData.xData( idx ), plotData.yData( idx ), useLogarithmicScale );
|
||||
}
|
||||
curve->updateCurveAppearance();
|
||||
curve->appearanceChanged.connect( this, &RimVfpPlot::curveAppearanceChanged );
|
||||
}
|
||||
}
|
||||
|
||||
@ -754,66 +645,41 @@ void RimVfpPlot::onPlotZoomed()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::populatePlotData( const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
VfpPlotData& plotData ) const
|
||||
void RimVfpPlot::curveAppearanceChanged( const caf::SignalEmitter* emitter )
|
||||
{
|
||||
QString xAxisTitle = axisTitle( primaryVariable, flowingPhase );
|
||||
plotData.setXAxisTitle( xAxisTitle );
|
||||
scheduleReplot();
|
||||
}
|
||||
|
||||
QString yAxisTitle = QString( "%1 %2" ).arg( caf::AppEnum<RimVfpDefines::InterpolatedVariableType>::uiText( interpolatedVariable ),
|
||||
getDisplayUnitWithBracket( RimVfpDefines::ProductionVariableType::THP ) );
|
||||
plotData.setYAxisTitle( yAxisTitle );
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::initializeFromInitData( const VfpTableInitialData& table )
|
||||
{
|
||||
m_tableType = table.isProductionTable ? RimVfpDefines::TableType::PRODUCTION : RimVfpDefines::TableType::INJECTION;
|
||||
m_tableNumber = table.tableNumber;
|
||||
m_referenceDepth = table.datumDepth;
|
||||
m_flowingPhase = table.flowingPhase;
|
||||
m_flowingGasFraction = table.gasFraction;
|
||||
m_flowingWaterFraction = table.waterFraction;
|
||||
}
|
||||
|
||||
size_t numFamilyValues = getProductionTableData( table, familyVariable ).size();
|
||||
for ( size_t familyIdx = 0; familyIdx < numFamilyValues; familyIdx++ )
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const RigVfpTables* RimVfpPlot::vfpTables() const
|
||||
{
|
||||
if ( m_vfpTableData )
|
||||
{
|
||||
std::vector<double> primaryAxisValues = getProductionTableData( table, primaryVariable );
|
||||
std::vector<double> familyVariableValues = getProductionTableData( table, familyVariable );
|
||||
std::vector<double> thpValues = getProductionTableData( table, RimVfpDefines::ProductionVariableType::THP );
|
||||
|
||||
size_t numValues = primaryAxisValues.size();
|
||||
std::vector<double> yVals( numValues, 0.0 );
|
||||
|
||||
for ( size_t y = 0; y < numValues; y++ )
|
||||
{
|
||||
size_t wfr_idx =
|
||||
getVariableIndex( table, RimVfpDefines::ProductionVariableType::WATER_CUT, primaryVariable, y, familyVariable, familyIdx );
|
||||
size_t gfr_idx =
|
||||
getVariableIndex( table, RimVfpDefines::ProductionVariableType::GAS_LIQUID_RATIO, primaryVariable, y, familyVariable, familyIdx );
|
||||
size_t alq_idx = getVariableIndex( table,
|
||||
RimVfpDefines::ProductionVariableType::ARTIFICIAL_LIFT_QUANTITY,
|
||||
primaryVariable,
|
||||
y,
|
||||
familyVariable,
|
||||
familyIdx );
|
||||
size_t flo_idx =
|
||||
getVariableIndex( table, RimVfpDefines::ProductionVariableType::FLOW_RATE, primaryVariable, y, familyVariable, familyIdx );
|
||||
size_t thp_idx =
|
||||
getVariableIndex( table, RimVfpDefines::ProductionVariableType::THP, primaryVariable, y, familyVariable, familyIdx );
|
||||
|
||||
yVals[y] = table( thp_idx, wfr_idx, gfr_idx, alq_idx, flo_idx );
|
||||
if ( m_interpolatedVariable == RimVfpDefines::InterpolatedVariableType::BHP_THP_DIFF )
|
||||
{
|
||||
yVals[y] -= thpValues[thp_idx];
|
||||
}
|
||||
}
|
||||
|
||||
double familyValue = convertToDisplayUnit( familyVariableValues[familyIdx], familyVariable );
|
||||
QString familyUnit = getDisplayUnit( familyVariable );
|
||||
QString familyTitle = QString( "%1: %2 %3" )
|
||||
.arg( caf::AppEnum<RimVfpDefines::ProductionVariableType>::uiText( familyVariable ) )
|
||||
.arg( familyValue )
|
||||
.arg( familyUnit );
|
||||
|
||||
convertToDisplayUnit( yVals, RimVfpDefines::ProductionVariableType::THP );
|
||||
convertToDisplayUnit( primaryAxisValues, primaryVariable );
|
||||
|
||||
plotData.appendCurve( familyTitle, primaryAxisValues, yVals );
|
||||
m_vfpTableData->ensureDataIsImported();
|
||||
return m_vfpTableData->vfpTables();
|
||||
}
|
||||
|
||||
if ( m_vfpTables )
|
||||
{
|
||||
return m_vfpTables.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -868,64 +734,12 @@ QString RimVfpPlot::getDisplayUnit( RimVfpDefines::ProductionVariableType variab
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimVfpPlot::getProductionTableData( const Opm::VFPProdTable& table, RimVfpDefines::ProductionVariableType variableType ) const
|
||||
{
|
||||
std::vector<double> xVals;
|
||||
if ( variableType == RimVfpDefines::ProductionVariableType::WATER_CUT )
|
||||
{
|
||||
xVals = table.getWFRAxis();
|
||||
}
|
||||
else if ( variableType == RimVfpDefines::ProductionVariableType::GAS_LIQUID_RATIO )
|
||||
{
|
||||
xVals = table.getGFRAxis();
|
||||
}
|
||||
else if ( variableType == RimVfpDefines::ProductionVariableType::ARTIFICIAL_LIFT_QUANTITY )
|
||||
{
|
||||
xVals = table.getALQAxis();
|
||||
}
|
||||
else if ( variableType == RimVfpDefines::ProductionVariableType::FLOW_RATE )
|
||||
{
|
||||
xVals = table.getFloAxis();
|
||||
}
|
||||
else if ( variableType == RimVfpDefines::ProductionVariableType::THP )
|
||||
{
|
||||
xVals = table.getTHPAxis();
|
||||
}
|
||||
|
||||
return xVals;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RimVfpPlot::getVariableIndex( const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType targetVariable,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
size_t primaryValue,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
size_t familyValue ) const
|
||||
{
|
||||
if ( targetVariable == primaryVariable ) return primaryValue;
|
||||
if ( targetVariable == familyVariable ) return familyValue;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::WATER_CUT ) return m_waterCutIdx;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::GAS_LIQUID_RATIO ) return m_gasLiquidRatioIdx;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::ARTIFICIAL_LIFT_QUANTITY ) return m_articifialLiftQuantityIdx;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::FLOW_RATE ) return m_flowRateIdx;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::THP ) return m_thpIdx;
|
||||
|
||||
return getProductionTableData( table, targetVariable ).size() - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_filePath );
|
||||
m_filePath.uiCapability()->setUiReadOnly( m_dataIsImportedExternally );
|
||||
uiOrdering.add( &m_vfpTableData );
|
||||
|
||||
uiOrdering.add( &m_tableType );
|
||||
uiOrdering.add( &m_tableNumber );
|
||||
@ -999,89 +813,26 @@ QList<caf::PdmOptionItemInfo> RimVfpPlot::calculateValueOptions( const caf::PdmF
|
||||
calculateTableValueOptions( RimVfpDefines::ProductionVariableType::GAS_LIQUID_RATIO, options );
|
||||
}
|
||||
|
||||
else if ( fieldNeedingOptions == &m_vfpTableData )
|
||||
{
|
||||
RimVfpDataCollection* vfpDataCollection = RimVfpDataCollection::instance();
|
||||
for ( auto table : vfpDataCollection->vfpTableData() )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( table->name(), table ) );
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDefines::FlowingPhaseType RimVfpPlot::getFlowingPhaseType( const Opm::VFPProdTable& table )
|
||||
{
|
||||
switch ( table.getFloType() )
|
||||
{
|
||||
case Opm::VFPProdTable::FLO_TYPE::FLO_OIL:
|
||||
return RimVfpDefines::FlowingPhaseType::OIL;
|
||||
case Opm::VFPProdTable::FLO_TYPE::FLO_GAS:
|
||||
return RimVfpDefines::FlowingPhaseType::GAS;
|
||||
case Opm::VFPProdTable::FLO_TYPE::FLO_LIQ:
|
||||
return RimVfpDefines::FlowingPhaseType::LIQUID;
|
||||
default:
|
||||
return RimVfpDefines::FlowingPhaseType::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDefines::FlowingPhaseType RimVfpPlot::getFlowingPhaseType( const Opm::VFPInjTable& table )
|
||||
{
|
||||
switch ( table.getFloType() )
|
||||
{
|
||||
case Opm::VFPInjTable::FLO_TYPE::FLO_OIL:
|
||||
return RimVfpDefines::FlowingPhaseType::OIL;
|
||||
case Opm::VFPInjTable::FLO_TYPE::FLO_GAS:
|
||||
return RimVfpDefines::FlowingPhaseType::GAS;
|
||||
case Opm::VFPInjTable::FLO_TYPE::FLO_WAT:
|
||||
return RimVfpDefines::FlowingPhaseType::WATER;
|
||||
default:
|
||||
return RimVfpDefines::FlowingPhaseType::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDefines::FlowingGasFractionType RimVfpPlot::getFlowingGasFractionType( const Opm::VFPProdTable& table )
|
||||
{
|
||||
switch ( table.getGFRType() )
|
||||
{
|
||||
case Opm::VFPProdTable::GFR_TYPE::GFR_GOR:
|
||||
return RimVfpDefines::FlowingGasFractionType::GOR;
|
||||
case Opm::VFPProdTable::GFR_TYPE::GFR_GLR:
|
||||
return RimVfpDefines::FlowingGasFractionType::GLR;
|
||||
case Opm::VFPProdTable::GFR_TYPE::GFR_OGR:
|
||||
return RimVfpDefines::FlowingGasFractionType::OGR;
|
||||
default:
|
||||
return RimVfpDefines::FlowingGasFractionType::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDefines::FlowingWaterFractionType RimVfpPlot::getFlowingWaterFractionType( const Opm::VFPProdTable& table )
|
||||
{
|
||||
switch ( table.getWFRType() )
|
||||
{
|
||||
case Opm::VFPProdTable::WFR_TYPE::WFR_WOR:
|
||||
return RimVfpDefines::FlowingWaterFractionType::WOR;
|
||||
case Opm::VFPProdTable::WFR_TYPE::WFR_WCT:
|
||||
return RimVfpDefines::FlowingWaterFractionType::WCT;
|
||||
case Opm::VFPProdTable::WFR_TYPE::WFR_WGR:
|
||||
return RimVfpDefines::FlowingWaterFractionType::WGR;
|
||||
default:
|
||||
return RimVfpDefines::FlowingWaterFractionType::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::calculateTableValueOptions( RimVfpDefines::ProductionVariableType variableType, QList<caf::PdmOptionItemInfo>& options )
|
||||
{
|
||||
if ( m_prodTable )
|
||||
if ( vfpTables() )
|
||||
{
|
||||
std::vector<double> values = getProductionTableData( *m_prodTable, variableType );
|
||||
auto values = vfpTables()->getProductionTableData( m_tableNumber(), variableType );
|
||||
|
||||
for ( size_t i = 0; i < values.size(); i++ )
|
||||
{
|
||||
@ -1098,10 +849,32 @@ void RimVfpPlot::calculateTableValueOptions( RimVfpDefines::ProductionVariableTy
|
||||
void RimVfpPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
||||
{
|
||||
RimPlot::fieldChangedByUi( changedField, oldValue, newValue );
|
||||
|
||||
loadDataAndUpdate();
|
||||
updateLayout();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::initAfterRead()
|
||||
{
|
||||
auto filePath = m_filePath_OBSOLETE.v().path();
|
||||
if ( filePath.isEmpty() ) return;
|
||||
|
||||
QString fileName = RimProject::current()->updatedFilePathFromPathId( filePath );
|
||||
|
||||
auto vfpDataCollection = RimVfpDataCollection::instance();
|
||||
if ( vfpDataCollection )
|
||||
{
|
||||
auto tableData = vfpDataCollection->appendTableDataObject( fileName );
|
||||
if ( tableData )
|
||||
{
|
||||
setDataSource( tableData );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -1143,3 +916,22 @@ caf::PdmFieldHandle* RimVfpPlot::userDescriptionField()
|
||||
{
|
||||
return &m_plotTitle;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::scheduleReplot()
|
||||
{
|
||||
if ( m_plotWidget )
|
||||
{
|
||||
m_plotWidget->scheduleReplot();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
VfpTableSelection RimVfpPlot::tableSelection() const
|
||||
{
|
||||
return { m_flowRateIdx(), m_thpIdx(), m_articifialLiftQuantityIdx(), m_waterCutIdx(), m_gasLiquidRatioIdx() };
|
||||
}
|
||||
|
@ -22,15 +22,24 @@
|
||||
#include "RimVfpDefines.h"
|
||||
|
||||
#include "cafFilePath.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
#include "opm/input/eclipse/Schedule/VFPInjTable.hpp"
|
||||
#include "opm/input/eclipse/Schedule/VFPProdTable.hpp"
|
||||
|
||||
class RiuPlotWidget;
|
||||
class VfpPlotData;
|
||||
class RimPlotAxisProperties;
|
||||
class RigVfpTables;
|
||||
class RimVfpTableData;
|
||||
|
||||
struct VfpTableSelection;
|
||||
struct VfpTableInitialData;
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
class VFPInjTable;
|
||||
class VFPProdTable;
|
||||
} // namespace Opm
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Vertical Flow Performance Plot
|
||||
@ -43,7 +52,9 @@ public:
|
||||
RimVfpPlot();
|
||||
~RimVfpPlot() override;
|
||||
|
||||
void setFileName( const QString& filename );
|
||||
void setDataSource( RimVfpTableData* vfpTableData );
|
||||
void setTableNumber( int tableNumber );
|
||||
void initializeObject();
|
||||
|
||||
// RimPlot implementations
|
||||
RiuPlotWidget* plotWidget() override;
|
||||
@ -65,43 +76,30 @@ public:
|
||||
QImage snapshotWindowContent() override;
|
||||
void zoomAll() override;
|
||||
|
||||
void setProductionTable( const Opm::VFPProdTable& table );
|
||||
void setInjectionTable( const Opm::VFPInjTable& table );
|
||||
void setDataIsImportedExternally( bool dataIsImportedExternally );
|
||||
int tableNumber() const;
|
||||
|
||||
private:
|
||||
// RimPlot implementations
|
||||
void doRemoveFromCollection();
|
||||
|
||||
// RimViewWindow implementations
|
||||
void onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& updatedObjects ) override;
|
||||
void deleteViewWidget() override;
|
||||
void onLoadDataAndUpdate() override;
|
||||
|
||||
// PDM methods
|
||||
caf::PdmFieldHandle* userDescriptionField() override;
|
||||
|
||||
void scheduleReplot();
|
||||
|
||||
private:
|
||||
RiuPlotWidget* doCreatePlotViewWidget( QWidget* mainWindowParent ) override;
|
||||
|
||||
void populatePlotWidgetWithCurveData( RiuPlotWidget* plotWidget, const Opm::VFPInjTable& table );
|
||||
void populatePlotWidgetWithCurveData( RiuPlotWidget* plotWidget,
|
||||
const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable );
|
||||
std::vector<double> getProductionTableData( const Opm::VFPProdTable& table, RimVfpDefines::ProductionVariableType variableType ) const;
|
||||
size_t getVariableIndex( const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType targetVariable,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
size_t primaryValue,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
size_t familyValue ) const;
|
||||
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
void initAfterRead() override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
|
||||
VfpTableSelection tableSelection() const;
|
||||
void initializeFromInitData( const VfpTableInitialData& table );
|
||||
const RigVfpTables* vfpTables() const;
|
||||
|
||||
RiuPlotWidget* doCreatePlotViewWidget( QWidget* mainWindowParent ) override;
|
||||
|
||||
void calculateTableValueOptions( RimVfpDefines::ProductionVariableType variableType, QList<caf::PdmOptionItemInfo>& options );
|
||||
|
||||
void setFixedVariableUiEditability( caf::PdmField<int>& field, RimVfpDefines::ProductionVariableType variableType );
|
||||
@ -114,30 +112,11 @@ private:
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable );
|
||||
|
||||
static double convertToDisplayUnit( double value, RimVfpDefines::ProductionVariableType variableType );
|
||||
static void convertToDisplayUnit( std::vector<double>& values, RimVfpDefines::ProductionVariableType variableType );
|
||||
|
||||
static double convertToDisplayUnit( double value, RimVfpDefines::ProductionVariableType variableType );
|
||||
static void convertToDisplayUnit( std::vector<double>& values, RimVfpDefines::ProductionVariableType variableType );
|
||||
static QString getDisplayUnit( RimVfpDefines::ProductionVariableType variableType );
|
||||
|
||||
static QString getDisplayUnitWithBracket( RimVfpDefines::ProductionVariableType variableType );
|
||||
|
||||
static RimVfpDefines::FlowingPhaseType getFlowingPhaseType( const Opm::VFPProdTable& table );
|
||||
static RimVfpDefines::FlowingPhaseType getFlowingPhaseType( const Opm::VFPInjTable& table );
|
||||
static RimVfpDefines::FlowingWaterFractionType getFlowingWaterFractionType( const Opm::VFPProdTable& table );
|
||||
static RimVfpDefines::FlowingGasFractionType getFlowingGasFractionType( const Opm::VFPProdTable& table );
|
||||
|
||||
void populatePlotData( const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
VfpPlotData& plotData ) const;
|
||||
|
||||
static void populatePlotData( const Opm::VFPInjTable& table,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
VfpPlotData& plotData );
|
||||
|
||||
void populatePlotWidgetWithPlotData( RiuPlotWidget* plotWidget, const VfpPlotData& plotData );
|
||||
|
||||
static QString axisTitle( RimVfpDefines::ProductionVariableType variableType, RimVfpDefines::FlowingPhaseType flowingPhase );
|
||||
@ -149,10 +128,11 @@ private:
|
||||
void updateAxisRangesFromPlotWidget() override;
|
||||
|
||||
void onPlotZoomed();
|
||||
void curveAppearanceChanged( const caf::SignalEmitter* emitter );
|
||||
|
||||
private:
|
||||
caf::PdmField<QString> m_plotTitle;
|
||||
caf::PdmField<caf::FilePath> m_filePath;
|
||||
caf::PdmPtrField<RimVfpTableData*> m_vfpTableData;
|
||||
caf::PdmField<int> m_tableNumber;
|
||||
caf::PdmField<double> m_referenceDepth;
|
||||
caf::PdmField<caf::AppEnum<RimVfpDefines::FlowingPhaseType>> m_flowingPhase;
|
||||
@ -173,9 +153,12 @@ private:
|
||||
caf::PdmChildField<RimPlotAxisProperties*> m_yAxisProperties;
|
||||
caf::PdmChildField<RimPlotAxisProperties*> m_xAxisProperties;
|
||||
|
||||
QPointer<RiuPlotWidget> m_plotWidget;
|
||||
std::unique_ptr<Opm::VFPProdTable> m_prodTable;
|
||||
std::unique_ptr<Opm::VFPInjTable> m_injectionTable;
|
||||
caf::PdmChildArrayField<RimPlotCurve*> m_plotCurves;
|
||||
|
||||
QPointer<RiuPlotWidget> m_plotWidget;
|
||||
|
||||
std::unique_ptr<RigVfpTables> m_vfpTables;
|
||||
caf::PdmField<caf::FilePath> m_filePath_OBSOLETE;
|
||||
|
||||
bool m_dataIsImportedExternally;
|
||||
};
|
||||
|
@ -18,16 +18,8 @@
|
||||
|
||||
#include "RimVfpPlotCollection.h"
|
||||
|
||||
#include "RiaApplication.h"
|
||||
|
||||
#include "RigCaseCellResultsData.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseResultAddress.h"
|
||||
#include "RigEquil.h"
|
||||
|
||||
#include "RimEclipseResultCase.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimVfpDeck.h"
|
||||
#include "RimVfpTableData.h"
|
||||
|
||||
#include "cafCmdFeatureMenuBuilder.h"
|
||||
|
||||
@ -47,8 +39,43 @@ RimVfpPlotCollection::RimVfpPlotCollection()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpPlotCollection::~RimVfpPlotCollection()
|
||||
RimVfpPlot* RimVfpPlotCollection::createAndAppendPlots( RimVfpTableData* tableData )
|
||||
{
|
||||
if ( !tableData ) return nullptr;
|
||||
|
||||
tableData->ensureDataIsImported();
|
||||
|
||||
if ( !tableData->vfpTables() ) return nullptr;
|
||||
|
||||
RimVfpPlot* firstPlot = nullptr;
|
||||
|
||||
if ( tableData->tableCount() > 1 )
|
||||
{
|
||||
auto* deck = new RimVfpDeck();
|
||||
deck->setDataSource( tableData );
|
||||
addDeck( deck );
|
||||
deck->loadDataAndUpdate();
|
||||
deck->updateAllRequiredEditors();
|
||||
|
||||
auto plots = deck->plots();
|
||||
if ( !plots.empty() )
|
||||
{
|
||||
firstPlot = plots.front();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto vfpPlot = new RimVfpPlot();
|
||||
vfpPlot->setDataSource( tableData );
|
||||
vfpPlot->initializeObject();
|
||||
|
||||
addPlot( vfpPlot );
|
||||
vfpPlot->loadDataAndUpdate();
|
||||
|
||||
firstPlot = vfpPlot;
|
||||
}
|
||||
|
||||
return firstPlot;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -75,14 +102,6 @@ std::vector<RimVfpPlot*> RimVfpPlotCollection::plots() const
|
||||
return m_vfpPlots.childrenByType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlotCollection::deleteChildren()
|
||||
{
|
||||
m_vfpPlots.deleteChildren();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -119,13 +138,30 @@ void RimVfpPlotCollection::removePlot( RimVfpPlot* vfpPlot )
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDeck* RimVfpPlotCollection::addDeck( const QString& filename )
|
||||
void RimVfpPlotCollection::addDeck( RimVfpDeck* deck )
|
||||
{
|
||||
RimVfpDeck* deck = new RimVfpDeck();
|
||||
deck->setFileName( filename );
|
||||
m_vfpDecks.push_back( deck );
|
||||
}
|
||||
|
||||
return deck;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlotCollection::deleteAllPlots()
|
||||
{
|
||||
m_vfpPlots.deleteChildren();
|
||||
m_vfpDecks.deleteChildren();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlotCollection::addImportItems( caf::CmdFeatureMenuBuilder& menuBuilder )
|
||||
{
|
||||
// A variant with a true value is used to indicate that the VFP data is imported from a file
|
||||
// This is used to distinguish between VFP data imported from a file and VFP data imported from a simulator
|
||||
QVariant variant( QVariant::fromValue( true ) );
|
||||
menuBuilder.addCmdFeatureWithUserData( "RicImportVfpDataFeature", "Import VFP Files", variant );
|
||||
menuBuilder.addCmdFeature( "RicImportVfpDataFeature", "Import VFP from Simulator Files" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -160,9 +196,5 @@ void RimVfpPlotCollection::loadDataAndUpdateAllPlots()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlotCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
|
||||
{
|
||||
// A variant with a true value is used to indicate that the VFP data is imported from a file
|
||||
// This is used to distinguish between VFP data imported from a file and VFP data imported from a simulator
|
||||
QVariant variant( QVariant::fromValue( true ) );
|
||||
menuBuilder.addCmdFeatureWithUserData( "RicImportVfpDataFeature", "Import VFP Files", variant );
|
||||
menuBuilder.addCmdFeature( "RicImportVfpDataFeature", "Import VFP from Simulator Files" );
|
||||
addImportItems( menuBuilder );
|
||||
}
|
||||
|
@ -35,18 +35,19 @@ class RimVfpPlotCollection : public caf::PdmObject, public RimTypedPlotCollectio
|
||||
|
||||
public:
|
||||
RimVfpPlotCollection();
|
||||
~RimVfpPlotCollection() override;
|
||||
|
||||
RimVfpPlot* createAndAppendPlots( RimVfpTableData* tableData );
|
||||
RimVfpPlot* plotForTableNumber( int tableNumber ) const;
|
||||
|
||||
void addPlot( RimVfpPlot* newPlot ) override;
|
||||
std::vector<RimVfpPlot*> plots() const override;
|
||||
void deleteChildren();
|
||||
RimVfpPlot* plotForTableNumber( int tableNumber ) const;
|
||||
|
||||
size_t plotCount() const final;
|
||||
void insertPlot( RimVfpPlot* vfpPlot, size_t index ) final;
|
||||
void removePlot( RimVfpPlot* vfpPlot ) final;
|
||||
void deleteAllPlots() override;
|
||||
|
||||
RimVfpDeck* addDeck( const QString& filename );
|
||||
static void addImportItems( caf::CmdFeatureMenuBuilder& menuBuilder );
|
||||
|
||||
private:
|
||||
void loadDataAndUpdateAllPlots() override;
|
||||
@ -54,6 +55,8 @@ private:
|
||||
|
||||
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
|
||||
|
||||
void addDeck( RimVfpDeck* deck );
|
||||
|
||||
private:
|
||||
caf::PdmChildArrayField<RimVfpPlot*> m_vfpPlots;
|
||||
caf::PdmChildArrayField<RimVfpDeck*> m_vfpDecks;
|
||||
|
@ -0,0 +1,126 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimVfpTableData.h"
|
||||
|
||||
#include "RiaOpmParserTools.h"
|
||||
|
||||
#include "RigVfpTables.h"
|
||||
|
||||
#include "cafCmdFeatureMenuBuilder.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimVfpTableData, "RimVfpTableData" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpTableData::RimVfpTableData()
|
||||
{
|
||||
CAF_PDM_InitObject( "VFP Plot", ":/VfpPlot.svg" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_filePath, "FilePath", "File Path" );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpTableData::setFileName( const QString& filename )
|
||||
{
|
||||
m_filePath = filename;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimVfpTableData::baseFileName()
|
||||
{
|
||||
QFileInfo fileInfo( m_filePath().path() );
|
||||
return fileInfo.baseName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpTableData::ensureDataIsImported()
|
||||
{
|
||||
if ( m_vfpTables ) return;
|
||||
|
||||
updateObjectName();
|
||||
|
||||
m_vfpTables = std::make_unique<RigVfpTables>();
|
||||
|
||||
const auto [vfpProdTables, vfpInjTables] = RiaOpmParserTools::extractVfpTablesFromDataFile( m_filePath().path().toStdString() );
|
||||
for ( const auto& prod : vfpProdTables )
|
||||
{
|
||||
m_vfpTables->addProductionTable( prod );
|
||||
}
|
||||
|
||||
for ( const auto& inj : vfpInjTables )
|
||||
{
|
||||
m_vfpTables->addInjectionTable( inj );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RimVfpTableData::tableCount() const
|
||||
{
|
||||
if ( m_vfpTables )
|
||||
{
|
||||
return m_vfpTables->injectionTableNumbers().size() + m_vfpTables->productionTableNumbers().size();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const RigVfpTables* RimVfpTableData::vfpTables() const
|
||||
{
|
||||
return m_vfpTables.get();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpTableData::updateObjectName()
|
||||
{
|
||||
QString name = "VFP Plots";
|
||||
|
||||
QFileInfo fileInfo( m_filePath().path() );
|
||||
auto fileName = fileInfo.fileName();
|
||||
if ( !fileName.isEmpty() )
|
||||
{
|
||||
name = fileName;
|
||||
}
|
||||
setName( name );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpTableData::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
|
||||
{
|
||||
menuBuilder << "RicNewVfpPlotFeature";
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimNamedObject.h"
|
||||
|
||||
#include "cafFilePath.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class RigVfpTables;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
class RimVfpTableData : public RimNamedObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimVfpTableData();
|
||||
|
||||
void setFileName( const QString& filename );
|
||||
QString baseFileName();
|
||||
void ensureDataIsImported();
|
||||
|
||||
size_t tableCount() const;
|
||||
|
||||
const RigVfpTables* vfpTables() const;
|
||||
|
||||
private:
|
||||
void updateObjectName();
|
||||
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
|
||||
|
||||
private:
|
||||
caf::PdmField<caf::FilePath> m_filePath;
|
||||
|
||||
std::unique_ptr<RigVfpTables> m_vfpTables;
|
||||
};
|
@ -98,6 +98,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigWellResultBranch.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigWellResultFrame.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigReservoirBuilder.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigVfpTables.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@ -194,6 +195,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigWellResultFrame.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigDeclineCurveCalculator.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigReservoirBuilder.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigVfpTables.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
569
ApplicationLibCode/ReservoirDataModel/RigVfpTables.cpp
Normal file
569
ApplicationLibCode/ReservoirDataModel/RigVfpTables.cpp
Normal file
@ -0,0 +1,569 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RigVfpTables.h"
|
||||
|
||||
#include "RiaEclipseUnitTools.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
|
||||
#include "opm/input/eclipse/Schedule/VFPInjTable.hpp"
|
||||
#include "opm/input/eclipse/Schedule/VFPProdTable.hpp"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
VfpPlotData RigVfpTables::populatePlotData( const Opm::VFPInjTable& table,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase )
|
||||
{
|
||||
VfpPlotData plotData;
|
||||
|
||||
QString xAxisTitle = axisTitle( RimVfpDefines::ProductionVariableType::FLOW_RATE, flowingPhase );
|
||||
plotData.setXAxisTitle( xAxisTitle );
|
||||
|
||||
QString yAxisTitle = QString( "%1 %2" ).arg( caf::AppEnum<RimVfpDefines::InterpolatedVariableType>::uiText( interpolatedVariable ),
|
||||
getDisplayUnitWithBracket( RimVfpDefines::ProductionVariableType::THP ) );
|
||||
plotData.setYAxisTitle( yAxisTitle );
|
||||
|
||||
std::vector<double> thpValues = table.getTHPAxis();
|
||||
|
||||
for ( size_t thp = 0; thp < thpValues.size(); thp++ )
|
||||
{
|
||||
size_t numValues = table.getFloAxis().size();
|
||||
std::vector<double> xVals = table.getFloAxis();
|
||||
std::vector<double> yVals( numValues, 0.0 );
|
||||
for ( size_t y = 0; y < numValues; y++ )
|
||||
{
|
||||
yVals[y] = table( thp, y );
|
||||
if ( interpolatedVariable == RimVfpDefines::InterpolatedVariableType::BHP_THP_DIFF )
|
||||
{
|
||||
yVals[y] -= thpValues[thp];
|
||||
}
|
||||
}
|
||||
|
||||
double value = convertToDisplayUnit( thpValues[thp], RimVfpDefines::ProductionVariableType::THP );
|
||||
QString unit = getDisplayUnit( RimVfpDefines::ProductionVariableType::THP );
|
||||
QString title = QString( "%1 [%2]: %3" )
|
||||
.arg( caf::AppEnum<RimVfpDefines::ProductionVariableType>::uiText( RimVfpDefines::ProductionVariableType::THP ) )
|
||||
.arg( unit )
|
||||
.arg( value );
|
||||
|
||||
convertToDisplayUnit( yVals, RimVfpDefines::ProductionVariableType::THP );
|
||||
convertToDisplayUnit( xVals, RimVfpDefines::ProductionVariableType::FLOW_RATE );
|
||||
|
||||
plotData.appendCurve( title, xVals, yVals );
|
||||
}
|
||||
|
||||
return plotData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
VfpPlotData RigVfpTables::populatePlotData( const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
const VfpTableSelection& tableSelection )
|
||||
{
|
||||
VfpPlotData plotData;
|
||||
|
||||
QString xAxisTitle = axisTitle( primaryVariable, flowingPhase );
|
||||
plotData.setXAxisTitle( xAxisTitle );
|
||||
|
||||
QString yAxisTitle = QString( "%1 %2" ).arg( caf::AppEnum<RimVfpDefines::InterpolatedVariableType>::uiText( interpolatedVariable ),
|
||||
getDisplayUnitWithBracket( RimVfpDefines::ProductionVariableType::THP ) );
|
||||
plotData.setYAxisTitle( yAxisTitle );
|
||||
|
||||
size_t numFamilyValues = getProductionTableData( table, familyVariable ).size();
|
||||
for ( size_t familyIdx = 0; familyIdx < numFamilyValues; familyIdx++ )
|
||||
{
|
||||
std::vector<double> primaryAxisValues = getProductionTableData( table, primaryVariable );
|
||||
std::vector<double> familyVariableValues = getProductionTableData( table, familyVariable );
|
||||
std::vector<double> thpValues = getProductionTableData( table, RimVfpDefines::ProductionVariableType::THP );
|
||||
|
||||
size_t numValues = primaryAxisValues.size();
|
||||
std::vector<double> yVals( numValues, 0.0 );
|
||||
|
||||
for ( size_t y = 0; y < numValues; y++ )
|
||||
{
|
||||
size_t wfr_idx =
|
||||
getVariableIndex( table, RimVfpDefines::ProductionVariableType::WATER_CUT, primaryVariable, y, familyVariable, familyIdx, tableSelection );
|
||||
size_t gfr_idx = getVariableIndex( table,
|
||||
RimVfpDefines::ProductionVariableType::GAS_LIQUID_RATIO,
|
||||
primaryVariable,
|
||||
y,
|
||||
familyVariable,
|
||||
familyIdx,
|
||||
tableSelection );
|
||||
size_t alq_idx = getVariableIndex( table,
|
||||
RimVfpDefines::ProductionVariableType::ARTIFICIAL_LIFT_QUANTITY,
|
||||
primaryVariable,
|
||||
y,
|
||||
familyVariable,
|
||||
familyIdx,
|
||||
tableSelection );
|
||||
size_t flo_idx =
|
||||
getVariableIndex( table, RimVfpDefines::ProductionVariableType::FLOW_RATE, primaryVariable, y, familyVariable, familyIdx, tableSelection );
|
||||
size_t thp_idx =
|
||||
getVariableIndex( table, RimVfpDefines::ProductionVariableType::THP, primaryVariable, y, familyVariable, familyIdx, tableSelection );
|
||||
|
||||
yVals[y] = table( thp_idx, wfr_idx, gfr_idx, alq_idx, flo_idx );
|
||||
if ( interpolatedVariable == RimVfpDefines::InterpolatedVariableType::BHP_THP_DIFF )
|
||||
{
|
||||
yVals[y] -= thpValues[thp_idx];
|
||||
}
|
||||
}
|
||||
|
||||
double familyValue = convertToDisplayUnit( familyVariableValues[familyIdx], familyVariable );
|
||||
QString familyUnit = getDisplayUnit( familyVariable );
|
||||
QString familyTitle = QString( "%1: %2 %3" )
|
||||
.arg( caf::AppEnum<RimVfpDefines::ProductionVariableType>::uiText( familyVariable ) )
|
||||
.arg( familyValue )
|
||||
.arg( familyUnit );
|
||||
|
||||
convertToDisplayUnit( yVals, RimVfpDefines::ProductionVariableType::THP );
|
||||
convertToDisplayUnit( primaryAxisValues, primaryVariable );
|
||||
|
||||
plotData.appendCurve( familyTitle, primaryAxisValues, yVals );
|
||||
}
|
||||
|
||||
return plotData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
VfpPlotData RigVfpTables::populatePlotData( int tableIndex,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
const VfpTableSelection& tableSelection ) const
|
||||
{
|
||||
auto prodTable = productionTable( tableIndex );
|
||||
if ( prodTable.has_value() )
|
||||
{
|
||||
return populatePlotData( *prodTable, primaryVariable, familyVariable, interpolatedVariable, flowingPhase, tableSelection );
|
||||
};
|
||||
|
||||
auto injContainer = injectionTable( tableIndex );
|
||||
if ( injContainer.has_value() )
|
||||
{
|
||||
return populatePlotData( *injContainer, interpolatedVariable, flowingPhase );
|
||||
};
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RigVfpTables::asciiDataForTable( int tableNumber,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
const VfpTableSelection& tableSelection ) const
|
||||
{
|
||||
VfpPlotData plotData;
|
||||
auto prodTable = productionTable( tableNumber );
|
||||
if ( prodTable.has_value() )
|
||||
{
|
||||
plotData = populatePlotData( *prodTable, primaryVariable, familyVariable, interpolatedVariable, flowingPhase, tableSelection );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto injTable = injectionTable( tableNumber );
|
||||
if ( injTable.has_value() )
|
||||
{
|
||||
plotData = populatePlotData( *injTable, interpolatedVariable, flowingPhase );
|
||||
}
|
||||
}
|
||||
|
||||
return textForPlotData( plotData );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RigVfpTables::axisTitle( RimVfpDefines::ProductionVariableType variableType, RimVfpDefines::FlowingPhaseType flowingPhase )
|
||||
{
|
||||
QString title;
|
||||
|
||||
if ( flowingPhase == RimVfpDefines::FlowingPhaseType::GAS )
|
||||
{
|
||||
title = "Gas ";
|
||||
}
|
||||
else
|
||||
{
|
||||
title = "Liquid ";
|
||||
}
|
||||
title += QString( "%1 %2" ).arg( caf::AppEnum<RimVfpDefines::ProductionVariableType>::uiText( variableType ),
|
||||
getDisplayUnitWithBracket( variableType ) );
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RigVfpTables::getDisplayUnit( RimVfpDefines::ProductionVariableType variableType )
|
||||
{
|
||||
if ( variableType == RimVfpDefines::ProductionVariableType::THP ) return "Bar";
|
||||
|
||||
if ( variableType == RimVfpDefines::ProductionVariableType::FLOW_RATE ) return "Sm3/day";
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RigVfpTables::getDisplayUnitWithBracket( RimVfpDefines::ProductionVariableType variableType )
|
||||
{
|
||||
QString unit = getDisplayUnit( variableType );
|
||||
if ( !unit.isEmpty() ) return QString( "[%1]" ).arg( unit );
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigVfpTables::convertToDisplayUnit( double value, RimVfpDefines::ProductionVariableType variableType )
|
||||
{
|
||||
if ( variableType == RimVfpDefines::ProductionVariableType::THP )
|
||||
{
|
||||
return RiaEclipseUnitTools::pascalToBar( value );
|
||||
}
|
||||
|
||||
if ( variableType == RimVfpDefines::ProductionVariableType::FLOW_RATE )
|
||||
{
|
||||
// Convert to m3/sec to m3/day
|
||||
return value * static_cast<double>( 24 * 60 * 60 );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigVfpTables::convertToDisplayUnit( std::vector<double>& values, RimVfpDefines::ProductionVariableType variableType )
|
||||
{
|
||||
for ( double& value : values )
|
||||
value = convertToDisplayUnit( value, variableType );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RigVfpTables::textForPlotData( const VfpPlotData& plotData )
|
||||
{
|
||||
QString dataText;
|
||||
|
||||
if ( plotData.size() > 0 )
|
||||
{
|
||||
// The curves should have same dimensions
|
||||
const size_t curveSize = plotData.curveSize( 0 );
|
||||
|
||||
// Generate the headers for the columns
|
||||
// First column is the primary variable
|
||||
QString columnTitleLine( plotData.xAxisTitle() );
|
||||
|
||||
// Then one column per "family"
|
||||
for ( size_t s = 0; s < plotData.size(); s++ )
|
||||
{
|
||||
columnTitleLine.append( QString( "\t%1" ).arg( plotData.curveTitle( s ) ) );
|
||||
}
|
||||
columnTitleLine.append( "\n" );
|
||||
|
||||
dataText.append( columnTitleLine );
|
||||
|
||||
// Add the rows: one row per primary variable value
|
||||
for ( size_t idx = 0; idx < curveSize; idx++ )
|
||||
{
|
||||
QString line;
|
||||
|
||||
// First item on each line is the primary variable
|
||||
line.append( QString( "%1" ).arg( plotData.xData( 0 )[idx] ) );
|
||||
|
||||
for ( size_t s = 0; s < plotData.size(); s++ )
|
||||
{
|
||||
line.append( QString( "\t%1" ).arg( plotData.yData( s )[idx] ) );
|
||||
}
|
||||
dataText.append( line );
|
||||
dataText.append( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
return dataText;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RigVfpTables::getProductionTableData( const Opm::VFPProdTable& table, RimVfpDefines::ProductionVariableType variableType )
|
||||
{
|
||||
std::vector<double> xVals;
|
||||
if ( variableType == RimVfpDefines::ProductionVariableType::WATER_CUT )
|
||||
{
|
||||
xVals = table.getWFRAxis();
|
||||
}
|
||||
else if ( variableType == RimVfpDefines::ProductionVariableType::GAS_LIQUID_RATIO )
|
||||
{
|
||||
xVals = table.getGFRAxis();
|
||||
}
|
||||
else if ( variableType == RimVfpDefines::ProductionVariableType::ARTIFICIAL_LIFT_QUANTITY )
|
||||
{
|
||||
xVals = table.getALQAxis();
|
||||
}
|
||||
else if ( variableType == RimVfpDefines::ProductionVariableType::FLOW_RATE )
|
||||
{
|
||||
xVals = table.getFloAxis();
|
||||
}
|
||||
else if ( variableType == RimVfpDefines::ProductionVariableType::THP )
|
||||
{
|
||||
xVals = table.getTHPAxis();
|
||||
}
|
||||
|
||||
return xVals;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RigVfpTables::getProductionTableData( int tableIndex, RimVfpDefines::ProductionVariableType variableType ) const
|
||||
{
|
||||
auto prodTable = productionTable( tableIndex );
|
||||
if ( prodTable.has_value() )
|
||||
{
|
||||
return getProductionTableData( *prodTable, variableType );
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RigVfpTables::getVariableIndex( const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType targetVariable,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
size_t primaryValue,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
size_t familyValue,
|
||||
const VfpTableSelection& tableSelection )
|
||||
{
|
||||
if ( targetVariable == primaryVariable ) return primaryValue;
|
||||
if ( targetVariable == familyVariable ) return familyValue;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::WATER_CUT ) return tableSelection.waterCutIdx;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::GAS_LIQUID_RATIO ) return tableSelection.gasLiquidRatioIdx;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::ARTIFICIAL_LIFT_QUANTITY )
|
||||
return tableSelection.articifialLiftQuantityIdx;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::FLOW_RATE ) return tableSelection.flowRateIdx;
|
||||
if ( targetVariable == RimVfpDefines::ProductionVariableType::THP ) return tableSelection.thpIdx;
|
||||
|
||||
return getProductionTableData( table, targetVariable ).size() - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::optional<Opm::VFPInjTable> RigVfpTables::injectionTable( int tableNumber ) const
|
||||
{
|
||||
for ( const auto& table : m_injectionTables )
|
||||
{
|
||||
if ( table.getTableNum() == tableNumber )
|
||||
{
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::optional<Opm::VFPProdTable> RigVfpTables::productionTable( int tableNumber ) const
|
||||
{
|
||||
for ( const auto& table : m_productionTables )
|
||||
{
|
||||
if ( table.getTableNum() == tableNumber )
|
||||
{
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDefines::FlowingPhaseType RigVfpTables::getFlowingPhaseType( const Opm::VFPProdTable& table )
|
||||
{
|
||||
switch ( table.getFloType() )
|
||||
{
|
||||
case Opm::VFPProdTable::FLO_TYPE::FLO_OIL:
|
||||
return RimVfpDefines::FlowingPhaseType::OIL;
|
||||
case Opm::VFPProdTable::FLO_TYPE::FLO_GAS:
|
||||
return RimVfpDefines::FlowingPhaseType::GAS;
|
||||
case Opm::VFPProdTable::FLO_TYPE::FLO_LIQ:
|
||||
return RimVfpDefines::FlowingPhaseType::LIQUID;
|
||||
default:
|
||||
return RimVfpDefines::FlowingPhaseType::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDefines::FlowingPhaseType RigVfpTables::getFlowingPhaseType( const Opm::VFPInjTable& table )
|
||||
{
|
||||
switch ( table.getFloType() )
|
||||
{
|
||||
case Opm::VFPInjTable::FLO_TYPE::FLO_OIL:
|
||||
return RimVfpDefines::FlowingPhaseType::OIL;
|
||||
case Opm::VFPInjTable::FLO_TYPE::FLO_GAS:
|
||||
return RimVfpDefines::FlowingPhaseType::GAS;
|
||||
case Opm::VFPInjTable::FLO_TYPE::FLO_WAT:
|
||||
return RimVfpDefines::FlowingPhaseType::WATER;
|
||||
default:
|
||||
return RimVfpDefines::FlowingPhaseType::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDefines::FlowingWaterFractionType RigVfpTables::getFlowingWaterFractionType( const Opm::VFPProdTable& table )
|
||||
{
|
||||
switch ( table.getWFRType() )
|
||||
{
|
||||
case Opm::VFPProdTable::WFR_TYPE::WFR_WOR:
|
||||
return RimVfpDefines::FlowingWaterFractionType::WOR;
|
||||
case Opm::VFPProdTable::WFR_TYPE::WFR_WCT:
|
||||
return RimVfpDefines::FlowingWaterFractionType::WCT;
|
||||
case Opm::VFPProdTable::WFR_TYPE::WFR_WGR:
|
||||
return RimVfpDefines::FlowingWaterFractionType::WGR;
|
||||
default:
|
||||
return RimVfpDefines::FlowingWaterFractionType::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimVfpDefines::FlowingGasFractionType RigVfpTables::getFlowingGasFractionType( const Opm::VFPProdTable& table )
|
||||
{
|
||||
switch ( table.getGFRType() )
|
||||
{
|
||||
case Opm::VFPProdTable::GFR_TYPE::GFR_GOR:
|
||||
return RimVfpDefines::FlowingGasFractionType::GOR;
|
||||
case Opm::VFPProdTable::GFR_TYPE::GFR_GLR:
|
||||
return RimVfpDefines::FlowingGasFractionType::GLR;
|
||||
case Opm::VFPProdTable::GFR_TYPE::GFR_OGR:
|
||||
return RimVfpDefines::FlowingGasFractionType::OGR;
|
||||
default:
|
||||
return RimVfpDefines::FlowingGasFractionType::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigVfpTables::addInjectionTable( const Opm::VFPInjTable& table )
|
||||
{
|
||||
m_injectionTables.push_back( table );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigVfpTables::addProductionTable( const Opm::VFPProdTable& table )
|
||||
{
|
||||
m_productionTables.push_back( table );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<int> RigVfpTables::injectionTableNumbers() const
|
||||
{
|
||||
std::vector<int> tableNumbers;
|
||||
|
||||
for ( const auto& table : m_injectionTables )
|
||||
{
|
||||
tableNumbers.push_back( table.getTableNum() );
|
||||
}
|
||||
|
||||
return tableNumbers;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<int> RigVfpTables::productionTableNumbers() const
|
||||
{
|
||||
std::vector<int> tableNumbers;
|
||||
|
||||
for ( const auto& table : m_productionTables )
|
||||
{
|
||||
tableNumbers.push_back( table.getTableNum() );
|
||||
}
|
||||
|
||||
return tableNumbers;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
VfpTableInitialData RigVfpTables::getTableInitialData( int tableIndex ) const
|
||||
{
|
||||
auto prodTable = productionTable( tableIndex );
|
||||
if ( prodTable.has_value() )
|
||||
{
|
||||
VfpTableInitialData initialData;
|
||||
initialData.isProductionTable = true;
|
||||
initialData.tableNumber = prodTable->getTableNum();
|
||||
initialData.datumDepth = prodTable->getDatumDepth();
|
||||
initialData.flowingPhase = getFlowingPhaseType( *prodTable );
|
||||
initialData.waterFraction = getFlowingWaterFractionType( *prodTable );
|
||||
initialData.gasFraction = getFlowingGasFractionType( *prodTable );
|
||||
|
||||
return initialData;
|
||||
}
|
||||
|
||||
auto injTable = injectionTable( tableIndex );
|
||||
if ( injTable.has_value() )
|
||||
{
|
||||
VfpTableInitialData initialData;
|
||||
initialData.isProductionTable = false;
|
||||
initialData.tableNumber = injTable->getTableNum();
|
||||
initialData.datumDepth = injTable->getDatumDepth();
|
||||
initialData.flowingPhase = getFlowingPhaseType( *injTable );
|
||||
return initialData;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
157
ApplicationLibCode/ReservoirDataModel/RigVfpTables.h
Normal file
157
ApplicationLibCode/ReservoirDataModel/RigVfpTables.h
Normal file
@ -0,0 +1,157 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VerticalFlowPerformance/RimVfpDefines.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
class VFPInjTable;
|
||||
class VFPProdTable;
|
||||
} // namespace Opm
|
||||
|
||||
class VfpPlotData
|
||||
{
|
||||
public:
|
||||
void setXAxisTitle( const QString& xAxisTitle ) { m_xAxisTitle = xAxisTitle; }
|
||||
void setYAxisTitle( const QString& yAxisTitle ) { m_yAxisTitle = yAxisTitle; }
|
||||
|
||||
const QString& xAxisTitle() const { return m_xAxisTitle; }
|
||||
const QString& yAxisTitle() const { return m_yAxisTitle; }
|
||||
|
||||
void appendCurve( const QString& curveTitle, const std::vector<double>& xData, const std::vector<double>& yData )
|
||||
{
|
||||
m_curveTitles.push_back( curveTitle );
|
||||
m_xData.push_back( xData );
|
||||
m_yData.push_back( yData );
|
||||
}
|
||||
|
||||
const QString& curveTitle( size_t idx ) const { return m_curveTitles[idx]; }
|
||||
|
||||
size_t size() const { return m_xData.size(); }
|
||||
|
||||
size_t curveSize( size_t idx ) const { return m_xData[idx].size(); }
|
||||
|
||||
const std::vector<double>& xData( size_t idx ) const { return m_xData[idx]; }
|
||||
const std::vector<double>& yData( size_t idx ) const { return m_yData[idx]; }
|
||||
|
||||
private:
|
||||
QString m_xAxisTitle;
|
||||
QString m_yAxisTitle;
|
||||
std::vector<QString> m_curveTitles;
|
||||
std::vector<std::vector<double>> m_xData;
|
||||
std::vector<std::vector<double>> m_yData;
|
||||
};
|
||||
|
||||
struct VfpTableSelection
|
||||
{
|
||||
int flowRateIdx;
|
||||
int thpIdx;
|
||||
int articifialLiftQuantityIdx;
|
||||
int waterCutIdx;
|
||||
int gasLiquidRatioIdx;
|
||||
};
|
||||
|
||||
struct VfpTableInitialData
|
||||
{
|
||||
bool isProductionTable;
|
||||
int tableNumber;
|
||||
double datumDepth;
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase;
|
||||
RimVfpDefines::FlowingWaterFractionType waterFraction;
|
||||
RimVfpDefines::FlowingGasFractionType gasFraction;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RigVfpTables
|
||||
{
|
||||
public:
|
||||
void addInjectionTable( const Opm::VFPInjTable& table );
|
||||
void addProductionTable( const Opm::VFPProdTable& table );
|
||||
|
||||
std::vector<int> injectionTableNumbers() const;
|
||||
std::vector<int> productionTableNumbers() const;
|
||||
|
||||
VfpTableInitialData getTableInitialData( int tableIndex ) const;
|
||||
|
||||
std::vector<double> getProductionTableData( int tableIndex, RimVfpDefines::ProductionVariableType variableType ) const;
|
||||
|
||||
VfpPlotData populatePlotData( int tableIndex,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
const VfpTableSelection& tableSelection ) const;
|
||||
|
||||
QString asciiDataForTable( int tableNumber,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
const VfpTableSelection& tableSelection ) const;
|
||||
|
||||
private:
|
||||
static VfpPlotData populatePlotData( const Opm::VFPInjTable& table,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase );
|
||||
|
||||
static VfpPlotData populatePlotData( const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
RimVfpDefines::InterpolatedVariableType interpolatedVariable,
|
||||
RimVfpDefines::FlowingPhaseType flowingPhase,
|
||||
const VfpTableSelection& tableSelection );
|
||||
|
||||
static QString axisTitle( RimVfpDefines::ProductionVariableType variableType, RimVfpDefines::FlowingPhaseType flowingPhase );
|
||||
static QString getDisplayUnit( RimVfpDefines::ProductionVariableType variableType );
|
||||
static QString getDisplayUnitWithBracket( RimVfpDefines::ProductionVariableType variableType );
|
||||
|
||||
static double convertToDisplayUnit( double value, RimVfpDefines::ProductionVariableType variableType );
|
||||
static void convertToDisplayUnit( std::vector<double>& values, RimVfpDefines::ProductionVariableType variableType );
|
||||
|
||||
static QString textForPlotData( const VfpPlotData& plotData );
|
||||
|
||||
static std::vector<double> getProductionTableData( const Opm::VFPProdTable& table, RimVfpDefines::ProductionVariableType variableType );
|
||||
static size_t getVariableIndex( const Opm::VFPProdTable& table,
|
||||
RimVfpDefines::ProductionVariableType targetVariable,
|
||||
RimVfpDefines::ProductionVariableType primaryVariable,
|
||||
size_t primaryValue,
|
||||
RimVfpDefines::ProductionVariableType familyVariable,
|
||||
size_t familyValue,
|
||||
const VfpTableSelection& tableSelection );
|
||||
|
||||
std::optional<Opm::VFPInjTable> injectionTable( int tableNumber ) const;
|
||||
std::optional<Opm::VFPProdTable> productionTable( int tableNumber ) const;
|
||||
|
||||
static RimVfpDefines::FlowingPhaseType getFlowingPhaseType( const Opm::VFPProdTable& table );
|
||||
static RimVfpDefines::FlowingPhaseType getFlowingPhaseType( const Opm::VFPInjTable& table );
|
||||
static RimVfpDefines::FlowingWaterFractionType getFlowingWaterFractionType( const Opm::VFPProdTable& table );
|
||||
static RimVfpDefines::FlowingGasFractionType getFlowingGasFractionType( const Opm::VFPProdTable& table );
|
||||
|
||||
private:
|
||||
std::vector<Opm::VFPInjTable> m_injectionTables;
|
||||
std::vector<Opm::VFPProdTable> m_productionTables;
|
||||
};
|
Loading…
Reference in New Issue
Block a user