///////////////////////////////////////////////////////////////////////////////// // // 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"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const std::vector<time_t> RimDerivedEnsembleCase::EMPTY_TIME_STEPS_VECTOR; const std::vector<double> RimDerivedEnsembleCase::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", "", "", ""); m_inUse = false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimDerivedEnsembleCase::~RimDerivedEnsembleCase() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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(); std::vector<double>& allValues1 = merger.interpolatedCurveValuesForAllTimeSteps(0); std::vector<double>& allValues2 = merger.interpolatedCurveValuesForAllTimeSteps(1); 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(allValues1[i] - allValues2[i]); } else if (op == DERIVED_ENSEMBLE_ADD) { calculatedValues.push_back(allValues1[i] + allValues2[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); }