From ada2fb1480ca825febe96e4cc5b55f2703808216 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 19 Jun 2019 13:36:33 +0200 Subject: [PATCH] #4495 Active Cells : Add helper class to import active cells --- .../FileInterface/CMakeLists_files.cmake | 3 + .../FileInterface/RifActiveCellsReader.cpp | 93 ++++++++++++++ .../FileInterface/RifActiveCellsReader.h | 38 ++++++ .../UnitTests/CMakeLists_files.cmake | 1 + .../UnitTests/RifActiveCellsReader-Test.cpp | 119 ++++++++++++++++++ 5 files changed, 254 insertions(+) create mode 100644 ApplicationCode/FileInterface/RifActiveCellsReader.cpp create mode 100644 ApplicationCode/FileInterface/RifActiveCellsReader.h create mode 100644 ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp diff --git a/ApplicationCode/FileInterface/CMakeLists_files.cmake b/ApplicationCode/FileInterface/CMakeLists_files.cmake index c2a01d4dce..b8ea98a084 100644 --- a/ApplicationCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/FileInterface/CMakeLists_files.cmake @@ -43,6 +43,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.h ${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.h ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.h ${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.h +${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.h + # HDF5 file reader is directly included in ResInsight main CmakeList.txt #${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.h @@ -90,6 +92,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.cpp ${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.cpp +${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.cpp # HDF5 file reader is directly included in ResInsight main CmakeList.txt #${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp diff --git a/ApplicationCode/FileInterface/RifActiveCellsReader.cpp b/ApplicationCode/FileInterface/RifActiveCellsReader.cpp new file mode 100644 index 0000000000..0364dadbe1 --- /dev/null +++ b/ApplicationCode/FileInterface/RifActiveCellsReader.cpp @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 "RifActiveCellsReader.h" + +#include "ert/ecl/ecl_file.hpp" +#include "ert/ecl/ecl_grid.hpp" +#include "ert/ecl/ecl_kw_magic.hpp" + +#include "cafAssert.h" + +#include "RiaStringEncodingTools.h" + +#include "RifEclipseOutputFileTools.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RifActiveCellsReader::activeCellsFromActnumKeyword(const ecl_grid_type* mainEclGrid, + const ecl_file_type* ecl_file) +{ + std::vector> activeCellsAllGrids; + + int actnumKeywordCount = ecl_file_get_num_named_kw(ecl_file, ACTNUM_KW); + for (size_t gridIdx = 0; gridIdx < static_cast(actnumKeywordCount); gridIdx++) + { + std::vector nativeActnumvValues; + RifEclipseOutputFileTools::keywordData(ecl_file, ACTNUM_KW, gridIdx, &nativeActnumvValues); + + activeCellsAllGrids.push_back(nativeActnumvValues); + } + + return activeCellsAllGrids; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RifActiveCellsReader::activeCellsFromPorvKeyword(const ecl_grid_type* mainEclGrid, + const ecl_file_type* ecl_file) +{ + CAF_ASSERT(mainEclGrid && ecl_file); + + std::vector> activeCellsAllGrids; + + // When PORV is used as criteria, make sure all active cells are assigned both + // active matrix state and active fracture state. This will make sure that + // both single porosity models and dual porosity models are initialized with + // the correct bit mask. See documentation in top of ecl_grid.cpp + // + const int combinedActnumValueForMatrixAndFracture = CELL_ACTIVE_MATRIX + CELL_ACTIVE_FRACTURE; + + int porvKeywordCount = ecl_file_get_num_named_kw(ecl_file, PORV_KW); + for (size_t gridIdx = 0; gridIdx < static_cast(porvKeywordCount); gridIdx++) + { + std::vector porvValues; + RifEclipseOutputFileTools::keywordData(ecl_file, PORV_KW, gridIdx, &porvValues); + + std::vector activeCellsOneGrid; + activeCellsOneGrid.resize(porvValues.size()); + + for (size_t i = 0; i < porvValues.size(); i++) + { + if (porvValues[i] > 0.0) + { + activeCellsOneGrid[i] = combinedActnumValueForMatrixAndFracture; + } + else + { + activeCellsOneGrid[i] = 0; + } + } + + activeCellsAllGrids.push_back(activeCellsOneGrid); + } + + return activeCellsAllGrids; +} diff --git a/ApplicationCode/FileInterface/RifActiveCellsReader.h b/ApplicationCode/FileInterface/RifActiveCellsReader.h new file mode 100644 index 0000000000..b6212b4895 --- /dev/null +++ b/ApplicationCode/FileInterface/RifActiveCellsReader.h @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +typedef struct ecl_grid_struct ecl_grid_type; +typedef struct ecl_file_struct ecl_file_type; + +//================================================================================================== +// +// +//================================================================================================== +class RifActiveCellsReader +{ +public: + static std::vector> activeCellsFromActnumKeyword(const ecl_grid_type* mainEclGrid, + const ecl_file_type* ecl_file); + + static std::vector> activeCellsFromPorvKeyword(const ecl_grid_type* mainEclGrid, + const ecl_file_type* ecl_file); +}; diff --git a/ApplicationCode/UnitTests/CMakeLists_files.cmake b/ApplicationCode/UnitTests/CMakeLists_files.cmake index 4cc33352a1..0d16177430 100644 --- a/ApplicationCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationCode/UnitTests/CMakeLists_files.cmake @@ -55,6 +55,7 @@ ${CMAKE_CURRENT_LIST_DIR}/Intersect-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifPerforationIntervalReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellPathCompletions-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimSummaryCaseCollection-Test.cpp +${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader-Test.cpp ) if (RESINSIGHT_ENABLE_GRPC) diff --git a/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp b/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp new file mode 100644 index 0000000000..ecfbbbe8c5 --- /dev/null +++ b/ApplicationCode/UnitTests/RifActiveCellsReader-Test.cpp @@ -0,0 +1,119 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 "gtest/gtest.h" + +#include "RiaStringEncodingTools.h" +#include "RiaTestDataDirectory.h" +#include "RifActiveCellsReader.h" + +#include "ert/ecl/ecl_grid.hpp" +#include "ert/ecl/ecl_file.hpp" + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(RifActiveCellsReaderTest, BasicTest10k) +{ + QDir baseFolder(TEST_MODEL_DIR); + bool subFolderExists = baseFolder.cd("TEST10K_FLT_LGR_NNC"); + EXPECT_TRUE(subFolderExists); + + ecl_grid_type* mainEclGrid = nullptr; + + { + QString filename("TEST10K_FLT_LGR_NNC.EGRID"); + QString filePath = baseFolder.absoluteFilePath(filename); + + mainEclGrid = ecl_grid_alloc(RiaStringEncodingTools::toNativeEncoded(filePath).data()); + } + + std::vector> activeCellsFromActnum; + std::vector> activeCellsFromPorv; + { + QString filename("TEST10K_FLT_LGR_NNC.EGRID"); + QString filePath = baseFolder.absoluteFilePath(filename); + + ecl_file_type* gridFile = ecl_file_open(RiaStringEncodingTools::toNativeEncoded(filePath).data(), ECL_FILE_CLOSE_STREAM); + activeCellsFromActnum = RifActiveCellsReader::activeCellsFromActnumKeyword(mainEclGrid, gridFile); + EXPECT_EQ(2, activeCellsFromActnum.size()); + ecl_file_close(gridFile); + } + + { + QString filename("TEST10K_FLT_LGR_NNC.INIT"); + QString filePath = baseFolder.absoluteFilePath(filename); + + ecl_file_type* initFile = ecl_file_open(RiaStringEncodingTools::toNativeEncoded(filePath).data(), ECL_FILE_CLOSE_STREAM); + + activeCellsFromPorv = RifActiveCellsReader::activeCellsFromPorvKeyword(mainEclGrid, initFile); + EXPECT_EQ(2, activeCellsFromPorv.size()); + + ecl_file_close(initFile); + } + + for (size_t gridIndex = 0; gridIndex < activeCellsFromActnum.size(); gridIndex++) + { + for (size_t valueIndex = 0; valueIndex < activeCellsFromActnum[gridIndex].size(); valueIndex++) + { + auto actnumValue = activeCellsFromActnum[gridIndex][valueIndex]; + auto porvValue = activeCellsFromPorv[gridIndex][valueIndex]; + if (actnumValue > 0) + { + EXPECT_TRUE(porvValue > 0); + } + else + { + EXPECT_EQ(0, porvValue); + } + } + } + + std::vector expectedActiveCellCountPerGrid; + expectedActiveCellCountPerGrid.push_back(8517); + expectedActiveCellCountPerGrid.push_back(2608); + + for (int gridIndex = 0; gridIndex < static_cast(activeCellsFromActnum.size()); gridIndex++) + { + ecl_grid_type* currentGrid = nullptr; + if (gridIndex == 0) + { + currentGrid = mainEclGrid; + } + else + { + currentGrid = ecl_grid_iget_lgr(mainEclGrid, gridIndex - 1); + } + + auto activeCellsForGrid = activeCellsFromActnum[gridIndex]; + if (ecl_grid_get_global_size(currentGrid) == static_cast(activeCellsForGrid.size())) + { + int expectedCellCount = expectedActiveCellCountPerGrid[gridIndex]; + EXPECT_EQ(expectedCellCount, ecl_grid_get_nactive(currentGrid)); + + int* actnum_values = activeCellsForGrid.data(); + + ecl_grid_reset_actnum(currentGrid, actnum_values); + EXPECT_EQ(expectedCellCount, ecl_grid_get_nactive(currentGrid)); + } + } + + ecl_grid_free(mainEclGrid); +}