#3096 Implemented ensemble calulations

This commit is contained in:
Bjørn Erik Jensen 2018-06-25 15:14:47 +02:00
parent 2ea84bdb63
commit 898df5b68a
44 changed files with 1378 additions and 99 deletions

View File

@ -57,6 +57,7 @@
#include "RimRftPlotCollection.h" #include "RimRftPlotCollection.h"
#include "RimStimPlanColors.h" #include "RimStimPlanColors.h"
#include "RimSummaryCase.h" #include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCaseMainCollection.h" #include "RimSummaryCaseMainCollection.h"
#include "RimSummaryCrossPlotCollection.h" #include "RimSummaryCrossPlotCollection.h"
#include "RimSummaryPlot.h" #include "RimSummaryPlot.h"
@ -597,6 +598,17 @@ bool RiaApplication::loadProject(const QString& projectFileName, ProjectLoadActi
cas->intersectionViewCollection()->syncFromExistingIntersections(false); cas->intersectionViewCollection()->syncFromExistingIntersections(false);
} }
// Init summary case groups
for (RimOilField* oilField : m_project->oilFields)
{
auto sumMainCollection = oilField->summaryCaseMainCollection();
if(!sumMainCollection) continue;
for (auto sumCaseGroup : sumMainCollection->summaryCaseCollections())
{
sumCaseGroup->loadDataAndUpdate();
}
}
loadAndUpdatePlotData(); loadAndUpdatePlotData();

View File

