diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 0d31c27e3..163bdc0da 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -99,6 +99,7 @@ list(APPEND TEST_SOURCE_FILES tests/test_repairzcorn.cpp tests/test_sparsetable.cpp tests/test_subgridpart.cpp + tests/cpgrid/deformedCell_localCorners_test.cpp tests/cpgrid/distribution_test.cpp tests/cpgrid/entityrep_test.cpp tests/cpgrid/entity_test.cpp diff --git a/tests/cpgrid/deformedCell_localCorners_test.cpp b/tests/cpgrid/deformedCell_localCorners_test.cpp new file mode 100644 index 000000000..2fa70c759 --- /dev/null +++ b/tests/cpgrid/deformedCell_localCorners_test.cpp @@ -0,0 +1,171 @@ +/* + Copyright 2026 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 LocalCoordinatesTests +#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); + +std::array,8> unitCube = {{ + {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, + {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} + }}; + + +bool areClose(const Dune::FieldVector& v, + const Dune::FieldVector& w) +{ + return (std::abs(v[0] - w[0]) < 1e-12) && (std::abs(v[1] - w[1]) < 1e-12) && (std::abs(v[2] - w[2])< 1e-12); +} + +void checkUnitCubeCorners(const Dune::cpgrid::CpGridData& grid, + const std::array,8>& expectedLocalCorners) +{ + for (int elemIdx = 0; elemIdx < grid.size(0); ++elemIdx) { + + const auto cellGeom = Dune::cpgrid::Entity<0>( grid, elemIdx, true).geometry(); + const auto& cellToPoint = grid.cellToPoint(elemIdx); + + BOOST_CHECK_EQUAL(cellToPoint.size(), 8); + + for (int corner = 0; corner < 8; ++corner) { + const auto vertex = Dune::cpgrid::Entity<3>( grid, cellToPoint[corner], true).geometry().center(); + const auto localVtx = cellGeom.local(vertex); + + BOOST_CHECK( areClose(cellGeom.local(vertex), expectedLocalCorners[corner]) ); + + BOOST_CHECK( areClose(cellGeom.global(localVtx), vertex) ); + } + } +} + +BOOST_AUTO_TEST_CASE(cellWithFewerThanEightCornersDoesNotMapToUnitCube) +{ + const std::string deckString = R"( +RUNSPEC + +DIMENS + 1 1 1/ + +GRID + +-- COORD: 4 pillars × 6 values (x1 y1 z1 x2 y2 z2) +COORD +0 0 0 0 0 1 -- Pillar 1: bottom at (0,0,0), top at (0,0,1) +1 0 0 1 0 0 -- Pillar 2: bottom at (1,0,0) = same at top +0 1 0 0 1 1 -- Pillar 3: bottom at (0,1,0), top at (0,1,1) +1 1 0 1 1 0 -- Pillar 4: bottom at (1,1,0) = same at top +/ + +-- ZCORN: eight Z values: top 4, then bottom 4 +ZCORN +0 0 0 0 -- bottom end of the pillars +1 0 1 0 -- top end of the pillars +/ + +ACTNUM +1*1 +/ + +PORO +1*0.15 +/ +)"; + + Dune::CpGrid grid; + Opm::createGridFromDeckString(grid, deckString); + + /** Global cell [collapsed] corners = { {0,0,0}, {1,0,0}, {0,1,0}, {1,1,0}, + {0,0,1}, {1,0,0}, {0,1,1}, {1,1,0} } + Local cell [collapsed] corners = { {0,0,0}, {1,0,.5}, {0,1,0}, {1,1,.5}, + {0,0,1}, {1,0,.5}, {0,1,1}, {1,1,.5} } + */ + std::array,8> expected = {{ {0,0,0}, {1,0,.5}, {0,1,0}, {1,1,.5}, + {0,0,1}, {1,0,.5}, {0,1,1}, {1,1,.5} }}; + + checkUnitCubeCorners(grid.currentLeafData(), expected); // Collaped corners also in reference element +} + + + +BOOST_AUTO_TEST_CASE(skewPillarsSimpleGrid) +{ + /* For a grid with dimensions 2x1x1, in ZCORN: z-coord of + corner0-cell0 corner1-cell0 corner0-cell1 corner1-cell1 corner2-cell0 corner3-cell0 corner2-cell1 corner3-cell1 (bottom layer 1) + corner4-cell0 corner5-cell0 corner4-cell1 corner5-cell1 corner6-cell0 corner7-cell0 corner6-cell1 corner7-cell1 ( top layer 1) + */ + + const std::string deckString = + R"(RUNSPEC +DIMENS + 2 1 1 / -- nx ny nz + +GRID + +COORD -- (nx+1)*(ny+1) = (2+1)*(1+1) = 6 pillars + 0 0 0 0 0 9 -- bottom - top pillar 0 + 6 0 0 6 3 9 -- bottom - top pillar 1 +12 0 0 12 0 9 -- bottom - top pillar 2 + + 0 6 0 0 6 9 -- bottom - top pillar 3 + 6 6 0 6 6 9 -- bottom - top pillar 4 +12 6 0 12 6 9 -- bottom - top pillar 5 +/ + +ZCORN -- 8*nx*ny values = 8*2*1 = 16 +0 0 1 1 0 0 1 1 -- bottom layer 1 +8 8.2 9 9 7.1 5 9 9 -- top layer 1 +/ + +ACTNUM +2*1 +/ + +PORO +2*0.15 +/ +)"; + + Dune::CpGrid grid; + Opm::createGridFromDeckString(grid, deckString); + + checkUnitCubeCorners(grid.currentLeafData(), unitCube); +}