mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#1321 Wip: First shot on bringing the flow characteristics curves up into the open.
This commit is contained in:
parent
f102befd84
commit
1fefc6124f
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
154
ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp
Normal file
154
ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp
Normal 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()
|
||||
{
|
||||
|
||||
}
|
||||
|
70
ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h
Normal file
70
ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h
Normal 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;
|
||||
|
||||
};
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user