- now supporting parsing/reading of lgrs - detect if radial grid is used - return xyz coordinates also for radial grids - support for getting nnc data
347 lines
12 KiB
C++
347 lines
12 KiB
C++
/*
|
|
+ Copyright 2019 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 <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include <opm/io/eclipse/EGrid.hpp>
|
|
#include <opm/io/eclipse/EInit.hpp>
|
|
#include <opm/common/utility/numeric/calculateCellVol.hpp>
|
|
|
|
|
|
#define BOOST_TEST_MODULE Test EGrid
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <fstream>
|
|
#include <initializer_list>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <tuple>
|
|
|
|
using Opm::EclIO::EGrid;
|
|
|
|
template<typename InputIterator1, typename InputIterator2>
|
|
bool
|
|
range_equal(InputIterator1 first1, InputIterator1 last1,
|
|
InputIterator2 first2, InputIterator2 last2)
|
|
{
|
|
while(first1 != last1 && first2 != last2)
|
|
{
|
|
if(*first1 != *first2) return false;
|
|
++first1;
|
|
++first2;
|
|
}
|
|
return (first1 == last1) && (first2 == last2);
|
|
}
|
|
|
|
bool compare_files(const std::string& filename1, const std::string& filename2)
|
|
{
|
|
std::ifstream file1(filename1);
|
|
std::ifstream file2(filename2);
|
|
|
|
std::istreambuf_iterator<char> begin1(file1);
|
|
std::istreambuf_iterator<char> begin2(file2);
|
|
|
|
std::istreambuf_iterator<char> end;
|
|
|
|
return range_equal(begin1, end, begin2, end);
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
bool operator==(const std::vector<T> & t1, const std::vector<T> & t2)
|
|
{
|
|
return std::equal(t1.begin(), t1.end(), t2.begin(), t2.end());
|
|
}
|
|
|
|
// test is using SPE1CASE1, with minor modifications in order to test API for EGrid class
|
|
// -> 6 cells made inactive, box: 5 7 5 6 1 1
|
|
|
|
// first pilar at x=0.0, y=0.0 and z=0.0
|
|
// dx = 1000 ft, dy = 1000 ft. dz = 20 ft for layer 1, 30 ft for layer 2 and 50 ft for layer 3.
|
|
// size of grid is 10x10x3
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(DimensAndIndices) {
|
|
|
|
std::string testFile="SPE1CASE1.EGRID";
|
|
|
|
EGrid grid1(testFile);
|
|
|
|
int nAct=grid1.activeCells();
|
|
int nTot=grid1.totalNumberOfCells();
|
|
|
|
BOOST_CHECK_EQUAL(nAct,294);
|
|
BOOST_CHECK_EQUAL(nTot,300);
|
|
|
|
auto dim = grid1.dimension();
|
|
|
|
BOOST_CHECK_EQUAL(dim[0],10);
|
|
BOOST_CHECK_EQUAL(dim[1],10);
|
|
BOOST_CHECK_EQUAL(dim[2],3);
|
|
|
|
int globInd = grid1.global_index(3, 2, 1);
|
|
|
|
BOOST_CHECK_EQUAL(globInd, 123); // 10*10*1 + 10*2 + 3 = 100+20+3 = 123
|
|
|
|
BOOST_CHECK_EQUAL(grid1.global_index(0, 0, 0), 0);
|
|
BOOST_CHECK_EQUAL(grid1.global_index(dim[0] - 1, dim[1] - 1, dim[2] - 1), nTot - 1);
|
|
|
|
// check global_index valid range, should throw exception if outside
|
|
|
|
BOOST_CHECK_THROW(grid1.global_index(-1, -1, -1), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.global_index(0, -1, 0), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.global_index(0, 0, -1), std::invalid_argument);
|
|
|
|
BOOST_CHECK_THROW(grid1.global_index(dim[0], 0, 0), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.global_index(dim[0], dim[1], 0), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.global_index(dim[0], dim[1], dim[2]), std::invalid_argument);
|
|
|
|
// 6 inactive cells in first layer, actInd not same as glogInd
|
|
// actInd and globInd are zero based indices
|
|
|
|
int actInd = grid1.active_index(3,2,1);
|
|
|
|
BOOST_CHECK_EQUAL(actInd, 117); // global index 123, - 6 inactive
|
|
BOOST_CHECK_EQUAL(grid1.active_index(0, 0, 0), 0);
|
|
BOOST_CHECK_EQUAL(grid1.active_index(dim[0] - 1, dim[1] - 1, dim[2] - 1), nAct - 1);
|
|
|
|
// check active_index valid range, should throw exception if outside
|
|
|
|
BOOST_CHECK_THROW(grid1.active_index(-1, 0, 0), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.active_index(-1, -1, 0), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.active_index(-1, -1, -1), std::invalid_argument);
|
|
|
|
BOOST_CHECK_THROW(grid1.active_index(dim[0], 0, 0), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.active_index(dim[0], dim[1], 0), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.active_index(dim[0], dim[1], dim[2]), std::invalid_argument);
|
|
|
|
auto res = grid1.ijk_from_active_index(actInd);
|
|
|
|
BOOST_CHECK_EQUAL(res[0], 3);
|
|
BOOST_CHECK_EQUAL(res[1], 2);
|
|
BOOST_CHECK_EQUAL(res[2], 1);
|
|
|
|
BOOST_CHECK_THROW(grid1.ijk_from_active_index(-1), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.ijk_from_active_index(nAct), std::invalid_argument);
|
|
|
|
res = grid1.ijk_from_global_index(globInd);
|
|
|
|
BOOST_CHECK_EQUAL(res[0], 3);
|
|
BOOST_CHECK_EQUAL(res[1], 2);
|
|
BOOST_CHECK_EQUAL(res[2], 1);
|
|
|
|
BOOST_CHECK_THROW(grid1.ijk_from_global_index(-1), std::invalid_argument);
|
|
BOOST_CHECK_THROW(grid1.ijk_from_global_index(nTot), std::invalid_argument);
|
|
}
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(getCellCorners) {
|
|
|
|
std::string testFile="SPE1CASE1.EGRID";
|
|
|
|
std::array<double,8> ref_X = {3000,4000,3000,4000,3000,4000,3000,4000};
|
|
std::array<double,8> ref_Y = {2000,2000,3000,3000,2000,2000,3000,3000};
|
|
std::array<double,8> ref_Z = {8345,8345,8345,8345,8375,8375,8375,8375};
|
|
|
|
EGrid grid1(testFile);
|
|
|
|
std::array<double,8> X = {0.0};
|
|
std::array<double,8> Y = {0.0};
|
|
std::array<double,8> Z = {0.0};
|
|
|
|
// cell 4,3,2 => zero based 3,2,1
|
|
grid1.getCellCorners({3, 2, 1}, X, Y, Z);
|
|
|
|
BOOST_CHECK_EQUAL(X == ref_X, true);
|
|
BOOST_CHECK_EQUAL(Y == ref_Y, true);
|
|
BOOST_CHECK_EQUAL(Z == ref_Z, true);
|
|
|
|
X = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
|
Y = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
|
Z = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
|
|
|
int globInd=grid1.global_index(3,2,1);
|
|
|
|
grid1.getCellCorners(globInd,X,Y,Z);
|
|
|
|
BOOST_CHECK_EQUAL(X == ref_X, true);
|
|
BOOST_CHECK_EQUAL(Y == ref_Y, true);
|
|
BOOST_CHECK_EQUAL(Z == ref_Z, true);
|
|
}
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(lgr_1) {
|
|
|
|
std::string testEgridFile = "LGR_TESTMOD.EGRID";
|
|
std::string testInitFile = "LGR_TESTMOD.INIT";
|
|
|
|
std::vector<EGrid::NNCentry> nnc_global_ref = {{0,0,1,0,1,0,8.52637}, {0,0,2,0,1,1,8.52637},
|
|
{0,0,3,0,1,2,8.52637}, {0,0,4,0,1,3,8.52637}, {1,0,1,1,1,0,8.52637}, {1,0,2,1,1,1,8.52637},
|
|
{1,0,3,1,1,2,8.52637}, {1,0,4,1,1,3,8.52637} };
|
|
|
|
std::vector<EGrid::NNCentry> nnc_lgr1_ref = {{0,3,1,0,4,0,7.67373}, {0,3,2,0,4,1,7.67373},
|
|
{0,3,3,0,4,2,7.67373}, {1,3,1,1,4,0,7.67373}, {1,3,2,1,4,1,7.67373}, {1,3,3,1,4,2,7.67373},
|
|
{2,3,1,2,4,0,7.67373}, {2,3,2,2,4,1,7.67373}, {2,3,3,2,4,2,7.67373}, {3,3,1,3,4,0,7.67373},
|
|
{3,3,2,3,4,1,7.67373}, {3,3,3,3,4,2,7.67373}};
|
|
|
|
const std::vector<std::string> ref_lgr_list = {"LGR1", "LGR2"};
|
|
|
|
const std::array<int, 3> ref_dim_global = {2,3,5};
|
|
const std::array<int, 3> ref_dim_lgr1 = {4,8,4};
|
|
const std::array<int, 3> ref_dim_lgr2 = {6,8,4};
|
|
|
|
EGrid grid1(testEgridFile);
|
|
|
|
auto nijk_global = grid1.dimension();
|
|
BOOST_CHECK_EQUAL(nijk_global == ref_dim_global, true);
|
|
|
|
auto lgr_list = grid1.list_of_lgrs();
|
|
|
|
BOOST_CHECK_EQUAL(lgr_list.size(), 2);
|
|
BOOST_CHECK_EQUAL(lgr_list[0], "LGR1");
|
|
BOOST_CHECK_EQUAL(lgr_list[1], "LGR2");
|
|
|
|
BOOST_CHECK_EQUAL(grid1.is_radial(), false);
|
|
|
|
BOOST_CHECK_EQUAL(grid1.activeCells(), 30);
|
|
BOOST_CHECK_EQUAL(grid1.totalNumberOfCells(), 30);
|
|
|
|
std::array<double,8> global_X_1_1_0 = { 2099.985, 2199.969, 2099.985, 2199.969, 2099.974, 2199.958, 2099.974, 2199.958 };
|
|
std::array<double,8> global_Y_1_1_0 = { 2100.000, 2100.000, 2200.000, 2200.000, 2100.000, 2100.000, 2200.000, 2200.000 };
|
|
std::array<double,8> global_Z_1_1_0 = { 2002.745, 2004.490, 2002.745, 2004.490, 2005.245, 2006.990, 2005.245, 2006.990 };
|
|
|
|
std::array<double,8> X = {0.0};
|
|
std::array<double,8> Y = {0.0};
|
|
std::array<double,8> Z = {0.0};
|
|
|
|
// cell 2,2,1 => zero based 1,1,0
|
|
grid1.getCellCorners({1, 1, 0}, X, Y, Z);
|
|
|
|
for (size_t n = 0; n < 8; n++){
|
|
BOOST_REQUIRE_CLOSE(global_X_1_1_0[n], X[n], 1e-3);
|
|
BOOST_REQUIRE_CLOSE(global_Y_1_1_0[n], Y[n], 1e-3);
|
|
BOOST_REQUIRE_CLOSE(global_Z_1_1_0[n], Z[n], 1e-3);
|
|
}
|
|
|
|
Opm::EclIO::EInit init1(testInitFile);
|
|
|
|
{
|
|
auto porv = init1.getInitData<float>("PORV");
|
|
auto poro = init1.getInitData<float>("PORO");
|
|
|
|
BOOST_REQUIRE_CLOSE(calculateCellVol(X, Y, Z), porv[3] / poro[3], 1e-2);
|
|
}
|
|
|
|
auto nnc_list = grid1.get_nnc_ijk();
|
|
|
|
BOOST_CHECK_EQUAL(nnc_list.size(), nnc_global_ref.size());
|
|
|
|
for (size_t n=0; n< nnc_list.size(); n++){
|
|
BOOST_CHECK_EQUAL(std::get<0>(nnc_list[n]), std::get<0>(nnc_global_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<1>(nnc_list[n]), std::get<1>(nnc_global_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<2>(nnc_list[n]), std::get<2>(nnc_global_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<3>(nnc_list[n]), std::get<3>(nnc_global_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<4>(nnc_list[n]), std::get<4>(nnc_global_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<5>(nnc_list[n]), std::get<5>(nnc_global_ref[n]));
|
|
BOOST_REQUIRE_CLOSE(std::get<6>(nnc_list[n]), std::get<6>(nnc_global_ref[n]), 1e-3);
|
|
}
|
|
|
|
// testing LGR1 - cartesian grid
|
|
|
|
EGrid lgr1(testEgridFile, "LGR1");
|
|
|
|
BOOST_CHECK_EQUAL(lgr1.is_radial(), false);
|
|
|
|
auto nijk_lgr1 = lgr1.dimension();
|
|
BOOST_CHECK_EQUAL(nijk_lgr1 == ref_dim_lgr1, true);
|
|
|
|
BOOST_CHECK_EQUAL(lgr1.activeCells(), 128);
|
|
BOOST_CHECK_EQUAL(lgr1.totalNumberOfCells(), 128);
|
|
|
|
std::array<double,8> lgr1_X_1_2_0 = { 2124.983, 2149.979, 2124.984, 2149.980, 2124.978, 2149.974, 2124.979, 2149.975 };
|
|
std::array<double,8> lgr1_Y_1_2_0 = { 2050.000, 2050.000, 2075.000, 2075.000, 2050.000, 2050.000, 2075.000, 2075.000 };
|
|
std::array<double,8> lgr1_Z_1_2_0 = { 2002.182, 2002.618, 2002.182, 2002.618, 2003.431, 2003.868, 2003.431, 2003.868 };
|
|
|
|
// cell 2,3,1 => zero based 1,2,0
|
|
lgr1.getCellCorners({1, 2, 0}, X, Y, Z);
|
|
|
|
for (size_t n = 0; n < 8; n++){
|
|
BOOST_REQUIRE_CLOSE(lgr1_X_1_2_0[n], X[n], 1e-3);
|
|
BOOST_REQUIRE_CLOSE(lgr1_Y_1_2_0[n], Y[n], 1e-3);
|
|
BOOST_REQUIRE_CLOSE(lgr1_Z_1_2_0[n], Z[n], 1e-3);
|
|
}
|
|
|
|
{
|
|
int act_ind = lgr1.active_index(1,2,0);
|
|
auto porv = init1.getInitData<float>("PORV", "LGR1");
|
|
auto poro = init1.getInitData<float>("PORO", "LGR1");
|
|
|
|
BOOST_REQUIRE_CLOSE(calculateCellVol(X, Y, Z), porv[act_ind] / poro[act_ind], 1e-2);
|
|
}
|
|
|
|
auto nnc_list_lgr1 = lgr1.get_nnc_ijk();
|
|
|
|
for (size_t n=0; n< nnc_list_lgr1.size(); n++){
|
|
BOOST_CHECK_EQUAL(std::get<0>(nnc_list_lgr1[n]), std::get<0>(nnc_lgr1_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<1>(nnc_list_lgr1[n]), std::get<1>(nnc_lgr1_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<2>(nnc_list_lgr1[n]), std::get<2>(nnc_lgr1_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<3>(nnc_list_lgr1[n]), std::get<3>(nnc_lgr1_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<4>(nnc_list_lgr1[n]), std::get<4>(nnc_lgr1_ref[n]));
|
|
BOOST_CHECK_EQUAL(std::get<5>(nnc_list_lgr1[n]), std::get<5>(nnc_lgr1_ref[n]));
|
|
BOOST_REQUIRE_CLOSE(std::get<6>(nnc_list_lgr1[n]), std::get<6>(nnc_lgr1_ref[n]), 1e-3);
|
|
}
|
|
|
|
|
|
// testing LGR2 - radial grid
|
|
|
|
EGrid lgr2(testEgridFile, "LGR2");
|
|
|
|
BOOST_CHECK_EQUAL(lgr2.is_radial(), true);
|
|
|
|
auto nijk_lgr2 = lgr2.dimension();
|
|
BOOST_CHECK_EQUAL(nijk_lgr2 == ref_dim_lgr2, true);
|
|
|
|
BOOST_CHECK_EQUAL(lgr2.activeCells(), 192);
|
|
BOOST_CHECK_EQUAL(lgr2.totalNumberOfCells(), 192);
|
|
|
|
std::array<double,8> lgr2_X_4_1_0 = { 8.469, 23.561, 0.000, 0.000, 8.469, 23.561, 0.000, 0.000 };
|
|
std::array<double,8> lgr2_Y_4_1_0 = { 8.471, 23.564, 11.978, 33.322, 8.471, 23.564, 11.978, 33.322 };
|
|
std::array<double,8> lgr2_Z_4_1_0 = { 2011.892, 2012.155, 2011.744, 2011.744, 2013.892, 2014.155, 2013.744, 2013.744 };
|
|
|
|
// cell 5,2,1 => zero based 4,1,0
|
|
lgr2.getCellCorners({4, 1, 0}, X, Y, Z);
|
|
|
|
for (size_t n = 0; n < 8; n++){
|
|
BOOST_CHECK_EQUAL(abs(lgr2_X_4_1_0[n]- X[n]) < 1e-3, true);
|
|
BOOST_CHECK_EQUAL(abs(lgr2_Y_4_1_0[n]- Y[n]) < 1e-3, true);
|
|
BOOST_CHECK_EQUAL(abs(lgr2_Z_4_1_0[n]- Z[n]) < 1e-3, true);
|
|
}
|
|
|
|
auto hostcells_ijk = lgr1.hostCellsIJK();
|
|
auto hostcells_gind = lgr1.hostCellsGlobalIndex();
|
|
|
|
for (size_t n = 0; n < hostcells_gind.size(); n++)
|
|
BOOST_CHECK_EQUAL(grid1.ijk_from_global_index(hostcells_gind[n]) == hostcells_ijk[n], true);
|
|
}
|
|
|