From cb506cf86d6a8da0b219a4988ead3f4e38c92339 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Aug 2017 06:51:56 +0200 Subject: [PATCH] #1769 Add time step filtering when importing model Move import code from RiaApplication to command feature Show time step selection UI when importing Eclipse data Support time step reading of HDF data --- .../Application/RiaApplication.cpp | 311 +----------------- ApplicationCode/Application/RiaApplication.h | 4 - .../Application/Tools/CMakeLists_files.cmake | 2 + .../Tools/RiaImportEclipseCaseTools.cpp | 311 ++++++++++++++++++ .../Tools/RiaImportEclipseCaseTools.h | 40 +++ .../CommandFileInterface/RicfLoadCase.cpp | 5 +- .../EclipseCommands/CMakeLists_files.cmake | 2 + .../RicCreateGridCaseGroupFeature.cpp | 6 +- .../RicImportEclipseCaseFeature.cpp | 8 +- ...ImportEclipseCaseTimeStepFilterFeature.cpp | 69 ++++ ...icImportEclipseCaseTimeStepFilterFeature.h | 38 +++ .../RicImportInputEclipseCaseFeature.cpp | 58 +++- .../RicImportInputEclipseCaseFeature.h | 6 + .../RifEclipseOutputFileTools.cpp | 34 ++ .../FileInterface/RifEclipseOutputFileTools.h | 14 +- .../FileInterface/RifReaderEclipseOutput.cpp | 105 +++--- .../FileInterface/RifReaderEclipseOutput.h | 5 +- .../ProjectDataModel/RimEclipseCase.cpp | 68 +--- .../ProjectDataModel/RimEclipseResultCase.cpp | 69 +++- .../ProjectDataModel/RimEclipseResultCase.h | 3 + .../ProjectDataModel/RimTimeStepFilter.cpp | 66 +++- .../ProjectDataModel/RimTimeStepFilter.h | 14 +- ApplicationCode/ProjectDataModel/RimTools.cpp | 47 +++ ApplicationCode/ProjectDataModel/RimTools.h | 7 + 24 files changed, 843 insertions(+), 449 deletions(-) create mode 100644 ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp create mode 100644 ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h create mode 100644 ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseTimeStepFilterFeature.cpp create mode 100644 ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseTimeStepFilterFeature.h diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index e9f278c327..e61f7f777a 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -23,6 +23,7 @@ #include "RiaBaseDefs.h" #include "RiaImageCompareReporter.h" #include "RiaImageFileCompare.h" +#include "RiaImportEclipseCaseTools.h" #include "RiaLogging.h" #include "RiaPreferences.h" #include "RiaProjectModifier.h" @@ -38,20 +39,13 @@ #include "RimCellRangeFilterCollection.h" #include "RimCommandObject.h" #include "RimEclipseCaseCollection.h" -#include "RimEclipseCellColors.h" -#include "RimEclipseFaultColors.h" -#include "RimEclipseInputCase.h" -#include "RimEclipseInputPropertyCollection.h" -#include "RimEclipsePropertyFilterCollection.h" -#include "RimEclipseResultCase.h" -#include "RimEclipseStatisticsCase.h" #include "RimEclipseView.h" -#include "RimEclipseWellCollection.h" #include "RimFaultCollection.h" #include "RimFlowCharacteristicsPlot.h" #include "RimFlowPlotCollection.h" #include "RimFormationNamesCollection.h" +#include "RimEclipseCase.h" #include "RimGeoMechCase.h" #include "RimGeoMechCellColors.h" #include "RimGeoMechModels.h" @@ -94,6 +88,7 @@ #endif // USE_PROTOTYPE_FEATURE_FRACTURES +#include "RicImportInputEclipseCaseFeature.h" #include "RicImportSummaryCaseFeature.h" #include "ExportCommands/RicSnapshotViewToFileFeature.h" #include "ExportCommands/RicSnapshotAllPlotsToFileFeature.h" @@ -963,192 +958,6 @@ QString RiaApplication::createAbsolutePathFromProjectRelativePath(QString projec return projectDir.absoluteFilePath(projectRelativePath); } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::openEclipseCaseFromFile(const QString& fileName) -{ - if (!caf::Utils::fileExists(fileName)) return false; - - QFileInfo gridFileName(fileName); - QString caseName = gridFileName.completeBaseName(); - - return openEclipseCase(caseName, fileName); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::openEclipseCase(const QString& caseName, const QString& caseFileName) -{ - RimEclipseResultCase* rimResultReservoir = new RimEclipseResultCase(); - rimResultReservoir->setCaseInfo(caseName, caseFileName); - - RimEclipseCaseCollection* analysisModels = m_project->activeOilField() ? m_project->activeOilField()->analysisModels() : NULL; - if (analysisModels == NULL) return false; - - RiuMainWindow::instance()->show(); - - analysisModels->cases.push_back(rimResultReservoir); - - RimEclipseView* riv = rimResultReservoir->createAndAddReservoirView(); - - // Select SOIL as default result variable - riv->cellResult()->setResultType(RiaDefines::DYNAMIC_NATIVE); - - if (m_preferences->loadAndShowSoil) - { - riv->cellResult()->setResultVariable("SOIL"); - } - riv->hasUserRequestedAnimation = true; - - riv->loadDataAndUpdate(); - - if (analysisModels->cases.size() > 0) - { - if (rimResultReservoir->eclipseCaseData()) - { -#ifdef USE_PROTOTYPE_FEATURE_FRACTURES - project()->activeOilField()->fractureDefinitionCollection->defaultUnitsForFracTemplates = rimResultReservoir->eclipseCaseData()->unitsType(); -#endif // USE_PROTOTYPE_FEATURE_FRACTURES - } - } - - - - // Add a corresponding summary case if it exists - { - RimSummaryCaseCollection* sumCaseColl = m_project->activeOilField() ? m_project->activeOilField()->summaryCaseCollection() : NULL; - if(sumCaseColl) - { - if (sumCaseColl->summaryCaseCount() == 0 && m_mainPlotWindow) - { - m_mainPlotWindow->hide(); - } - - if (!sumCaseColl->findSummaryCaseFromEclipseResultCase(rimResultReservoir)) - { - RimSummaryCase* newSumCase = sumCaseColl->createAndAddSummaryCaseFromEclipseResultCase(rimResultReservoir); - - if (newSumCase) - { - newSumCase->loadCase(); - - RimSummaryCase* existingFileSummaryCase = sumCaseColl->findSummaryCaseFromFileName(newSumCase->summaryHeaderFilename()); - if (existingFileSummaryCase) - { - // Replace all occurrences of file sum with ecl sum - - std::vector referringObjects; - existingFileSummaryCase->objectsWithReferringPtrFields(referringObjects); - - std::set curveFilters; - - for (caf::PdmObjectHandle* objHandle : referringObjects) - { - RimSummaryCurve* summaryCurve = dynamic_cast(objHandle); - if (summaryCurve) - { - summaryCurve->setSummaryCase(newSumCase); - summaryCurve->updateConnectedEditors(); - - RimSummaryCurveFilter* parentFilter = nullptr; - summaryCurve->firstAncestorOrThisOfType(parentFilter); - if (parentFilter) - { - curveFilters.insert(parentFilter); - } - } - } - - // UI settings of a curve filter is updated based - // on the new case association for the curves in the curve filter - // UI is updated by loadDataAndUpdate() - - for (RimSummaryCurveFilter* curveFilter : curveFilters) - { - curveFilter->loadDataAndUpdate(); - curveFilter->updateConnectedEditors(); - } - - sumCaseColl->deleteCase(existingFileSummaryCase); - - delete existingFileSummaryCase; - - } - else - { - if (m_preferences->autoCreatePlotsOnImport()) - { - RimMainPlotCollection* mainPlotColl = m_project->mainPlotCollection(); - RimSummaryPlotCollection* summaryPlotColl = mainPlotColl->summaryPlotCollection(); - - RicNewSummaryPlotFeature::createNewSummaryPlot(summaryPlotColl, newSumCase); - } - } - - sumCaseColl->updateConnectedEditors(); - } - } - } - } - - if (!riv->cellResult()->hasResult()) - { - riv->cellResult()->setResultVariable(RiaDefines::undefinedResultName()); - } - - analysisModels->updateConnectedEditors(); - - RiuMainWindow::instance()->selectAsCurrentItem(riv->cellResult()); - - - return true; -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::openInputEclipseCaseFromFileNames(const QStringList& fileNames) -{ - RimEclipseInputCase* rimInputReservoir = new RimEclipseInputCase(); - m_project->assignCaseIdToCase(rimInputReservoir); - - rimInputReservoir->openDataFileSet(fileNames); - - RimEclipseCaseCollection* analysisModels = m_project->activeOilField() ? m_project->activeOilField()->analysisModels() : NULL; - if (analysisModels == NULL) return false; - - analysisModels->cases.push_back(rimInputReservoir); - - RimEclipseView* riv = rimInputReservoir->createAndAddReservoirView(); - - riv->cellResult()->setResultType(RiaDefines::INPUT_PROPERTY); - riv->hasUserRequestedAnimation = true; - - riv->loadDataAndUpdate(); - - if (!riv->cellResult()->hasResult()) - { - riv->cellResult()->setResultVariable(RiaDefines::undefinedResultName()); - } - - analysisModels->updateConnectedEditors(); - - RiuMainWindow::instance()->selectAsCurrentItem(riv->cellResult()); - - if (fileNames.size() == 1) - { - addToRecentFiles(fileNames[0]); - } - - return true; -} - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1201,7 +1010,7 @@ bool RiaApplication::openOdbCaseFromFile(const QString& fileName) //-------------------------------------------------------------------------------------------------- void RiaApplication::createMockModel() { - openEclipseCase(RiaDefines::mockModelBasic(), RiaDefines::mockModelBasic()); + RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelBasic()); } //-------------------------------------------------------------------------------------------------- @@ -1209,7 +1018,7 @@ void RiaApplication::createMockModel() //-------------------------------------------------------------------------------------------------- void RiaApplication::createResultsMockModel() { - openEclipseCase(RiaDefines::mockModelBasicWithResults(), RiaDefines::mockModelBasicWithResults()); + RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelBasicWithResults()); } @@ -1218,7 +1027,7 @@ void RiaApplication::createResultsMockModel() //-------------------------------------------------------------------------------------------------- void RiaApplication::createLargeResultsMockModel() { - openEclipseCase(RiaDefines::mockModelLargeWithResults(), RiaDefines::mockModelLargeWithResults()); + RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelLargeWithResults()); } @@ -1227,7 +1036,7 @@ void RiaApplication::createLargeResultsMockModel() //-------------------------------------------------------------------------------------------------- void RiaApplication::createMockModelCustomized() { - openEclipseCase(RiaDefines::mockModelCustomized(), RiaDefines::mockModelCustomized()); + RiaImportEclipseCaseTools::openMockModel(RiaDefines::mockModelCustomized()); } //-------------------------------------------------------------------------------------------------- @@ -1235,7 +1044,7 @@ void RiaApplication::createMockModelCustomized() //-------------------------------------------------------------------------------------------------- void RiaApplication::createInputMockModel() { - openInputEclipseCaseFromFileNames(QStringList(RiaDefines::mockModelBasicInputCase())); + RicImportInputEclipseCaseFeature::openInputEclipseCaseFromFileNames(QStringList(RiaDefines::mockModelBasicInputCase())); } //-------------------------------------------------------------------------------------------------- @@ -1549,21 +1358,21 @@ bool RiaApplication::parseArguments() if (caf::Utils::fileExists(caseName) && (fileExtension == "EGRID" || fileExtension == "GRID")) { - openEclipseCaseFromFile(caseName); + RiaImportEclipseCaseTools::openEclipseCaseFromFile(caseName); } else { QString caseFileNameWithExt = caseName + ".EGRID"; if (caf::Utils::fileExists(caseFileNameWithExt)) { - openEclipseCaseFromFile(caseFileNameWithExt); + RiaImportEclipseCaseTools::openEclipseCaseFromFile(caseFileNameWithExt); } else { caseFileNameWithExt = caseName + ".GRID"; if (caf::Utils::fileExists(caseFileNameWithExt)) { - openEclipseCaseFromFile(caseFileNameWithExt); + RiaImportEclipseCaseTools::openEclipseCaseFromFile(caseFileNameWithExt); } } } @@ -2270,11 +2079,11 @@ bool RiaApplication::openFile(const QString& fileName) } else if (fileName.contains(".egrid", Qt::CaseInsensitive) || fileName.contains(".grid", Qt::CaseInsensitive)) { - loadingSucceded = openEclipseCaseFromFile(fileName); + loadingSucceded = RiaImportEclipseCaseTools::openEclipseCaseFromFile(fileName); } else if (fileName.contains(".grdecl", Qt::CaseInsensitive)) { - loadingSucceded = openInputEclipseCaseFromFileNames(QStringList(fileName)); + loadingSucceded = RicImportInputEclipseCaseFeature::openInputEclipseCaseFromFileNames(QStringList(fileName)); } else if (fileName.contains(".odb", Qt::CaseInsensitive)) { @@ -2574,100 +2383,6 @@ void RiaApplication::updateRegressionTest(const QString& testRootPath) } } -//-------------------------------------------------------------------------------------------------- -/// Make sure changes in this functions is validated to RimIdenticalGridCaseGroup::initAfterRead() -//-------------------------------------------------------------------------------------------------- -bool RiaApplication::addEclipseCases(const QStringList& fileNames) -{ - if (fileNames.size() == 0) return true; - - // First file is read completely including grid. - // The main grid from the first case is reused directly in for the other cases. - // When reading active cell info, only the total cell count is tested for consistency - RimEclipseResultCase* mainResultCase = NULL; - std::vector< std::vector > mainCaseGridDimensions; - RimIdenticalGridCaseGroup* gridCaseGroup = NULL; - - { - QString firstFileName = fileNames[0]; - QFileInfo gridFileName(firstFileName); - - QString caseName = gridFileName.completeBaseName(); - - RimEclipseResultCase* rimResultReservoir = new RimEclipseResultCase(); - rimResultReservoir->setCaseInfo(caseName, firstFileName); - if (!rimResultReservoir->openEclipseGridFile()) - { - delete rimResultReservoir; - - return false; - } - - rimResultReservoir->readGridDimensions(mainCaseGridDimensions); - - mainResultCase = rimResultReservoir; - RimOilField* oilField = m_project->activeOilField(); - if (oilField && oilField->analysisModels()) - { - gridCaseGroup = oilField->analysisModels->createIdenticalCaseGroupFromMainCase(mainResultCase); - } - } - - caf::ProgressInfo info(fileNames.size(), "Reading Active Cell data"); - - for (int i = 1; i < fileNames.size(); i++) - { - QString caseFileName = fileNames[i]; - QFileInfo gridFileName(caseFileName); - - QString caseName = gridFileName.completeBaseName(); - - RimEclipseResultCase* rimResultReservoir = new RimEclipseResultCase(); - rimResultReservoir->setCaseInfo(caseName, caseFileName); - - std::vector< std::vector > caseGridDimensions; - rimResultReservoir->readGridDimensions(caseGridDimensions); - - bool identicalGrid = RigGridManager::isGridDimensionsEqual(mainCaseGridDimensions, caseGridDimensions); - if (identicalGrid) - { - if (rimResultReservoir->openAndReadActiveCellData(mainResultCase->eclipseCaseData())) - { - RimOilField* oilField = m_project->activeOilField(); - if (oilField && oilField->analysisModels()) - { - oilField->analysisModels()->insertCaseInCaseGroup(gridCaseGroup, rimResultReservoir); - } - } - else - { - delete rimResultReservoir; - } - } - else - { - delete rimResultReservoir; - } - - info.setProgress(i); - } - - if (gridCaseGroup) - { - // Create placeholder results and propagate results info from main case to all other cases - gridCaseGroup->loadMainCaseAndActiveCellInfo(); - } - - m_project->activeOilField()->analysisModels()->updateConnectedEditors(); - - if (gridCaseGroup->statisticsCaseCollection()->reservoirs.size() > 0) - { - RiuMainWindow::instance()->selectAsCurrentItem(gridCaseGroup->statisticsCaseCollection()->reservoirs[0]); - } - - return true; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index 033e4e65b0..08f5f0f243 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -121,10 +121,6 @@ public: void setLastUsedDialogDirectory(const QString& dialogName, const QString& directory); bool openFile(const QString& fileName); - bool openEclipseCaseFromFile(const QString& fileName); - bool openEclipseCase(const QString& caseName, const QString& caseFileName); - bool addEclipseCases(const QStringList& fileNames); - bool openInputEclipseCaseFromFileNames(const QStringList& fileNames); bool openOdbCaseFromFile(const QString& fileName); diff --git a/ApplicationCode/Application/Tools/CMakeLists_files.cmake b/ApplicationCode/Application/Tools/CMakeLists_files.cmake index 70ee339008..93a097b20e 100644 --- a/ApplicationCode/Application/Tools/CMakeLists_files.cmake +++ b/ApplicationCode/Application/Tools/CMakeLists_files.cmake @@ -13,6 +13,7 @@ ${CEE_CURRENT_LIST_DIR}RiaImageFileCompare.h ${CEE_CURRENT_LIST_DIR}RiaLogging.h ${CEE_CURRENT_LIST_DIR}RiaProjectModifier.h ${CEE_CURRENT_LIST_DIR}RiaRegressionTest.h +${CEE_CURRENT_LIST_DIR}RiaImportEclipseCaseTools.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -23,6 +24,7 @@ ${CEE_CURRENT_LIST_DIR}RiaImageFileCompare.cpp ${CEE_CURRENT_LIST_DIR}RiaLogging.cpp ${CEE_CURRENT_LIST_DIR}RiaProjectModifier.cpp ${CEE_CURRENT_LIST_DIR}RiaRegressionTest.cpp +${CEE_CURRENT_LIST_DIR}RiaImportEclipseCaseTools.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp new file mode 100644 index 0000000000..f82bdb32c2 --- /dev/null +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.cpp @@ -0,0 +1,311 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RiaImportEclipseCaseTools.h" + +#include "../SummaryPlotCommands/RicNewSummaryPlotFeature.h" + +#include "RiaApplication.h" +#include "RiaPreferences.h" + +#include "RigGridManager.h" + +#include "RimCaseCollection.h" +#include "RimEclipseCaseCollection.h" +#include "RimEclipseCellColors.h" +#include "RimEclipseResultCase.h" +#include "RimEclipseView.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimMainPlotCollection.h" +#include "RimOilField.h" +#include "RimProject.h" +#include "RimSummaryCase.h" +#include "RimSummaryCaseCollection.h" +#include "RimSummaryCurve.h" +#include "RimSummaryCurveFilter.h" +#include "RimSummaryPlotCollection.h" + +#include "RiuMainPlotWindow.h" +#include "RiuMainWindow.h" + +#include "cafUtils.h" +#include "cafProgressInfo.h" + +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaImportEclipseCaseTools::openEclipseCaseFromFile(const QString& fileName) +{ + if (!caf::Utils::fileExists(fileName)) return false; + + return RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(fileName, false); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilter(const QString& fileName) +{ + if (!caf::Utils::fileExists(fileName)) return false; + + return RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(fileName, true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaImportEclipseCaseTools::openMockModel(const QString& name) +{ + return RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(name, false); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilterImpl(const QString& fileName, bool showTimeStepFilter) +{ + QFileInfo gridFileName(fileName); + QString caseName = gridFileName.completeBaseName(); + + RimEclipseResultCase* rimResultReservoir = new RimEclipseResultCase(); + rimResultReservoir->setCaseInfo(caseName, fileName); + + RiaApplication* app = RiaApplication::instance(); + RimProject* project = app->project(); + + RimEclipseCaseCollection* analysisModels = project->activeOilField() ? project->activeOilField()->analysisModels() : NULL; + if (analysisModels == NULL) return false; + + RiuMainWindow::instance()->show(); + + analysisModels->cases.push_back(rimResultReservoir); + + if (!rimResultReservoir->importGridAndResultMetaData(showTimeStepFilter)) + { + analysisModels->removeCaseFromAllGroups(rimResultReservoir); + + delete rimResultReservoir; + + return false; + } + + RimEclipseView* riv = rimResultReservoir->createAndAddReservoirView(); + + // Select SOIL as default result variable + riv->cellResult()->setResultType(RiaDefines::DYNAMIC_NATIVE); + + if (app->preferences()->loadAndShowSoil) + { + riv->cellResult()->setResultVariable("SOIL"); + } + riv->hasUserRequestedAnimation = true; + + riv->loadDataAndUpdate(); + + // Add a corresponding summary case if it exists + { + RimSummaryCaseCollection* sumCaseColl = project->activeOilField() ? project->activeOilField()->summaryCaseCollection() : NULL; + if (sumCaseColl) + { + { + RiuMainPlotWindow* mainPlotWindow = app->mainPlotWindow(); + if (sumCaseColl->summaryCaseCount() == 0 && mainPlotWindow) + { + mainPlotWindow->hide(); + } + } + + if (!sumCaseColl->findSummaryCaseFromEclipseResultCase(rimResultReservoir)) + { + RimSummaryCase* newSumCase = sumCaseColl->createAndAddSummaryCaseFromEclipseResultCase(rimResultReservoir); + + if (newSumCase) + { + newSumCase->loadCase(); + + RimSummaryCase* existingFileSummaryCase = sumCaseColl->findSummaryCaseFromFileName(newSumCase->summaryHeaderFilename()); + if (existingFileSummaryCase) + { + // Replace all occurrences of file sum with ecl sum + + std::vector referringObjects; + existingFileSummaryCase->objectsWithReferringPtrFields(referringObjects); + + std::set curveFilters; + + for (caf::PdmObjectHandle* objHandle : referringObjects) + { + RimSummaryCurve* summaryCurve = dynamic_cast(objHandle); + if (summaryCurve) + { + summaryCurve->setSummaryCase(newSumCase); + summaryCurve->updateConnectedEditors(); + + RimSummaryCurveFilter* parentFilter = nullptr; + summaryCurve->firstAncestorOrThisOfType(parentFilter); + if (parentFilter) + { + curveFilters.insert(parentFilter); + } + } + } + + // UI settings of a curve filter is updated based + // on the new case association for the curves in the curve filter + // UI is updated by loadDataAndUpdate() + + for (RimSummaryCurveFilter* curveFilter : curveFilters) + { + curveFilter->loadDataAndUpdate(); + curveFilter->updateConnectedEditors(); + } + + sumCaseColl->deleteCase(existingFileSummaryCase); + + delete existingFileSummaryCase; + + } + else + { + if (app->preferences()->autoCreatePlotsOnImport()) + { + RimMainPlotCollection* mainPlotColl = project->mainPlotCollection(); + RimSummaryPlotCollection* summaryPlotColl = mainPlotColl->summaryPlotCollection(); + + RicNewSummaryPlotFeature::createNewSummaryPlot(summaryPlotColl, newSumCase); + } + } + + sumCaseColl->updateConnectedEditors(); + } + } + } + } + + if (!riv->cellResult()->hasResult()) + { + riv->cellResult()->setResultVariable(RiaDefines::undefinedResultName()); + } + + analysisModels->updateConnectedEditors(); + + RiuMainWindow::instance()->selectAsCurrentItem(riv->cellResult()); + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiaImportEclipseCaseTools::addEclipseCases(const QStringList& fileNames) +{ + if (fileNames.size() == 0) return true; + + // First file is read completely including grid. + // The main grid from the first case is reused directly in for the other cases. + // When reading active cell info, only the total cell count is tested for consistency + RimEclipseResultCase* mainResultCase = NULL; + std::vector< std::vector > mainCaseGridDimensions; + RimIdenticalGridCaseGroup* gridCaseGroup = NULL; + + RiaApplication* app = RiaApplication::instance(); + RimProject* project = app->project(); + + { + QString firstFileName = fileNames[0]; + QFileInfo gridFileName(firstFileName); + + QString caseName = gridFileName.completeBaseName(); + + RimEclipseResultCase* rimResultReservoir = new RimEclipseResultCase(); + rimResultReservoir->setCaseInfo(caseName, firstFileName); + if (!rimResultReservoir->openEclipseGridFile()) + { + delete rimResultReservoir; + + return false; + } + + rimResultReservoir->readGridDimensions(mainCaseGridDimensions); + + mainResultCase = rimResultReservoir; + RimOilField* oilField = project->activeOilField(); + if (oilField && oilField->analysisModels()) + { + gridCaseGroup = oilField->analysisModels->createIdenticalCaseGroupFromMainCase(mainResultCase); + } + } + + caf::ProgressInfo info(fileNames.size(), "Reading Active Cell data"); + + for (int i = 1; i < fileNames.size(); i++) + { + QString caseFileName = fileNames[i]; + QFileInfo gridFileName(caseFileName); + + QString caseName = gridFileName.completeBaseName(); + + RimEclipseResultCase* rimResultReservoir = new RimEclipseResultCase(); + rimResultReservoir->setCaseInfo(caseName, caseFileName); + + std::vector< std::vector > caseGridDimensions; + rimResultReservoir->readGridDimensions(caseGridDimensions); + + bool identicalGrid = RigGridManager::isGridDimensionsEqual(mainCaseGridDimensions, caseGridDimensions); + if (identicalGrid) + { + if (rimResultReservoir->openAndReadActiveCellData(mainResultCase->eclipseCaseData())) + { + RimOilField* oilField = project->activeOilField(); + if (oilField && oilField->analysisModels()) + { + oilField->analysisModels()->insertCaseInCaseGroup(gridCaseGroup, rimResultReservoir); + } + } + else + { + delete rimResultReservoir; + } + } + else + { + delete rimResultReservoir; + } + + info.setProgress(i); + } + + if (gridCaseGroup) + { + // Create placeholder results and propagate results info from main case to all other cases + gridCaseGroup->loadMainCaseAndActiveCellInfo(); + } + + project->activeOilField()->analysisModels()->updateConnectedEditors(); + + if (gridCaseGroup->statisticsCaseCollection()->reservoirs.size() > 0) + { + RiuMainWindow::instance()->selectAsCurrentItem(gridCaseGroup->statisticsCaseCollection()->reservoirs[0]); + } + + return true; +} + diff --git a/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h new file mode 100644 index 0000000000..34d9e3689a --- /dev/null +++ b/ApplicationCode/Application/Tools/RiaImportEclipseCaseTools.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +class QString; +class QStringList; + +//================================================================================================== +/// +//================================================================================================== +class RiaImportEclipseCaseTools +{ +public: + static bool openEclipseCaseFromFile(const QString& fileName); + static bool openEclipseCaseShowTimeStepFilter(const QString& fileName); + + static bool openMockModel(const QString& name); + + static bool addEclipseCases(const QStringList& fileNames); + +private: + static bool openEclipseCaseShowTimeStepFilterImpl(const QString& fileName, bool showTimeStepFilter); +}; + diff --git a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp index 505e4d7c69..09bb6ea5c4 100644 --- a/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp +++ b/ApplicationCode/CommandFileInterface/RicfLoadCase.cpp @@ -18,7 +18,8 @@ #include "RicfLoadCase.h" -#include "RiaApplication.h" +#include "RiaImportEclipseCaseTools.h" + #include "RiaLogging.h" CAF_PDM_SOURCE_INIT(RicfLoadCase, "loadCase"); @@ -36,7 +37,7 @@ RicfLoadCase::RicfLoadCase() //-------------------------------------------------------------------------------------------------- void RicfLoadCase::execute() { - bool ok = RiaApplication::instance()->openEclipseCaseFromFile(m_path); + bool ok = RiaImportEclipseCaseTools::openEclipseCaseFromFile(m_path); if (!ok) { RiaLogging::error(QString("loadCase: Unable to load case from %1").arg(m_path())); diff --git a/ApplicationCode/Commands/EclipseCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/EclipseCommands/CMakeLists_files.cmake index d166800548..939ca0d038 100644 --- a/ApplicationCode/Commands/EclipseCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/EclipseCommands/CMakeLists_files.cmake @@ -19,6 +19,7 @@ ${CEE_CURRENT_LIST_DIR}RicImportEclipseCaseFeature.h ${CEE_CURRENT_LIST_DIR}RicImportInputEclipseCaseFeature.h ${CEE_CURRENT_LIST_DIR}RicNewStatisticsCaseFeature.h ${CEE_CURRENT_LIST_DIR}RicApplyPropertyFilterAsCellResultFeature.h +${CEE_CURRENT_LIST_DIR}RicImportEclipseCaseTimeStepFilterFeature.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -36,6 +37,7 @@ ${CEE_CURRENT_LIST_DIR}RicImportEclipseCaseFeature.cpp ${CEE_CURRENT_LIST_DIR}RicImportInputEclipseCaseFeature.cpp ${CEE_CURRENT_LIST_DIR}RicNewStatisticsCaseFeature.cpp ${CEE_CURRENT_LIST_DIR}RicApplyPropertyFilterAsCellResultFeature.cpp +${CEE_CURRENT_LIST_DIR}RicImportEclipseCaseTimeStepFilterFeature.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/Commands/EclipseCommands/RicCreateGridCaseGroupFeature.cpp b/ApplicationCode/Commands/EclipseCommands/RicCreateGridCaseGroupFeature.cpp index c5f69fe3de..b304a5ef4b 100644 --- a/ApplicationCode/Commands/EclipseCommands/RicCreateGridCaseGroupFeature.cpp +++ b/ApplicationCode/Commands/EclipseCommands/RicCreateGridCaseGroupFeature.cpp @@ -19,8 +19,9 @@ #include "RicCreateGridCaseGroupFeature.h" +#include "RiaImportEclipseCaseTools.h" + #include "RimEclipseCaseCollection.h" -#include "RiaApplication.h" #include "RiuMultiCaseImportDialog.h" #include "cafSelectionManager.h" @@ -42,13 +43,12 @@ bool RicCreateGridCaseGroupFeature::isCommandEnabled() //-------------------------------------------------------------------------------------------------- void RicCreateGridCaseGroupFeature::onActionTriggered(bool isChecked) { - RiaApplication* app = RiaApplication::instance(); RiuMultiCaseImportDialog dialog; int action = dialog.exec(); if (action == QDialog::Accepted) { QStringList gridFileNames = dialog.eclipseCaseFileNames(); - app->addEclipseCases(gridFileNames); + RiaImportEclipseCaseTools::addEclipseCases(gridFileNames); } } diff --git a/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseFeature.cpp b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseFeature.cpp index ee0ff4175f..b208bed484 100644 --- a/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseFeature.cpp +++ b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseFeature.cpp @@ -19,8 +19,12 @@ #include "RicImportEclipseCaseFeature.h" -#include "RimEclipseCaseCollection.h" +#include "RiaImportEclipseCaseTools.h" + #include "RiaApplication.h" + +#include "RimEclipseCaseCollection.h" + #include "RiuMainWindow.h" #include "cafSelectionManager.h" @@ -57,7 +61,7 @@ void RicImportEclipseCaseFeature::onActionTriggered(bool isChecked) if (!fileNames.isEmpty()) { - if (app->openEclipseCaseFromFile(fileName)) + if (RiaImportEclipseCaseTools::openEclipseCaseFromFile(fileName)) { app->addToRecentFiles(fileName); } diff --git a/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseTimeStepFilterFeature.cpp b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseTimeStepFilterFeature.cpp new file mode 100644 index 0000000000..c174b6796e --- /dev/null +++ b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseTimeStepFilterFeature.cpp @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicImportEclipseCaseTimeStepFilterFeature.h" + +#include "RiaApplication.h" +#include "RiaImportEclipseCaseTools.h" + +#include "RiuMainWindow.h" + +#include +#include +#include + +CAF_CMD_SOURCE_INIT(RicImportEclipseCaseTimeStepFilterFeature, "RicImportEclipseCaseTimeStepFilterFeature"); + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportEclipseCaseTimeStepFilterFeature::onActionTriggered(bool isChecked) +{ + RiaApplication* app = RiaApplication::instance(); + + QString defaultDir = app->lastUsedDialogDirectory("BINARY_GRID"); + QString fileName = QFileDialog::getOpenFileName(RiuMainWindow::instance(), "Import Eclipse File", defaultDir, "Eclipse Grid Files (*.GRID *.EGRID)"); + if (!fileName.isEmpty()) + { + defaultDir = QFileInfo(fileName).absolutePath(); + app->setLastUsedDialogDirectory("BINARY_GRID", defaultDir); + + if (RiaImportEclipseCaseTools::openEclipseCaseShowTimeStepFilter(fileName)) + { + app->addToRecentFiles(fileName); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportEclipseCaseTimeStepFilterFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setIcon(QIcon(":/Case48x48.png")); + actionToSetup->setText("Import Eclipse Case (Time Step Filtered)"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicImportEclipseCaseTimeStepFilterFeature::isCommandEnabled() +{ + return true; +} diff --git a/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseTimeStepFilterFeature.h b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseTimeStepFilterFeature.h new file mode 100644 index 0000000000..9a7aa65038 --- /dev/null +++ b/ApplicationCode/Commands/EclipseCommands/RicImportEclipseCaseTimeStepFilterFeature.h @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +#include + +//================================================================================================== +/// +//================================================================================================== +class RicImportEclipseCaseTimeStepFilterFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + virtual void onActionTriggered(bool isChecked) override; + virtual void setupActionLook(QAction* actionToSetup) override; + virtual bool isCommandEnabled() override; +}; + + diff --git a/ApplicationCode/Commands/EclipseCommands/RicImportInputEclipseCaseFeature.cpp b/ApplicationCode/Commands/EclipseCommands/RicImportInputEclipseCaseFeature.cpp index 4658451699..aedb38a3df 100644 --- a/ApplicationCode/Commands/EclipseCommands/RicImportInputEclipseCaseFeature.cpp +++ b/ApplicationCode/Commands/EclipseCommands/RicImportInputEclipseCaseFeature.cpp @@ -19,17 +19,68 @@ #include "RicImportInputEclipseCaseFeature.h" -#include "RimEclipseCaseCollection.h" #include "RiaApplication.h" +#include "RiaPorosityModel.h" + +#include "RimEclipseCaseCollection.h" +#include "RimEclipseCellColors.h" +#include "RimEclipseInputCase.h" +#include "RimEclipseView.h" +#include "RimOilField.h" +#include "RimProject.h" + #include "RiuMainWindow.h" #include "cafSelectionManager.h" - + #include #include CAF_CMD_SOURCE_INIT(RicImportInputEclipseCaseFeature, "RicImportInputEclipseCaseFeature"); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicImportInputEclipseCaseFeature::openInputEclipseCaseFromFileNames(const QStringList& fileNames) +{ + RimEclipseInputCase* rimInputReservoir = new RimEclipseInputCase(); + + RiaApplication* app = RiaApplication::instance(); + RimProject* project = app->project(); + + project->assignCaseIdToCase(rimInputReservoir); + + rimInputReservoir->openDataFileSet(fileNames); + + RimEclipseCaseCollection* analysisModels = project->activeOilField() ? project->activeOilField()->analysisModels() : NULL; + if (analysisModels == NULL) return false; + + analysisModels->cases.push_back(rimInputReservoir); + + RimEclipseView* riv = rimInputReservoir->createAndAddReservoirView(); + + riv->cellResult()->setResultType(RiaDefines::INPUT_PROPERTY); + riv->hasUserRequestedAnimation = true; + + riv->loadDataAndUpdate(); + + if (!riv->cellResult()->hasResult()) + { + riv->cellResult()->setResultVariable(RiaDefines::undefinedResultName()); + } + + analysisModels->updateConnectedEditors(); + + RiuMainWindow::instance()->selectAsCurrentItem(riv->cellResult()); + + if (fileNames.size() == 1) + { + app->addToRecentFiles(fileNames[0]); + } + + return true; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -52,8 +103,7 @@ void RicImportInputEclipseCaseFeature::onActionTriggered(bool isChecked) // Remember the path to next time app->setLastUsedDialogDirectory("INPUT_FILES", QFileInfo(fileNames.last()).absolutePath()); - app->openInputEclipseCaseFromFileNames(fileNames); - + RicImportInputEclipseCaseFeature::openInputEclipseCaseFromFileNames(fileNames); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/EclipseCommands/RicImportInputEclipseCaseFeature.h b/ApplicationCode/Commands/EclipseCommands/RicImportInputEclipseCaseFeature.h index dcf3d8b27b..85ad907df9 100644 --- a/ApplicationCode/Commands/EclipseCommands/RicImportInputEclipseCaseFeature.h +++ b/ApplicationCode/Commands/EclipseCommands/RicImportInputEclipseCaseFeature.h @@ -23,6 +23,8 @@ #include +class QStringList; + //================================================================================================== /// //================================================================================================== @@ -30,6 +32,10 @@ class RicImportInputEclipseCaseFeature : public caf::CmdFeature { CAF_CMD_HEADER_INIT; +public: + static bool openInputEclipseCaseFromFileNames(const QStringList& fileNames); + + protected: // Overrides virtual bool isCommandEnabled(); diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp index d2dab4a787..a562932270 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp @@ -20,6 +20,9 @@ #include "RifEclipseOutputFileTools.h" +#include "RifEclipseRestartFilesetAccess.h" +#include "RifEclipseUnifiedRestartFileAccess.h" + #include "ert/ecl/ecl_file.h" #include "ert/ecl/ecl_grid.h" #include "ert/ecl/ecl_kw_magic.h" @@ -337,6 +340,37 @@ int RifEclipseOutputFileTools::readUnitsType(ecl_file_type* ecl_file) return unitsType; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RifEclipseOutputFileTools::createDynamicResultAccess(const QString& fileName) +{ + QStringList filesWithSameBaseName; + RifEclipseOutputFileTools::findSiblingFilesWithSameBaseName(fileName, &filesWithSameBaseName); + + cvf::ref resultsAccess; + + // Look for unified restart file + QString unrstFileName = RifEclipseOutputFileTools::firstFileNameOfType(filesWithSameBaseName, ECL_UNIFIED_RESTART_FILE); + if (unrstFileName.size() > 0) + { + resultsAccess = new RifEclipseUnifiedRestartFileAccess(); + resultsAccess->setRestartFiles(QStringList(unrstFileName)); + } + else + { + // Look for set of restart files (one file per time step) + QStringList restartFiles = RifEclipseOutputFileTools::filterFileNamesOfType(filesWithSameBaseName, ECL_RESTART_FILE); + if (restartFiles.size() > 0) + { + resultsAccess = new RifEclipseRestartFilesetAccess(); + resultsAccess->setRestartFiles(restartFiles); + } + } + + return resultsAccess; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h index a9f6a87aaf..cafb60a05f 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h @@ -20,20 +20,23 @@ #pragma once +#include "RifEclipseRestartDataAccess.h" + +#include "ert/ecl/ecl_util.h" + #include "cvfBase.h" #include "cvfObject.h" -#include "RifReaderInterface.h" -#include "RifEclipseRestartDataAccess.h" - #include #include #include -#include "ert/ecl/ecl_util.h" +#include typedef struct ecl_file_struct ecl_file_type; +class RifEclipseRestartDataAccess; + //================================================================================================== // @@ -62,6 +65,9 @@ public: static int readUnitsType(ecl_file_type* ecl_file); + static cvf::ref createDynamicResultAccess(const QString& fileName); + + private: static void createReportStepsMetaData(std::vector ecl_files, std::vector* reportSteps); }; diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 6f35b548e0..d91c13465e 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -24,9 +24,6 @@ #include "RifEclipseInputFileTools.h" #include "RifEclipseOutputFileTools.h" -#include "RifEclipseRestartFilesetAccess.h" -#include "RifEclipseUnifiedRestartFileAccess.h" -#include "RifHdf5ReaderInterface.h" #ifdef USE_HDF5 #include "RifHdf5Reader.h" @@ -372,6 +369,8 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigEclipseCaseData* e // Get set of files QStringList fileSet; if (!RifEclipseOutputFileTools::findSiblingFilesWithSameBaseName(fileName, &fileSet)) return false; + + m_fileName = fileName; progInfo.incrementProgress(); @@ -470,12 +469,7 @@ void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) RiaLogging::info("HDF: Removing all existing Sour Sim data ..."); matrixModelResults->eraseAllSourSimData(); - std::vector dateTimes; - std::vector daysSinceSimulationStart; - if (m_dynamicResultsAccess.notNull()) - { - m_dynamicResultsAccess->timeSteps(&dateTimes, &daysSinceSimulationStart); - } + std::vector timeStepInfos = createFilteredTimeStepInfos(); std::unique_ptr myReader; #ifdef USE_HDF5 @@ -490,27 +484,21 @@ void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) } std::vector hdfTimeSteps = myReader->timeSteps(); - if (dateTimes.size() > 0) - { - if (hdfTimeSteps.size() != dateTimes.size()) - { - RiaLogging::error("HDF: Time step count does not match"); - RiaLogging::error(QString("HDF: Eclipse count %1").arg(dateTimes.size())); - RiaLogging::error(QString("HDF: HDF count %1").arg(hdfTimeSteps.size())); - - return; - } + if (timeStepInfos.size() > 0) + { bool isTimeStampsEqual = true; - for (size_t i = 0; i < dateTimes.size(); i++) + + for (size_t i = 0; i < timeStepInfos.size(); i++) { - if (hdfTimeSteps[i].date() != dateTimes[i].date()) + size_t indexOnFile = timeStepIndexOnFile(i); + QString dateStr("yyyy.MMM.ddd hh:mm"); + + if (!isEclipseAndSoursimTimeStepsEqual(hdfTimeSteps[indexOnFile], timeStepInfos[i].m_date)) { RiaLogging::error("HDF: Time steps does not match"); - QString dateStr("yyyy.MMM.ddd hh:mm"); - - RiaLogging::error(QString("HDF: Eclipse date %1").arg(dateTimes[i].toString(dateStr))); + RiaLogging::error(QString("HDF: Eclipse date %1").arg(timeStepInfos[i].m_date.toString(dateStr))); RiaLogging::error(QString("HDF: HDF date %1").arg(hdfTimeSteps[i].toString(dateStr))); isTimeStampsEqual = false; @@ -522,19 +510,15 @@ void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) else { // Use time steps from HDF to define the time steps - dateTimes = hdfTimeSteps; - QDateTime firstDate = hdfTimeSteps[0]; + std::vector daysSinceSimulationStart; + for (auto d : hdfTimeSteps) { daysSinceSimulationStart.push_back(firstDate.daysTo(d)); } - } - - std::vector timeStepInfos; - { std::vector reportNumbers; if (m_dynamicResultsAccess.notNull()) { @@ -542,13 +526,13 @@ void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) } else { - for (size_t i = 0; i < dateTimes.size(); i++) + for (size_t i = 0; i < hdfTimeSteps.size(); i++) { reportNumbers.push_back(static_cast(i)); } } - timeStepInfos = RigEclipseTimeStepInfo::createTimeStepInfos(dateTimes, reportNumbers, daysSinceSimulationStart); + timeStepInfos = RigEclipseTimeStepInfo::createTimeStepInfos(hdfTimeSteps, reportNumbers, daysSinceSimulationStart); } QStringList resultNames = myReader->propertyNames(); @@ -561,6 +545,14 @@ void RifReaderEclipseOutput::setHdf5FileName(const QString& fileName) m_hdfReaderInterface = std::move(myReader); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifReaderEclipseOutput::setFileDataAccess(RifEclipseRestartDataAccess* restartDataAccess) +{ + m_dynamicResultsAccess = restartDataAccess; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -686,7 +678,7 @@ bool RifReaderEclipseOutput::openAndReadActiveCellData(const QString& fileName, return false; } - m_dynamicResultsAccess = createDynamicResultsAccess(); + ensureDynamicResultAccessIsPresent(); if (m_dynamicResultsAccess.notNull()) { m_dynamicResultsAccess->setTimeSteps(mainCaseTimeSteps); @@ -801,7 +793,7 @@ void RifReaderEclipseOutput::buildMetaData() std::vector timeStepInfos; // Create access object for dynamic results - m_dynamicResultsAccess = createDynamicResultsAccess(); + ensureDynamicResultAccessIsPresent(); if (m_dynamicResultsAccess.notNull()) { m_dynamicResultsAccess->open(); @@ -914,29 +906,12 @@ void RifReaderEclipseOutput::buildMetaData() //-------------------------------------------------------------------------------------------------- /// Create results access object (.UNRST or .X0001 ... .XNNNN) //-------------------------------------------------------------------------------------------------- -RifEclipseRestartDataAccess* RifReaderEclipseOutput::createDynamicResultsAccess() +void RifReaderEclipseOutput::ensureDynamicResultAccessIsPresent() { - RifEclipseRestartDataAccess* resultsAccess = NULL; - - // Look for unified restart file - QString unrstFileName = RifEclipseOutputFileTools::firstFileNameOfType(m_filesWithSameBaseName, ECL_UNIFIED_RESTART_FILE); - if (unrstFileName.size() > 0) + if (m_dynamicResultsAccess.isNull()) { - resultsAccess = new RifEclipseUnifiedRestartFileAccess(); - resultsAccess->setRestartFiles(QStringList(unrstFileName)); + m_dynamicResultsAccess = RifEclipseOutputFileTools::createDynamicResultAccess(m_fileName); } - else - { - // Look for set of restart files (one file per time step) - QStringList restartFiles = RifEclipseOutputFileTools::filterFileNamesOfType(m_filesWithSameBaseName, ECL_RESTART_FILE); - if (restartFiles.size() > 0) - { - resultsAccess = new RifEclipseRestartFilesetAccess(); - resultsAccess->setRestartFiles(restartFiles); - } - } - - return resultsAccess; } //-------------------------------------------------------------------------------------------------- @@ -997,7 +972,9 @@ void RifReaderEclipseOutput::sourSimRlResult(const QString& result, size_t stepI fracActCellInfo->gridActiveCellCounts(0, activeCellCount); } - bool readCellResultOk = m_hdfReaderInterface->dynamicResult(result, stepIndex, values); + size_t fileIndex = timeStepIndexOnFile(stepIndex); + + bool readCellResultOk = m_hdfReaderInterface->dynamicResult(result, fileIndex, values); if (activeCellCount != values->size()) { @@ -1013,12 +990,7 @@ void RifReaderEclipseOutput::sourSimRlResult(const QString& result, size_t stepI //-------------------------------------------------------------------------------------------------- bool RifReaderEclipseOutput::dynamicResult(const QString& result, RiaDefines::PorosityModelType matrixOrFracture, size_t stepIndex, std::vector* values) { - - - if (m_dynamicResultsAccess.isNull()) - { - m_dynamicResultsAccess = createDynamicResultsAccess(); - } + ensureDynamicResultAccessIsPresent(); if (m_dynamicResultsAccess.notNull()) { @@ -1976,6 +1948,17 @@ std::vector RifReaderEclipseOutput::createFilteredTimeSt return timeStepInfos; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifReaderEclipseOutput::isEclipseAndSoursimTimeStepsEqual(const QDateTime& dt1, const QDateTime& dt2) +{ + // Currently, HDF files do not contain hours and minutes + // Only compare date, and skip hour/minutes + + return dt1.date() == dt2.date(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h index 014585a537..7f19622cce 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h @@ -54,6 +54,7 @@ public: bool open(const QString& fileName, RigEclipseCaseData* eclipseCase); void setHdf5FileName(const QString& fileName); + void setFileDataAccess(RifEclipseRestartDataAccess* restartDataAccess); virtual bool openAndReadActiveCellData(const QString& fileName, const std::vector& mainCaseTimeSteps, RigEclipseCaseData* eclipseCase); void close(); @@ -82,12 +83,14 @@ private: void transferStaticNNCData(const ecl_grid_type* mainEclGrid , ecl_file_type* init_file, RigMainGrid* mainGrid); void transferDynamicNNCData(const ecl_grid_type* mainEclGrid, RigMainGrid* mainGrid); - RifEclipseRestartDataAccess* createDynamicResultsAccess(); + void ensureDynamicResultAccessIsPresent(); QStringList validKeywordsForPorosityModel(const QStringList& keywords, const std::vector& keywordDataItemCounts, const RigActiveCellInfo* activeCellInfo, const RigActiveCellInfo* fractureActiveCellInfo, RiaDefines::PorosityModelType matrixOrFracture, size_t timeStepCount) const; std::vector createFilteredTimeStepInfos(); + static bool isEclipseAndSoursimTimeStepsEqual(const QDateTime& dt1, const QDateTime& dt2); + private: QString m_fileName; // Name of file used to start accessing Eclipse output files QStringList m_filesWithSameBaseName; // Set of files in filename's path with same base name as filename diff --git a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp index 3c6ab732ba..4100aaa8e0 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseCase.cpp @@ -37,17 +37,18 @@ #include "RimEclipsePropertyFilter.h" #include "RimEclipsePropertyFilterCollection.h" #include "RimEclipseView.h" -#include "RimFormationNames.h" -#include "RimReservoirCellResultsStorage.h" -#include "RimProject.h" -#include "RimMainPlotCollection.h" -#include "RimWellLogPlotCollection.h" -#include "RimSummaryPlotCollection.h" -#include "RimFlowPlotCollection.h" -#include "RimWellLogPlot.h" -#include "RimSummaryPlot.h" #include "RimFlowCharacteristicsPlot.h" +#include "RimFlowPlotCollection.h" +#include "RimFormationNames.h" +#include "RimMainPlotCollection.h" +#include "RimProject.h" +#include "RimReservoirCellResultsStorage.h" +#include "RimSummaryPlot.h" +#include "RimSummaryPlotCollection.h" +#include "RimTools.h" #include "RimWellAllocationPlot.h" +#include "RimWellLogPlot.h" +#include "RimWellLogPlotCollection.h" #include "cafPdmDocument.h" #include "cafProgressInfo.h" @@ -435,42 +436,7 @@ void RimEclipseCase::createTimeStepFormatString() { std::vector timeStepDates = this->timeStepDates(); - bool hasHoursAndMinutesInTimesteps = false; - bool hasSecondsInTimesteps = false; - bool hasMillisecondsInTimesteps = false; - for (size_t i = 0; i < timeStepDates.size(); i++) - { - if (timeStepDates[i].time().msec() != 0.0) - { - hasMillisecondsInTimesteps = true; - hasSecondsInTimesteps = true; - hasHoursAndMinutesInTimesteps = true; - break; - } - else if (timeStepDates[i].time().second() != 0.0) - { - hasHoursAndMinutesInTimesteps = true; - hasSecondsInTimesteps = true; - } - else if (timeStepDates[i].time().hour() != 0.0 || timeStepDates[i].time().minute() != 0.0) - { - hasHoursAndMinutesInTimesteps = true; - } - } - - m_timeStepFormatString = "dd.MMM yyyy"; - if (hasHoursAndMinutesInTimesteps) - { - m_timeStepFormatString += " - hh:mm"; - if (hasSecondsInTimesteps) - { - m_timeStepFormatString += ":ss"; - if (hasMillisecondsInTimesteps) - { - m_timeStepFormatString += ".zzz"; - } - } - } + m_timeStepFormatString = RimTools::createTimeFormatStringFromDates(timeStepDates); } //-------------------------------------------------------------------------------------------------- @@ -582,10 +548,6 @@ void RimEclipseCase::setFilesContainingFaults(const std::vector& val) //-------------------------------------------------------------------------------------------------- bool RimEclipseCase::openReserviorCase() { - // If read already, return - - if (this->eclipseCaseData() != NULL) return true; - if (!openEclipseGridFile()) { return false; @@ -593,7 +555,7 @@ bool RimEclipseCase::openReserviorCase() { RimReservoirCellResultsStorage* results = this->results(RiaDefines::MATRIX_MODEL); - if (results->cellResults()) + if (results && results->cellResults()) { results->cellResults()->createPlaceholderResultEntries(); // After the placeholder result for combined transmissibility is created, @@ -621,9 +583,13 @@ bool RimEclipseCase::openReserviorCase() } } + { RimReservoirCellResultsStorage* results = this->results(RiaDefines::FRACTURE_MODEL); - if (results->cellResults()) results->cellResults()->createPlaceholderResultEntries(); + if (results && results->cellResults()) + { + results->cellResults()->createPlaceholderResultEntries(); + } } createTimeStepFormatString(); diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp index 6b1e020865..cda9f03ed1 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.cpp @@ -93,11 +93,19 @@ RimEclipseResultCase::RimEclipseResultCase() //-------------------------------------------------------------------------------------------------- bool RimEclipseResultCase::openEclipseGridFile() { - caf::ProgressInfo progInfo(50, "Reading Eclipse Grid File"); + return importGridAndResultMetaData(false); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimEclipseResultCase::importGridAndResultMetaData(bool showTimeStepFilter) +{ + caf::ProgressInfo progInfo(50, "Reading Eclipse Grid File"); + + progInfo.setProgressDescription("Open Grid File"); + progInfo.setNextProgressIncrement(48); - progInfo.setProgressDescription("Open Grid File"); - progInfo.setNextProgressIncrement(48); - // Early exit if data is already read if (m_gridAndWellDataIsReadFromFile) return true; @@ -115,24 +123,59 @@ bool RimEclipseResultCase::openEclipseGridFile() } RiaPreferences* prefs = RiaApplication::instance()->preferences(); - readerInterface = new RifReaderEclipseOutput; - readerInterface->setReaderSetting(prefs->readerSettings()); - readerInterface->setFilenamesWithFaults(this->filesContainingFaults()); + cvf::ref readerEclipseOutput = new RifReaderEclipseOutput; + readerEclipseOutput->setReaderSetting(prefs->readerSettings()); + readerEclipseOutput->setFilenamesWithFaults(this->filesContainingFaults()); - if (!m_timeStepFilter->timeStepIndicesToImport().empty()) + if (showTimeStepFilter) { - readerInterface->setTimeStepFilter(m_timeStepFilter->timeStepIndicesToImport()); + cvf::ref restartDataAccess = RifEclipseOutputFileTools::createDynamicResultAccess(caseFileName()); + if (restartDataAccess.isNull()) + { + return false; + } + + { + std::vector timeSteps; + std::vector daysSinceSimulationStart; + + restartDataAccess->timeSteps(&timeSteps, &daysSinceSimulationStart); + + // Show GUI to select time steps + + RimTimeStepFilter myTimeStepFilter; + myTimeStepFilter.setCustomTimeSteps(timeSteps); + + caf::PdmUiPropertyViewDialog propertyDialog(NULL, &myTimeStepFilter, "Time Step Filter", "", QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + propertyDialog.resize(QSize(400, 200)); + + if (propertyDialog.exec() != QDialog::Accepted) + { + return false; + } + + m_timeStepFilter->setSelectedTimeStepIndices(myTimeStepFilter.selectedTimeStepIndices()); + } + + readerEclipseOutput->setFileDataAccess(restartDataAccess.p()); + } + + if (!m_timeStepFilter->selectedTimeStepIndices().empty()) + { + readerEclipseOutput->setTimeStepFilter(m_timeStepFilter->selectedTimeStepIndices()); } cvf::ref eclipseCase = new RigEclipseCaseData; - if (!readerInterface->open(caseFileName(), eclipseCase.p())) + if (!readerEclipseOutput->open(caseFileName(), eclipseCase.p())) { return false; } - this->setFilesContainingFaults(readerInterface->filenamesWithFaults()); + this->setFilesContainingFaults(readerEclipseOutput->filenamesWithFaults()); - this->setReservoirData( eclipseCase.p() ); + this->setReservoirData(eclipseCase.p()); + + readerInterface = readerEclipseOutput; } results(RiaDefines::MATRIX_MODEL)->setReaderInterface(readerInterface.p()); @@ -163,7 +206,7 @@ bool RimEclipseResultCase::openEclipseGridFile() } return true; - } +} //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.h b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.h index a543cb3b1d..7c3cef8767 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultCase.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultCase.h @@ -46,6 +46,9 @@ public: bool hasSourSimFile(); virtual bool openEclipseGridFile(); + + bool importGridAndResultMetaData(bool showTimeStepFilter); + virtual void reloadEclipseGridFile(); bool openAndReadActiveCellData(RigEclipseCaseData* mainEclipseCase); void readGridDimensions(std::vector< std::vector >& gridDimensions); diff --git a/ApplicationCode/ProjectDataModel/RimTimeStepFilter.cpp b/ApplicationCode/ProjectDataModel/RimTimeStepFilter.cpp index 1d176929cd..407c69f5c2 100644 --- a/ApplicationCode/ProjectDataModel/RimTimeStepFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimTimeStepFilter.cpp @@ -18,6 +18,11 @@ #include "RimTimeStepFilter.h" +#include "RimCase.h" +#include "RimTools.h" + +#include + CAF_PDM_SOURCE_INIT(RimTimeStepFilter, "TimeStepFilter"); //-------------------------------------------------------------------------------------------------- @@ -27,21 +32,76 @@ RimTimeStepFilter::RimTimeStepFilter() { CAF_PDM_InitObject("Time Step Filter", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_timeStepIndicesToImport, "TimeStepIndicesToImport", "Values", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_selectedTimeStepIndices, "TimeStepIndicesToImport", "Values", "", "", ""); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimTimeStepFilter::timeStepIndicesToImport() const +void RimTimeStepFilter::setCustomTimeSteps(const std::vector& timeSteps) +{ + m_customTimeSteps = timeSteps; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimTimeStepFilter::selectedTimeStepIndices() const { std::vector indices; // Convert vector from int to size_t - for (auto intValue : m_timeStepIndicesToImport.v()) + for (auto intValue : m_selectedTimeStepIndices.v()) { indices.push_back(intValue); } return indices; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTimeStepFilter::setSelectedTimeStepIndices(const std::vector& indices) +{ + m_selectedTimeStepIndices.v().clear(); + + for (auto sizetValue : indices) + { + m_selectedTimeStepIndices.v().push_back(static_cast(sizetValue)); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimTimeStepFilter::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) +{ + QList optionItems; + + if (fieldNeedingOptions == &m_selectedTimeStepIndices) + { + RimCase* rimCase = nullptr; + this->firstAncestorOrThisOfType(rimCase); + if (rimCase) + { + QStringList timeSteps = rimCase->timeStepStrings(); + + for (int i = 0; i < timeSteps.size(); i++) + { + optionItems.push_back(caf::PdmOptionItemInfo(timeSteps[i], static_cast(i))); + } + } + else + { + QString formatString = RimTools::createTimeFormatStringFromDates(m_customTimeSteps); + + for (size_t i = 0; i < m_customTimeSteps.size(); i++) + { + optionItems.push_back(caf::PdmOptionItemInfo(m_customTimeSteps[i].toString(formatString), static_cast(i))); + } + } + } + + return optionItems; +} diff --git a/ApplicationCode/ProjectDataModel/RimTimeStepFilter.h b/ApplicationCode/ProjectDataModel/RimTimeStepFilter.h index 12830b44b9..03fa166b3e 100644 --- a/ApplicationCode/ProjectDataModel/RimTimeStepFilter.h +++ b/ApplicationCode/ProjectDataModel/RimTimeStepFilter.h @@ -23,6 +23,8 @@ #include +class QDateTime; + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -32,9 +34,15 @@ class RimTimeStepFilter : public caf::PdmObject public: RimTimeStepFilter(); - std::vector timeStepIndicesToImport() const; + void setCustomTimeSteps(const std::vector& timeSteps); + + std::vector selectedTimeStepIndices() const; + void setSelectedTimeStepIndices(const std::vector& indices); private: - caf::PdmField< std::vector > m_timeStepIndicesToImport; -}; + virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override; +private: + caf::PdmField< std::vector > m_selectedTimeStepIndices; + std::vector m_customTimeSteps; +}; diff --git a/ApplicationCode/ProjectDataModel/RimTools.cpp b/ApplicationCode/ProjectDataModel/RimTools.cpp index 2d47f7c43a..49b91cc70d 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationCode/ProjectDataModel/RimTools.cpp @@ -34,6 +34,7 @@ #include #include +#include //-------------------------------------------------------------------------------------------------- /// @@ -259,3 +260,49 @@ void RimTools::caseOptionItems(QList* options) } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimTools::createTimeFormatStringFromDates(const std::vector& dates) +{ + bool hasHoursAndMinutesInTimesteps = false; + bool hasSecondsInTimesteps = false; + bool hasMillisecondsInTimesteps = false; + + for (size_t i = 0; i < dates.size(); i++) + { + if (dates[i].time().msec() != 0.0) + { + hasMillisecondsInTimesteps = true; + hasSecondsInTimesteps = true; + hasHoursAndMinutesInTimesteps = true; + break; + } + else if (dates[i].time().second() != 0.0) + { + hasHoursAndMinutesInTimesteps = true; + hasSecondsInTimesteps = true; + } + else if (dates[i].time().hour() != 0.0 || dates[i].time().minute() != 0.0) + { + hasHoursAndMinutesInTimesteps = true; + } + } + + QString formatString = "dd.MMM yyyy"; + if (hasHoursAndMinutesInTimesteps) + { + formatString += " - hh:mm"; + if (hasSecondsInTimesteps) + { + formatString += ":ss"; + if (hasMillisecondsInTimesteps) + { + formatString += ".zzz"; + } + } + } + + return formatString; +} diff --git a/ApplicationCode/ProjectDataModel/RimTools.h b/ApplicationCode/ProjectDataModel/RimTools.h index 8078c44f39..be5f62117c 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.h +++ b/ApplicationCode/ProjectDataModel/RimTools.h @@ -25,10 +25,15 @@ #include +class QDateTime; + namespace caf { class PdmOptionItemInfo; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- class RimTools { public: @@ -38,4 +43,6 @@ public: static void wellPathOptionItems(QList* options); static void caseOptionItems(QList* options); + + static QString createTimeFormatStringFromDates(const std::vector& dates); };