From f09f4876359d504313e65ccb9dbd18c1ad181251 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Mon, 18 Mar 2019 12:52:01 +0100 Subject: [PATCH] #4143 First implementation of export sector model --- .../RicfExportVisibleCells.cpp | 17 +- .../RicfExportVisibleCells.h | 4 +- .../ExportCommands/CMakeLists_files.cmake | 4 + .../RicExportEclipseInputGridFeature.cpp | 218 ++++++++++++++++ .../RicExportEclipseInputGridFeature.h | 50 ++++ .../RicExportEclipseInputGridUi.cpp | 238 ++++++++++++++++++ .../RicExportEclipseInputGridUi.h | 75 ++++++ .../Commands/RicImportGeneralDataFeature.cpp | 6 +- .../RifEclipseOutputFileTools.cpp | 40 +++ .../FileInterface/RifEclipseOutputFileTools.h | 5 +- .../FileInterface/RifReaderEclipseOutput.cpp | 176 +++++++++++++ .../FileInterface/RifReaderEclipseOutput.h | 9 + .../RimContextCommandBuilder.cpp | 2 + .../RimEclipseResultDefinition.cpp | 140 +++++------ .../RimEclipseResultDefinition.h | 12 +- .../UnitTests/RiaTestDataDirectory.h.cmake | 1 + .../UnitTests/RifReaderEclipseOutput-Test.cpp | 202 +++++++++++---- ApplicationCode/UnitTests/TestData/.gitignore | 2 + .../cafUserInterface/cafPdmUiFilePathEditor.h | 6 +- 19 files changed, 1060 insertions(+), 147 deletions(-) create mode 100644 ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridFeature.cpp create mode 100644 ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridFeature.h create mode 100644 ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridUi.cpp create mode 100644 ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridUi.h create mode 100644 ApplicationCode/UnitTests/TestData/.gitignore diff --git a/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.cpp b/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.cpp index ecd1d4c6de..e7da2911db 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.cpp +++ b/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.cpp @@ -21,8 +21,8 @@ #include "RiaFilePathTools.h" #include "RiaViewRedrawScheduler.h" -#include "ExportCommands/RicSaveEclipseInputVisibleCellsFeature.h" -#include "ExportCommands/RicSaveEclipseInputVisibleCellsUi.h" +#include "ExportCommands/RicExportEclipseInputGridFeature.h" +#include "ExportCommands/RicExportEclipseInputGridUi.h" #include "RicfApplicationTools.h" #include "RicfCommandFileExecutor.h" @@ -98,25 +98,26 @@ void RicfExportVisibleCells::execute() RiaViewRedrawScheduler::instance()->clearViewsScheduledForUpdate(); - RicSaveEclipseInputVisibleCellsUi exportSettings; + RicExportEclipseInputGridUi exportSettings(eclipseView->eclipseCase()->eclipseCaseData()); buildExportSettings(exportFolder, &exportSettings); - RicSaveEclipseInputVisibleCellsFeature::executeCommand(eclipseView, exportSettings, "exportVisibleCells"); + RicExportEclipseInputGridFeature::executeCommand(eclipseView, exportSettings, "exportVisibleCells"); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RicfExportVisibleCells::buildExportSettings(const QString& exportFolder, RicSaveEclipseInputVisibleCellsUi* exportSettings) +void RicfExportVisibleCells::buildExportSettings(const QString& exportFolder, RicExportEclipseInputGridUi* exportSettings) { QDir baseDir(exportFolder); - exportSettings->exportFilename = baseDir.absoluteFilePath(QString("%1.grdecl").arg(m_exportKeyword().text())); + exportSettings->exportResultsFilename = baseDir.absoluteFilePath(QString("%1.grdecl").arg(m_exportKeyword().text())); - if (m_exportKeyword == ExportKeyword::FLUXNUM) +/* +if (m_exportKeyword == ExportKeyword::FLUXNUM) exportSettings->exportKeyword = RicSaveEclipseInputVisibleCellsUi::FLUXNUM; else if (m_exportKeyword == ExportKeyword::MULTNUM) exportSettings->exportKeyword = RicSaveEclipseInputVisibleCellsUi::MULTNUM; exportSettings->visibleActiveCellsValue = m_visibleActiveCellsValue; exportSettings->hiddenActiveCellsValue = m_hiddenActiveCellsValue; - exportSettings->inactiveCellsValue = m_inactiveCellsValue; + exportSettings->inactiveCellsValue = m_inactiveCellsValue; */ } diff --git a/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.h b/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.h index e5bb4986e9..404fa17461 100644 --- a/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.h +++ b/ApplicationCode/CommandFileInterface/RicfExportVisibleCells.h @@ -25,7 +25,7 @@ #include "cafPdmField.h" class RimEclipseView; -class RicSaveEclipseInputVisibleCellsUi; +class RicExportEclipseInputGridUi; //================================================================================================== // @@ -48,7 +48,7 @@ public: void execute() override; private: - void buildExportSettings(const QString& exportFolder, RicSaveEclipseInputVisibleCellsUi* exportSettings); + void buildExportSettings(const QString& exportFolder, RicExportEclipseInputGridUi* exportSettings); caf::PdmField m_caseId; caf::PdmField m_viewName; diff --git a/ApplicationCode/Commands/ExportCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/ExportCommands/CMakeLists_files.cmake index b044e3b81c..3b7556fef6 100644 --- a/ApplicationCode/Commands/ExportCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/ExportCommands/CMakeLists_files.cmake @@ -11,6 +11,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicSaveEclipseInputVisibleCellsFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicSaveEclipseInputVisibleCellsUi.h ${CMAKE_CURRENT_LIST_DIR}/RicSaveEclipseResultAsInputPropertyExec.h ${CMAKE_CURRENT_LIST_DIR}/RicSaveEclipseResultAsInputPropertyFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicExportEclipseInputGridFeature.h +${CMAKE_CURRENT_LIST_DIR}/RicExportEclipseInputGridUi.h ${CMAKE_CURRENT_LIST_DIR}/RicSnapshotAllPlotsToFileFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicSnapshotAllViewsToFileFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicSnapshotFilenameGenerator.h @@ -36,6 +38,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RicExportToLasFileResampleUi.cpp ${CMAKE_CURRENT_LIST_DIR}/RicSaveEclipseInputPropertyFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicSaveEclipseInputVisibleCellsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicSaveEclipseInputVisibleCellsUi.cpp +${CMAKE_CURRENT_LIST_DIR}/RicExportEclipseInputGridFeature.cpp +${CMAKE_CURRENT_LIST_DIR}/RicExportEclipseInputGridUi.cpp ${CMAKE_CURRENT_LIST_DIR}/RicSaveEclipseResultAsInputPropertyExec.cpp ${CMAKE_CURRENT_LIST_DIR}/RicSaveEclipseResultAsInputPropertyFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicSnapshotAllPlotsToFileFeature.cpp diff --git a/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridFeature.cpp b/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridFeature.cpp new file mode 100644 index 0000000000..f0336ad850 --- /dev/null +++ b/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridFeature.cpp @@ -0,0 +1,218 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- Equinor 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 "RicExportEclipseInputGridFeature.h" + +#include "RiaApplication.h" +#include "RiaLogging.h" + +#include "RicExportFeatureImpl.h" +#include "RicExportEclipseInputGridUi.h" + +#include "RifReaderEclipseOutput.h" + +#include "RimEclipseCase.h" +#include "RimEclipseCellColors.h" +#include "RimEclipseView.h" +#include "Rim3dView.h" + +#include "RigEclipseCaseData.h" +#include "RigMainGrid.h" + +#include "Riu3DMainWindowTools.h" + +#include "cafPdmUiPropertyViewDialog.h" +#include "cafProgressInfo.h" +#include "cafSelectionManager.h" + +#include +#include +#include + +CAF_CMD_SOURCE_INIT(RicExportEclipseInputGridFeature, "RicExportEclipseInputGridFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportEclipseInputGridFeature::openDialogAndExecuteCommand(RimEclipseView* view) +{ + if (!view) return; + + RigEclipseCaseData* caseData = view->eclipseCase()->eclipseCaseData(); + + RicExportEclipseInputGridUi exportSettings(caseData); + caf::PdmUiPropertyViewDialog propertyDialog(Riu3DMainWindowTools::mainWindowWidget(), &exportSettings, "Export Input Grid", ""); + RicExportFeatureImpl::configureForExport(&propertyDialog); + + if (propertyDialog.exec() == QDialog::Accepted) + { + executeCommand(view, exportSettings, "ExportInputGrid"); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportEclipseInputGridFeature::executeCommand(RimEclipseView* view, + const RicExportEclipseInputGridUi& exportSettings, + const QString& logPrefix) +{ + int resultProgressPercentage = exportSettings.exportResults() ? + std::min((int) exportSettings.exportMainKeywords().size(), 30) : 0; + + int gridProgressPercentage = 100 - resultProgressPercentage; + caf::ProgressInfo progress(gridProgressPercentage + resultProgressPercentage, "Export Eclipse Data"); + + cvf::Vec3st min, max; + std::tie(min, max) = getVisibleCellRange(view); + if (exportSettings.exportGrid()) + { + auto task = progress.task("Export Input Grid", gridProgressPercentage); + bool worked = RifReaderEclipseOutput::saveEclipseGrid(exportSettings.exportGridFilename(), view->eclipseCase()->eclipseCaseData(), &min, &max); + if (!worked) + { + RiaLogging::error( + QString("Unable to write grid to '%1'").arg(exportSettings.exportGridFilename)); + } + } + + if (exportSettings.exportResults() != RicExportEclipseInputGridUi::EXPORT_NO_RESULTS) + { + auto task = progress.task("Export Results", resultProgressPercentage); + std::vector keywords = exportSettings.allSelectedKeywords(); + + if (exportSettings.exportResults == RicExportEclipseInputGridUi::EXPORT_TO_SEPARATE_FILE_PER_RESULT) + { + QFileInfo info(exportSettings.exportGridFilename()); + QDir dirPath = info.absoluteDir(); + QString fileWriteMode = "w"; + for (QString keyword : keywords) + { + QString fileName = dirPath.absoluteFilePath(keyword + ".GRDECL"); + bool worked = RifReaderEclipseOutput::saveEclipseResults(fileName, + view->eclipseCase()->eclipseCaseData(), + {keyword}, + fileWriteMode, + &min, + &max); + if (!worked) + { + RiaLogging::error(QString("Unable to write results to '%1'").arg(fileName)); + } + } + } + else + { + QString fileWriteMode = "w"; + QString fileName = exportSettings.exportResultsFilename(); + if (exportSettings.exportResults() == RicExportEclipseInputGridUi::EXPORT_TO_GRID_FILE) + { + fileWriteMode = "a"; + fileName = exportSettings.exportGridFilename(); + } + + bool worked = RifReaderEclipseOutput::saveEclipseResults(fileName, + view->eclipseCase()->eclipseCaseData(), + keywords, + fileWriteMode, + &min, + &max); + + if (!worked) + { + RiaLogging::error(QString("Unable to write results to '%1'").arg(fileName)); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RicExportEclipseInputGridFeature::getVisibleCellRange(RimEclipseView* view) +{ + cvf::UByteArray visibleCells; + view->calculateCurrentTotalCellVisibility(&visibleCells, view->currentTimeStep()); + + const RigMainGrid* mainGrid = view->eclipseCase()->mainGrid(); + cvf::Vec3st max = cvf::Vec3st::ZERO; + cvf::Vec3st min = cvf::Vec3st(mainGrid->cellCountI() - 1, + mainGrid->cellCountJ() - 1, + mainGrid->cellCountK() - 1); + + size_t cellCount = mainGrid->cellCount(); + for (size_t index = 0; index < cellCount; ++index) + { + if (visibleCells[index]) + { + cvf::Vec3st ijk; + mainGrid->ijkFromCellIndex(index, &ijk[0], &ijk[1], &ijk[2]); + for (int n = 0; n < 3; ++n) + { + min[n] = std::min(min[n], ijk[n]); + max[n] = std::max(max[n], ijk[n]); + } + } + } + return std::make_pair(min, max); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicExportEclipseInputGridFeature::isCommandEnabled() +{ + return selectedView() != nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportEclipseInputGridFeature::onActionTriggered(bool isChecked) +{ + RimEclipseView* view = RicExportEclipseInputGridFeature::selectedView(); + openDialogAndExecuteCommand(view); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportEclipseInputGridFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setText("Export Visible Cells as Eclipse Input Grid"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseView* RicExportEclipseInputGridFeature::selectedView() const +{ + RimEclipseView* view = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); + if (view) + { + return view; + } + + RimEclipseCellColors* cellResultItem = dynamic_cast(caf::SelectionManager::instance()->selectedItem()); + if (cellResultItem) + { + cellResultItem->firstAncestorOrThisOfType(view); + } + + return view; +} diff --git a/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridFeature.h b/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridFeature.h new file mode 100644 index 0000000000..3dc49ac8b4 --- /dev/null +++ b/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridFeature.h @@ -0,0 +1,50 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cvfBase.h" +#include "cvfArray.h" +#include "cvfVector3.h" + +class RimEclipseView; +class RicExportEclipseInputGridUi; + +//================================================================================================== +/// +//================================================================================================== +class RicExportEclipseInputGridFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +public : + static void openDialogAndExecuteCommand(RimEclipseView* view); + static void executeCommand(RimEclipseView* view, + const RicExportEclipseInputGridUi& exportSettings, + const QString& logPrefix); + + static std::pair getVisibleCellRange(RimEclipseView* view); +protected: + bool isCommandEnabled() override; + void onActionTriggered(bool isChecked) override; + void setupActionLook(QAction* actionToSetup) override; + +private: + RimEclipseView* selectedView() const; +}; diff --git a/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridUi.cpp b/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridUi.cpp new file mode 100644 index 0000000000..2bf96bf458 --- /dev/null +++ b/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridUi.cpp @@ -0,0 +1,238 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RicExportEclipseInputGridUi.h" + +#include "RiaApplication.h" +#include "RigCaseCellResultsData.h" +#include "RigEclipseCaseData.h" + +#include "RimEclipseResultDefinition.h" + +#include "cafPdmUiFilePathEditor.h" +#include "cafPdmUiGroup.h" +#include "cafPdmUiListEditor.h" +#include "cafPdmUiOrdering.h" + +#include +#include + +CAF_PDM_SOURCE_INIT(RicExportEclipseInputGridUi, "RicExportEclipseInputGridUi"); + +namespace caf +{ +template<> +void RicExportEclipseInputGridUi::ResultExportOptionsEnum::setUp() +{ + addItem(RicExportEclipseInputGridUi::EXPORT_NO_RESULTS, "NO_RESULTS", "Do not export results"); + addItem(RicExportEclipseInputGridUi::EXPORT_TO_GRID_FILE, "TO_GRID_FILE", "Export to grid file"); + addItem(RicExportEclipseInputGridUi::EXPORT_TO_SINGLE_SEPARATE_FILE, "TO_SINGLE_RESULT_FILE", "Export to single results file"); + addItem(RicExportEclipseInputGridUi::EXPORT_TO_SEPARATE_FILE_PER_RESULT, "TO_SEPARATE_RESULT_FILES", "Export to a separate file per result"); + + setDefault(RicExportEclipseInputGridUi::EXPORT_TO_GRID_FILE); +} +} // namespace caf + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicExportEclipseInputGridUi::RicExportEclipseInputGridUi(RigEclipseCaseData* caseData) + : m_caseData(caseData) +{ + CAF_PDM_InitObject("Export Visible Cells as Eclipse Input Grid", "", "", ""); + + CAF_PDM_InitField(&exportGrid, "ExportGrid", true, "Export Grid", "", "Includes COORD, ZCORN and ACTNUM", ""); + CAF_PDM_InitFieldNoDefault(&exportResults, "ExportResults", "Export Results", "", "", ""); + CAF_PDM_InitField(&exportResultsFilename, "ExportResultsFilename", QString(), "Results File Name", "", "", ""); + CAF_PDM_InitField(&exportGridFilename, "ExportGridFilename", QString(), "Grid File Name", "", "", ""); + exportGridFilename.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); + exportResultsFilename.uiCapability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); + CAF_PDM_InitFieldNoDefault(&exportMainKeywords, "ExportMainKeywords", "Main Keywords", "", "", ""); + CAF_PDM_InitFieldNoDefault(&exportAdditionalKeywords, "ExportAdditionalKeywords", "Additional Keywords", "", "", ""); + + exportGridFilename = defaultGridFileName(); + exportResultsFilename = defaultResultsFileName(); + + for (QString keyword : mainKeywords()) + { + exportMainKeywords.v().push_back(keyword); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicExportEclipseInputGridUi::~RicExportEclipseInputGridUi() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicExportEclipseInputGridUi::allSelectedKeywords() const +{ + std::vector additionalResults = exportAdditionalKeywords(); + std::vector allRes = exportMainKeywords(); + allRes.insert(allRes.end(), additionalResults.begin(), additionalResults.end()); + return allRes; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportEclipseInputGridUi::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute) +{ + if (field == &exportResultsFilename || field == &exportGridFilename) + { + caf::PdmUiFilePathEditorAttribute* myAttr = dynamic_cast(attribute); + if (myAttr) + { + myAttr->m_selectSaveFileName = true; + } + } + else if (field == &exportMainKeywords || field == &exportAdditionalKeywords) + { + caf::PdmUiListEditorAttribute* myAttr = dynamic_cast(attribute); + if (myAttr) + { + myAttr->m_heightHint = 200; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportEclipseInputGridUi::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + caf::PdmUiGroup* gridGroup = uiOrdering.addNewGroup("Grid Export"); + gridGroup->add(&exportGrid); + gridGroup->add(&exportGridFilename); + exportGridFilename.uiCapability()->setUiReadOnly(!exportGrid()); + + caf::PdmUiGroup* resultsGroup = uiOrdering.addNewGroup("Results Export"); + resultsGroup->add(&exportResults); + if (exportResults() != EXPORT_NO_RESULTS) + { + if (exportResults() == EXPORT_TO_SINGLE_SEPARATE_FILE) + resultsGroup->add(&exportResultsFilename); + + resultsGroup->add(&exportMainKeywords); + resultsGroup->add(&exportAdditionalKeywords); + } + uiOrdering.skipRemainingFields(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicExportEclipseInputGridUi::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + if (changedField == &exportGridFilename) + { + if (exportResultsFilename() == defaultResultsFileName()) + { + QFileInfo info(exportGridFilename()); + QDir gridDirPath = info.absoluteDir(); + exportResultsFilename = gridDirPath.absoluteFilePath("results.grdecl"); + } + } + else if (changedField == &exportResultsFilename) + { + if (exportGridFilename() == defaultGridFileName()) + { + QFileInfo info(exportResultsFilename()); + QDir resultsDirPath = info.absoluteDir(); + exportGridFilename = resultsDirPath.absoluteFilePath("grid.grdecl"); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList + RicExportEclipseInputGridUi::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) +{ + QList options; + if (fieldNeedingOptions == &exportMainKeywords) + { + RigCaseCellResultsData* resultData = m_caseData->results(RiaDefines::MATRIX_MODEL); + QList allOptions = RimEclipseResultDefinition::calcOptionsForVariableUiFieldStandard(RiaDefines::STATIC_NATIVE, resultData); + + std::set mainKeywords = this->mainKeywords(); + for (caf::PdmOptionItemInfo option : allOptions) + { + if (mainKeywords.count(option.optionUiText())) + { + options.push_back(option); + } + } + } + else if (fieldNeedingOptions == &exportAdditionalKeywords) + { + RigCaseCellResultsData* resultData = m_caseData->results(RiaDefines::MATRIX_MODEL); + QList allOptions = + RimEclipseResultDefinition::calcOptionsForVariableUiFieldStandard(RiaDefines::STATIC_NATIVE, resultData); + + std::set mainKeywords = this->mainKeywords(); + for (caf::PdmOptionItemInfo option : allOptions) + { + if (!mainKeywords.count(option.optionUiText())) + { + if (option.optionUiText() == "ACTNUM" && exportGrid()) + { + if (exportResults() != EXPORT_TO_GRID_FILE) + options.push_back(caf::PdmOptionItemInfo("ACTNUM (included in Grid File)", "ACTNUM")); + } + else + { + options.push_back(option); + } + } + } + } + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RicExportEclipseInputGridUi::mainKeywords() +{ + return { "EQLNUM", "FIPNUM", "NTG", "PERMX", "PERMY", "PERMZ", "PORO", "PVTNUM", "SATNUM", "SWATINIT" }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RicExportEclipseInputGridUi::defaultGridFileName() const +{ + QDir baseDir(RiaApplication::instance()->currentProjectPath()); + return baseDir.absoluteFilePath("GRID.GRDECL"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RicExportEclipseInputGridUi::defaultResultsFileName() const +{ + QDir baseDir(RiaApplication::instance()->currentProjectPath()); + return baseDir.absoluteFilePath("RESULTS.GRDECL"); +} diff --git a/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridUi.h b/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridUi.h new file mode 100644 index 0000000000..58ebb417b5 --- /dev/null +++ b/ApplicationCode/Commands/ExportCommands/RicExportEclipseInputGridUi.h @@ -0,0 +1,75 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmChildArrayField.h" +#include "cafAppEnum.h" + +#include +#include + +#include +#include + +class RigEclipseCaseData; + +//================================================================================================== +/// +//================================================================================================== +class RicExportEclipseInputGridUi : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + + enum ResultExportOptions + { + EXPORT_NO_RESULTS, + EXPORT_TO_GRID_FILE, + EXPORT_TO_SINGLE_SEPARATE_FILE, + EXPORT_TO_SEPARATE_FILE_PER_RESULT + }; + typedef caf::AppEnum ResultExportOptionsEnum; + +public: + RicExportEclipseInputGridUi(RigEclipseCaseData* caseData = nullptr); + ~RicExportEclipseInputGridUi() override; + + std::vector allSelectedKeywords() const; + + caf::PdmField exportGrid; + caf::PdmField exportResults; + caf::PdmField exportGridFilename; + caf::PdmField exportResultsFilename; + caf::PdmField> exportMainKeywords; + caf::PdmField> exportAdditionalKeywords; + +protected: + void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override; + void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override; + void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override; + QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly) override; + + static std::set mainKeywords(); + QString defaultGridFileName() const; + QString defaultResultsFileName() const; +private: + RigEclipseCaseData* m_caseData; +}; diff --git a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp index 8ab56df221..f35585e6eb 100644 --- a/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp +++ b/ApplicationCode/Commands/RicImportGeneralDataFeature.cpp @@ -74,15 +74,15 @@ void RicImportGeneralDataFeature::onActionTriggered(bool isChecked) for (const QString& fileName : fileNames) { - if (fileName.endsWith("GRID")) + if (fileName.endsWith("GRID", Qt::CaseInsensitive)) { eclipseCaseFiles.push_back(fileName); } - else if (fileName.endsWith("GRDECL")) + else if (fileName.endsWith("GRDECL", Qt::CaseInsensitive)) { eclipseInputFiles.push_back(fileName); } - else if (fileName.endsWith("SMSPEC")) + else if (fileName.endsWith("SMSPEC", Qt::CaseInsensitive)) { eclipseSummaryFiles.push_back(fileName); } diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp index 36e8556115..8d05154f7b 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp @@ -35,6 +35,7 @@ #include "cvfMath.h" +#include #include #include @@ -282,6 +283,25 @@ bool RifEclipseOutputFileTools::isValidEclipseFileName(const QString& fileName) return ecl_util_valid_basename(RiaStringEncodingTools::toNativeEncoded(fileNameBase).data()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QByteArray RifEclipseOutputFileTools::md5sum(const QString& fileName) +{ + QFile file(fileName); + if (file.open(QFile::ReadOnly)) + { + QCryptographicHash hash(QCryptographicHash::Md5); + QByteArray fileContent = file.readAll(); + if (!fileContent.isEmpty()) + { + hash.addData(fileContent); + return hash.result(); + } + } + return QByteArray(); +} + //-------------------------------------------------------------------------------------------------- /// Get set of Eclipse files based on an input file and its path //-------------------------------------------------------------------------------------------------- @@ -524,6 +544,26 @@ ecl_kw_type* RifEclipseOutputFileTools::createActnumFromPorv(ecl_file_type* ecl_ return nullptr; } +//-------------------------------------------------------------------------------------------------- +/// Convenience method to hide C fopen calls in #pragma declarations to avoid warnings on Windows +//-------------------------------------------------------------------------------------------------- +FILE* RifEclipseOutputFileTools::fopen(const QString& filePath, const QString& mode) +{ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) +#endif + + FILE* filePtr = std::fopen(RiaStringEncodingTools::toNativeEncoded(filePath).data(), RiaStringEncodingTools::toNativeEncoded(mode).data()); + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + return filePtr; + +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h index 276e051cd4..0486cfd337 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h @@ -36,7 +36,7 @@ typedef struct ecl_file_struct ecl_file_type; class RifEclipseRestartDataAccess; - +class QByteArray; //================================================================================================== // @@ -57,6 +57,7 @@ public: static void timeSteps(ecl_file_type* ecl_file, std::vector* timeSteps, std::vector* daysSinceSimulationStart); static bool isValidEclipseFileName(const QString& fileName); + static QByteArray md5sum(const QString& fileName); static bool findSiblingFilesWithSameBaseName(const QString& fileName, QStringList* fileSet); static QString firstFileNameOfType(const QStringList& fileSet, ecl_file_enum fileType); @@ -79,6 +80,8 @@ public: static ecl_kw_type* createActnumFromPorv(ecl_file_type* ecl_file); + static FILE* fopen(const QString& filePath, const QString& mode); + private: static void createReportStepsMetaData(std::vector ecl_files, std::vector* reportSteps); }; diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index e8ec04ded5..69722b3f87 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -351,6 +351,182 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, return true; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifReaderEclipseOutput::saveEclipseGrid(const QString& fileName, RigEclipseCaseData* eclipseCase, const cvf::Vec3st* min, const cvf::Vec3st* max) +{ + if (!eclipseCase) + { + return false; + } + + const RigActiveCellInfo* activeCellInfo = eclipseCase->activeCellInfo(RiaDefines::MATRIX_MODEL); + const RigActiveCellInfo* fractureActiveCellInfo = eclipseCase->activeCellInfo(RiaDefines::FRACTURE_MODEL); + + CVF_ASSERT(activeCellInfo && fractureActiveCellInfo); + + const RigMainGrid* mainGrid = eclipseCase->mainGrid(); + + int ecl_nx = (int) mainGrid->cellCountI(); + int ecl_ny = (int) mainGrid->cellCountJ(); + int ecl_nz = (int) mainGrid->cellCountK(); + + if (min && max) + { + ecl_nx = (int) (max->x() - min->x()) + 1; + ecl_ny = (int) (max->y() - min->y()) + 1; + ecl_nz = (int) (max->z() - min->z()) + 1; + } + + int ecl_cell_count = (int) mainGrid->cellCount(); + + caf::ProgressInfo progress(ecl_cell_count * 2, "Save Eclipse Grid"); + int cellProgressInterval = 1000; + + std::vector ecl_corners; ecl_corners.reserve(ecl_cell_count); + std::vector ecl_coords; ecl_coords.reserve(ecl_cell_count); + + int incrementalIndex = 0; + for (int index = 0; index < ecl_cell_count; ++index) + { + size_t i, j, k; + mainGrid->ijkFromCellIndex(index, &i, &j, &k); + + if (i < min->x() || i > max->x() || + j < min->y() || j > max->y() || + k < min->z() || k > max->z()) + { + continue; + } + + int active = activeCellInfo->isActive(index) ? 1 : 0; + + int* ecl_cell_coords = new int[5]; + ecl_cell_coords[0] = (int) (i + 1 - min->x()); + ecl_cell_coords[1] = (int) (j + 1 - min->y()); + ecl_cell_coords[2] = (int) (k + 1 - min->z()); + ecl_cell_coords[3] = incrementalIndex++; + ecl_cell_coords[4] = active; + ecl_coords.push_back(ecl_cell_coords); + + cvf::Vec3d cellCorners[8]; + mainGrid->cellCornerVertices(index, cellCorners); + + float* ecl_cell_corners = new float[24]; + for (size_t corner = 0; corner < 8; ++corner) + { + ecl_cell_corners[cellMappingECLRi[corner] * 3 ] = cellCorners[corner][0]; + ecl_cell_corners[cellMappingECLRi[corner] * 3 + 1] = cellCorners[corner][1]; + ecl_cell_corners[cellMappingECLRi[corner] * 3 + 2] = -cellCorners[corner][2]; + } + ecl_corners.push_back(ecl_cell_corners); + + if (index % cellProgressInterval == 0) + { + progress.setProgress(index); + } + } + + ecl_grid_type* mainEclGrid = ecl_grid_alloc_GRID_data((int) ecl_coords.size(), ecl_nx, ecl_ny, ecl_nz, 5, &ecl_coords[0], &ecl_corners[0], false, NULL); + progress.setProgress(ecl_cell_count * 2); + + for (float* floatArray : ecl_corners) + { + delete floatArray; + } + + for (int* intArray : ecl_coords) + { + delete intArray; + } + + FILE* filePtr = RifEclipseOutputFileTools::fopen(fileName, "w"); + + if (!filePtr) + { + return false; + } + + ecl_grid_fprintf_grdecl(mainEclGrid, filePtr); + ecl_grid_free(mainEclGrid); + fclose(filePtr); + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifReaderEclipseOutput::saveEclipseResults(const QString& resultFileName, + RigEclipseCaseData* eclipseCase, + const std::vector& keywords, + const QString& fileWriteMode, + const cvf::Vec3st* min, + const cvf::Vec3st* max) +{ + FILE* filePtr = RifEclipseOutputFileTools::fopen(resultFileName, fileWriteMode); + if (!filePtr) + { + return false; + } + RigCaseCellResultsData* cellResultsData = eclipseCase->results(RiaDefines::MATRIX_MODEL); + RigActiveCellInfo* activeCells = cellResultsData->activeCellInfo(); + RigMainGrid* mainGrid = eclipseCase->mainGrid(); + + caf::ProgressInfo progress(keywords.size(), "Saving Keywords"); + + for (const QString& keyword : keywords) + { + std::vector resultValues; + + RigEclipseResultAddress resAddr(RiaDefines::STATIC_NATIVE, keyword); + cellResultsData->ensureKnownResultLoaded(resAddr); + resultValues = cellResultsData->cellScalarResults(resAddr)[0]; + CVF_ASSERT(!resultValues.empty()); + + std::vector filteredResults; + filteredResults.reserve(resultValues.size()); + for (size_t index = 0; index < mainGrid->cellCount(); ++index) + { + size_t i, j, k; + mainGrid->ijkFromCellIndex(index, &i, &j, &k); + if (i < min->x() || i > max->x() || j < min->y() || j > max->y() || k < min->z() || k > max->z()) + { + continue; + } + size_t resIndex = activeCells->cellResultIndex(index); + if (resIndex != cvf::UNDEFINED_SIZE_T) + { + filteredResults.push_back(resultValues[resIndex]); + } + } + + ecl_kw_type* ecl_kw = nullptr; + + if (keyword.endsWith("NUM")) + { + std::vector resultValuesInt; resultValuesInt.reserve(filteredResults.size()); + for (double val : filteredResults) + { + resultValuesInt.push_back(static_cast(val)); + } + ecl_kw = ecl_kw_alloc_new(keyword.toLatin1().data(), (int) resultValuesInt.size(), ECL_INT, resultValuesInt.data()); + } + else + { + ecl_kw = ecl_kw_alloc_new(keyword.toLatin1().data(), (int) filteredResults.size(), ECL_DOUBLE, filteredResults.data()); + } + + ecl_kw_fprintf_grdecl(ecl_kw, filePtr); + ecl_kw_free(ecl_kw); + progress.incrementProgress(); + } + + fclose(filePtr); + return true; +} + //-------------------------------------------------------------------------------------------------- /// Open file and read geometry into given reservoir object //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h index e63f289157..5b09bf8b95 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h @@ -23,6 +23,7 @@ #include "RifReaderInterface.h" #include "cvfCollection.h" +#include "cvfVector3.h" #include @@ -66,6 +67,14 @@ public: std::vector allTimeSteps() const; static bool transferGeometry(const ecl_grid_type* mainEclGrid, RigEclipseCaseData* eclipseCase); + static bool saveEclipseGrid(const QString& gridFileName, RigEclipseCaseData* eclipseCase, const cvf::Vec3st* min = nullptr, const cvf::Vec3st* max = nullptr); + static bool saveEclipseResults(const QString& resultFileName, + RigEclipseCaseData* eclipseCase, + const std::vector& keywords, + const QString& fileWriteMode = "w", + const cvf::Vec3st* min = nullptr, + const cvf::Vec3st* max = nullptr); + static void transferCoarseningInfo(const ecl_grid_type* eclGrid, RigGridBase* grid); std::set availablePhases() const override; diff --git a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp index 17668c95f1..3136ba07f3 100644 --- a/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -171,6 +171,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicCreateGridCrossPlotFeature"; menuBuilder << "Separator"; menuBuilder << "RicCopyReferencesToClipboardFeature"; + menuBuilder << "RicExportEclipseInputGridFeature"; menuBuilder << "RicSaveEclipseInputVisibleCellsFeature"; } else if (dynamic_cast(uiItem)) @@ -231,6 +232,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() else if (dynamic_cast(uiItem)) { menuBuilder << "RicSaveEclipseResultAsInputPropertyFeature"; + menuBuilder << "RicExportEclipseInputGridFeature"; menuBuilder << "RicSaveEclipseInputVisibleCellsFeature"; menuBuilder << "RicCreateGridCrossPlotFeature"; } diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 2d485413d9..fad79de3db 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -208,7 +208,7 @@ void RimEclipseResultDefinition::fieldChangedByUi(const caf::PdmFieldHandle* cha // If the user are seeing the list with the actually selected result, // select that result in the list. Otherwise select nothing. - QStringList varList = getResultNamesForCurrentUiResultType(); + QStringList varList = getResultNamesForResultType(m_resultTypeUiField(), this->currentGridCellResults()); bool isFlowDiagFieldsRelevant = (m_resultType() == RiaDefines::FLOW_DIAGNOSTICS); @@ -635,7 +635,10 @@ QList RimEclipseResultDefinition::calculateValueOptions( { if (fieldNeedingOptions == &m_resultVariableUiField) { - options = calcOptionsForVariableUiFieldStandard(); + options = calcOptionsForVariableUiFieldStandard(m_resultTypeUiField(), + this->currentGridCellResults(), + showDerivedResultsFirstInVariableUiField(), + addPerCellFaceOptionsForVariableUiField()); } else if (fieldNeedingOptions == &m_differenceCase) { @@ -1445,20 +1448,22 @@ QString RimEclipseResultDefinition::flowDiagResUiText(bool shortLabel, int maxTr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QList RimEclipseResultDefinition::calcOptionsForVariableUiFieldStandard() +QList +RimEclipseResultDefinition::calcOptionsForVariableUiFieldStandard(RiaDefines::ResultCatType resultCatType, + const RigCaseCellResultsData* results, + bool showDerivedResultsFirst, + bool addPerCellFaceOptionItems) { - CVF_ASSERT(m_resultTypeUiField() != RiaDefines::FLOW_DIAGNOSTICS && m_resultTypeUiField() != RiaDefines::INJECTION_FLOODING); + CVF_ASSERT(resultCatType != RiaDefines::FLOW_DIAGNOSTICS && resultCatType != RiaDefines::INJECTION_FLOODING); - if (this->currentGridCellResults()) + if (results) { QList optionList; QStringList cellCenterResultNames; QStringList cellFaceResultNames; - RigCaseCellResultsData* results = this->currentGridCellResults(); - - foreach (QString s, getResultNamesForCurrentUiResultType()) + for (QString s : getResultNamesForResultType(resultCatType, results)) { if (s == RiaDefines::completionTypeResultName()) { @@ -1479,7 +1484,7 @@ QList RimEclipseResultDefinition::calcOptionsForVariable cellFaceResultNames.sort(); // Cell Center result names - foreach (QString s, cellCenterResultNames) + for (QString s : cellCenterResultNames) { optionList.push_back(caf::PdmOptionItemInfo(s, s)); } @@ -1493,52 +1498,29 @@ QList RimEclipseResultDefinition::calcOptionsForVariable else if (cellCenterResultNames.contains("SWAT")) hasAtLeastOneTernaryComponent = true; - if (m_resultTypeUiField == RiaDefines::DYNAMIC_NATIVE && hasAtLeastOneTernaryComponent) + if (resultCatType == RiaDefines::DYNAMIC_NATIVE && hasAtLeastOneTernaryComponent) { optionList.push_front( caf::PdmOptionItemInfo(RiaDefines::ternarySaturationResultName(), RiaDefines::ternarySaturationResultName())); } - // Cell Face result names - bool showDerivedResultsFirstInList = false; + if (addPerCellFaceOptionItems) { - RimEclipseFaultColors* rimEclipseFaultColors = nullptr; - this->firstAncestorOrThisOfType(rimEclipseFaultColors); - - if (rimEclipseFaultColors) showDerivedResultsFirstInList = true; - } - - foreach (QString s, cellFaceResultNames) - { - if (showDerivedResultsFirstInList) + for (QString s : cellFaceResultNames) { - optionList.push_front(caf::PdmOptionItemInfo(s, s)); - } - else - { - optionList.push_back(caf::PdmOptionItemInfo(s, s)); + if (showDerivedResultsFirst) + { + optionList.push_front(caf::PdmOptionItemInfo(s, s)); + } + else + { + optionList.push_back(caf::PdmOptionItemInfo(s, s)); + } } } optionList.push_front(caf::PdmOptionItemInfo(RiaDefines::undefinedResultName(), RiaDefines::undefinedResultName())); - // Remove Per Cell Face options - { - RimPlotCurve* curve = nullptr; - this->firstAncestorOrThisOfType(curve); - - RimEclipsePropertyFilter* propFilter = nullptr; - this->firstAncestorOrThisOfType(propFilter); - - RimCellEdgeColors* cellEdge = nullptr; - this->firstAncestorOrThisOfType(cellEdge); - - if (propFilter || curve || cellEdge) - { - removePerCellFaceOptionItems(optionList); - } - } - return optionList; } @@ -1701,15 +1683,13 @@ QString RimEclipseResultDefinition::selectedTracersString() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QStringList RimEclipseResultDefinition::getResultNamesForCurrentUiResultType() +QStringList RimEclipseResultDefinition::getResultNamesForResultType(RiaDefines::ResultCatType resultCatType, const RigCaseCellResultsData* results) { - if (m_resultTypeUiField() != RiaDefines::FLOW_DIAGNOSTICS) + if (resultCatType != RiaDefines::FLOW_DIAGNOSTICS) { - RigCaseCellResultsData* cellResultsStorage = currentGridCellResults(); + if (!results) return QStringList(); - if (!cellResultsStorage) return QStringList(); - - return cellResultsStorage->resultNames(m_resultTypeUiField()); + return results->resultNames(resultCatType); } else { @@ -1722,31 +1702,6 @@ QStringList RimEclipseResultDefinition::getResultNamesForCurrentUiResultType() } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimEclipseResultDefinition::removePerCellFaceOptionItems(QList& optionItems) -{ - std::vector indicesToRemove; - for (int i = 0; i < optionItems.size(); i++) - { - QString text = optionItems[i].value().toString(); - - if (RiaDefines::isPerCellFaceResult(text)) - { - indicesToRemove.push_back(i); - } - } - - std::sort(indicesToRemove.begin(), indicesToRemove.end()); - - std::vector::reverse_iterator rit; - for (rit = indicesToRemove.rbegin(); rit != indicesToRemove.rend(); ++rit) - { - optionItems.takeAt(*rit); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1974,6 +1929,43 @@ bool RimEclipseResultDefinition::isCaseDiffResult() const return isCaseDiffResultAvailable() && m_differenceCase() != nullptr; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimEclipseResultDefinition::showDerivedResultsFirstInVariableUiField() const +{ + // Cell Face result names + bool showDerivedResultsFirstInList = false; + RimEclipseFaultColors* rimEclipseFaultColors = nullptr; + this->firstAncestorOrThisOfType(rimEclipseFaultColors); + + if (rimEclipseFaultColors) showDerivedResultsFirstInList = true; + + return showDerivedResultsFirstInList; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimEclipseResultDefinition::addPerCellFaceOptionsForVariableUiField() const +{ + RimPlotCurve* curve = nullptr; + this->firstAncestorOrThisOfType(curve); + + RimEclipsePropertyFilter* propFilter = nullptr; + this->firstAncestorOrThisOfType(propFilter); + + RimCellEdgeColors* cellEdge = nullptr; + this->firstAncestorOrThisOfType(cellEdge); + + if (propFilter || curve || cellEdge) + { + return false; + } + + return true; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h index dd72a0d3c6..d2fbd0eec3 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h @@ -125,6 +125,11 @@ public: bool hasDualPorFractureResult(); + static QList calcOptionsForVariableUiFieldStandard(RiaDefines::ResultCatType resultCatType, + const RigCaseCellResultsData* results, + bool showDerivedResultsFirst = false, + bool addPerCellFaceOptionItems = false); + protected: virtual void updateLegendCategorySettings() {}; @@ -185,7 +190,6 @@ private: QString flowDiagResUiText(bool shortLabel, int maxTracerStringLength = std::numeric_limits::max()) const; - QList calcOptionsForVariableUiFieldStandard(); QList calcOptionsForSelectedTracerField(bool injector); QString timeOfFlightString(bool shorter) const; @@ -194,8 +198,7 @@ private: QString selectedTracersString() const; void changedTracerSelectionField(bool injector); - QStringList getResultNamesForCurrentUiResultType(); - static void removePerCellFaceOptionItems(QList& optionItems); + static QStringList getResultNamesForResultType(RiaDefines::ResultCatType resultCatType, const RigCaseCellResultsData* results); std::vector allTracerNames() const; std::set setOfTracersOfType(bool injector) const; @@ -212,6 +215,9 @@ private: bool isCaseDiffResultAvailable() const; bool isCaseDiffResult() const; + bool showDerivedResultsFirstInVariableUiField() const; + bool addPerCellFaceOptionsForVariableUiField() const; + void ensureProcessingOfObsoleteFields(); private: diff --git a/ApplicationCode/UnitTests/RiaTestDataDirectory.h.cmake b/ApplicationCode/UnitTests/RiaTestDataDirectory.h.cmake index cc9abc663e..89de75ac64 100644 --- a/ApplicationCode/UnitTests/RiaTestDataDirectory.h.cmake +++ b/ApplicationCode/UnitTests/RiaTestDataDirectory.h.cmake @@ -1,3 +1,4 @@ // Test data directory used by unit tests #define TEST_DATA_DIR "${CMAKE_CURRENT_LIST_DIR}/TestData" +#define TEST_MODEL_DIR "${CMAKE_CURRENT_LIST_DIR}/../../TestModels" \ No newline at end of file diff --git a/ApplicationCode/UnitTests/RifReaderEclipseOutput-Test.cpp b/ApplicationCode/UnitTests/RifReaderEclipseOutput-Test.cpp index a7b2e38b9f..917d53ecbd 100644 --- a/ApplicationCode/UnitTests/RifReaderEclipseOutput-Test.cpp +++ b/ApplicationCode/UnitTests/RifReaderEclipseOutput-Test.cpp @@ -25,27 +25,91 @@ #include #include "ert/ecl/ecl_kw_magic.h" +#include "RiaStringEncodingTools.h" +#include "RiaTestDataDirectory.h" #include "RifReaderEclipseOutput.h" #include "RifEclipseOutputFileTools.h" +#include "RigEclipseCaseData.h" #include "RigCaseCellResultsData.h" #include "RifEclipseUnifiedRestartFileAccess.h" #include "RifReaderSettings.h" +#include "RimEclipseResultCase.h" #include +#include +#include + +using namespace RiaDefines; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -TEST(RigReservoirTest, BasicTest) +TEST(RigReservoirTest, BasicTest10k) +{ + QDir baseFolder(TEST_MODEL_DIR); + bool subFolderExists = baseFolder.cd("TEST10K_FLT_LGR_NNC"); + EXPECT_TRUE(subFolderExists); + QString filename("TEST10K_FLT_LGR_NNC.EGRID"); + QString filePath = baseFolder.absoluteFilePath(filename); + EXPECT_TRUE(QFile::exists(filePath)); + + std::unique_ptr resultCase(new RimEclipseResultCase); + cvf::ref reservoir = new RigEclipseCaseData(resultCase.get()); + + { + RigCaseCellResultsData* cellData = reservoir->results(MATRIX_MODEL); + + QStringList staticResults = cellData->resultNames(STATIC_NATIVE); + EXPECT_EQ(0, staticResults.size()); + //qDebug() << "Static results\n" << staticResults; + + QStringList dynamicResults = cellData->resultNames(DYNAMIC_NATIVE); + EXPECT_EQ(0, dynamicResults.size()); + //qDebug() << "Dynamic results\n" << dynamicResults; + + int numTimeSteps = static_cast(cellData->maxTimeStepCount()); + EXPECT_EQ(0, numTimeSteps); + + } + + { + cvf::ref readerInterfaceEcl = new RifReaderEclipseOutput; + bool result = readerInterfaceEcl->open(filePath, reservoir.p()); + EXPECT_TRUE(result); + int numTimeSteps = static_cast(readerInterfaceEcl->allTimeSteps().size()); + EXPECT_EQ(9, numTimeSteps); + } + + { + RigCaseCellResultsData* cellData = reservoir->results(MATRIX_MODEL); + + QStringList staticResults = cellData->resultNames(STATIC_NATIVE); + EXPECT_EQ(44, staticResults.size()); + //qDebug() << "Static results\n" << staticResults; + + QStringList dynamicResults = cellData->resultNames(DYNAMIC_NATIVE); + EXPECT_EQ(23, dynamicResults.size()); + //qDebug() << "Dynamic results\n" << dynamicResults; + + int numTimeSteps = static_cast(cellData->maxTimeStepCount()); + EXPECT_EQ(9, numTimeSteps); + } +} + +TEST(RigReservoirTest, BasicTest10kRestart) { RifEclipseUnifiedRestartFileAccess unrstAccess; -/* - QStringList filenames; - //filenames << "d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"; - filenames << "d:/Models/MRST/simple/SIMPLE.UNRST"; + QDir baseFolder(TEST_MODEL_DIR); + bool subFolderExists = baseFolder.cd("TEST10K_FLT_LGR_NNC"); + EXPECT_TRUE(subFolderExists); + QString filename("TEST10K_FLT_LGR_NNC.UNRST"); + QString filePath = baseFolder.absoluteFilePath(filename); + EXPECT_TRUE(QFile::exists(filePath)); + QStringList filenames; + filenames << filePath; unrstAccess.setRestartFiles(filenames); @@ -54,70 +118,98 @@ TEST(RigReservoirTest, BasicTest) unrstAccess.resultNames(&resultNames, &dataItemCount); - for (size_t i = 0; i < resultNames.size(); i++) + EXPECT_EQ(resultNames.size(), dataItemCount.size()); + EXPECT_EQ(83, resultNames.size()); + + /* for (int i = 0; i < resultNames.size(); i++) { qDebug() << resultNames[i] << "\t" << dataItemCount[i]; - } + } */ auto reportNums = unrstAccess.reportNumbers(); - for (auto reportNum : reportNums) + EXPECT_EQ((size_t) 9, reportNums.size()); + + /* for (auto reportNum : reportNums) { qDebug() << reportNum; - } -*/ + } */ +} -/* - cvf::ref readerInterfaceEcl = new RifReaderEclipseOutput; - cvf::ref reservoir = new RigCaseData; - - // Location of test dataset received from Håkon Høgstøl in July 2011 with 10k active cells -#ifdef WIN32 +TEST(RigReservoirTest, BasicTest10k_NativeECL) +{ + QDir baseFolder(TEST_MODEL_DIR); + bool subFolderExists = baseFolder.cd("TEST10K_FLT_LGR_NNC"); + EXPECT_TRUE(subFolderExists); QString filename("TEST10K_FLT_LGR_NNC.EGRID"); -#else - QString filename("/mnt/hgfs/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.EGRID"); + QString filePath = baseFolder.absoluteFilePath(filename); + EXPECT_TRUE(QFile::exists(filePath)); + + ecl_grid_type* grid = ecl_grid_alloc(RiaStringEncodingTools::toNativeEncoded(filePath).data()); + EXPECT_TRUE(grid); + + QString subDir("RifReaderEclipseOutput"); + QDir dataDir(TEST_DATA_DIR); + dataDir.mkdir(subDir); + dataDir.cd(subDir); + QString outFilePath = dataDir.absoluteFilePath("TEST10K_FLT_LGR_NNC_OUT.GRDECL"); + +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning(disable : 4996) #endif + FILE* filePtr = fopen(RiaStringEncodingTools::toNativeEncoded(outFilePath).data(), "w"); + EXPECT_TRUE(filePtr != nullptr); + ecl_grid_fprintf_grdecl(grid, filePtr); + fclose(filePtr); + EXPECT_TRUE(QFile::exists(outFilePath)); - bool result = readerInterfaceEcl->open(filename, reservoir.p()); - EXPECT_TRUE(result); - - { - QStringList staticResults = readerInterfaceEcl->staticResults(); - EXPECT_EQ(42, staticResults.size()); - qDebug() << "Static results\n" << staticResults; - - QStringList dynamicResults = readerInterfaceEcl->dynamicResults(); - EXPECT_EQ(23, dynamicResults.size()); - qDebug() << "Dynamic results\n" << dynamicResults; - - int numTimeSteps = static_cast(readerInterfaceEcl->numTimeSteps()); - EXPECT_EQ(9, numTimeSteps); - - QStringList timeStepText = readerInterfaceEcl->timeStepText(); - EXPECT_EQ(numTimeSteps, timeStepText.size()); - qDebug() << "Time step texts\n" << timeStepText; - } - - - readerInterfaceEcl->close(); - - { - QStringList staticResults = readerInterfaceEcl->staticResults(); - EXPECT_EQ(0, staticResults.size()); - - QStringList dynamicResults = readerInterfaceEcl->dynamicResults(); - EXPECT_EQ(0, dynamicResults.size()); - - int numTimeSteps = static_cast(readerInterfaceEcl->numTimeSteps()); - EXPECT_EQ(0, numTimeSteps); - - QStringList timeStepText = readerInterfaceEcl->timeStepText(); - EXPECT_EQ(numTimeSteps, timeStepText.size()); - } -*/ + QString expectedMd5("\xE9\x93\xB8Q@V\x8F\x13\xF4\xC3\x84\x96\x04p\n\x0F"); + QByteArray generatedMd5 = RifEclipseOutputFileTools::md5sum(outFilePath); + EXPECT_TRUE(generatedMd5 == expectedMd5); +#ifdef _MSC_VER +#pragma warning(pop) +#endif } +TEST(RigReservoirTest, Test10k_ReadThenWriteToECL) +{ + QDir baseFolder(TEST_MODEL_DIR); + bool subFolderExists = baseFolder.cd("TEST10K_FLT_LGR_NNC"); + EXPECT_TRUE(subFolderExists); + QString filename("TEST10K_FLT_LGR_NNC.EGRID"); + QString filePath = baseFolder.absoluteFilePath(filename); + EXPECT_TRUE(QFile::exists(filePath)); + + std::unique_ptr resultCase(new RimEclipseResultCase); + resultCase->setGridFileName(filePath); + resultCase->importGridAndResultMetaData(false); + + QString subDir("RifReaderEclipseOutput"); + QDir dataDir(TEST_DATA_DIR); + dataDir.mkdir(subDir); + dataDir.cd(subDir); + QString outFilePath = dataDir.absoluteFilePath("TEST10K_FLT_LGR_NNC_OUT_FROM_RES.GRDECL"); + + bool worked = RifReaderEclipseOutput::saveEclipseGrid(outFilePath, resultCase->eclipseCaseData()); + EXPECT_TRUE(worked); + EXPECT_TRUE(QFile::exists(outFilePath)); + + QString dataFilePath = dataDir.absoluteFilePath("TEST10K_FLT_LGR_NNC_OUT_FROM_RES.VARS"); + + QStringList allStaticResults = resultCase->eclipseCaseData()->results(MATRIX_MODEL)->resultNames(RiaDefines::STATIC_NATIVE); + + std::vector keywords; + for (QString keyword : allStaticResults) + { + keywords.push_back(keyword); + } + + worked = RifReaderEclipseOutput::saveEclipseResults(dataFilePath, resultCase->eclipseCaseData(), keywords); + EXPECT_TRUE(worked); + EXPECT_TRUE(QFile::exists(dataFilePath)); +} #if 0 diff --git a/ApplicationCode/UnitTests/TestData/.gitignore b/ApplicationCode/UnitTests/TestData/.gitignore new file mode 100644 index 0000000000..8c274c7837 --- /dev/null +++ b/ApplicationCode/UnitTests/TestData/.gitignore @@ -0,0 +1,2 @@ +RifReaderEclipseOutput/TEST10K_FLT_LGR_NNC_OUT.GRDECL +RifReaderEclipseOutput/TEST10K_FLT_LGR_NNC_OUT_FROM_RES.GRDECL \ No newline at end of file diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFilePathEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiFilePathEditor.h index 986a6ee349..057b78c462 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFilePathEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFilePathEditor.h @@ -60,7 +60,11 @@ public: PdmUiFilePathEditorAttribute() { m_selectSaveFileName = false; - m_fileSelectionFilter = "All files (*.* *)"; +#ifdef _WIN32 + m_fileSelectionFilter = "All files (*.*)"; +#else + m_fileSelectionFilter = "All files (*)"; +#endif m_defaultPath = QString(); m_selectDirectory = false;