#1321 Wip: First shot on bringing the flow characteristics curves up into the open.

This commit is contained in:
Jacob Støren 2017-03-24 15:10:39 +01:00
parent f102befd84
commit 1fefc6124f
13 changed files with 644 additions and 28 deletions

View File

@ -11,6 +11,7 @@ ${CEE_CURRENT_LIST_DIR}RimWellAllocationPlot.h
${CEE_CURRENT_LIST_DIR}RimTotalWellAllocationPlot.h
${CEE_CURRENT_LIST_DIR}RimWellFlowRateCurve.h
${CEE_CURRENT_LIST_DIR}RimWellAllocationPlotLegend.h
${CEE_CURRENT_LIST_DIR}RimFlowCharacteristicsPlot.h
)
set (SOURCE_GROUP_SOURCE_FILES
@ -20,6 +21,7 @@ ${CEE_CURRENT_LIST_DIR}RimWellAllocationPlot.cpp
${CEE_CURRENT_LIST_DIR}RimTotalWellAllocationPlot.cpp
${CEE_CURRENT_LIST_DIR}RimWellFlowRateCurve.cpp
${CEE_CURRENT_LIST_DIR}RimWellAllocationPlotLegend.cpp
${CEE_CURRENT_LIST_DIR}RimFlowCharacteristicsPlot.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@ -0,0 +1,225 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimFlowCharacteristicsPlot.h"
#include "RimFlowDiagSolution.h"
#include "RimEclipseResultCase.h"
#include "RigFlowDiagResults.h"
#include "RiuFlowCharacteristicsPlot.h"
#include "RimProject.h"
CAF_PDM_SOURCE_INIT(RimFlowCharacteristicsPlot, "FlowCharacteristicsPlot");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowCharacteristicsPlot::RimFlowCharacteristicsPlot()
{
CAF_PDM_InitObject("Flow Characteristics", ":/WellAllocPie16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_case, "FlowCase", "Case", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_flowDiagSolution, "FlowDiagSolution", "Flow Diag Solution", "", "", "");
this->m_showWindow = false;
setAsPlotMdiWindow();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowCharacteristicsPlot::~RimFlowCharacteristicsPlot()
{
removeMdiWindowFromMdiArea();
deleteViewWidget();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::setFromFlowSolution(RimFlowDiagSolution* flowSolution)
{
if ( !flowSolution )
{
m_case = nullptr;
}
else
{
RimEclipseResultCase* eclCase;
flowSolution->firstAncestorOrThisOfType(eclCase);
m_case = eclCase;
}
m_flowDiagSolution = flowSolution;
loadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::deleteViewWidget()
{
if (m_flowCharPlotWidget)
{
m_flowCharPlotWidget->deleteLater();
m_flowCharPlotWidget= nullptr;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimFlowCharacteristicsPlot::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_case )
{
RimProject* proj = nullptr;
this->firstAncestorOrThisOfType(proj);
if ( proj )
{
std::vector<RimEclipseResultCase*> cases;
proj->descendantsIncludingThisOfType(cases);
for ( RimEclipseResultCase* c : cases )
{
options.push_back(caf::PdmOptionItemInfo(c->caseUserDescription(), c, false, c->uiIcon()));
}
}
}
else if ( fieldNeedingOptions == &m_flowDiagSolution )
{
if ( m_case )
{
std::vector<RimFlowDiagSolution*> flowSols = m_case->flowDiagSolutions();
for ( RimFlowDiagSolution* flowSol : flowSols )
{
options.push_back(caf::PdmOptionItemInfo("None", nullptr));
options.push_back(caf::PdmOptionItemInfo(flowSol->userDescription(), flowSol, false, flowSol->uiIcon()));
}
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimFlowCharacteristicsPlot::viewWidget()
{
return m_flowCharPlotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::zoomAll()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
RimViewWindow::fieldChangedByUi(changedField, oldValue, newValue);
if ( &m_case == changedField
|| &m_flowDiagSolution == changedField)
{
this->loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimFlowCharacteristicsPlot::snapshotWindowContent()
{
QImage image;
if (m_flowCharPlotWidget)
{
QPixmap pix = QPixmap::grabWidget(m_flowCharPlotWidget);
image = pix.toImage();
}
return image;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFlowCharacteristicsPlot::loadDataAndUpdate()
{
updateMdiWindowVisibility();
if (m_flowDiagSolution)
{
RigFlowDiagResults* flowResult = m_flowDiagSolution->flowDiagResults();
std::vector<int> calculatedTimesteps = flowResult->calculatedTimeSteps();
std::vector<QDateTime> timeStepDates = m_case->timeStepDates();
std::vector<double> lorenzVals(timeStepDates.size(), HUGE_VAL);
for (int timeStepIdx: calculatedTimesteps)
{
lorenzVals[timeStepIdx] = flowResult->flowCharacteristicsResults(timeStepIdx).m_lorenzCoefficient;
if ( m_flowCharPlotWidget)
{
const auto & flowCharResults = flowResult->flowCharacteristicsResults(timeStepIdx);
m_flowCharPlotWidget->addFlowCapStorageCapCurve(timeStepDates[timeStepIdx],
flowCharResults.m_flowCapStorageCapCurve.first,
flowCharResults.m_flowCapStorageCapCurve.second);
m_flowCharPlotWidget->addSweepEfficiencyCurve(timeStepDates[timeStepIdx],
flowCharResults.m_sweepEfficiencyCurve.first,
flowCharResults.m_sweepEfficiencyCurve.second);
}
}
if ( m_flowCharPlotWidget) m_flowCharPlotWidget->setLorenzCurve(timeStepDates, lorenzVals);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimFlowCharacteristicsPlot::createViewWidget(QWidget* mainWindowParent)
{
m_flowCharPlotWidget = new RiuFlowCharacteristicsPlot(this, mainWindowParent);
return m_flowCharPlotWidget;
}

View File

@ -0,0 +1,82 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimViewWindow.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
#include <QPointer>
class RimFlowDiagSolution;
class RimEclipseResultCase;
class RiuFlowCharacteristicsPlot;
namespace caf {
class PdmOptionItemInfo;
}
namespace cvf {
class Color3f;
}
//==================================================================================================
///
///
//==================================================================================================
class RimFlowCharacteristicsPlot : public RimViewWindow
{
CAF_PDM_HEADER_INIT;
public:
RimFlowCharacteristicsPlot();
virtual ~RimFlowCharacteristicsPlot();
void setFromFlowSolution(RimFlowDiagSolution* flowSolution);
// RimViewWindow overrides
virtual QWidget* viewWidget() override;
virtual void zoomAll() override;
virtual QWidget* createViewWidget(QWidget* mainWindowParent) override;
virtual void deleteViewWidget() override;
protected:
// RimViewWindow overrides
virtual void loadDataAndUpdate() override;
virtual QImage snapshotWindowContent() override;
// Overridden PDM methods
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
private:
caf::PdmPtrField<RimEclipseResultCase*> m_case;
caf::PdmPtrField<RimFlowDiagSolution*> m_flowDiagSolution;
QPointer<RiuFlowCharacteristicsPlot> m_flowCharPlotWidget;
};

View File

@ -19,6 +19,7 @@
#include "RimFlowPlotCollection.h"
#include "RimWellAllocationPlot.h"
#include "RimFlowCharacteristicsPlot.h"
#include "cvfAssert.h"
@ -33,6 +34,10 @@ RimFlowPlotCollection::RimFlowPlotCollection()
{
CAF_PDM_InitObject("Flow Diagnostics Plots", ":/WellAllocPlots16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_flowCharacteristicsPlot, "FlowCharacteristicsPlot", "", "", "", "");
m_flowCharacteristicsPlot.uiCapability()->setUiHidden(true);
m_flowCharacteristicsPlot = new RimFlowCharacteristicsPlot;
CAF_PDM_InitFieldNoDefault(&m_defaultPlot, "DefaultFlowPlot", "", "", "", "");
m_defaultPlot.uiCapability()->setUiHidden(true);

View File

@ -23,6 +23,7 @@
#include "cafPdmChildField.h"
class RimWellAllocationPlot;
class RimFlowCharacteristicsPlot;
//==================================================================================================
///
@ -43,6 +44,7 @@ public:
RimWellAllocationPlot* defaultPlot();
private:
caf::PdmChildField<RimFlowCharacteristicsPlot*> m_flowCharacteristicsPlot;
caf::PdmChildField<RimWellAllocationPlot*> m_defaultPlot;
caf::PdmChildArrayField<RimWellAllocationPlot*> m_flowPlots;
};

View File

@ -39,6 +39,7 @@ RigFlowDiagResults::RigFlowDiagResults(RimFlowDiagSolution* flowSolution, size_t
m_timeStepCount = timeStepCount;
m_hasAtemptedNativeResults.resize(timeStepCount, false);
m_injProdPairFluxCommunicationTimesteps.resize(timeStepCount);
m_flowCharResultFrames.resize(timeStepCount);
}
//--------------------------------------------------------------------------------------------------
@ -118,6 +119,12 @@ void RigFlowDiagResults::calculateNativeResultsIfNotPreviouslyAttempted(size_t f
m_injProdPairFluxCommunicationTimesteps[frameIndex].swap(nativeTimestepResults.injProdWellPairFluxes());
m_flowCharResultFrames[frameIndex].m_lorenzCoefficient = nativeTimestepResults.lorenzCoefficient();
m_flowCharResultFrames[frameIndex].m_flowCapStorageCapCurve.first.swap(nativeTimestepResults.flowCapStorageCapCurve().first);
m_flowCharResultFrames[frameIndex].m_flowCapStorageCapCurve.second.swap(nativeTimestepResults.flowCapStorageCapCurve().second);
m_flowCharResultFrames[frameIndex].m_sweepEfficiencyCurve.first.swap(nativeTimestepResults.sweepEfficiencyCurve().first);
m_flowCharResultFrames[frameIndex].m_sweepEfficiencyCurve.second.swap(nativeTimestepResults.sweepEfficiencyCurve().second);
m_hasAtemptedNativeResults[frameIndex] = true;
}
}
@ -652,3 +659,17 @@ double RigFlowDiagResults::maxAbsPairFlux(int frameIndex)
return maxFlux;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<int> RigFlowDiagResults::calculatedTimeSteps()
{
std::vector<int> timestepIndices;
for (size_t tsIdx = 0; tsIdx < m_timeStepCount; ++tsIdx)
{
if (m_hasAtemptedNativeResults[tsIdx]) timestepIndices.push_back(static_cast<int>(tsIdx));
}
return timestepIndices;
}

View File

@ -62,6 +62,21 @@ public:
std::pair<double, double> injectorProducerPairFluxes(const std::string& injTracername, const std::string& prodTracerName, int frameIndex);
double maxAbsPairFlux(int frameIndex);
std::vector<int> calculatedTimeSteps();
struct FlowCharacteristicsResultFrame
{
FlowCharacteristicsResultFrame() : m_lorenzCoefficient(HUGE_VAL) {}
using Curve = std::pair< std::vector<double>, std::vector<double> >;
Curve m_flowCapStorageCapCurve;
Curve m_sweepEfficiencyCurve;
double m_lorenzCoefficient;
};
const FlowCharacteristicsResultFrame& flowCharacteristicsResults(int frameIndex) { return m_flowCharResultFrames[frameIndex];}
private:
const std::vector<double>* findOrCalculateResult (const RigFlowDiagResultAddress& resVarAddr, size_t frameIndex);
void calculateNativeResultsIfNotPreviouslyAttempted(size_t frameIndex);
@ -118,6 +133,10 @@ private:
using InjectorProducerCommunicationMap = std::map< std::pair<std::string, std::string>, std::pair<double, double> >;
std::vector<InjectorProducerCommunicationMap> m_injProdPairFluxCommunicationTimesteps;
std::vector<FlowCharacteristicsResultFrame> m_flowCharResultFrames;
};

View File

@ -39,7 +39,7 @@
///
//--------------------------------------------------------------------------------------------------
RigFlowDiagTimeStepResult::RigFlowDiagTimeStepResult(size_t activeCellCount)
: m_activeCellCount(activeCellCount)
: m_activeCellCount(activeCellCount), m_lorenzCoefficient(HUGE_VAL)
{
}
@ -107,12 +107,16 @@ void RigFlowDiagTimeStepResult::addResult(const RigFlowDiagResultAddress& resAdd
class RigOpmFldStaticData : public cvf::Object
{
public:
RigOpmFldStaticData(const std::string& grid, const std::string& init) : eclGraph(Opm::ECLGraph::load(grid, init)), m_hasUnifiedRestartFile(false) {}
RigOpmFldStaticData(const std::string& grid, const std::string& init) : m_eclGraph(Opm::ECLGraph::load(grid, init)), m_hasUnifiedRestartFile(false)
{
m_poreVolume = m_eclGraph.poreVolume();
}
Opm::ECLGraph eclGraph;
std::unique_ptr<Opm::FlowDiagnostics::Toolbox> fldToolbox;
bool m_hasUnifiedRestartFile;
QStringList restartFileNames;
Opm::ECLGraph m_eclGraph;
std::vector<double> m_poreVolume;
std::unique_ptr<Opm::FlowDiagnostics::Toolbox> m_fldToolbox;
bool m_hasUnifiedRestartFile;
QStringList m_restartFileNames;
};
@ -168,31 +172,31 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
progressInfo.setProgressDescription("Calculating Connectivities");
const Opm::FlowDiagnostics::ConnectivityGraph connGraph =
Opm::FlowDiagnostics::ConnectivityGraph{ static_cast<int>(m_opmFldData->eclGraph.numCells()),
m_opmFldData->eclGraph.neighbours() };
Opm::FlowDiagnostics::ConnectivityGraph{ static_cast<int>(m_opmFldData->m_eclGraph.numCells()),
m_opmFldData->m_eclGraph.neighbours() };
progressInfo.incrementProgress();
progressInfo.setProgressDescription("Initialize Solver");
// Create the Toolbox.
m_opmFldData->fldToolbox.reset(new Opm::FlowDiagnostics::Toolbox{ connGraph });
m_opmFldData->fldToolbox->assignPoreVolume( m_opmFldData->eclGraph.poreVolume());
m_opmFldData->m_fldToolbox.reset(new Opm::FlowDiagnostics::Toolbox{ connGraph });
m_opmFldData->m_fldToolbox->assignPoreVolume( m_opmFldData->m_poreVolume);
// Look for unified restart file
QString restartFileName = RifEclipseOutputFileTools::firstFileNameOfType(m_filesWithSameBaseName, ECL_UNIFIED_RESTART_FILE);
if ( !restartFileName.isEmpty() )
{
m_opmFldData->eclGraph.assignFluxDataSource(restartFileName.toStdString());
m_opmFldData->m_eclGraph.assignFluxDataSource(restartFileName.toStdString());
m_opmFldData->m_hasUnifiedRestartFile = true;
}
else
{
m_opmFldData->restartFileNames = RifEclipseOutputFileTools::filterFileNamesOfType(m_filesWithSameBaseName, ECL_RESTART_FILE);
m_opmFldData->m_restartFileNames = RifEclipseOutputFileTools::filterFileNamesOfType(m_filesWithSameBaseName, ECL_RESTART_FILE);
size_t restartFileCount = static_cast<size_t>(m_opmFldData->restartFileNames.size());
size_t restartFileCount = static_cast<size_t>(m_opmFldData->m_restartFileNames.size());
size_t maxTimeStepCount = m_eclipseCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->maxTimeStepCount();
if (restartFileCount <= timeStepIndex && restartFileCount != maxTimeStepCount )
@ -201,7 +205,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
return result;
}
m_opmFldData->restartFileNames.sort(); // To make sure they are sorted in increasing *.X000N order. Hack. Should probably be actual time stored on file.
m_opmFldData->m_restartFileNames.sort(); // To make sure they are sorted in increasing *.X000N order. Hack. Should probably be actual time stored on file.
m_opmFldData->m_hasUnifiedRestartFile = false;
}
}
@ -211,8 +215,8 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
if ( ! m_opmFldData->m_hasUnifiedRestartFile )
{
QString restartFileName = m_opmFldData->restartFileNames[static_cast<int>(timeStepIndex)];
m_opmFldData->eclGraph.assignFluxDataSource(restartFileName.toStdString());
QString restartFileName = m_opmFldData->m_restartFileNames[static_cast<int>(timeStepIndex)];
m_opmFldData->m_eclGraph.assignFluxDataSource(restartFileName.toStdString());
}
size_t resultIndexWithMaxTimeSteps = cvf::UNDEFINED_SIZE_T;
@ -220,7 +224,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
int reportStepNumber = m_eclipseCase->eclipseCaseData()->results(RifReaderInterface::MATRIX_RESULTS)->reportStepNumber(resultIndexWithMaxTimeSteps, timeStepIndex);
if ( ! m_opmFldData->eclGraph.selectReportStep(reportStepNumber) )
if ( ! m_opmFldData->m_eclGraph.selectReportStep(reportStepNumber) )
{
QMessageBox::critical(nullptr, "ResInsight", "Flow Diagnostics: Could not find the requested timestep in the result file. Results will not be loaded.");
return result;
@ -231,20 +235,20 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
Opm::FlowDiagnostics::CellSetValues sumWellFluxPrCell;
{
Opm::FlowDiagnostics::ConnectionValues connectionsVals = RigFlowDiagInterfaceTools::extractFluxField(m_opmFldData->eclGraph, false);
Opm::FlowDiagnostics::ConnectionValues connectionsVals = RigFlowDiagInterfaceTools::extractFluxField(m_opmFldData->m_eclGraph, false);
m_opmFldData->fldToolbox->assignConnectionFlux(connectionsVals);
m_opmFldData->m_fldToolbox->assignConnectionFlux(connectionsVals);
progressInfo.incrementProgress();
Opm::ECLWellSolution wsol = Opm::ECLWellSolution{-1.0 , false};
const std::vector<Opm::ECLWellSolution::WellData> well_fluxes =
wsol.solution(m_opmFldData->eclGraph.rawResultData(), m_opmFldData->eclGraph.numGrids());
wsol.solution(m_opmFldData->m_eclGraph.rawResultData(), m_opmFldData->m_eclGraph.numGrids());
sumWellFluxPrCell = RigFlowDiagInterfaceTools::extractWellFlows(m_opmFldData->eclGraph, well_fluxes);
sumWellFluxPrCell = RigFlowDiagInterfaceTools::extractWellFlows(m_opmFldData->m_eclGraph, well_fluxes);
m_opmFldData->fldToolbox->assignInflowFlux(sumWellFluxPrCell);
m_opmFldData->m_fldToolbox->assignInflowFlux(sumWellFluxPrCell);
// Filter connection cells with inconsistent well in flow direction (Hack, we should do something better)
@ -295,7 +299,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
std::unique_ptr<Toolbox::Forward> injectorSolution;
try
{
injectorSolution.reset(new Toolbox::Forward( m_opmFldData->fldToolbox->computeInjectionDiagnostics(injectorCellSets)));
injectorSolution.reset(new Toolbox::Forward( m_opmFldData->m_fldToolbox->computeInjectionDiagnostics(injectorCellSets)));
}
catch (const std::exception& e)
{
@ -325,7 +329,7 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
std::unique_ptr<Toolbox::Reverse> producerSolution;
try
{
producerSolution.reset(new Toolbox::Reverse(m_opmFldData->fldToolbox->computeProductionDiagnostics(prodjCellSets)));
producerSolution.reset(new Toolbox::Reverse(m_opmFldData->m_fldToolbox->computeProductionDiagnostics(prodjCellSets)));
}
catch ( const std::exception& e )
{
@ -366,6 +370,21 @@ RigFlowDiagTimeStepResult RigFlowDiagSolverInterface::calculate(size_t timeStepI
}
}
}
try
{
Graph flowCapStorCapCurve = flowCapacityStorageCapacityCurve(*(injectorSolution.get()),
*(producerSolution.get()),
m_opmFldData->m_poreVolume);
result.setFlowCapStorageCapCurve(flowCapStorCapCurve);
result.setSweepEfficiencyCurve(sweepEfficiency(flowCapStorCapCurve));
result.setLorenzCoefficient(lorenzCoefficient(flowCapStorCapCurve));
}
catch ( const std::exception& e )
{
QMessageBox::critical(nullptr, "ResInsight", "Flow Diagnostics: " + QString(e.what()));
}
}
return result; // Relying on implicit move constructor

View File

@ -41,17 +41,30 @@ public:
const std::string& producerTracerName,
const std::pair<double, double>& injProdFluxes) ;
// Use to "steal" the data from this one using swap
std::map<RigFlowDiagResultAddress, std::vector<double> >& nativeResults() { return m_nativeResults; }
using Curve = std::pair< std::vector<double>, std::vector<double> >;
void setFlowCapStorageCapCurve(const Curve& flCapStCapCurve) { m_flowCapStorageCapCurve = flCapStCapCurve;}
void setSweepEfficiencyCurve(const Curve& sweepEffCurve) { m_sweepEfficiencyCurve = sweepEffCurve; }
void setLorenzCoefficient(double coeff) { m_lorenzCoefficient = coeff;}
// Used to "steal" the data from this one using swap
std::map<RigFlowDiagResultAddress, std::vector<double> >& nativeResults() { return m_nativeResults; }
std::map<std::pair<std::string, std::string>, std::pair<double, double> > & injProdWellPairFluxes() { return m_injProdWellPairFluxes; }
Curve& flowCapStorageCapCurve() { return m_flowCapStorageCapCurve; }
Curve& sweepEfficiencyCurve() { return m_sweepEfficiencyCurve; }
double lorenzCoefficient() { return m_lorenzCoefficient;}
private:
void addResult(const RigFlowDiagResultAddress& resAddr, const std::map<int, double>& cellValues);
std::map<RigFlowDiagResultAddress, std::vector<double> > m_nativeResults;
std::map<RigFlowDiagResultAddress, std::vector<double> > m_nativeResults;
std::map<std::pair<std::string, std::string>, std::pair<double, double> > m_injProdWellPairFluxes;
Curve m_flowCapStorageCapCurve;
Curve m_sweepEfficiencyCurve;
double m_lorenzCoefficient;
size_t m_activeCellCount;
};

View File

@ -39,6 +39,7 @@ ${CEE_CURRENT_LIST_DIR}RiuGeoMechXfTensorResultAccessor.h
${CEE_CURRENT_LIST_DIR}RiuFemTimeHistoryResultAccessor.h
${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.h
${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.h
${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.h
${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.h
${CEE_CURRENT_LIST_DIR}RiuMessagePanel.h
)
@ -78,6 +79,7 @@ ${CEE_CURRENT_LIST_DIR}RiuGeoMechXfTensorResultAccessor.cpp
${CEE_CURRENT_LIST_DIR}RiuFemTimeHistoryResultAccessor.cpp
${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.cpp
${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.cpp
${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.cpp
${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.cpp
${CEE_CURRENT_LIST_DIR}RiuMessagePanel.cpp
)
@ -107,6 +109,7 @@ ${CEE_CURRENT_LIST_DIR}RiuSummaryQwtPlot.h
${CEE_CURRENT_LIST_DIR}RiuQwtScalePicker.h
${CEE_CURRENT_LIST_DIR}RiuExportMultipleSnapshotsWidget.h
${CEE_CURRENT_LIST_DIR}RiuWellAllocationPlot.h
${CEE_CURRENT_LIST_DIR}RiuFlowCharacteristicsPlot.h
${CEE_CURRENT_LIST_DIR}RiuNightchartsWidget.h
${CEE_CURRENT_LIST_DIR}RiuMessagePanel.h
)

View File

@ -0,0 +1,154 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuFlowCharacteristicsPlot.h"
#include "RimFlowCharacteristicsPlot.h"
#include "RiuResultQwtPlot.h"
#include "qwt_plot.h"
#include "cvfBase.h"
#include "cvfColor3.h"
#include <QBoxLayout>
#include <QContextMenuEvent>
#include <QLabel>
#include <QMenu>
#include "RiuLineSegmentQwtPlotCurve.h"
#include <QDateTime>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuFlowCharacteristicsPlot::RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlot* plotDefinition, QWidget* parent)
: m_plotDefinition(plotDefinition),
QFrame(parent)
{
Q_ASSERT(m_plotDefinition);
QVBoxLayout* mainLayout = new QVBoxLayout();
this->setLayout(mainLayout);
this->layout()->setMargin(0);
this->layout()->setSpacing(2);
// White background
QPalette pal = this->palette();
pal.setColor(QPalette::Background, Qt::white);
this->setAutoFillBackground(true);
this->setPalette(pal);
m_lorenzPlot = new RiuResultQwtPlot(this);
m_flowCapVsStorageCapPlot = new RiuResultQwtPlot(this);
m_sweepEffPlot = new RiuResultQwtPlot(this);
mainLayout->addWidget(m_lorenzPlot);
mainLayout->addWidget(m_flowCapVsStorageCapPlot);
mainLayout->addWidget(m_sweepEffPlot);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuFlowCharacteristicsPlot::~RiuFlowCharacteristicsPlot()
{
if (m_plotDefinition)
{
m_plotDefinition->handleMdiWindowClosed();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::setLorenzCurve(const std::vector<QDateTime>& dateTimes, const std::vector<double>& timeHistoryValues)
{
m_lorenzPlot->deleteAllCurves();
m_lorenzPlot->addCurve("Lorenz Coefficient", cvf::Color3f::BLUE, dateTimes, timeHistoryValues);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::addFlowCapStorageCapCurve(const QDateTime& dateTime, const std::vector<double>& xVals, const std::vector<double>& yVals)
{
RiuLineSegmentQwtPlotCurve* plotCurve = new RiuLineSegmentQwtPlotCurve(dateTime.toString());
plotCurve->setSamplesFromTimeAndValues(xVals, yVals, false);
plotCurve->setTitle(dateTime.toString());
plotCurve->setPen(QPen(QColor(180, 0, 20)));
plotCurve->attach(m_flowCapVsStorageCapPlot);
m_flowCapVsStorageCapPlot->setAxisScale( QwtPlot::xBottom, 0.0, 1.0);
m_flowCapVsStorageCapPlot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::addSweepEfficiencyCurve(const QDateTime& dateTime, const std::vector<double>& xVals, const std::vector<double>& yVals)
{
RiuLineSegmentQwtPlotCurve* plotCurve = new RiuLineSegmentQwtPlotCurve(dateTime.toString());
plotCurve->setSamplesFromTimeAndValues(xVals, yVals, false);
plotCurve->setTitle(dateTime.toString());
plotCurve->setPen(QPen(QColor(180, 0, 20)));
plotCurve->attach(m_sweepEffPlot);
//m_sweepEffPlot->setAxisScale( QwtPlot::xBottom, 0.0, 1.0);
m_sweepEffPlot->replot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFlowCharacteristicsPlot* RiuFlowCharacteristicsPlot::ownerPlotDefinition()
{
return m_plotDefinition;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuFlowCharacteristicsPlot::minimumSizeHint() const
{
return QSize(0, 100);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QSize RiuFlowCharacteristicsPlot::sizeHint() const
{
return QSize(0, 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFlowCharacteristicsPlot::setDefaults()
{
}

View File

@ -0,0 +1,70 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "qwt_plot.h"
#include "cafPdmPointer.h"
#include <QPointer>
#include <QFrame>
class RimFlowCharacteristicsPlot;
class RiuNightchartsWidget;
class RiuResultQwtPlot;
class QLabel;
namespace cvf {
class Color3f;
}
//==================================================================================================
//
//
//
//==================================================================================================
class RiuFlowCharacteristicsPlot : public QFrame
{
Q_OBJECT;
public:
RiuFlowCharacteristicsPlot(RimFlowCharacteristicsPlot* plotDefinition, QWidget* parent = NULL);
virtual ~RiuFlowCharacteristicsPlot();
void setLorenzCurve(const std::vector<QDateTime>& dateTimes, const std::vector<double>& timeHistoryValues);
void addFlowCapStorageCapCurve(const QDateTime& dateTime, const std::vector<double>& xVals, const std::vector<double>& yVals);
void addSweepEfficiencyCurve(const QDateTime& dateTime, const std::vector<double>& xVals, const std::vector<double>& yVals);
RimFlowCharacteristicsPlot* ownerPlotDefinition();
protected:
virtual QSize sizeHint() const override;
virtual QSize minimumSizeHint() const override;
private:
void setDefaults();
private:
caf::PdmPointer<RimFlowCharacteristicsPlot> m_plotDefinition;
QPointer<RiuResultQwtPlot> m_lorenzPlot;
QPointer<RiuResultQwtPlot> m_flowCapVsStorageCapPlot;
QPointer<RiuResultQwtPlot> m_sweepEffPlot;
};

View File

@ -63,7 +63,8 @@ protected:
virtual QSize sizeHint() const override;
virtual QSize minimumSizeHint() const override;
virtual void contextMenuEvent(QContextMenuEvent *) override;
virtual void contextMenuEvent(QContextMenuEvent *) override;
private:
friend class RiuQwtPlotPicker;
QPointF closestCurvePoint(const QPoint& pos, QString* valueString, QString* timeString, int* yAxis) const;