diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 26a480c2a..874f5c16f 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -116,7 +116,7 @@ if(Boost_VERSION_STRING VERSION_GREATER 1.53) tests/cpgrid/grid_lgr_test.cpp tests/cpgrid/inactiveCell_lgr_test.cpp tests/cpgrid/lgr_cartesian_idx_test.cpp - tests/cpgrid/localIJK_test.cpp + tests/cpgrid/lgrIJK_test.cpp tests/cpgrid/lookUpCellCentroid_cpgrid_test.cpp tests/cpgrid/lookupdataCpGrid_test.cpp tests/cpgrid/replace_lgr1_corner_idx_by_lgr2_corner_idx_test.cpp diff --git a/opm/grid/cpgrid/CpGridUtilities.cpp b/opm/grid/cpgrid/CpGridUtilities.cpp index 8dc05f760..db7b145fd 100644 --- a/opm/grid/cpgrid/CpGridUtilities.cpp +++ b/opm/grid/cpgrid/CpGridUtilities.cpp @@ -26,7 +26,7 @@ namespace Opm { -std::vector> localIJK(const Dune::CpGrid& grid, const std::string& lgr_name) +std::vector> lgrIJK(const Dune::CpGrid& grid, const std::string& lgr_name) { // Check lgr_name exists in lgr_names_ const auto& lgr_names = grid.getLgrNameToLevel(); @@ -35,23 +35,39 @@ std::vector> localIJK(const Dune::CpGrid& grid, const std::str OPM_THROW(std::runtime_error, "LGR name not found: " + lgr_name); } - const Opm::LevelCartesianIndexMapper levelCartMapp(grid); + const Opm::LevelCartesianIndexMapper levelCartMapper(grid); const auto& level = it->second; - std::vector> localIJK; - localIJK.resize(grid.levelGridView(level).size(0)); + // Determine the logical Cartesian size of the LGR and total cells (including inactive ones) + const auto lgr_dim = grid.currentData()[level]->logicalCartesianSize(); + const int lgr_cells = lgr_dim[0] * lgr_dim[1] * lgr_dim[2]; // (including inactive ones) + // Actual size is given by grid.levelGridView(level).size(0) - // To be improved - const auto& leaf_to_lgr_idx = grid.mapLeafIndexSetToLocalCartesianIndexSets(); + // Initialize level IJKs with inactive values + static constexpr std::array inactiveIJK = { -1, -1, -1 }; + std::vector> lgrIJK(lgr_cells); + lgrIJK.assign(lgr_cells, inactiveIJK); // Ensures all elements are set to inactive + + // Iterate over active elements in the grid. Rewrite ijks at the specified refined level active cells. + // + // Note: to avoid go over all the leaf elements and replace this approach with the + // corresponding grid.levelGridView(level), a map relating level_to_lgr_idx is needed. for (const auto& element : Dune::elements(grid.leafGridView())) { - if (element.level() == level) - { - std::array local_ijk; - levelCartMapp.cartesianCoordinate( element.getLevelElem().index(), local_ijk, level); - localIJK[ leaf_to_lgr_idx[element.index()][1] ] = local_ijk; + if (element.level() != level) { + continue; } + + std::array ijk; + levelCartMapper.cartesianCoordinate(element.getLevelElem().index(), ijk, level); + // In general, element.getLevelElem().index() != element.getLevelCartesianIdx(). + // - element.getLevelElem().index() : integer between 0 and "total active cells - 1" on the level grid. + // - element.getLevelCartesianIdx() : integer between 0 and "lgr_cells - 1", representing an index of + // the underlying Cartesian grid for the level (with/without INACTIVE cells). + + const int lgr_cart_index = element.getLevelCartesianIdx(); + lgrIJK[lgr_cart_index] = ijk; } - return localIJK; + return lgrIJK; } } diff --git a/opm/grid/cpgrid/CpGridUtilities.hpp b/opm/grid/cpgrid/CpGridUtilities.hpp index 0fe174902..a00d6e5d2 100644 --- a/opm/grid/cpgrid/CpGridUtilities.hpp +++ b/opm/grid/cpgrid/CpGridUtilities.hpp @@ -25,14 +25,16 @@ namespace Opm { -/// @brief Retrieves the local IJKs of cells within a specified LGR. +/// @brief Retrieves the local grid refinement (LGR) IJKs of cells. /// /// This method returns a vector of IJK indices corresponding to underlying Cartesian grid of the local -/// grid refinement (LGR) specified by its name. If the specified LGR name is not found, it throws. +/// grid refinement (LGR) specified by its name. If the specified name is not found, an exception is thrown. +/// For inactive cells—i.e., non-existing child cells of inactive coarse cells defined by the CARFIN keyword— +/// the corresponding IJK index is set to {-1, -1, -1}. /// /// @param lgr_name The name of the LGR whose local IJK coordinates are requested. /// @return std::vector> A list of (i, j, k)'s for each cell in the LGR. -std::vector> localIJK(const Dune::CpGrid& grid, const std::string& lgr_name); +std::vector> lgrIJK(const Dune::CpGrid& grid, const std::string& lgr_name); } diff --git a/tests/cpgrid/lgrIJK_test.cpp b/tests/cpgrid/lgrIJK_test.cpp new file mode 100644 index 000000000..3440567b6 --- /dev/null +++ b/tests/cpgrid/lgrIJK_test.cpp @@ -0,0 +1,591 @@ +//=========================================================================== +// +// File: lgrIJK_test.cpp +// +// Created: Thursday 30.01.2025 08:17:00 +// +// Author(s): Antonella Ritorto +// +// $Date$ +// +// $Revision$ +// +//=========================================================================== +/* + Copyright 2025 Equinor ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM 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. + + OPM 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 for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ +#include "config.h" + +#define BOOST_TEST_MODULE LgrIJKTests +#include +#include +#if BOOST_VERSION / 100000 == 1 && BOOST_VERSION / 100 % 1000 < 71 +#include +#else +#include +#endif + + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct Fixture +{ + Fixture() + { + int m_argc = boost::unit_test::framework::master_test_suite().argc; + char** m_argv = boost::unit_test::framework::master_test_suite().argv; + Dune::MPIHelper::instance(m_argc, m_argv); + Opm::OpmLog::setupSimpleDefaultLogging(); + } + +}; + + +BOOST_GLOBAL_FIXTURE(Fixture); + +Dune::CpGrid createGridAndAddLgrs(const std::vector>& cells_per_dim_vec, + const std::vector>& startIJK_vec , + const std::vector>& endIJK_vec, + const std::vector& lgr_name_vec, + const std::string& deck_string = std::string{}, + const std::array& cell_sizes = std::array{}, + const std::array& grid_dim = std::array{}) +{ + Dune::CpGrid grid; + // Create the starting grid (before adding LGRs) + if (!deck_string.empty()) { // via deck + Opm::Parser parser; + const auto deck = parser.parseString(deck_string); + Opm::EclipseState ecl_state(deck); + Opm::EclipseGrid eclipse_grid = ecl_state.getInputGrid(); + + grid.processEclipseFormat(&eclipse_grid, &ecl_state, false, false, false); + } + else { // via grid dimensions and cell size + grid.createCartesian(grid_dim, cell_sizes); + } + + // Add LGR and update grid view + grid.addLgrsUpdateLeafView(cells_per_dim_vec, startIJK_vec, endIJK_vec, lgr_name_vec); + return grid; +} + +/* Tests lgrIJK() for a grid containing inactive cells within the LGR block. + +The test passes if initLgr() is not invoked in opm-common/opm/input/eclipse/EclipseState/EclipseState.cpp. +Currently, inactive cells in LGRs are not supported in "opm-common." +*/ + +BOOST_AUTO_TEST_CASE(thrwoWhenQueryingLgrIJKofInactiveLgrCell) +{ + const std::string deck_string = R"( +RUNSPEC +DIMENS + 3 3 1 / +GRID +CARFIN +-- NAME I1-I2 J1-J2 K1-K2 NX NY NZ +'LGR1' 2 3 2 3 1 1 6 6 3/ +ENDFIN +DX + 9*1000 / +DY + 9*1000 / +DZ + 9*20 / +TOPS + 9*8325 / + ACTNUM + 1 1 1 + 1 1 1 + 1 1 0 + / +PORO + 9*0.15 / +PERMX + 9*1 / +COPY + PERMX PERMZ / + PERMX PERMY / +/ +EDIT +OIL +GAS +TITLE +The title +START +16 JUN 1988 / +PROPS +REGIONS +SOLUTION +SCHEDULE +)"; + + // LGR1: 3x3x1 child cells in x-,y-, and z-direction per ACTIVE parent cell + const std::vector> cells_per_dim_vec = { {3, 3, 3} }; + // LGR1 starts at (1,1,0) in coarse grid - equivalent to (I1-1, J1-1, K1-1) from its CARFIN block + const std::vector> startIJK_vec = { {1, 1, 0} }; + // LGR1 ends at (3,3,1) in coarse grid - equivalent to (I2, J2, K2) from its CARFIN block + const std::vector> endIJK_vec = { {3, 3, 1} }; + const std::vector lgr_name_vec = {"LGR1"}; + + const auto grid = createGridAndAddLgrs(cells_per_dim_vec, startIJK_vec, endIJK_vec, lgr_name_vec, deck_string); + + // Get LGR levels + const auto& lgr_name_to_level = grid.getLgrNameToLevel(); // map std::string to int level: {"GLOBAL", 0}, {"LGR1", 1}, ... + const int lgr1_level = lgr_name_to_level.at("LGR1"); + + // Get vector of local ijk for each LGR + const std::vector> ijk_lgr1 = Opm::lgrIJK(grid, "LGR1"); + + // Note: k = 0, indicating a single-layer grid with dimensions 3x3x1. + // ACTNUM represents the active cell indicator for the parent grid of the LGR (Local Grid Refinement). + // The grid structure is as follows, where '1' denotes an active cell and '0' denotes an inactive cell: + // + // 1 1 1 + // 1 1 1 + // 1 1 0 + // + // The corresponding LGR block parent cell representation appears as: + // 1 1 + // 1 0 + + // Verify the size matches expected elements + BOOST_TEST(grid.levelGridView(lgr1_level).size(0) == 81); // 3 ACTIVE parent cellS into 3x3x3 children each -> 81 + BOOST_TEST(ijk_lgr1.size() == 108); // Block size - inlcuding inactive cells (6x6x3) + + // LGR1 dimension 6x6x3 + // Visual representation per k-layer: + // + // level Cartesian cell indices internal ordering, i.e. element.index() in levelGridView(level); + // + // k = 2 | 102 103 104 | | 78 79 80 | + // | 96 97 98 | INACTIVE | 75 76 77 | INACTIVE + // | 90 91 92 | | 72 73 74 | + // ---------------------------- ---------------------------- + // | 84 85 86 | 87 88 89 | 24 25 26 | 51 52 53 + // | 78 79 80 | 81 82 83 | 21 22 23 | 48 49 50 + // | 72 73 74 | 75 76 77 | 18 19 20 | 45 46 47 + //------------------------------------ ---------------------------- + // k = 1 | 66 67 68 | | 69 70 71 | + // | 60 61 62 | INACTIVE | 66 67 68 | INACTIVE + // | 54 55 56 | | 63 64 65 | + // ---------------------------- ---------------------------- + // | 48 49 50 | 51 52 53 | 15 16 17 | 42 43 44 + // | 42 43 44 | 45 46 47 | 12 13 14 | 39 40 41 + // | 36 37 38 | 39 40 41 | 9 10 11 | 36 37 38 + //------------------------------------ ---------------------------- + // k = 0 | 30 31 32 | | 60 61 62 | + // | 24 25 26 | INACTIVE | 57 58 59 | INACTIVE + // | 18 19 20 | | 54 55 56 | + // ---------------------------- ---------------------------- + // | 12 13 14 | 15 16 17 | 6 7 8 | 33 34 35 + // | 6 7 8 | 9 10 11 | 3 4 5 | 30 31 32 + // | 0 1 2 | 3 4 5 | 0 1 2 | 27 28 29 + + + // Verify that cell with local (level Cartesian) index 97 in LGR1 has local ijk = {1,4,2} + BOOST_TEST(ijk_lgr1[97][0] == 1); + BOOST_TEST(ijk_lgr1[97][1] == 4); + BOOST_TEST(ijk_lgr1[97][2] == 2); + + + // Verify that cell with local (level Cartesian) index 88 in LGR1 has local ijk = {4,2,2} + BOOST_TEST(ijk_lgr1[88][0] == 4); + BOOST_TEST(ijk_lgr1[88][1] == 2); + BOOST_TEST(ijk_lgr1[88][2] == 2); + + // Accessing inactive (non-existing) cells + for (int i = 0; i < 3; ++i) { + BOOST_TEST(ijk_lgr1[107][i] == -1); + BOOST_TEST(ijk_lgr1[70][i] == -1); + } + // Potential improvement: If lgrIJK() returns a map instead of vector, then + // ijk_lgr1.at( non-exisiting-inactive-cell-cartesian-index ) throws, which + // might be better than accesing an invalid value {-1,-1,-1}. +} + + +BOOST_AUTO_TEST_CASE(fullInactiveParentCellsBlockTurnsIntoLgrWithZeroCellsButFullCartesianSize) +{ + + // To create a grid with one LGR('LGR1') with parent cells block + // dimensions 1x1x2, parent cell indices = {0, 1}. Both cells are + // INACTIVE + const std::string deck_string = + R"( RUNSPEC + DIMENS + 1 1 5 / + GRID + COORD + 0 0 0 + 0 0 1 + 1 0 0 + 1 0 1 + 0 1 0 + 0 1 1 + 1 1 0 + 1 1 1 + / + ZCORN + 4*0 + 8*1 + 8*2 + 8*3 + 8*4 + 4*5 + / + ACTNUM + 0 + 0 + 0 + 1 + 1 + / + CARFIN + -- NAME I1-I2 J1-J2 K1-K2 NX NY NZ + 'LGR1' 1 1 1 1 1 2 2 2 4/ + ENDFIN + PORO + 5*0.15 + /)"; + + const std::vector> cells_per_dim_vec = { {2, 2, 2} }; // LGR1: 2x2x2 child cells in x-,y-, and z-direction per parent cell + const std::vector> startIJK_vec = { {0, 0, 0} }; // LGR1 starts at (0,0,0) in coarse grid - equivalent to (I1-1, J1-1, K1-1) from its CARFIN block + const std::vector> endIJK_vec = { {1, 1, 2} }; // LGR1 ends at (1,1,2) in coarse grid - equivalent to (I2, J2, K2) from its CARFIN block + const std::vector lgr_name_vec = {"LGR1"}; + + const auto grid = createGridAndAddLgrs(cells_per_dim_vec, startIJK_vec, endIJK_vec, lgr_name_vec, deck_string); + + // Get vector of local ijk for each LGR + std::vector> ijk_lgr1 = Opm::lgrIJK(grid, "LGR1"); + + // Get LGR levels + const auto& lgr_name_to_level = grid.getLgrNameToLevel(); // map std::string to int level: {"GLOBAL", 0}, {"LGR1", 1}, ... + const int lgr1_level = lgr_name_to_level.at("LGR1"); + + // Verify the size matches expected elements + const int lgr_cartesian_size = 16; // 2x2x4 INACTIVE and ACTIVE cells. + + BOOST_CHECK_EQUAL(grid.levelGridView(lgr1_level).size(0), 0); // 2 INACTIVE parent cells into 2x2x2 children each -> 0 + BOOST_CHECK_EQUAL(ijk_lgr1.size(), lgr_cartesian_size); +} + +BOOST_AUTO_TEST_CASE(fullActiveParentCellsBlockTurnsIntoLgrWithFullCartesianSizeAndSameTotalCells) +{ + // LGR1 parent cell indices = {0 ACTIVE, 1 ACTIVE}, LGR2 parent cell indices = {3 AVTIVE, 4 ACTIVE}. + const std::string deck_string = + R"( RUNSPEC + DIMENS + 1 1 5 / + GRID + COORD + 0 0 0 + 0 0 1 + 1 0 0 + 1 0 1 + 0 1 0 + 0 1 1 + 1 1 0 + 1 1 1 + / + ZCORN + 4*0 + 8*1 + 8*2 + 8*3 + 8*4 + 4*5 + / + ACTNUM + 1 + 1 + 0 + 1 + 1 + / + CARFIN + -- NAME I1-I2 J1-J2 K1-K2 NX NY NZ + 'LGR1' 1 1 1 1 1 2 2 2 4/ + ENDFIN + CARFIN + -- NAME I1-I2 J1-J2 K1-K2 NX NY NZ + 'LGR2' 1 1 1 1 4 5 3 3 6/ + ENDFIN + PORO + 5*0.15 + /)"; + + const std::vector> cells_per_dim_vec = { + {2, 2, 2}, // LGR1: 2x2x2 child cells in x-,y-, and z-direction per parent cell + {3, 3, 3} // LGR2: 3x3x3 child cells in x-,y-, and z-direction per parent cell + }; + const std::vector> startIJK_vec = { + {0, 0, 0}, // LGR1 starts at (0,0,0) in coarse grid - equivalent to (I1-1, J1-1, K1-1) from its CARFIN block + {0, 0, 3} // LGR2 starts at (0,0,3) in coarse grid - equivalent to (I1-1, J1-1, K1-1) from its CARFIN block + }; + const std::vector> endIJK_vec = { + {1, 1, 2}, // LGR1 ends at (1,1,2) in coarse grid - equivalent to (I2, J2, K2) from its CARFIN block + {1, 1, 5} // LGR2 ends at (1,1,5) in coarse grid - equivalent to (I2, J2, K2) from its CARFIN block + }; + const std::vector lgr_name_vec = {"LGR1", "LGR2"}; + + const auto grid = createGridAndAddLgrs(cells_per_dim_vec, startIJK_vec, endIJK_vec, lgr_name_vec, deck_string); + + // Get LGR levels + const auto& lgr_name_to_level = grid.getLgrNameToLevel(); // map std::string to int level: {"GLOBAL", 0}, {"LGR1", 1}, ... + const int lgr1_level = lgr_name_to_level.at("LGR1"); + const int lgr2_level = lgr_name_to_level.at("LGR2"); + + // Get vector of local ijk for each LGR + std::vector> ijk_lgr1 = Opm::lgrIJK(grid, "LGR1"); + std::vector> ijk_lgr2 = Opm::lgrIJK(grid, "LGR2"); + + // Ensure it's not empty + BOOST_TEST(!ijk_lgr1.empty()); // 2 active parent cell refined into 2x2x2 refined cells + BOOST_TEST(!ijk_lgr2.empty()); // 2 active parent cell refined into 3x3x3 refined cells + + // Verify the size matches expected elements + BOOST_TEST(ijk_lgr1.size() == grid.levelGridView(lgr1_level).size(0)); // 2 parent cells into 2x2x2 children each -> 16 + BOOST_TEST(ijk_lgr1.size() == 16); + BOOST_TEST(ijk_lgr2.size() == grid.levelGridView(lgr2_level).size(0)); // 2 parent cells into 3x3x3 children each -> 54 + BOOST_TEST(ijk_lgr2.size() == 54); + + // Validate all ijk's are non-negative + for (const auto& ijk_set : {ijk_lgr1, ijk_lgr2}) { + for (const auto& ijk : ijk_set) { + BOOST_TEST(ijk[0] >= 0); + BOOST_TEST(ijk[1] >= 0); + BOOST_TEST(ijk[2] >= 0); + } + } + + // Invalid LGR should throw an exception + BOOST_CHECK_THROW(Opm::lgrIJK(grid, "LGR3DOESNOTEXIST"), std::runtime_error); + + // LGR1 Dimension: 2x2x4 (Width x Height x Depth) + // Visual representation of level Cartesian cell indices per k-layer: + // + // k = 3 | 14 15 + // | 12 13 + // ----------------- + // k = 2 | 10 11 + // | 8 9 + // ----------------- + // k = 1 | 6 7 + // | 4 5 + // ----------------- + // k = 0 | 2 3 + // | 0 1 + + // Verify that cell with local (level Cartesian) index 11 in LGR1 has local ijk = {1,1,2} + BOOST_TEST(ijk_lgr1[11][0] == 1); + BOOST_TEST(ijk_lgr1[11][1] == 1); + BOOST_TEST(ijk_lgr1[11][2] == 2); + + // Verify that cell with local (level Cartesian) index 4 in LGR1 has local ijk = {0,0,1} + BOOST_TEST(ijk_lgr1[4][0] == 0); + BOOST_TEST(ijk_lgr1[4][1] == 0); + BOOST_TEST(ijk_lgr1[4][2] == 1); + + + // LGR2 dimension 3x3x6 + // Visual representation of level Cartesian cell indices per k-layer: + // + // k = 5 | 51 52 53 + // | 48 49 50 + // | 45 46 47 + //---------------------- + // k = 4 | 42 43 44 + // | 39 40 41 + // | 36 37 38 + //---------------------- + // k = 3 | 33 34 35 + // | 30 31 32 + // | 27 28 29 + //---------------------- + // k = 2 | 24 25 26 + // | 21 22 23 + // | 18 19 20 + //---------------------- + // k = 1 | 15 16 17 + // | 12 13 14 + // | 9 10 11 + //---------------------- + // k = 0 | 6 7 8 + // | 3 4 5 + // | 0 1 2 + + // Verify that cell with local (level Cartesian) index 48 in LGR2 has local ijk = {0,1,5} + BOOST_TEST(ijk_lgr2[48][0] == 0); + BOOST_TEST(ijk_lgr2[48][1] == 1); + BOOST_TEST(ijk_lgr2[48][2] == 5); + + // Verify that cell with local (level Cartesian) index 31 in LGR2 has local ijk = {1,1,3} + BOOST_TEST(ijk_lgr2[31][0] == 1); + BOOST_TEST(ijk_lgr2[31][1] == 1); + BOOST_TEST(ijk_lgr2[31][2] == 3); + + // Verify that cell with local (level Cartesian) index 25 in LGR1 has local ijk = {1,2,2} + BOOST_TEST(ijk_lgr2[25][0] == 1); + BOOST_TEST(ijk_lgr2[25][1] == 2); + BOOST_TEST(ijk_lgr2[25][2] == 2); +} + +BOOST_AUTO_TEST_CASE(internal_order_differs_from_underlying_cartesian_level_grids) +{ + const std::array cell_sizes = {1.0, 1.0, 1.0}; + const std::array grid_dim = {4,3,3}; + + const std::vector> cells_per_dim_vec = { + {3, 3, 3}, // LGR1: 3x3x3 child cells in x-,y-, and z-direction per parent cell + {3, 3, 4} // LGR2: 3x3x4 child cells in x-,y-, and z-direction per parent cell + }; + const std::vector> startIJK_vec = { + {1, 1, 1}, // LGR1 starts at (1,1,1) in coarse grid + {2, 0, 2} // LGR2 starts at (2,0,2) in coarse grid + }; + const std::vector> endIJK_vec = { + {3, 3, 2}, // LGR1 ends at (3,3,2) in coarse grid + {4, 2, 3} // LGR2 ends at (4,2,3) in coarse grid + }; + const std::vector lgr_name_vec = {"LGR1", "LGR2"}; + + const auto grid = createGridAndAddLgrs(cells_per_dim_vec, startIJK_vec, endIJK_vec, lgr_name_vec, "", cell_sizes, grid_dim); + + // Get LGR levels + const auto& lgr_name_to_level = grid.getLgrNameToLevel(); // map std::string to int level: {"GLOBAL", 0}, {"LGR1", 1}, ... + const int lgr1_level = lgr_name_to_level.at("LGR1"); + const int lgr2_level = lgr_name_to_level.at("LGR2"); + + // Get vector of local ijk for each LGR + std::vector> ijk_lgr1 = Opm::lgrIJK(grid, "LGR1"); + std::vector> ijk_lgr2 = Opm::lgrIJK(grid, "LGR2"); + + // Verify the size matches expected elements + BOOST_TEST(ijk_lgr1.size() == grid.levelGridView(lgr1_level).size(0)); // 4 parent cells into 3x3x3 children each -> 108 + BOOST_TEST(ijk_lgr1.size() == 108); + BOOST_TEST(ijk_lgr2.size() == grid.levelGridView(lgr2_level).size(0)); // 4 parent cells into 3x3x4 children each -> 144 + BOOST_TEST(ijk_lgr2.size() == 144); + + // LGR1 dimension 6x6x3 + // Visual representation per k-layer: + // + // level Cartesian cell indices internal ordering, i.e. element.index() in levelGridView(level); + // + // k = 2 | 102 103 104 | 105 106 107 | 78 79 80 | 105 106 107 + // | 96 97 98 | 99 100 101 | 75 76 77 | 102 103 104 + // | 90 91 92 | 93 94 95 | 72 73 74 | 99 100 101 + // ---------------------------- ---------------------------- + // | 84 85 86 | 87 88 89 | 24 25 26 | 51 52 53 + // | 78 79 80 | 81 82 83 | 21 22 23 | 48 49 50 + // | 72 73 74 | 75 76 77 | 18 19 20 | 45 46 47 + //------------------------------------ ---------------------------- + // k = 1 | 66 67 68 | 69 70 71 | 69 70 71 | 96 97 98 + // | 60 61 62 | 63 64 65 | 66 67 68 | 93 94 95 + // | 54 55 56 | 57 58 59 | 63 64 65 | 90 91 92 + // ---------------------------- ---------------------------- + // | 48 49 50 | 51 52 53 | 15 16 17 | 42 43 44 + // | 42 43 44 | 45 46 47 | 12 13 14 | 39 40 41 + // | 36 37 38 | 39 40 41 | 9 10 11 | 36 37 38 + //------------------------------------ ---------------------------- + // k = 0 | 30 31 32 | 33 34 35 | 60 61 62 | 87 88 89 + // | 24 25 26 | 27 28 29 | 57 58 59 | 84 85 86 + // | 18 19 20 | 21 22 23 | 54 55 56 | 81 82 83 + // ---------------------------- ---------------------------- + // | 12 13 14 | 15 16 17 | 6 7 8 | 33 34 35 + // | 6 7 8 | 9 10 11 | 3 4 5 | 30 31 32 + // | 0 1 2 | 3 4 5 | 0 1 2 | 27 28 29 + + // Verify that cell with local (level Cartesian) index 25 in LGR1 has local ijk = {1,4,0} + BOOST_TEST(ijk_lgr1[25][0] == 1); + BOOST_TEST(ijk_lgr1[25][1] == 4); + BOOST_TEST(ijk_lgr1[25][2] == 0); + + // Verify that cell with local (level Cartesian) index 64 in LGR1 has local ijk = {4,4,1} + BOOST_TEST(ijk_lgr1[64][0] == 4); + BOOST_TEST(ijk_lgr1[64][1] == 4); + BOOST_TEST(ijk_lgr1[64][2] == 1); + + // Verify that cell with local (level Cartesian) index 98 in LGR1 has local ijk = {2,4,2} + BOOST_TEST(ijk_lgr1[98][0] == 2); + BOOST_TEST(ijk_lgr1[98][1] == 4); + BOOST_TEST(ijk_lgr1[98][2] == 2); + + + // LGR2 dimension 6x6x4 + // Visual representation of level Cartesian cell indices per k-layer: + // + // k = 3 | 138 139 140 | 141 142 143 + // | 132 133 134 | 135 136 137 + // | 126 127 128 | 129 130 131 + // ---------------------------- + // | 120 121 122 | 123 124 125 + // | 114 115 116 | 117 118 119 + // | 108 109 110 | 111 112 113 + //------------------------------------ + // k = 2 | 102 103 104 | 105 106 107 + // | 96 97 98 | 99 100 101 + // | 90 91 92 | 93 94 95 + // ---------------------------- + // | 84 85 86 | 87 88 89 + // | 78 79 80 | 81 82 83 + // | 72 73 74 | 75 76 77 + //------------------------------------ + // k = 1 | 66 67 68 | 69 70 71 + // | 60 61 62 | 63 64 65 + // | 54 55 56 | 57 58 59 + // ---------------------------- + // | 48 49 50 | 51 52 53 + // | 42 43 44 | 45 46 47 + // | 36 37 38 | 39 40 41 + //------------------------------------ + // k = 0 | 30 31 32 | 33 34 35 + // | 24 25 26 | 27 28 29 + // | 18 19 20 | 21 22 23 + // ---------------------------- + // | 12 13 14 | 15 16 17 + // | 6 7 8 | 9 10 11 + // | 0 1 2 | 3 4 5 + + // Verify that cell with local (level Cartesian) index 139 in LGR2 has local ijk = {1,5,3} + BOOST_TEST(ijk_lgr2[139][0] == 1); + BOOST_TEST(ijk_lgr2[139][1] == 5); + BOOST_TEST(ijk_lgr2[139][2] == 3); + + // Verify that cell with local (level Cartesian) index 119 in LGR2 has local ijk = {5,1,3} + BOOST_TEST(ijk_lgr2[119][0] == 5); + BOOST_TEST(ijk_lgr2[119][1] == 1); + BOOST_TEST(ijk_lgr2[119][2] == 3); + + // Verify that cell with local (level Cartesian) index 121 in LGR1 has local ijk = {1,2,3} + BOOST_TEST(ijk_lgr2[121][0] == 1); + BOOST_TEST(ijk_lgr2[121][1] == 2); + BOOST_TEST(ijk_lgr2[121][2] == 3); +} diff --git a/tests/cpgrid/localIJK_test.cpp b/tests/cpgrid/localIJK_test.cpp deleted file mode 100644 index 7def30dcc..000000000 --- a/tests/cpgrid/localIJK_test.cpp +++ /dev/null @@ -1,374 +0,0 @@ -//=========================================================================== -// -// File: localIJK_test.cpp -// -// Created: Thursday 30.01.2025 08:17:00 -// -// Author(s): Antonella Ritorto -// -// $Date$ -// -// $Revision$ -// -//=========================================================================== -/* - Copyright 2025 Equinor ASA. - - This file is part of the Open Porous Media project (OPM). - - OPM 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. - - OPM 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 for more details. - - You should have received a copy of the GNU General Public License - along with OPM. If not, see . -*/ -#include "config.h" - -#define BOOST_TEST_MODULE LocalIJKTests -#include -#include -#if BOOST_VERSION / 100000 == 1 && BOOST_VERSION / 100 % 1000 < 71 -#include -#else -#include -#endif - - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -struct Fixture -{ - Fixture() - { - int m_argc = boost::unit_test::framework::master_test_suite().argc; - char** m_argv = boost::unit_test::framework::master_test_suite().argv; - Dune::MPIHelper::instance(m_argc, m_argv); - Opm::OpmLog::setupSimpleDefaultLogging(); - } -}; - -BOOST_GLOBAL_FIXTURE(Fixture); - -BOOST_AUTO_TEST_CASE(localIJK_in_allActiveCellLGRs) -{ - - const std::string deckString = - R"( RUNSPEC - DIMENS - 1 1 5 / - GRID - COORD - 0 0 0 - 0 0 1 - 1 0 0 - 1 0 1 - 0 1 0 - 0 1 1 - 1 1 0 - 1 1 1 - / - ZCORN - 4*0 - 8*1 - 8*2 - 8*3 - 8*4 - 4*5 - / - ACTNUM - 1 - 1 - 0 - 1 - 1 - / - CARFIN - -- NAME I1-I2 J1-J2 K1-K2 NX NY NZ - 'LGR1' 1 1 1 1 1 2 2 2 4/ - ENDFIN - CARFIN - -- NAME I1-I2 J1-J2 K1-K2 NX NY NZ - 'LGR2' 1 1 1 1 4 5 3 3 6/ - ENDFIN - PORO - 5*0.15 - /)"; - - Opm::Parser parser; - const auto& deck = parser.parseString(std::move(deckString)); - Opm::EclipseState ecl_state(deck); - - Dune::CpGrid grid; - grid.processEclipseFormat(&ecl_state.getInputGrid(), &ecl_state, false, false, false); - - const std::vector> cells_per_dim_vec = { - {2, 2, 2}, // LGR1: 2x2x2 child cells in x-,y-, and z-direction per parent cell - {3, 3, 3} // LGR2: 3x3x3 child cells in x-,y-, and z-direction per parent cell - }; - - const std::vector> startIJK_vec = { - {0, 0, 0}, // LGR1 starts at (0,0,0) in coarse grid - equivalent to (I1-1, J1-1, K1-1) from its CARFIN block - {0, 0, 3} // LGR2 starts at (0,0,3) in coarse grid - equivalent to (I1-1, J1-1, K1-1) from its CARFIN block - }; - - const std::vector> endIJK_vec = { - {1, 1, 2}, // LGR1 ends at (1,1,2) in coarse grid - equivalent to (I2, J2, K2) from its CARFIN block - {1, 1, 5} // LGR2 ends at (1,1,5) in coarse grid - equivalent to (I2, J2, K2) from its CARFIN block - }; - // LGR1 parent cell indices = {0 ACTIVE, 1 ACTIVE}, LGR2 parent cell indices = {3 AVTIVE, 4 ACTIVE}. - - const std::vector lgr_name_vec = {"LGR1", "LGR2"}; - - grid.addLgrsUpdateLeafView(cells_per_dim_vec, startIJK_vec, endIJK_vec, lgr_name_vec); - - // Get LGR levels - const auto& lgr_name_to_level = grid.getLgrNameToLevel(); // map std::string to int level: {"GLOBAL", 0}, {"LGR1", 1}, ... - const int lgr1_level = lgr_name_to_level.at("LGR1"); - const int lgr2_level = lgr_name_to_level.at("LGR2"); - - // Get vector of local ijk for each LGR - std::vector> ijk_lgr1 = Opm::localIJK(grid, "LGR1"); - std::vector> ijk_lgr2 = Opm::localIJK(grid, "LGR2"); - - // Ensure it's not empty - BOOST_TEST(!ijk_lgr1.empty()); // 2 active parent cell refined into 2x2x2 refined cells - BOOST_TEST(!ijk_lgr2.empty()); // 2 active parent cell refined into 3x3x3 refined cells - - // Verify the size matches expected elements - BOOST_TEST(ijk_lgr1.size() == grid.levelGridView(lgr1_level).size(0)); // 2 parent cells into 2x2x2 children each -> 16 - BOOST_TEST(ijk_lgr1.size() == 16); - BOOST_TEST(ijk_lgr2.size() == grid.levelGridView(lgr2_level).size(0)); // 2 parent cells into 3x3x3 children each -> 54 - BOOST_TEST(ijk_lgr2.size() == 54); - - // Validate all ijk's are non-negative - for (const auto& ijk_set : {ijk_lgr1, ijk_lgr2}) { - for (const auto& ijk : ijk_set) { - BOOST_TEST(ijk[0] >= 0); - BOOST_TEST(ijk[1] >= 0); - BOOST_TEST(ijk[2] >= 0); - } - } - - // Invalid LGR should throw an exception - BOOST_CHECK_THROW(Opm::localIJK(grid, "LGR3DOESNOTEXIST"), std::runtime_error); - - // LGR1 Dimension: 2x2x4 (Width x Height x Depth) - // Visual representation of level Cartesian cell indices per k-layer: - // - // k = 3 | 14 15 - // | 12 13 - // ----------------- - // k = 2 | 10 11 - // | 8 9 - // ----------------- - // k = 1 | 6 7 - // | 4 5 - // ----------------- - // k = 0 | 2 3 - // | 0 1 - - // Verify that cell with local (level Cartesian) index 11 in LGR1 has local ijk = {1,1,2} - BOOST_TEST(ijk_lgr1[11][0] == 1); - BOOST_TEST(ijk_lgr1[11][1] == 1); - BOOST_TEST(ijk_lgr1[11][2] == 2); - - // Verify that cell with local (level Cartesian) index 4 in LGR1 has local ijk = {0,0,1} - BOOST_TEST(ijk_lgr1[4][0] == 0); - BOOST_TEST(ijk_lgr1[4][1] == 0); - BOOST_TEST(ijk_lgr1[4][2] == 1); - - - // LGR2 dimension 3x3x6 - // Visual representation of level Cartesian cell indices per k-layer: - // - // k = 5 | 51 52 53 - // | 48 49 50 - // | 45 46 47 - //---------------------- - // k = 4 | 42 43 44 - // | 39 40 41 - // | 36 37 38 - //---------------------- - // k = 3 | 33 34 35 - // | 30 31 32 - // | 27 28 29 - //---------------------- - // k = 2 | 24 25 26 - // | 21 22 23 - // | 18 19 20 - //---------------------- - // k = 1 | 15 16 17 - // | 12 13 14 - // | 9 10 11 - //---------------------- - // k = 0 | 6 7 8 - // | 3 4 5 - // | 0 1 2 - - // Verify that cell with local (level Cartesian) index 48 in LGR2 has local ijk = {0,1,5} - BOOST_TEST(ijk_lgr2[48][0] == 0); - BOOST_TEST(ijk_lgr2[48][1] == 1); - BOOST_TEST(ijk_lgr2[48][2] == 5); - - // Verify that cell with local (level Cartesian) index 31 in LGR2 has local ijk = {1,1,3} - BOOST_TEST(ijk_lgr2[31][0] == 1); - BOOST_TEST(ijk_lgr2[31][1] == 1); - BOOST_TEST(ijk_lgr2[31][2] == 3); - - // Verify that cell with local (level Cartesian) index 25 in LGR1 has local ijk = {1,2,2} - BOOST_TEST(ijk_lgr2[25][0] == 1); - BOOST_TEST(ijk_lgr2[25][1] == 2); - BOOST_TEST(ijk_lgr2[25][2] == 2); -} - -BOOST_AUTO_TEST_CASE(internal_order_differs_from_underlying_cartesian_level_grids) -{ - // Create a grid - Dune::CpGrid grid; - const std::array cell_sizes = {1.0, 1.0, 1.0}; - const std::array grid_dim = {4,3,3}; - grid.createCartesian(grid_dim, cell_sizes); - - // Add LGRs and update leaf grid view - const std::vector> cells_per_dim_vec = { - {3, 3, 3}, // LGR1: 3x3x3 child cells in x-,y-, and z-direction per parent cell - {3, 3, 4} // LGR2: 3x3x4 child cells in x-,y-, and z-direction per parent cell - }; - const std::vector> startIJK_vec = { - {1, 1, 1}, // LGR1 starts at (1,1,1) in coarse grid - {2, 0, 2} // LGR2 starts at (2,0,2) in coarse grid - }; - const std::vector> endIJK_vec = { - {3, 3, 2}, // LGR1 ends at (3,3,2) in coarse grid - {4, 2, 3} // LGR2 ends at (4,2,3) in coarse grid - }; - const std::vector lgr_name_vec = {"LGR1", "LGR2"}; - grid.addLgrsUpdateLeafView(cells_per_dim_vec, startIJK_vec, endIJK_vec, lgr_name_vec); - - // Get LGR levels - const auto& lgr_name_to_level = grid.getLgrNameToLevel(); // map std::string to int level: {"GLOBAL", 0}, {"LGR1", 1}, ... - const int lgr1_level = lgr_name_to_level.at("LGR1"); - const int lgr2_level = lgr_name_to_level.at("LGR2"); - - // Get vector of local ijk for each LGR - std::vector> ijk_lgr1 = Opm::localIJK(grid, "LGR1"); - std::vector> ijk_lgr2 = Opm::localIJK(grid, "LGR2"); - - // Verify the size matches expected elements - BOOST_TEST(ijk_lgr1.size() == grid.levelGridView(lgr1_level).size(0)); // 4 parent cells into 3x3x3 children each -> 108 - BOOST_TEST(ijk_lgr1.size() == 108); - BOOST_TEST(ijk_lgr2.size() == grid.levelGridView(lgr2_level).size(0)); // 4 parent cells into 3x3x4 children each -> 144 - BOOST_TEST(ijk_lgr2.size() == 144); - - // LGR1 dimension 6x6x3 - // Visual representation of level Cartesian cell indices per k-layer: - // - // k = 2 | 102 103 104 | 105 106 107 - // | 96 97 98 | 99 100 101 - // | 90 91 92 | 93 94 95 - // ---------------------------- - // | 84 85 86 | 87 88 89 - // | 78 79 80 | 81 82 83 - // | 72 73 74 | 75 76 77 - //------------------------------------ - // k = 1 | 66 67 68 | 69 70 71 - // | 60 61 62 | 63 64 65 - // | 54 55 56 | 57 58 59 - // ---------------------------- - // | 48 49 50 | 51 52 53 - // | 42 43 44 | 45 46 47 - // | 36 37 38 | 39 40 41 - //------------------------------------ - // k = 0 | 30 31 32 | 33 34 35 - // | 24 25 26 | 27 28 29 - // | 18 19 20 | 21 22 23 - // ---------------------------- - // | 12 13 14 | 15 16 17 - // | 6 7 8 | 9 10 11 - // | 0 1 2 | 3 4 5 - - // Verify that cell with local (level Cartesian) index 25 in LGR1 has local ijk = {1,4,0} - BOOST_TEST(ijk_lgr1[25][0] == 1); - BOOST_TEST(ijk_lgr1[25][1] == 4); - BOOST_TEST(ijk_lgr1[25][2] == 0); - - // Verify that cell with local (level Cartesian) index 64 in LGR1 has local ijk = {4,4,1} - BOOST_TEST(ijk_lgr1[64][0] == 4); - BOOST_TEST(ijk_lgr1[64][1] == 4); - BOOST_TEST(ijk_lgr1[64][2] == 1); - - // Verify that cell with local (level Cartesian) index 98 in LGR1 has local ijk = {2,4,2} - BOOST_TEST(ijk_lgr1[98][0] == 2); - BOOST_TEST(ijk_lgr1[98][1] == 4); - BOOST_TEST(ijk_lgr1[98][2] == 2); - - - // LGR2 dimension 6x6x4 - // Visual representation of level Cartesian cell indices per k-layer: - // - // k = 3 | 138 139 140 | 141 142 143 - // | 132 133 134 | 135 136 137 - // | 126 127 128 | 129 130 131 - // ---------------------------- - // | 120 121 122 | 123 124 125 - // | 114 115 116 | 117 118 119 - // | 108 109 110 | 111 112 113 - //------------------------------------ - // k = 2 | 102 103 104 | 105 106 107 - // | 96 97 98 | 99 100 101 - // | 90 91 92 | 93 94 95 - // ---------------------------- - // | 84 85 86 | 87 88 89 - // | 78 79 80 | 81 82 83 - // | 72 73 74 | 75 76 77 - //------------------------------------ - // k = 1 | 66 67 68 | 69 70 71 - // | 60 61 62 | 63 64 65 - // | 54 55 56 | 57 58 59 - // ---------------------------- - // | 48 49 50 | 51 52 53 - // | 42 43 44 | 45 46 47 - // | 36 37 38 | 39 40 41 - //------------------------------------ - // k = 0 | 30 31 32 | 33 34 35 - // | 24 25 26 | 27 28 29 - // | 18 19 20 | 21 22 23 - // ---------------------------- - // | 12 13 14 | 15 16 17 - // | 6 7 8 | 9 10 11 - // | 0 1 2 | 3 4 5 - - // Verify that cell with local (level Cartesian) index 139 in LGR2 has local ijk = {1,5,3} - BOOST_TEST(ijk_lgr2[139][0] == 1); - BOOST_TEST(ijk_lgr2[139][1] == 5); - BOOST_TEST(ijk_lgr2[139][2] == 3); - - // Verify that cell with local (level Cartesian) index 119 in LGR2 has local ijk = {5,1,3} - BOOST_TEST(ijk_lgr2[119][0] == 5); - BOOST_TEST(ijk_lgr2[119][1] == 1); - BOOST_TEST(ijk_lgr2[119][2] == 3); - - // Verify that cell with local (level Cartesian) index 121 in LGR1 has local ijk = {1,2,3} - BOOST_TEST(ijk_lgr2[121][0] == 1); - BOOST_TEST(ijk_lgr2[121][1] == 2); - BOOST_TEST(ijk_lgr2[121][2] == 3); - -}