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); };