mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Parse and display VFPPROD tables.
This commit is contained in:
parent
1b9a674213
commit
eea9e88bfe
@ -48,8 +48,6 @@
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp"
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
@ -58,6 +56,27 @@
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimVfpPlot, "VfpPlot" );
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimVfpPlot::TableType>::setUp()
|
||||
{
|
||||
addItem( RimVfpPlot::TableType::INJECTION, "INJECTION", "Injection" );
|
||||
addItem( RimVfpPlot::TableType::PRODUCTION, "PRODUCTION", "Production" );
|
||||
setDefault( RimVfpPlot::TableType::INJECTION );
|
||||
}
|
||||
|
||||
template <>
|
||||
void caf::AppEnum<RimVfpPlot::ProductionTableType>::setUp()
|
||||
{
|
||||
addItem( RimVfpPlot::ProductionTableType::LIQUID_FLOW_RATE, "LIQUID_FLOW_RATE", "Liquid Flow Rate" );
|
||||
addItem( RimVfpPlot::ProductionTableType::ARTIFICIAL_LIFT_QUANTITY, "ALQ", "Artificial Lift Quantity" );
|
||||
addItem( RimVfpPlot::ProductionTableType::WATER_CUT, "WATER_CUT", "Water Cut" );
|
||||
addItem( RimVfpPlot::ProductionTableType::GAS_LIQUID_RATIO, "GAS_LIQUID_RATIO", "Gas Liquid Ratio" );
|
||||
setDefault( RimVfpPlot::ProductionTableType::LIQUID_FLOW_RATE );
|
||||
}
|
||||
} // namespace caf
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -69,6 +88,19 @@ RimVfpPlot::RimVfpPlot()
|
||||
CAF_PDM_InitFieldNoDefault( &m_case, "Case", "Case", "", "", "" );
|
||||
CAF_PDM_InitField( &m_wellName, "WellName", QString( "None" ), "Well", "", "", "" );
|
||||
|
||||
caf::AppEnum<RimVfpPlot::TableType> defaultTableType = RimVfpPlot::TableType::INJECTION;
|
||||
CAF_PDM_InitField( &m_tableType, "TableType", defaultTableType, "Table Type", "", "", "" );
|
||||
|
||||
caf::AppEnum<RimVfpPlot::ProductionTableType> defaultProductionTableType =
|
||||
RimVfpPlot::ProductionTableType::LIQUID_FLOW_RATE;
|
||||
CAF_PDM_InitField( &m_productionTableType,
|
||||
"ProductionTableType",
|
||||
defaultProductionTableType,
|
||||
"Production Table Type",
|
||||
"",
|
||||
"",
|
||||
"" );
|
||||
|
||||
m_showWindow = false;
|
||||
m_showPlotLegends = true;
|
||||
|
||||
@ -325,41 +357,55 @@ void RimVfpPlot::onLoadDataAndUpdate()
|
||||
updateLegend();
|
||||
|
||||
QString phaseString = "N/A";
|
||||
bool isInjector = m_tableType == RimVfpPlot::TableType::INJECTION;
|
||||
if ( m_case && m_case->ensureReservoirCaseIsOpen() )
|
||||
{
|
||||
// TODO: extract data from data file
|
||||
//
|
||||
|
||||
std::set<std::string> wells = {"F2H", "C1H", "C2H", "C3H", "C4AH", "C4H", "F1H", "F3H", "F4H"};
|
||||
std::string strippedWellName = QString( m_wellName() ).remove( "-" ).toStdString();
|
||||
|
||||
if ( wells.find( strippedWellName ) != wells.end() )
|
||||
if ( isInjector )
|
||||
{
|
||||
QString gridFileName = m_case->gridFileName();
|
||||
std::cout << "Grid file name: " << gridFileName.toStdString() << std::endl;
|
||||
QFileInfo fi( gridFileName );
|
||||
std::set<std::string> wells = {"F2H", "C1H", "C2H", "C3H", "C4AH", "C4H", "F1H", "F3H", "F4H"};
|
||||
std::string strippedWellName = QString( m_wellName() ).remove( "-" ).toStdString();
|
||||
|
||||
std::string filename = fi.canonicalPath().toStdString() + "/INCLUDE/VFP/" + strippedWellName + ".Ecl";
|
||||
const std::vector<Opm::VFPInjTable> tables = RimVfpTableExtractor::extractVfpInjectionTables( filename );
|
||||
if ( wells.find( strippedWellName ) != wells.end() )
|
||||
{
|
||||
QString gridFileName = m_case->gridFileName();
|
||||
QFileInfo fi( gridFileName );
|
||||
|
||||
// TODO: populate with real data
|
||||
populatePlotWidgetWithCurveData( m_plotWidget, tables );
|
||||
std::string filename = fi.canonicalPath().toStdString() + "/INCLUDE/VFP/" + strippedWellName + ".Ecl";
|
||||
const std::vector<Opm::VFPInjTable> tables = RimVfpTableExtractor::extractVfpInjectionTables( filename );
|
||||
populatePlotWidgetWithCurveData( m_plotWidget, tables );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::set<std::string> wells = {"B1BH", "B2H", "B3H", "D1CH", "B4DH", "E1H", "D2H", "D3BH", "E3CH"};
|
||||
std::string strippedWellName = QString( m_wellName() ).remove( "-" ).toStdString();
|
||||
|
||||
// TODO: Maybe display the phase?
|
||||
// if ( m_phase == RiaDefines::OIL_PHASE )
|
||||
// phaseString = "Oil";
|
||||
// else if ( m_phase == RiaDefines::GAS_PHASE )
|
||||
// phaseString = "Gas";
|
||||
// else if ( m_phase == RiaDefines::WATER_PHASE )
|
||||
// phaseString = "Water";
|
||||
if ( wells.find( strippedWellName ) != wells.end() )
|
||||
{
|
||||
QString gridFileName = m_case->gridFileName();
|
||||
QFileInfo fi( gridFileName );
|
||||
|
||||
std::string filename = fi.canonicalPath().toStdString() + "/INCLUDE/VFP/" + strippedWellName + ".Ecl";
|
||||
const std::vector<Opm::VFPProdTable> tables = RimVfpTableExtractor::extractVfpProductionTables( filename );
|
||||
populatePlotWidgetWithCurveData( m_plotWidget, tables, m_productionTableType() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QString plotTitleStr = QString( "%1 Vertical Flow Performance Plot" ).arg( m_wellName );
|
||||
m_plotWidget->setTitle( plotTitleStr );
|
||||
|
||||
m_plotWidget->setAxisTitleText( QwtPlot::xBottom, "Liquid Flow Rate [sm3/d]" );
|
||||
m_plotWidget->setAxisTitleText( QwtPlot::yLeft, "Bottom Hole Pressure [Bar]" );
|
||||
if ( isInjector )
|
||||
{
|
||||
m_plotWidget->setAxisTitleText( QwtPlot::xBottom, "Liquid Flow Rate [sm3/d]" );
|
||||
m_plotWidget->setAxisTitleText( QwtPlot::yLeft, "Bottom Hole Pressure [Bar]" );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_plotWidget->setAxisTitleText( QwtPlot::xBottom, "x axis (todo) [x axis unit]" );
|
||||
m_plotWidget->setAxisTitleText( QwtPlot::yLeft, "y axis [y axis unit]" );
|
||||
}
|
||||
|
||||
m_plotWidget->setAxisTitleEnabled( QwtPlot::xBottom, true );
|
||||
m_plotWidget->setAxisTitleEnabled( QwtPlot::yLeft, true );
|
||||
|
||||
@ -424,7 +470,101 @@ void RimVfpPlot::populatePlotWidgetWithCurveData( RiuQwtPlotWidget* plotWidget,
|
||||
QwtPlotCurve* curve = new QwtPlotCurve;
|
||||
// Convert from Pascal to Bar
|
||||
curve->setTitle( QString( "THP: %1 Bar" ).arg( table.getTHPAxis()[thp] / 100000.0 ) );
|
||||
// curve->setBrush( qtClr );
|
||||
QwtSymbol* symbol = new QwtSymbol( QwtSymbol::Ellipse, QBrush( qtClr ), QPen( Qt::red, 2 ), QSize( 8, 8 ) );
|
||||
curve->setSymbol( symbol );
|
||||
|
||||
curve->setSamples( xVals.data(), yVals.data(), numValues );
|
||||
curve->attach( plotWidget );
|
||||
curve->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimVfpPlot::populatePlotWidgetWithCurveData( RiuQwtPlotWidget* plotWidget,
|
||||
const std::vector<Opm::VFPProdTable>& tables,
|
||||
RimVfpPlot::ProductionTableType productionTableType )
|
||||
{
|
||||
cvf::Trace::show( "RimVfpPlot::populatePlotWidgetWithCurves()" );
|
||||
|
||||
plotWidget->detachItems( QwtPlotItem::Rtti_PlotCurve );
|
||||
plotWidget->setAxisScale( QwtPlot::xBottom, 0, 1 );
|
||||
plotWidget->setAxisScale( QwtPlot::yLeft, 0, 1 );
|
||||
plotWidget->setAxisAutoScale( QwtPlot::xBottom, true );
|
||||
plotWidget->setAxisAutoScale( QwtPlot::yLeft, true );
|
||||
|
||||
size_t numTables = tables.size();
|
||||
|
||||
for ( size_t i = 0; i < numTables; i++ )
|
||||
{
|
||||
const Opm::VFPProdTable table = tables[i];
|
||||
std::cout << "Datum depth: " << table.getDatumDepth() << std::endl;
|
||||
std::cout << "Table number: " << table.getTableNum() << std::endl;
|
||||
std::cout << "Flow type: " << static_cast<int>( table.getFloType() ) << std::endl;
|
||||
std::cout << "Flo axis: " << table.getFloAxis().size() << std::endl;
|
||||
std::cout << "THP axis: " << table.getTHPAxis().size() << std::endl;
|
||||
std::cout << "WFR axis: " << table.getWFRAxis().size() << std::endl;
|
||||
std::cout << "GFR axis: " << table.getGFRAxis().size() << std::endl;
|
||||
std::cout << "ALQ axis: " << table.getALQAxis().size() << std::endl;
|
||||
|
||||
std::cout << "THP Axis:\n";
|
||||
for ( size_t x = 0; x < table.getTHPAxis().size(); x++ )
|
||||
{
|
||||
std::cout << " " << table.getTHPAxis()[x];
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
for ( size_t thp_idx = 0; thp_idx < table.getTHPAxis().size(); thp_idx++ )
|
||||
{
|
||||
size_t wfr_idx = table.getWFRAxis().size() - 1;
|
||||
size_t gfr_idx = table.getGFRAxis().size() - 1;
|
||||
size_t alq_idx = table.getALQAxis().size() - 1;
|
||||
size_t flo_idx = table.getFloAxis().size() - 1;
|
||||
|
||||
std::vector<double> xVals;
|
||||
if ( productionTableType == RimVfpPlot::ProductionTableType::WATER_CUT )
|
||||
{
|
||||
xVals = table.getWFRAxis();
|
||||
}
|
||||
else if ( productionTableType == RimVfpPlot::ProductionTableType::GAS_LIQUID_RATIO )
|
||||
{
|
||||
xVals = table.getGFRAxis();
|
||||
}
|
||||
else if ( productionTableType == RimVfpPlot::ProductionTableType::ARTIFICIAL_LIFT_QUANTITY )
|
||||
{
|
||||
xVals = table.getALQAxis();
|
||||
}
|
||||
else if ( productionTableType == RimVfpPlot::ProductionTableType::LIQUID_FLOW_RATE )
|
||||
{
|
||||
xVals = table.getFloAxis();
|
||||
}
|
||||
|
||||
size_t numValues = xVals.size();
|
||||
std::vector<double> yVals( numValues, 0.0 );
|
||||
|
||||
for ( size_t y = 0; y < numValues; y++ )
|
||||
{
|
||||
if ( productionTableType == RimVfpPlot::ProductionTableType::WATER_CUT )
|
||||
wfr_idx = y;
|
||||
else if ( productionTableType == RimVfpPlot::ProductionTableType::GAS_LIQUID_RATIO )
|
||||
gfr_idx = y;
|
||||
else if ( productionTableType == RimVfpPlot::ProductionTableType::ARTIFICIAL_LIFT_QUANTITY )
|
||||
alq_idx = y;
|
||||
else if ( productionTableType == RimVfpPlot::ProductionTableType::LIQUID_FLOW_RATE )
|
||||
flo_idx = y;
|
||||
|
||||
// Convert from Pascal to Bar
|
||||
yVals[y] = table( thp_idx, wfr_idx, gfr_idx, alq_idx, flo_idx ) / 100000.0;
|
||||
}
|
||||
|
||||
cvf::Color3f cvfClr = cvf::Color3::BLUE;
|
||||
QColor qtClr = RiaColorTools::toQColor( cvfClr );
|
||||
|
||||
QwtPlotCurve* curve = new QwtPlotCurve;
|
||||
// Convert from Pascal to Bar
|
||||
curve->setTitle( QString( "THP: %1 Bar" ).arg( table.getTHPAxis()[thp_idx] / 100000.0 ) );
|
||||
QwtSymbol* symbol = new QwtSymbol( QwtSymbol::Ellipse, QBrush( qtClr ), QPen( Qt::red, 2 ), QSize( 8, 8 ) );
|
||||
curve->setSymbol( symbol );
|
||||
|
||||
@ -442,8 +582,12 @@ void RimVfpPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiO
|
||||
{
|
||||
uiOrdering.add( &m_case );
|
||||
uiOrdering.add( &m_wellName );
|
||||
uiOrdering.add( &m_tableType );
|
||||
uiOrdering.add( &m_productionTableType );
|
||||
m_productionTableType.uiCapability()->setUiHidden( m_tableType != RimVfpPlot::TableType::PRODUCTION );
|
||||
|
||||
RimPlot::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
// RimPlot::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <QPointer>
|
||||
|
||||
#include "opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp"
|
||||
#include "opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp"
|
||||
|
||||
class RimEclipseResultCase;
|
||||
class RimFlowDiagSolution;
|
||||
@ -39,6 +40,20 @@ class RimVfpPlot : public RimPlot
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class TableType
|
||||
{
|
||||
INJECTION,
|
||||
PRODUCTION
|
||||
};
|
||||
|
||||
enum class ProductionTableType
|
||||
{
|
||||
LIQUID_FLOW_RATE,
|
||||
ARTIFICIAL_LIFT_QUANTITY,
|
||||
WATER_CUT,
|
||||
GAS_LIQUID_RATIO
|
||||
};
|
||||
|
||||
RimVfpPlot();
|
||||
~RimVfpPlot() override;
|
||||
|
||||
@ -82,6 +97,9 @@ private:
|
||||
|
||||
void fixupDependentFieldsAfterCaseChange();
|
||||
static void populatePlotWidgetWithCurveData( RiuQwtPlotWidget* plotWidget, const std::vector<Opm::VFPInjTable>& tables );
|
||||
static void populatePlotWidgetWithCurveData( RiuQwtPlotWidget* plotWidget,
|
||||
const std::vector<Opm::VFPProdTable>& tables,
|
||||
RimVfpPlot::ProductionTableType productionTableType );
|
||||
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
@ -93,5 +111,8 @@ private:
|
||||
caf::PdmPtrField<RimEclipseResultCase*> m_case;
|
||||
caf::PdmField<QString> m_wellName;
|
||||
|
||||
caf::PdmField<caf::AppEnum<RimVfpPlot::TableType>> m_tableType;
|
||||
caf::PdmField<caf::AppEnum<RimVfpPlot::ProductionTableType>> m_productionTableType;
|
||||
|
||||
QPointer<RiuQwtPlotWidget> m_plotWidget;
|
||||
};
|
||||
|
@ -65,3 +65,29 @@ std::vector<Opm::VFPInjTable> RimVfpTableExtractor::extractVfpInjectionTables( c
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<Opm::VFPProdTable> RimVfpTableExtractor::extractVfpProductionTables( const std::string& filename )
|
||||
{
|
||||
std::vector<Opm::VFPProdTable> tables;
|
||||
|
||||
Opm::Parser parser;
|
||||
auto deck = parser.parseFile( filename );
|
||||
|
||||
std::string myKeyword = "VFPPROD";
|
||||
auto keywordList = deck.getKeywordList( myKeyword );
|
||||
|
||||
Opm::UnitSystem unitSystem;
|
||||
|
||||
for ( auto kw : keywordList )
|
||||
{
|
||||
auto name = kw->name();
|
||||
|
||||
Opm::VFPProdTable table( *kw, unitSystem );
|
||||
tables.push_back( table );
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp"
|
||||
#include "opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
@ -29,5 +30,6 @@
|
||||
class RimVfpTableExtractor
|
||||
{
|
||||
public:
|
||||
static std::vector<Opm::VFPInjTable> extractVfpInjectionTables( const std::string& filename );
|
||||
static std::vector<Opm::VFPInjTable> extractVfpInjectionTables( const std::string& filename );
|
||||
static std::vector<Opm::VFPProdTable> extractVfpProductionTables( const std::string& filename );
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user