@ -130,7 +130,7 @@ std::vector<QString> RiaSummaryCurveAnalyzer::identifierTexts(RifEclipseSummaryA
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<RifEclipseSummaryAddress> std::vector<RifEclipseSummaryAddress>
RiaSummaryCurveAnalyzer::addressesForCategory(const std::vector<RifEclipseSummaryAddress>& addresses, RiaSummaryCurveAnalyzer::addressesForCategory(const std::set<RifEclipseSummaryAddress>& addresses,
RifEclipseSummaryAddress::SummaryVarCategory category) RifEclipseSummaryAddress::SummaryVarCategory category)
{ {
std::vector<RifEclipseSummaryAddress> filteredAddresses; std::vector<RifEclipseSummaryAddress> filteredAddresses;

View File

@ -50,7 +50,7 @@ public:
std::vector<QString> identifierTexts(RifEclipseSummaryAddress::SummaryVarCategory category) const; std::vector<QString> identifierTexts(RifEclipseSummaryAddress::SummaryVarCategory category) const;
static std::vector<RifEclipseSummaryAddress> addressesForCategory(const std::vector<RifEclipseSummaryAddress>& addresses, static std::vector<RifEclipseSummaryAddress> addressesForCategory(const std::set<RifEclipseSummaryAddress>& addresses,
RifEclipseSummaryAddress::SummaryVarCategory category); RifEclipseSummaryAddress::SummaryVarCategory category);
private: private:

View File

@ -36,19 +36,20 @@ CAF_CMD_SOURCE_INIT(RicCreateSummaryCaseCollectionFeature, "RicCreateSummaryCase
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RicCreateSummaryCaseCollectionFeature::groupSummaryCases(std::vector<RimSummaryCase*> cases, const QString& groupName, bool isEnsemble) RimSummaryCaseCollection* RicCreateSummaryCaseCollectionFeature::groupSummaryCases(std::vector<RimSummaryCase*> cases, const QString& groupName, bool isEnsemble)
{ {
RimSummaryCaseMainCollection* summaryCaseMainCollection = nullptr; RimSummaryCaseMainCollection* summaryCaseMainCollection = nullptr;
if (!cases.empty()) if (!cases.empty())
{ {
cases[0]->firstAncestorOrThisOfTypeAsserted(summaryCaseMainCollection); cases[0]->firstAncestorOrThisOfTypeAsserted(summaryCaseMainCollection);
summaryCaseMainCollection->addCaseCollection(cases, groupName, isEnsemble); auto newGroup = summaryCaseMainCollection->addCaseCollection(cases, groupName, isEnsemble);
summaryCaseMainCollection->updateConnectedEditors(); summaryCaseMainCollection->updateConnectedEditors();
RiuPlotMainWindowTools::showPlotMainWindow(); RiuPlotMainWindowTools::showPlotMainWindow();
RiuPlotMainWindowTools::selectAsCurrentItem(summaryCaseMainCollection->summaryCaseCollections().back()->allSummaryCases().front()); return newGroup;
} }
return nullptr;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -23,6 +23,7 @@
#include <vector> #include <vector>
class RimSummaryCase; class RimSummaryCase;
class RimSummaryCaseCollection;
//================================================================================================== //==================================================================================================
/// ///
@ -31,7 +32,7 @@ class RicCreateSummaryCaseCollectionFeature : public caf::CmdFeature
{ {
CAF_CMD_HEADER_INIT; CAF_CMD_HEADER_INIT;
static void groupSummaryCases(std::vector<RimSummaryCase*> cases, const QString& groupName, bool isEnsemble = false); static RimSummaryCaseCollection* groupSummaryCases(std::vector<RimSummaryCase*> cases, const QString& groupName, bool isEnsemble = false);
private: private:
virtual bool isCommandEnabled() override; virtual bool isCommandEnabled() override;

View File

@ -130,13 +130,12 @@ void RicImportEnsembleFeature::onActionTriggered(bool isChecked)
validateEnsembleCases(cases); validateEnsembleCases(cases);
RicImportSummaryCasesFeature::addSummaryCases(cases); RicImportSummaryCasesFeature::addSummaryCases(cases);
RicCreateSummaryCaseCollectionFeature::groupSummaryCases(cases, ensembleName, true); auto newGroup = RicCreateSummaryCaseCollectionFeature::groupSummaryCases(cases, ensembleName, true);
RiuPlotMainWindow* mainPlotWindow = app->getOrCreateAndShowMainPlotWindow(); RiuPlotMainWindow* mainPlotWindow = app->getOrCreateAndShowMainPlotWindow();
if (mainPlotWindow && !cases.empty()) if (mainPlotWindow && newGroup)
{ {
mainPlotWindow->selectAsCurrentItem(cases.back()); mainPlotWindow->selectAsCurrentItem(newGroup);
mainPlotWindow->updateSummaryPlotToolBar(); mainPlotWindow->updateSummaryPlotToolBar();
} }

View File

@ -35,6 +35,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCrossPlotCurveFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryEnsembleCurveSetFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryEnsembleCurveSetFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicPasteEnsembleCurveSetFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicPasteEnsembleCurveSetFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewEnsembleCurveFilterFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewEnsembleCurveFilterFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewDerivedEnsembleFeature.h
) )
set (SOURCE_GROUP_SOURCE_FILES set (SOURCE_GROUP_SOURCE_FILES
@ -73,6 +74,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCrossPlotCurveFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryEnsembleCurveSetFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryEnsembleCurveSetFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicPasteEnsembleCurveSetFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicPasteEnsembleCurveSetFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewEnsembleCurveFilterFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewEnsembleCurveFilterFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewDerivedEnsembleFeature.cpp
) )
list(APPEND CODE_HEADER_FILES list(APPEND CODE_HEADER_FILES

View File

@ -0,0 +1,86 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RicNewDerivedEnsembleFeature.h"
#include "RiaApplication.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimProject.h"
#include "RimSummaryCaseMainCollection.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include <QAction>
#include <memory>
CAF_CMD_SOURCE_INIT(RicNewDerivedEnsembleFeature, "RicNewDerivedEnsembleFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewDerivedEnsembleFeature::isCommandEnabled()
{
std::vector<RimSummaryCaseMainCollection*> mainColls = caf::selectedObjectsByTypeStrict<RimSummaryCaseMainCollection*>();
std::vector<RimSummaryCaseCollection*> ensembles = caf::selectedObjectsByTypeStrict<RimSummaryCaseCollection*>();
return mainColls.size() == 1 || ensembles.size() == 1 || ensembles.size() == 2;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewDerivedEnsembleFeature::onActionTriggered(bool isChecked)
{
if (isCommandEnabled())
{
auto project = RiaApplication::instance()->project();
auto mainColl = project->firstSummaryCaseMainCollection();
auto newColl = mainColl->addCaseCollection({}, "", true, []() {return new RimDerivedEnsembleCaseCollection(); });
auto newEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(newColl);
{
std::vector<RimSummaryCaseCollection*> ensembles = caf::selectedObjectsByType<RimSummaryCaseCollection*>();
if (ensembles.size() >= 1) newEnsemble->setEnsemble1(ensembles[0]);
if (ensembles.size() == 2)
{
newEnsemble->setEnsemble2(ensembles[1]);
newEnsemble->updateDerivedEnsembleCases();
}
}
mainColl->updateConnectedEditors();
RiuPlotMainWindowTools::selectAsCurrentItem(newEnsemble);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewDerivedEnsembleFeature::setupActionLook(QAction* actionToSetup)
{
actionToSetup->setText("New Derived Ensemble");
actionToSetup->setIcon(QIcon(":/SummaryEnsemble16x16.png"));
}

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "cafCmdFeature.h"
class RimSummaryPlotCollection;
class RimSummaryCase;
class RimSummaryPlot;
//==================================================================================================
///
//==================================================================================================
class RicNewDerivedEnsembleFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
// Overrides
virtual bool isCommandEnabled();
virtual void onActionTriggered( bool isChecked );
virtual void setupActionLook(QAction* actionToSetup);
};

View File

@ -27,6 +27,7 @@
#include "RifReaderEclipseSummary.h" #include "RifReaderEclipseSummary.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSet.h"
#include "RimEnsembleCurveSetCollection.h" #include "RimEnsembleCurveSetCollection.h"
#include "RimEnsembleCurveSetColorManager.h" #include "RimEnsembleCurveSetColorManager.h"
@ -509,13 +510,13 @@ std::set<std::string> RicSummaryCurveCreator::getAllSummaryWellNames()
if (reader) if (reader)
{ {
const std::vector<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses(); const std::set<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
for (size_t i = 0; i < allAddresses.size(); i++) for(auto& address : allAddresses)
{ {
if (allAddresses[i].category() == RifEclipseSummaryAddress::SUMMARY_WELL) if (address.category() == RifEclipseSummaryAddress::SUMMARY_WELL)
{ {
summaryWellNames.insert(allAddresses[i].wellName()); summaryWellNames.insert(address.wellName());
} }
} }
} }

View File

@ -43,6 +43,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleParametersReader.h
${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.h ${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.h
${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.h ${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.h
${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.h ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.h
${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.h
# HDF5 file reader is directly included in ResInsight main CmakeList.txt # HDF5 file reader is directly included in ResInsight main CmakeList.txt
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.h #${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.h
@ -90,6 +91,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleParametersReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.cpp
# HDF5 file reader is directly included in ResInsight main CmakeList.txt # HDF5 file reader is directly included in ResInsight main CmakeList.txt
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp #${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp

View File

@ -26,6 +26,7 @@
#include <QStringList> #include <QStringList>
#include <QDir> #include <QDir>
#include <functional>
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Constants /// Constants
@ -166,8 +167,6 @@ void RifCaseRealizationParametersReader::openFile()
if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text)) if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text))
{ {
closeFile(); closeFile();
//delete m_file;
//m_file = nullptr;
throw FileParseException(QString("Failed to open %1").arg(m_fileName)); throw FileParseException(QString("Failed to open %1").arg(m_fileName));
} }
} }

View File

@ -56,6 +56,7 @@ private:
void closeDataStream(); void closeDataStream();
void openFile(); void openFile();
void closeFile(); void closeFile();
private: private:
std::shared_ptr<RigCaseRealizationParameters> m_parameters; std::shared_ptr<RigCaseRealizationParameters> m_parameters;

View File

@ -163,7 +163,7 @@ void RifColumnBasedUserData::buildTimeStepsAndMappings()
{ {
RifEclipseSummaryAddress sumAddress = ci.summaryAddress; RifEclipseSummaryAddress sumAddress = ci.summaryAddress;
m_allResultAddresses.push_back(sumAddress); m_allResultAddresses.insert(sumAddress);
m_mapFromAddressToTimeStepIndex[sumAddress] = m_timeSteps.size() - 1; m_mapFromAddressToTimeStepIndex[sumAddress] = m_timeSteps.size() - 1;
m_mapFromAddressToResultIndex[sumAddress] = std::make_pair(tableIndex, columIndex); m_mapFromAddressToResultIndex[sumAddress] = std::make_pair(tableIndex, columIndex);

View File

@ -158,7 +158,7 @@ void RifCsvUserData::buildTimeStepsAndMappings()
{ {
RifEclipseSummaryAddress sumAddress = ci.summaryAddress; RifEclipseSummaryAddress sumAddress = ci.summaryAddress;
m_allResultAddresses.push_back(sumAddress); m_allResultAddresses.insert(sumAddress);
if (sumAddress.isErrorResult()) m_allErrorAddresses.insert(sumAddress); if (sumAddress.isErrorResult()) m_allErrorAddresses.insert(sumAddress);
m_mapFromAddressToTimeStepIndex[sumAddress] = m_timeSteps.size() - 1; m_mapFromAddressToTimeStepIndex[sumAddress] = m_timeSteps.size() - 1;

View File

@ -0,0 +1,73 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RifDerivedEnsembleReader.h"
#include "RimDerivedEnsembleCase.h"
static const std::vector<time_t> EMPTY_TIME_STEPS_VECTOR;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifDerivedEnsembleReader::RifDerivedEnsembleReader(RimDerivedEnsembleCase* derivedCase)
{
CVF_ASSERT(derivedCase);
m_derivedCase = derivedCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<time_t>& RifDerivedEnsembleReader::timeSteps(const RifEclipseSummaryAddress& resultAddress) const
{
if (!resultAddress.isValid()) return EMPTY_TIME_STEPS_VECTOR;
if (m_derivedCase->needsCalculation(resultAddress))
{
m_derivedCase->calculate(resultAddress);
}
return m_derivedCase->timeSteps(resultAddress);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifDerivedEnsembleReader::values(const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values) const
{
if (!resultAddress.isValid()) return false;
if (m_derivedCase->needsCalculation(resultAddress))
{
m_derivedCase->calculate(resultAddress);
}
auto dataValues = m_derivedCase->values(resultAddress);
values->clear();
values->reserve(dataValues.size());
for (auto val : dataValues) values->push_back(val);
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RifDerivedEnsembleReader::unitName(const RifEclipseSummaryAddress& resultAddress) const
{
return "";
}

View File

@ -0,0 +1,42 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RifEclipseSummaryAddress.h"
#include "RifSummaryReaderInterface.h"
class RimDerivedEnsembleCase;
//==================================================================================================
///
//==================================================================================================
class RifDerivedEnsembleReader : public RifSummaryReaderInterface
{
public:
RifDerivedEnsembleReader(RimDerivedEnsembleCase* derivedCase);
virtual const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& resultAddress) const override;
virtual bool values(const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values) const override;
virtual std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
private:
RimDerivedEnsembleCase* m_derivedCase;
};

View File

@ -167,7 +167,7 @@ QString RifEclipseSummaryTools::findGridCaseFileFromSummaryHeaderFile(const QStr
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RifEclipseSummaryTools::dumpMetaData(RifSummaryReaderInterface* readerEclipseSummary) void RifEclipseSummaryTools::dumpMetaData(RifSummaryReaderInterface* readerEclipseSummary)
{ {
std::vector<RifEclipseSummaryAddress> addresses = readerEclipseSummary->allResultAddresses(); std::set<RifEclipseSummaryAddress> addresses = readerEclipseSummary->allResultAddresses();
for (int category = 0; category < RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR; category++) for (int category = 0; category < RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR; category++)
{ {

View File

@ -32,7 +32,7 @@ RifEnsembleStatisticsReader::RifEnsembleStatisticsReader(RimEnsembleStatisticsCa
m_ensembleStatCase = ensStatCase; m_ensembleStatCase = ensStatCase;
m_allResultAddresses = std::vector<RifEclipseSummaryAddress>( m_allResultAddresses = std::set<RifEclipseSummaryAddress>(
{ {
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P10_QUANTITY_NAME, ""), RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P10_QUANTITY_NAME, ""),
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P50_QUANTITY_NAME, ""), RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P50_QUANTITY_NAME, ""),
@ -46,7 +46,7 @@ RifEnsembleStatisticsReader::RifEnsembleStatisticsReader(RimEnsembleStatisticsCa
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
const std::vector<time_t>& RifEnsembleStatisticsReader::timeSteps(const RifEclipseSummaryAddress& resultAddress) const const std::vector<time_t>& RifEnsembleStatisticsReader::timeSteps(const RifEclipseSummaryAddress& resultAddress) const
{ {
if (!resultAddress.isValid()) return EMPTY_TIME_STEPS_VECTOR; if (!validateAddress(resultAddress)) return EMPTY_TIME_STEPS_VECTOR;
return m_ensembleStatCase->timeSteps(); return m_ensembleStatCase->timeSteps();
} }
@ -78,7 +78,7 @@ bool RifEnsembleStatisticsReader::values(const RifEclipseSummaryAddress& resultA
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::string RifEnsembleStatisticsReader::unitName(const RifEclipseSummaryAddress& resultAddress) const std::string RifEnsembleStatisticsReader::unitName(const RifEclipseSummaryAddress& resultAddress) const
{ {
return "(RifEnsembleStatisticsReader::unitName)"; return "";
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -179,7 +179,7 @@ bool RifKeywordVectorUserData::parse(const QString& data, const QString& customW
-1, -1,
false); false);
m_allResultAddresses.push_back(addr); m_allResultAddresses.insert(addr);
m_mapFromAddressToTimeIndex[addr] = timeStepIndexIterator->second; m_mapFromAddressToTimeIndex[addr] = timeStepIndexIterator->second;
m_mapFromAddressToVectorIndex[addr] = i; m_mapFromAddressToVectorIndex[addr] = i;

View File

@ -441,7 +441,7 @@ void RifReaderEclipseSummary::buildMetaData()
{ {
const smspec_node_type * ertSumVarNode = ecl_smspec_iget_node(m_ecl_SmSpec, i); const smspec_node_type * ertSumVarNode = ecl_smspec_iget_node(m_ecl_SmSpec, i);
RifEclipseSummaryAddress addr = addressFromErtSmSpecNode(ertSumVarNode); RifEclipseSummaryAddress addr = addressFromErtSmSpecNode(ertSumVarNode);
m_allResultAddresses.push_back(addr); m_allResultAddresses.insert(addr);
m_resultAddressToErtNodeIdx[addr] = i; m_resultAddressToErtNodeIdx[addr] = i;
} }
} }

View File

@ -79,7 +79,7 @@ bool RifReaderObservedData::open(const QString& headerFileName,
m_allResultAddresses.clear(); m_allResultAddresses.clear();
for (auto s : m_asciiParser->tableData().columnInfos()) for (auto s : m_asciiParser->tableData().columnInfos())
{ {
m_allResultAddresses.push_back(s.summaryAddress); m_allResultAddresses.insert(s.summaryAddress);
} }
} }
@ -95,12 +95,14 @@ bool RifReaderObservedData::values(const RifEclipseSummaryAddress& resultAddress
{ {
size_t columnIndex = m_allResultAddresses.size(); size_t columnIndex = m_allResultAddresses.size();
for (size_t i = 0; i < m_allResultAddresses.size(); i++) int i = 0;
for(auto& address : m_allResultAddresses)
{ {
if (resultAddress == m_allResultAddresses[i]) if (address == resultAddress)
{ {
columnIndex = i; columnIndex = i;
} }
i++;
} }
if (columnIndex != m_allResultAddresses.size()) if (columnIndex != m_allResultAddresses.size())

View File

@ -26,7 +26,7 @@
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
const std::vector<RifEclipseSummaryAddress>& RifSummaryReaderInterface::allResultAddresses() const const std::set<RifEclipseSummaryAddress>& RifSummaryReaderInterface::allResultAddresses() const
{ {
return m_allResultAddresses; return m_allResultAddresses;
} }

View File

@ -25,6 +25,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <set>
class QDateTime; class QDateTime;
@ -37,7 +38,7 @@ class RifSummaryReaderInterface : public cvf::Object
{ {
public: public:
bool hasAddress(const RifEclipseSummaryAddress& resultAddress) const; bool hasAddress(const RifEclipseSummaryAddress& resultAddress) const;
const std::vector<RifEclipseSummaryAddress>& allResultAddresses() const; const std::set<RifEclipseSummaryAddress>& allResultAddresses() const;
RifEclipseSummaryAddress errorAddress(const RifEclipseSummaryAddress& resultAddress) const; RifEclipseSummaryAddress errorAddress(const RifEclipseSummaryAddress& resultAddress) const;
virtual const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& resultAddress) const = 0; virtual const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& resultAddress) const = 0;
@ -51,6 +52,6 @@ public:
static std::vector<QDateTime> fromTimeT(const std::vector<time_t>& timeSteps); static std::vector<QDateTime> fromTimeT(const std::vector<time_t>& timeSteps);
protected: protected:
std::vector<RifEclipseSummaryAddress> m_allResultAddresses; // Result and error addresses std::set<RifEclipseSummaryAddress> m_allResultAddresses; // Result and error addresses
std::set<RifEclipseSummaryAddress> m_allErrorAddresses; // Error addresses std::set<RifEclipseSummaryAddress> m_allErrorAddresses; // Error addresses
}; };

View File

@ -487,6 +487,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicImportSummaryCasesFeature"; menuBuilder << "RicImportSummaryCasesFeature";
menuBuilder << "RicImportSummaryGroupFeature"; menuBuilder << "RicImportSummaryGroupFeature";
menuBuilder << "RicImportEnsembleFeature"; menuBuilder << "RicImportEnsembleFeature";
menuBuilder << "RicNewDerivedEnsembleFeature";
} }
else if (dynamic_cast<RimSummaryCaseCollection*>(uiItem)) else if (dynamic_cast<RimSummaryCaseCollection*>(uiItem))
{ {
@ -497,6 +498,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicImportEnsembleFeature"; menuBuilder << "RicImportEnsembleFeature";
menuBuilder.subMenuEnd(); menuBuilder.subMenuEnd();
menuBuilder.addSeparator(); menuBuilder.addSeparator();
menuBuilder << "RicNewDerivedEnsembleFeature";
menuBuilder << "RicNewSummaryPlotFeature"; menuBuilder << "RicNewSummaryPlotFeature";
menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature";
menuBuilder.addSeparator(); menuBuilder.addSeparator();
@ -676,6 +678,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicShowPlotDataFeature"; menuBuilder << "RicShowPlotDataFeature";
menuBuilder << "RicShowTotalAllocationDataFeature"; menuBuilder << "RicShowTotalAllocationDataFeature";
menuBuilder << "RicNewDerivedEnsembleFeature";
menuBuilder << "RicNewSummaryPlotFeature"; menuBuilder << "RicNewSummaryPlotFeature";
menuBuilder << "RicNewSummaryCrossPlotFeature"; menuBuilder << "RicNewSummaryCrossPlotFeature";
menuBuilder << "RicSummaryCurveSwitchAxisFeature"; menuBuilder << "RicSummaryCurveSwitchAxisFeature";

View File

@ -624,6 +624,15 @@ std::vector<RimSummaryCaseCollection*> RimProject::summaryGroups() const
return groups; return groups;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCaseMainCollection* RimProject::firstSummaryCaseMainCollection() const
{
if (oilFields.empty()) return nullptr;
return oilFields[0]->summaryCaseMainCollection;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -48,6 +48,7 @@ class RimOilField;
class RimScriptCollection; class RimScriptCollection;
class RimSummaryCase; class RimSummaryCase;
class RimSummaryCaseCollection; class RimSummaryCaseCollection;
class RimSummaryCaseMainCollection;
class Rim3dView; class Rim3dView;
class RimGridView; class RimGridView;
class RimViewLinker; class RimViewLinker;
@ -108,6 +109,7 @@ public:
std::vector<RimSummaryCase*> allSummaryCases() const; std::vector<RimSummaryCase*> allSummaryCases() const;
std::vector<RimSummaryCaseCollection*> summaryGroups() const; std::vector<RimSummaryCaseCollection*> summaryGroups() const;
RimSummaryCaseMainCollection* firstSummaryCaseMainCollection() const;
void allVisibleViews(std::vector<Rim3dView*>& views); void allVisibleViews(std::vector<Rim3dView*>& views);
void allVisibleGridViews(std::vector<RimGridView*>& views); void allVisibleGridViews(std::vector<RimGridView*>& views);

View File

@ -36,6 +36,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilter.h
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilterCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilterCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatistics.h ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatistics.h
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsCase.h ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsCase.h
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCase.h
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCaseCollection.h
) )
set (SOURCE_GROUP_SOURCE_FILES set (SOURCE_GROUP_SOURCE_FILES
@ -75,6 +77,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilter.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilterCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilterCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatistics.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatistics.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsCase.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCaseCollection.cpp
) )
list(APPEND CODE_HEADER_FILES list(APPEND CODE_HEADER_FILES

View File

@ -86,7 +86,7 @@ void RifCalculatedSummaryCurveReader::buildMetaData()
for (RimSummaryCalculation* calc : m_calculationCollection->calculations()) for (RimSummaryCalculation* calc : m_calculationCollection->calculations())
{ {
m_allResultAddresses.push_back(RifEclipseSummaryAddress::calculatedAddress(calc->description().toStdString())); m_allResultAddresses.insert(RifEclipseSummaryAddress::calculatedAddress(calc->description().toStdString()));
} }
} }

View File

@ -0,0 +1,220 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RimDerivedEnsembleCase.h"
#include "RiaSummaryTools.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RifDerivedEnsembleReader.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimMainPlotCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSummaryCaseMainCollection.h"
#include "RimSummaryPlotCollection.h"
#include "RimSummaryCaseCollection.h"
#include "cvfAssert.h"
#include <QFileInfo>
CAF_PDM_ABSTRACT_SOURCE_INIT(RimDerivedEnsembleCase, "RimDerivedEnsembleCase");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
static const std::vector<time_t> EMPTY_TIME_STEPS_VECTOR;
static const std::vector<double> EMPTY_VALUES_VECTOR;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCase::RimDerivedEnsembleCase() : m_summaryCase1(nullptr), m_summaryCase2(nullptr)
{
CAF_PDM_InitObject("Summary Case",":/SummaryCase16x16.png","","");
CAF_PDM_InitFieldNoDefault(&m_summaryCase1, "SummaryCase1", "SummaryCase1", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_summaryCase2, "SummaryCase2", "SummaryCase2", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::setInUse(bool inUse)
{
m_inUse = inUse;
if (!m_inUse)
{
m_summaryCase1 = nullptr;
m_summaryCase2 = nullptr;
m_data.clear();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimDerivedEnsembleCase::isInUse() const
{
return m_inUse;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::setSummaryCases(RimSummaryCase* sumCase1, RimSummaryCase* sumCase2)
{
if (!sumCase1 || !sumCase2) return;
m_summaryCase1 = sumCase1;
m_summaryCase2 = sumCase2;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimDerivedEnsembleCase::needsCalculation(const RifEclipseSummaryAddress& address) const
{
return m_data.count(address) == 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<time_t>& RimDerivedEnsembleCase::timeSteps(const RifEclipseSummaryAddress& address) const
{
if (m_data.count(address) == 0) return EMPTY_TIME_STEPS_VECTOR;
return m_data.at(address).first;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<double>& RimDerivedEnsembleCase::values(const RifEclipseSummaryAddress& address) const
{
if (m_data.count(address) == 0) return EMPTY_VALUES_VECTOR;
return m_data.at(address).second;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::calculate(const RifEclipseSummaryAddress& address)
{
clearData(address);
RifSummaryReaderInterface* reader1 = m_summaryCase1 ? m_summaryCase1->summaryReader() : nullptr;
RifSummaryReaderInterface* reader2 = m_summaryCase2 ? m_summaryCase2->summaryReader() : nullptr;
if (!reader1 || !reader2 || !parentEnsemble()) return;
RiaTimeHistoryCurveMerger merger;
std::vector<double> values1;
std::vector<double> values2;
DerivedEnsembleOperator op = parentEnsemble()->op();
reader1->values(address, &values1);
reader2->values(address, &values2);
merger.addCurveData(values1, reader1->timeSteps(address));
merger.addCurveData(values2, reader2->timeSteps(address));
merger.computeInterpolatedValues();
size_t sampleCount = merger.allTimeSteps().size();
std::vector<double> calculatedValues;
calculatedValues.reserve(sampleCount);
for (size_t i = 0; i < sampleCount; i++)
{
if (op == DERIVED_ENSEMBLE_SUB)
{
calculatedValues.push_back(values1[i] - values2[i]);
}
else if (op == DERIVED_ENSEMBLE_ADD)
{
calculatedValues.push_back(values1[i] + values2[i]);
}
}
auto& dataItem = m_data[address];
dataItem.first = merger.allTimeSteps();
dataItem.second = calculatedValues;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimDerivedEnsembleCase::caseName()
{
auto case1Name = m_summaryCase1->caseName();
auto case2Name = m_summaryCase2->caseName();
if (case1Name == case2Name) return case1Name;
else return QString("%1/%2").arg(case1Name).arg(case2Name);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::createSummaryReaderInterface()
{
m_reader.reset(new RifDerivedEnsembleReader(this));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifSummaryReaderInterface* RimDerivedEnsembleCase::summaryReader()
{
return m_reader.get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath)
{
// NOP
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCaseCollection * RimDerivedEnsembleCase::parentEnsemble() const
{
RimDerivedEnsembleCaseCollection* ensemble;
firstAncestorOrThisOfType(ensemble);
return ensemble;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<std::vector<time_t>, std::vector<double>> RimDerivedEnsembleCase::lookupCachedData(const RifEclipseSummaryAddress& address)
{
auto itr = m_data.find(address);
if (itr == m_data.end()) return std::make_pair(std::vector<time_t>(), std::vector<double>());
return itr->second;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCase::clearData(const RifEclipseSummaryAddress& address)
{
m_data.erase(address);
}

View File

@ -0,0 +1,78 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016 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 "RimSummaryCase.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
#include <memory>
class RifEclipseSummaryAddress;
class RifSummaryReaderInterface;
class RifDerivedEnsembleReader;
class RimDerivedEnsembleCaseCollection;
//==================================================================================================
///
//==================================================================================================
enum DerivedEnsembleOperator
{
DERIVED_ENSEMBLE_SUB,
DERIVED_ENSEMBLE_ADD
};
//==================================================================================================
//
//==================================================================================================
class RimDerivedEnsembleCase : public RimSummaryCase
{
CAF_PDM_HEADER_INIT;
public:
RimDerivedEnsembleCase();
void setInUse(bool inUse);
bool isInUse() const;
void setSummaryCases(RimSummaryCase* sumCase1, RimSummaryCase* sumCase2);
bool needsCalculation(const RifEclipseSummaryAddress& address) const;
const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& address) const;
const std::vector<double>& values(const RifEclipseSummaryAddress& address) const;
void calculate(const RifEclipseSummaryAddress& address);
virtual QString caseName() override;
virtual void createSummaryReaderInterface() override;
virtual RifSummaryReaderInterface* summaryReader() override;
virtual void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) override;
RimDerivedEnsembleCaseCollection* parentEnsemble() const;
private:
std::pair<std::vector<time_t>, std::vector<double>> lookupCachedData(const RifEclipseSummaryAddress& address);
void clearData(const RifEclipseSummaryAddress& address);
std::unique_ptr<RifDerivedEnsembleReader> m_reader;
bool m_inUse;
caf::PdmPtrField<RimSummaryCase*> m_summaryCase1;
caf::PdmPtrField<RimSummaryCase*> m_summaryCase2;
std::map<RifEclipseSummaryAddress, std::pair<std::vector<time_t>, std::vector<double>>> m_data;
};

View File

@ -0,0 +1,440 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaApplication.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimDerivedEnsembleCase.h"
#include "RimProject.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCaseMainCollection.h"
#include "RifSummaryReaderInterface.h"
#include <cafPdmUiPushButtonEditor.h>
#include <cmath>
namespace caf
{
template<>
void caf::AppEnum<DerivedEnsembleOperator>::setUp()
{
addItem(DERIVED_ENSEMBLE_SUB, "Sub", "-");
addItem(DERIVED_ENSEMBLE_ADD, "Add", "+");
setDefault(DERIVED_ENSEMBLE_SUB);
}
}
CAF_PDM_SOURCE_INIT(RimDerivedEnsembleCaseCollection, "RimDerivedEnsembleCaseCollection");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCaseCollection::RimDerivedEnsembleCaseCollection()
{
CAF_PDM_InitObject("Derived Ensemble", ":/SummaryEnsemble16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(&m_ensemble1, "Ensemble1", "Ensemble 1", "", "", "");
m_ensemble1.uiCapability()->setUiTreeChildrenHidden(true);
m_ensemble1.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_ensemble2, "Ensemble2", "Ensemble 2", "", "", "");
m_ensemble1.uiCapability()->setUiTreeChildrenHidden(true);
m_ensemble2.uiCapability()->setAutoAddingOptionFromValue(false);
CAF_PDM_InitFieldNoDefault(&m_operator, "Operator", "Operator", "", "", "");
CAF_PDM_InitField(&m_swapEnsemblesButton, "SwapEnsembles", false, "SwapEnsembles", "", "", "");
m_swapEnsemblesButton.uiCapability()->setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName());
m_swapEnsemblesButton.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
m_swapEnsemblesButton.xmlCapability()->disableIO();
CAF_PDM_InitField(&m_caseCount, "CaseCount", 0, "Number of Cases", "", "", "");
m_caseCount.uiCapability()->setUiReadOnly(true);
// Do not show child cases
uiCapability()->setUiTreeChildrenHidden(true);
// Do not store child cases to project file
m_cases.xmlCapability()->disableIO();
setNameAsReadOnly();
setName("Derived Ensemble");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCaseCollection::~RimDerivedEnsembleCaseCollection()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::setEnsemble1(RimSummaryCaseCollection* ensemble)
{
m_ensemble1 = ensemble;
updateAutoName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::setEnsemble2(RimSummaryCaseCollection* ensemble)
{
m_ensemble2 = ensemble;
updateAutoName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCase*> RimDerivedEnsembleCaseCollection::allSummaryCases() const
{
std::vector<RimSummaryCase*> cases;
for (auto sumCase : allDerivedCases(true)) cases.push_back(sumCase);
return cases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RimDerivedEnsembleCaseCollection::calculateUnionOfSummaryAddresses() const
{
std::set<RifEclipseSummaryAddress> addresses;
if (!m_ensemble1 || !m_ensemble2) return addresses;
addresses = m_ensemble1->calculateUnionOfSummaryAddresses();
auto addrs2 = m_ensemble2->calculateUnionOfSummaryAddresses();
addresses.insert(addrs2.begin(), addrs2.end());
return addresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::updateDerivedEnsembleCases()
{
if (!m_ensemble1 || !m_ensemble2) return;
setAllCasesNotInUse();
const auto cases1 = m_ensemble1->allSummaryCases();
const auto cases2 = m_ensemble2->allSummaryCases();
for (auto& sumCase1 : cases1)
{
auto crp = sumCase1->caseRealizationParameters();
if (!crp) continue;
const auto& sumCase2 = findCaseByParametersHash(cases2, crp->parametersHash());
if (!sumCase2) continue;
auto derivedCase = firstCaseNotInUse();
derivedCase->createSummaryReaderInterface();
derivedCase->setSummaryCases(sumCase1, sumCase2);
derivedCase->setCaseRealizationParameters(crp);
derivedCase->setInUse(true);
}
// If other derived ensembles are referring to this ensemble, update their cases as well
for (auto referring : findReferringEnsembles())
{
referring->updateDerivedEnsembleCases();
}
deleteCasesNoInUse();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimDerivedEnsembleCaseCollection::hasCaseReference(const RimSummaryCase* sumCase) const
{
for (auto currCase : m_ensemble1->allSummaryCases())
{
if (currCase == sumCase) return true;
}
for (auto currCase : m_ensemble2->allSummaryCases())
{
if (currCase == sumCase) return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::onLoadDataAndUpdate()
{
updateDerivedEnsembleCases();
updateReferringCurveSets();
updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimDerivedEnsembleCaseCollection::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
if (fieldNeedingOptions == &m_ensemble1 || fieldNeedingOptions == &m_ensemble2)
{
for (auto ensemble : allEnsembles())
{
if(ensemble != this) options.push_back(caf::PdmOptionItemInfo(ensemble->name(), ensemble));
}
}
else if (fieldNeedingOptions == &m_caseCount)
{
m_caseCount = (int)m_cases.size();
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
RimSummaryCaseCollection::defineUiOrdering(uiConfigName, uiOrdering);
uiOrdering.add(&m_caseCount);
uiOrdering.add(&m_ensemble1);
uiOrdering.add(&m_operator);
uiOrdering.add(&m_ensemble2);
uiOrdering.add(&m_swapEnsemblesButton);
uiOrdering.skipRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
{
bool doUpdate = false;
bool doUpdateCases = false;
bool doClearAllData = false;
if (changedField == &m_ensemble1 || changedField == &m_ensemble2)
{
doUpdate = true;
doUpdateCases = true;
}
else if (changedField == &m_operator)
{
doUpdate = true;
doUpdateCases = true;
}
else if (changedField == &m_swapEnsemblesButton)
{
m_swapEnsemblesButton = false;
auto temp = m_ensemble1();
m_ensemble1 = m_ensemble2();
m_ensemble2 = temp;
doUpdate = true;
doUpdateCases = true;
}
if (doUpdate)
{
updateAutoName();
//if (doClearAllData) clearAllData();
if (doUpdateCases)
{
updateDerivedEnsembleCases();
updateConnectedEditors();
}
updateReferringCurveSets();
// If other derived ensembles are referring to this ensemble, update their cases as well
for (auto refering : findReferringEnsembles())
{
refering->updateReferringCurveSets();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute)
{
if (field == &m_swapEnsemblesButton)
{
caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>(attribute);
if (attrib)
{
attrib->m_buttonText = "Swap Ensembles";
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::setAllCasesNotInUse()
{
for (auto derCase : allDerivedCases(true)) derCase->setInUse(false);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::deleteCasesNoInUse()
{
std::vector<RimDerivedEnsembleCase*> inactiveCases;
auto allCases = allDerivedCases(false);
std::copy_if(allCases.begin(), allCases.end(), std::back_inserter(inactiveCases), [](RimDerivedEnsembleCase* derCase) { return !derCase->isInUse(); });
for (auto derCase : inactiveCases)
{
removeCase(derCase);
delete derCase;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDerivedEnsembleCase* RimDerivedEnsembleCaseCollection::firstCaseNotInUse()
{
auto allCases = allDerivedCases(false);
auto itr = std::find_if(allCases.begin(), allCases.end(), [](RimDerivedEnsembleCase* derCase) { return !derCase->isInUse(); });
if (itr != allCases.end())
{
return *itr;
}
// If no active case was found, add a new case to the collection
auto newCase = new RimDerivedEnsembleCase();
m_cases.push_back(newCase);
return newCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimDerivedEnsembleCase*> RimDerivedEnsembleCaseCollection::allDerivedCases(bool activeOnly) const
{
std::vector<RimDerivedEnsembleCase*> activeCases;
for (auto sumCase : RimSummaryCaseCollection::allSummaryCases())
{
auto derivedCase = dynamic_cast<RimDerivedEnsembleCase*>(sumCase);
if (derivedCase && (!activeOnly || derivedCase->isInUse()))
{
activeCases.push_back(derivedCase);
}
}
return activeCases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimDerivedEnsembleCaseCollection::updateAutoName()
{
QString op = caf::AppEnum<DerivedEnsembleOperator>::uiText(m_operator());
auto derivedEnsemble1 = dynamic_cast<RimDerivedEnsembleCaseCollection*>(m_ensemble1());
auto derivedEnsemble2 = dynamic_cast<RimDerivedEnsembleCaseCollection*>(m_ensemble2());
bool isDerived1 = derivedEnsemble1 != nullptr;
bool isDerived2 = derivedEnsemble2 != nullptr;
QString name =
(isDerived1 ? "(" : "") +
(m_ensemble1 ? m_ensemble1->name() : "") +
(isDerived1 ? ")" : "") +
" " + op + " " +
(isDerived2 ? "(" : "") +
(m_ensemble2 ? m_ensemble2->name() : "") +
(isDerived2 ? ")" : "");
setName(name);
// If other derived ensembles are referring to this ensemble, update theirs name as well
for (auto refering : findReferringEnsembles())
{
refering->updateAutoName();
refering->updateConnectedEditors();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimDerivedEnsembleCaseCollection::findCaseByParametersHash(const std::vector<RimSummaryCase*>& cases, size_t hash) const
{
for (auto sumCase : cases)
{
auto ensembleParameters = sumCase->caseRealizationParameters();
if (ensembleParameters && ensembleParameters->parametersHash() == hash) return sumCase;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimDerivedEnsembleCaseCollection*> RimDerivedEnsembleCaseCollection::findReferringEnsembles() const
{
std::vector<RimDerivedEnsembleCaseCollection*> referringEnsembles;
RimSummaryCaseMainCollection* mainColl;
firstAncestorOrThisOfType(mainColl);
if (mainColl)
{
for (auto group : mainColl->summaryCaseCollections())
{
auto derivedEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(group);
if (derivedEnsemble)
{
if (derivedEnsemble->m_ensemble1() == this || derivedEnsemble->m_ensemble2() == this)
{
referringEnsembles.push_back(derivedEnsemble);
}
}
}
}
return referringEnsembles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCaseCollection*> RimDerivedEnsembleCaseCollection::allEnsembles() const
{
std::vector<RimSummaryCaseCollection*> ensembles;
auto project = RiaApplication::instance()->project();
for (auto group : project->summaryGroups())
{
if (group->isEnsemble()) ensembles.push_back(group);
}
return ensembles;
}

View File

@ -0,0 +1,85 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016- 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 "RifEclipseSummaryAddress.h"
#include "RimDerivedEnsembleCase.h"
#include "RimSummaryCaseCollection.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmField.h"
#include "cafPdmPtrField.h"
#include "cafPdmObject.h"
#include "cafPdmProxyValueField.h"
#include <vector>
class RimSummaryCase;
//==================================================================================================
///
//==================================================================================================
class RimDerivedEnsembleCaseCollection : public RimSummaryCaseCollection
{
CAF_PDM_HEADER_INIT;
public:
RimDerivedEnsembleCaseCollection();
virtual ~RimDerivedEnsembleCaseCollection();
RimSummaryCaseCollection* ensemble1() const { return m_ensemble1; }
RimSummaryCaseCollection* ensemble2() const { return m_ensemble2; }
DerivedEnsembleOperator op() const { return m_operator(); }
void setEnsemble1(RimSummaryCaseCollection* ensemble);
void setEnsemble2(RimSummaryCaseCollection* ensemble);
virtual std::vector<RimSummaryCase*> allSummaryCases() const override;
virtual std::set<RifEclipseSummaryAddress> calculateUnionOfSummaryAddresses() const override;
void updateDerivedEnsembleCases();
bool hasCaseReference(const RimSummaryCase* sumCase) const;
virtual void onLoadDataAndUpdate() override;
private:
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName,
caf::PdmUiEditorAttribute* attribute) override;
void setAllCasesNotInUse();
void deleteCasesNoInUse();
RimDerivedEnsembleCase* firstCaseNotInUse();
std::vector<RimDerivedEnsembleCase*> allDerivedCases(bool activeOnly) const;
void updateAutoName();
RimSummaryCase* findCaseByParametersHash(const std::vector<RimSummaryCase*>& cases, size_t hash) const;
std::vector<RimDerivedEnsembleCaseCollection*> findReferringEnsembles() const;
private:
std::vector<RimSummaryCaseCollection*> allEnsembles() const;
private:
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble1;
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble2;
caf::PdmField<caf::AppEnum<DerivedEnsembleOperator>> m_operator;
caf::PdmField<bool> m_swapEnsemblesButton;
caf::PdmField<int> m_caseCount;
};

View File

@ -29,6 +29,7 @@
#include "RigStatisticsMath.h" #include "RigStatisticsMath.h"
#include "RiaTimeHistoryCurveMerger.h" #include "RiaTimeHistoryCurveMerger.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEnsembleCurveFilter.h" #include "RimEnsembleCurveFilter.h"
#include "RimEnsembleCurveFilterCollection.h" #include "RimEnsembleCurveFilterCollection.h"
#include "RimEnsembleCurveSetCollection.h" #include "RimEnsembleCurveSetCollection.h"
@ -735,7 +736,7 @@ void RimEnsembleCurveSet::appendOptionItemsForSummaryAddresses(QList<caf::PdmOpt
for (RimSummaryCase* summaryCase : summaryCaseGroup->allSummaryCases()) for (RimSummaryCase* summaryCase : summaryCaseGroup->allSummaryCases())
{ {
RifSummaryReaderInterface* reader = summaryCase->summaryReader(); RifSummaryReaderInterface* reader = summaryCase->summaryReader();
const std::vector<RifEclipseSummaryAddress>& addrs = reader ? reader->allResultAddresses() : std::vector<RifEclipseSummaryAddress>(); const std::set<RifEclipseSummaryAddress>& addrs = reader ? reader->allResultAddresses() : std::set<RifEclipseSummaryAddress>();
for (auto& addr : addrs) for (auto& addr : addrs)
{ {

View File

@ -18,6 +18,7 @@
#include "RimSummaryCaseCollection.h" #include "RimSummaryCaseCollection.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSet.h"
#include "RimGridSummaryCase.h" #include "RimGridSummaryCase.h"
#include "RimProject.h" #include "RimProject.h"
@ -71,10 +72,31 @@ void RimSummaryCaseCollection::removeCase(RimSummaryCase* summaryCase)
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::addCase(RimSummaryCase* summaryCase) void RimSummaryCaseCollection::deleteAllCases()
{
m_cases.deleteAllChildObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::addCase(RimSummaryCase* summaryCase, bool updateCurveSets)
{ {
m_cases.push_back(summaryCase); m_cases.push_back(summaryCase);
updateReferringCurveSets();
// Update derived ensemble cases (if any)
std::vector<caf::PdmObjectHandle*> referringObjects;
objectsWithReferringPtrFields(referringObjects);
for (auto refObj : referringObjects)
{
auto derEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(refObj);
if (!derEnsemble) continue;
derEnsemble->updateDerivedEnsembleCases();
if (updateCurveSets) derEnsemble->updateReferringCurveSets();
}
if(updateCurveSets) updateReferringCurveSets();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -133,11 +155,9 @@ std::set<RifEclipseSummaryAddress> RimSummaryCaseCollection::calculateUnionOfSum
if ( !reader ) continue; if ( !reader ) continue;
const std::vector<RifEclipseSummaryAddress>& readerAddresses = reader->allResultAddresses(); const std::set<RifEclipseSummaryAddress>& readerAddresses = reader->allResultAddresses();
addressUnion.insert(readerAddresses.begin(), readerAddresses.end()); addressUnion.insert(readerAddresses.begin(), readerAddresses.end());
} }
return addressUnion; return addressUnion;
} }
@ -234,6 +254,14 @@ EnsembleParameter RimSummaryCaseCollection::ensembleParameter(const QString& par
return eParam; return eParam;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::loadDataAndUpdate()
{
onLoadDataAndUpdate();
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -245,7 +273,15 @@ caf::PdmFieldHandle* RimSummaryCaseCollection::userDescriptionField()
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::updateReferringCurveSets() const void RimSummaryCaseCollection::onLoadDataAndUpdate()
{
// NOP
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::updateReferringCurveSets()
{ {
// Update curve set referring to this group // Update curve set referring to this group
std::vector<PdmObjectHandle*> referringObjects; std::vector<PdmObjectHandle*> referringObjects;
@ -299,3 +335,20 @@ void RimSummaryCaseCollection::fieldChangedByUi(const caf::PdmFieldHandle* chang
updateIcon(); updateIcon();
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
uiOrdering.add(&m_name);
uiOrdering.skipRemainingFields(true);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseCollection::setNameAsReadOnly()
{
m_name.uiCapability()->setUiReadOnly(true);
}

View File

@ -65,26 +65,35 @@ public:
virtual ~RimSummaryCaseCollection(); virtual ~RimSummaryCaseCollection();
void removeCase(RimSummaryCase* summaryCase); void removeCase(RimSummaryCase* summaryCase);
void addCase(RimSummaryCase* summaryCase); void deleteAllCases();
std::vector<RimSummaryCase*> allSummaryCases() const; void addCase(RimSummaryCase* summaryCase, bool updateCurveSets = true);
virtual std::vector<RimSummaryCase*> allSummaryCases() const;
void setName(const QString& name); void setName(const QString& name);
QString name() const; QString name() const;
bool isEnsemble() const; bool isEnsemble() const;
void setAsEnsemble(bool isEnsemble); void setAsEnsemble(bool isEnsemble);
std::set<RifEclipseSummaryAddress> calculateUnionOfSummaryAddresses() const; virtual std::set<RifEclipseSummaryAddress> calculateUnionOfSummaryAddresses() const;
EnsembleParameter ensembleParameter(const QString& paramName) const; EnsembleParameter ensembleParameter(const QString& paramName) const;
void loadDataAndUpdate();
private: private:
caf::PdmFieldHandle* userDescriptionField() override; caf::PdmFieldHandle* userDescriptionField() override;
void updateReferringCurveSets() const;
QString nameAndItemCount() const; QString nameAndItemCount() const;
void updateIcon(); void updateIcon();
virtual void initAfterRead() override; virtual void initAfterRead() override;
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
private: protected:
virtual void onLoadDataAndUpdate();
void updateReferringCurveSets();
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
void setNameAsReadOnly();
caf::PdmChildArrayField<RimSummaryCase*> m_cases; caf::PdmChildArrayField<RimSummaryCase*> m_cases;
private:
caf::PdmField<QString> m_name; caf::PdmField<QString> m_name;
caf::PdmProxyValueField<QString> m_nameAndItemCount; caf::PdmProxyValueField<QString> m_nameAndItemCount;
caf::PdmField<bool> m_isEnsemble; caf::PdmField<bool> m_isEnsemble;

View File

@ -21,6 +21,7 @@
#include "RifSummaryCaseRestartSelector.h" #include "RifSummaryCaseRestartSelector.h"
#include "RifCaseRealizationParametersReader.h" #include "RifCaseRealizationParametersReader.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEclipseResultCase.h" #include "RimEclipseResultCase.h"
#include "RimFileSummaryCase.h" #include "RimFileSummaryCase.h"
#include "RimGridSummaryCase.h" #include "RimGridSummaryCase.h"
@ -201,19 +202,43 @@ void RimSummaryCaseMainCollection::addCase(RimSummaryCase* summaryCase)
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RimSummaryCaseMainCollection::removeCase(RimSummaryCase* summaryCase) void RimSummaryCaseMainCollection::removeCase(RimSummaryCase* summaryCase)
{ {
std::vector<RimDerivedEnsembleCaseCollection*> derivedEnsembles;
// Build a list of derived ensembles that must be updated after delete
for (auto group : summaryCaseCollections())
{
auto derEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(group);
if (derEnsemble)
{
if (derEnsemble->hasCaseReference(summaryCase))
{
derivedEnsembles.push_back(derEnsemble);
}
}
}
m_cases.removeChildObject(summaryCase); m_cases.removeChildObject(summaryCase);
for (RimSummaryCaseCollection* summaryCaseCollection : m_caseCollections) for (RimSummaryCaseCollection* summaryCaseCollection : m_caseCollections)
{ {
summaryCaseCollection->removeCase(summaryCase); summaryCaseCollection->removeCase(summaryCase);
} }
// Update derived ensemble cases (if any)
for (auto derEnsemble : derivedEnsembles)
{
derEnsemble->updateDerivedEnsembleCases();
}
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RimSummaryCaseMainCollection::addCaseCollection(std::vector<RimSummaryCase*> summaryCases, const QString& collectionName, bool isEnsemble) RimSummaryCaseCollection* RimSummaryCaseMainCollection::addCaseCollection(std::vector<RimSummaryCase*> summaryCases,
const QString& collectionName,
bool isEnsemble,
std::function<RimSummaryCaseCollection* ()> allocator)
{ {
RimSummaryCaseCollection* summaryCaseCollection = new RimSummaryCaseCollection(); RimSummaryCaseCollection* summaryCaseCollection = allocator();
if(!collectionName.isEmpty()) summaryCaseCollection->setName(collectionName); if(!collectionName.isEmpty()) summaryCaseCollection->setName(collectionName);
summaryCaseCollection->setAsEnsemble(isEnsemble); summaryCaseCollection->setAsEnsemble(isEnsemble);
@ -235,6 +260,8 @@ void RimSummaryCaseMainCollection::addCaseCollection(std::vector<RimSummaryCase*
} }
m_caseCollections.push_back(summaryCaseCollection); m_caseCollections.push_back(summaryCaseCollection);
return summaryCaseCollection;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -330,6 +357,14 @@ void RimSummaryCaseMainCollection::loadSummaryCaseData(std::vector<RimSummaryCas
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCaseCollection* RimSummaryCaseMainCollection::defaultAllocator()
{
return new RimSummaryCaseCollection();
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -21,6 +21,7 @@
#include "cafPdmObject.h" #include "cafPdmObject.h"
#include <vector> #include <vector>
#include <functional>
class RimGridSummaryCase; class RimGridSummaryCase;
class RimSummaryCase; class RimSummaryCase;
@ -56,7 +57,10 @@ public:
void addCase(RimSummaryCase* summaryCase); void addCase(RimSummaryCase* summaryCase);
void removeCase(RimSummaryCase* summaryCase); void removeCase(RimSummaryCase* summaryCase);
void addCaseCollection(std::vector<RimSummaryCase*> summaryCases, const QString& coolectionName, bool isEnsemble); RimSummaryCaseCollection* addCaseCollection(std::vector<RimSummaryCase*> summaryCases,
const QString& coolectionName,
bool isEnsemble,
std::function<RimSummaryCaseCollection* ()> allocator = defaultAllocator);
void removeCaseCollection(RimSummaryCaseCollection* caseCollection); void removeCaseCollection(RimSummaryCaseCollection* caseCollection);
void loadAllSummaryCaseData(); void loadAllSummaryCaseData();
@ -67,6 +71,7 @@ public:
private: private:
static void loadSummaryCaseData(std::vector<RimSummaryCase*> summaryCases); static void loadSummaryCaseData(std::vector<RimSummaryCase*> summaryCases);
static RimSummaryCaseCollection* defaultAllocator();
private: private:
caf::PdmChildArrayField<RimSummaryCase*> m_cases; caf::PdmChildArrayField<RimSummaryCase*> m_cases;

View File

@ -593,7 +593,7 @@ void RimSummaryCurve::appendOptionItemsForSummaryAddresses(QList<caf::PdmOptionI
RifSummaryReaderInterface* reader = summaryCase->summaryReader(); RifSummaryReaderInterface* reader = summaryCase->summaryReader();
if (reader) if (reader)
{ {
const std::vector<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses(); const std::set<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
for (auto& address : allAddresses) for (auto& address : allAddresses)
{ {

View File

@ -17,7 +17,12 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
#include "RigCaseRealizationParameters.h" #include "RigCaseRealizationParameters.h"
#include <QString>
#include <QStringList>
#include <limits> #include <limits>
#include <functional>
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
@ -109,3 +114,45 @@ std::map<QString, RigCaseRealizationParameters::Value> RigCaseRealizationParamet
{ {
return m_parameters; return m_parameters;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigCaseRealizationParameters::parameterHash(const QString& name) const
{
auto itr = m_parameters.find(name);
if (itr == m_parameters.end() || !itr->second.isValid()) return 0;
std::hash<std::string> stringHasher;
std::hash<double> doubleHasher;
size_t nameHash;
size_t valueHash;
nameHash = stringHasher(name.toStdString());
auto value = itr->second;
if (value.isNumeric()) valueHash = doubleHasher(value.numericValue());
else if (value.isText()) valueHash = stringHasher(value.textValue().toStdString());
QString s = QString::number(nameHash) + QString::number(valueHash);
return stringHasher((QString::number(nameHash) + QString::number(valueHash)).toStdString());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigCaseRealizationParameters::parametersHash()
{
if (m_parametersHash == 0)
{
QStringList hashes;
for (auto param : m_parameters)
{
hashes.push_back(QString::number(parameterHash(param.first)));
}
std::hash<std::string> stringHasher;
m_parametersHash = stringHasher(hashes.join("").toStdString());
}
return m_parametersHash;
}

View File

@ -59,12 +59,18 @@ public:
QString m_textValue; QString m_textValue;
}; };
RigCaseRealizationParameters() : m_parametersHash(0) { }
void addParameter(const QString& name, double value); void addParameter(const QString& name, double value);
void addParameter(const QString& name, const QString& value); void addParameter(const QString& name, const QString& value);
Value parameterValue(const QString& name); Value parameterValue(const QString& name);
std::map<QString, Value> parameters() const; std::map<QString, Value> parameters() const;
size_t parameterHash(const QString& name) const;
size_t parametersHash();
private: private:
std::map<QString, Value> m_parameters; std::map<QString, Value> m_parameters;
size_t m_parametersHash;
}; };

View File

@ -255,42 +255,42 @@ std::vector<RiaSummaryCurveDefinition> RiuSummaryCurveDefSelection::allCurveDefi
{ {
std::set<RiaSummaryCurveDefinition> curveDefinitions; std::set<RiaSummaryCurveDefinition> curveDefinitions;
std::set<RifEclipseSummaryAddress> selectedAddressesFromUi = buildAddressListFromSelections(); std::set<RifEclipseSummaryAddress> selectedAddressesFromUi = buildAddressListFromSelections();
for (SummarySource* currSource : selectedSummarySources()) for (SummarySource* currSource : selectedSummarySources())
{ {
std::vector<RimSummaryCase*> sourceCases; std::vector<SummarySource*> sourceSources;
RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>(currSource); RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>(currSource);
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>(currSource);
std::set<RifEclipseSummaryAddress> addressesFromSource;
std::vector<RimSummaryCase*> casesFromSource;
// Build case list // Build case list
if (ensemble) if (ensemble)
{ {
auto sumCases = ensemble->allSummaryCases(); auto addresses = ensemble->calculateUnionOfSummaryAddresses();
sourceCases.insert(sourceCases.end(), sumCases.begin(), sumCases.end()); addressesFromSource.insert(addresses.begin(), addresses.end());
auto ensembleCases = ensemble->allSummaryCases();
casesFromSource.insert(casesFromSource.end(), ensembleCases.begin(), ensembleCases.end());
} }
else else
{ {
RimSummaryCase* sourceCase = dynamic_cast<RimSummaryCase*>(currSource); RifSummaryReaderInterface* reader = sumCase ? sumCase->summaryReader() : nullptr;
if (sourceCase) if (reader)
{ {
sourceCases.push_back(sourceCase); addressesFromSource.insert(reader->allResultAddresses().begin(), reader->allResultAddresses().end());
casesFromSource.push_back(sumCase);
} }
} }
for (const auto& currCase : sourceCases) for (auto caseFromSource : casesFromSource)
{ {
if (currCase && currCase->summaryReader()) for (const auto& addressFromSource : addressesFromSource)
{ {
RifSummaryReaderInterface* reader = currCase->summaryReader(); if (selectedAddressesFromUi.count(addressFromSource) > 0)
const std::vector<RifEclipseSummaryAddress>& readerAddresses = reader->allResultAddresses();
for (const auto& readerAddress : readerAddresses)
{ {
if (selectedAddressesFromUi.count(readerAddress) > 0) curveDefinitions.insert(RiaSummaryCurveDefinition(caseFromSource, addressFromSource, ensemble));
{
curveDefinitions.insert(RiaSummaryCurveDefinition(currCase, readerAddress, ensemble));
}
} }
} }
} }
@ -313,6 +313,7 @@ std::vector<RiaSummaryCurveDefinition> RiuSummaryCurveDefSelection::selection()
{ {
RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>(currSource); RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>(currSource);
RimSummaryCase* sourceCase = dynamic_cast<RimSummaryCase*>(currSource); RimSummaryCase* sourceCase = dynamic_cast<RimSummaryCase*>(currSource);
if (ensemble) if (ensemble)
{ {
std::set<RifEclipseSummaryAddress> addressUnion = ensemble->calculateUnionOfSummaryAddresses(); std::set<RifEclipseSummaryAddress> addressUnion = ensemble->calculateUnionOfSummaryAddresses();
@ -328,10 +329,10 @@ std::vector<RiaSummaryCurveDefinition> RiuSummaryCurveDefSelection::selection()
{ {
if (!(sourceCase && sourceCase->summaryReader())) continue; if (!(sourceCase && sourceCase->summaryReader())) continue;
const std::vector<RifEclipseSummaryAddress>& readerAddresses = sourceCase->summaryReader()->allResultAddresses(); const std::set<RifEclipseSummaryAddress>& readerAddresses = sourceCase->summaryReader()->allResultAddresses();
for ( const auto& addr : readerAddresses) for ( const auto& addr : selectedAddressesFromUi)
{ {
if (selectedAddressesFromUi.count(addr)) if (readerAddresses.count(addr))
{ {
curveDefSelection.push_back(RiaSummaryCurveDefinition(sourceCase, addr, nullptr)); curveDefSelection.push_back(RiaSummaryCurveDefinition(sourceCase, addr, nullptr));
} }
@ -481,7 +482,7 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
{ {
RimSummaryCase* calcSumCase = calculatedSummaryCase(); RimSummaryCase* calcSumCase = calculatedSummaryCase();
const std::vector<RifEclipseSummaryAddress> allAddresses = calcSumCase->summaryReader()->allResultAddresses(); const std::set<RifEclipseSummaryAddress> allAddresses = calcSumCase->summaryReader()->allResultAddresses();
for (const auto& adr : allAddresses) for (const auto& adr : allAddresses)
{ {
addressSet.insert(adr); addressSet.insert(adr);
@ -868,7 +869,7 @@ void RiuSummaryCurveDefSelection::defineUiOrdering(QString uiConfigName, caf::Pd
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddressesFromSelectedCases(const SummaryIdentifierAndField *identifierAndField) std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddressesFromSelectedCases(const SummaryIdentifierAndField *identifierAndField)
{ {
std::vector<RimSummaryCase*> cases; std::vector<SummarySource*> sources;
for (const auto& source : m_selectedSources()) for (const auto& source : m_selectedSources())
{ {
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>(source.p()); RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>(source.p());
@ -876,15 +877,14 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
if (sumCase) if (sumCase)
{ {
if(!isObservedData(sumCase)) cases.push_back(sumCase); if(!isObservedData(sumCase)) sources.push_back(sumCase);
} }
else if (ensemble) else if (ensemble)
{ {
const auto& ensembleCases = ensemble->allSummaryCases(); sources.push_back(ensemble);
cases.insert(cases.end(), ensembleCases.begin(), ensembleCases.end());
} }
} }
return findPossibleSummaryAddresses(cases, identifierAndField); return findPossibleSummaryAddresses(sources, identifierAndField);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -892,7 +892,7 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddressesFromSelectedObservedData(const SummaryIdentifierAndField *identifierAndField) std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddressesFromSelectedObservedData(const SummaryIdentifierAndField *identifierAndField)
{ {
std::vector<RimSummaryCase*> obsData; std::vector<SummarySource*> obsData;
for (const auto& source : m_selectedSources()) for (const auto& source : m_selectedSources())
{ {
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>(source.p()); RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>(source.p());
@ -908,7 +908,7 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Returns the summary addresses that match the selected item type and input selections made in GUI /// Returns the summary addresses that match the selected item type and input selections made in GUI
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddresses(const std::vector<RimSummaryCase*> &selectedCases, std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddresses(const std::vector<SummarySource*> &selectedSources,
const SummaryIdentifierAndField *identifierAndField) const SummaryIdentifierAndField *identifierAndField)
{ {
std::set<RifEclipseSummaryAddress> addrUnion; std::set<RifEclipseSummaryAddress> addrUnion;
@ -920,32 +920,42 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
return addrUnion; return addrUnion;
} }
for (RimSummaryCase* currCase : selectedCases) for (SummarySource* currSource : selectedSources)
{ {
RifSummaryReaderInterface* reader = nullptr; std::set<RifEclipseSummaryAddress> allAddresses;
if (currCase) reader = currCase->summaryReader();
if (reader) RimSummaryCase* currCase = dynamic_cast<RimSummaryCase*>(currSource);
RimSummaryCaseCollection* currEnsemble = dynamic_cast<RimSummaryCaseCollection*>(currSource);
if (currCase)
{ {
const std::vector<RifEclipseSummaryAddress>& allAddresses = reader->allResultAddresses(); RifSummaryReaderInterface* reader = nullptr;
int addressCount = static_cast<int>(allAddresses.size()); if (currCase) reader = currCase->summaryReader();
if (reader) allAddresses = reader->allResultAddresses();
}
else if (currEnsemble)
{
allAddresses = currEnsemble->calculateUnionOfSummaryAddresses();
}
bool applySelections = identifierAndField == nullptr || (!isVectorField && controllingIdentifierAndField != nullptr); int addressCount = static_cast<int>(allAddresses.size());
std::vector<SummaryIdentifierAndField*> controllingFields;
if (applySelections)
{
// Build selections vector
controllingFields = buildControllingFieldList(identifierAndField);
}
for (int i = 0; i < addressCount; i++) bool applySelections = identifierAndField == nullptr || (!isVectorField && controllingIdentifierAndField != nullptr);
std::vector<SummaryIdentifierAndField*> controllingFields;
if (applySelections)
{
// Build selections vector
controllingFields = buildControllingFieldList(identifierAndField);
}
for(auto& address : allAddresses)
{
if (address.category() == m_currentSummaryCategory())
{ {
if (allAddresses[i].category() == m_currentSummaryCategory()) bool addressSelected = applySelections ? isAddressCompatibleWithControllingFieldSelection(address, controllingFields) : true;
if (addressSelected)
{ {
bool addressSelected = applySelections ? isAddressCompatibleWithControllingFieldSelection(allAddresses[i], controllingFields) : true; addrUnion.insert(address);
if (addressSelected)
{
addrUnion.insert(allAddresses[i]);
}
} }
} }
} }

View File

@ -76,7 +76,7 @@ private:
caf::PdmUiEditorAttribute* attribute) override; caf::PdmUiEditorAttribute* attribute) override;
std::set<RifEclipseSummaryAddress> findPossibleSummaryAddresses(const std::vector<RimSummaryCase*> &selectedCases, std::set<RifEclipseSummaryAddress> findPossibleSummaryAddresses(const std::vector<SummarySource*> &selectedSources,
const SummaryIdentifierAndField *identifierAndField); const SummaryIdentifierAndField *identifierAndField);
std::set<RifEclipseSummaryAddress> findPossibleSummaryAddressesFromSelectedCases(const SummaryIdentifierAndField *identifierAndField); std::set<RifEclipseSummaryAddress> findPossibleSummaryAddressesFromSelectedCases(const SummaryIdentifierAndField *identifierAndField);
std::set<RifEclipseSummaryAddress> findPossibleSummaryAddressesFromSelectedObservedData(const SummaryIdentifierAndField *identifierAndField); std::set<RifEclipseSummaryAddress> findPossibleSummaryAddressesFromSelectedObservedData(const SummaryIdentifierAndField *identifierAndField);

View File

@ -1,7 +1,6 @@
@startuml @startuml
left to right direction left to right direction
RifSummaryReaderInterface <|-- RifCalculatedSummaryCurveReader RifSummaryReaderInterface <|-- RifCalculatedSummaryCurveReader
RifSummaryReaderInterface <|-- RifColumnBasedUserData RifSummaryReaderInterface <|-- RifColumnBasedUserData
RifSummaryReaderInterface <|-- RifCsvUserData RifSummaryReaderInterface <|-- RifCsvUserData
@ -9,17 +8,24 @@ RifSummaryReaderInterface <|-- RifKeywordVectorUserData
RifSummaryReaderInterface <|-- RifReaderEclipseSummary RifSummaryReaderInterface <|-- RifReaderEclipseSummary
RifSummaryReaderInterface <|-- RifReaderObservedData RifSummaryReaderInterface <|-- RifReaderObservedData
RifSummaryReaderInterface <|-- RifEnsembleStatisticsReader RifSummaryReaderInterface <|-- RifEnsembleStatisticsReader
RifSummaryReaderInterface <|-- RifDerivedEnsembleReader
RifColumnBasedUserData *-- "1" RifColumnBasedUserDataParser RifColumnBasedUserData *-- "1" RifColumnBasedUserDataParser
RifKeywordVectorUserData *-- "1" RifKeywordVectorUserDataParser RifKeywordVectorUserData *-- "1" RifKeywordVectorUserDataParser
RifReaderObservedData --> RifCsvUserDataParser RifReaderObservedData --> RifCsvUserDataParser
RimSummaryCaseCollection -> "*" RimSummaryCase RimSummaryCaseCollection --> "*" RimSummaryCase
RimSummaryCaseCollection <|-- RimDerivedEnsembleCaseCollection
RimDerivedEnsembleCaseCollection --> "*" RimDerivedEnsembleCase
RimSummaryCase <|-- RimCalculatedSummaryCase RimSummaryCase <|-- RimCalculatedSummaryCase
RimSummaryCase <|-- RimFileSummaryCase RimSummaryCase <|-- RimFileSummaryCase
RimSummaryCase <|-- RimGridSummaryCase RimSummaryCase <|-- RimGridSummaryCase
RimSummaryCase <|-- RimObservedData RimSummaryCase <|-- RimObservedData
RimSummaryCase <|-- RimEnsembleStatisticsCase
RimSummaryCase <|-- RimDerivedEnsembleCase
RimObservedData <|-- RimObservedEclipseUserData RimObservedData <|-- RimObservedEclipseUserData
RimObservedData <|-- RimCsvUserData RimObservedData <|-- RimCsvUserData
@ -27,6 +33,8 @@ RimObservedData <|-- RimSummaryObservedDataFile
RimCalculatedSummaryCase --> RifCalculatedSummaryCurveReader RimCalculatedSummaryCase --> RifCalculatedSummaryCurveReader
RimDerivedEnsembleCase --> RifDerivedEnsembleReader
RimSummaryObservedDataFile --> RifReaderObservedData RimSummaryObservedDataFile --> RifReaderObservedData
RimObservedEclipseUserData *--> RifSummaryReaderInterface RimObservedEclipseUserData *--> RifSummaryReaderInterface
@ -44,4 +52,7 @@ RimEnsembleCurveSet -> "1" RimSummaryCaseCollection
RimEnsembleCurveSet --> "1" RimEnsembleStatisticsCase RimEnsembleCurveSet --> "1" RimEnsembleStatisticsCase
RimEnsembleStatisticsCase --> RifEnsembleStatisticsReader RimEnsembleStatisticsCase --> RifEnsembleStatisticsReader
RimSummaryCaseMainCollection -> "*" RimSummaryCase
RimSummaryCaseMainCollection -> "*" RimSummaryCaseCollection
@enduml @enduml