From 24a8efb2e3222cf113c6929efebab6267569bc30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Skille?= Date: Thu, 28 Mar 2019 14:33:30 +0100 Subject: [PATCH] added: ERft class for reading RFT simulation data from ECL files --- CMakeLists.txt | 3 +- CMakeLists_files.cmake | 1 + examples/test_util/ERft.cpp | 310 ++++++++++++++++++++++++++++++++++++ examples/test_util/ERft.hpp | 83 ++++++++++ tests/SPE1CASE1.RFT | Bin 0 -> 3652 bytes tests/test_ERft.cpp | 202 +++++++++++++++++++++++ 6 files changed, 598 insertions(+), 1 deletion(-) create mode 100644 examples/test_util/ERft.cpp create mode 100644 examples/test_util/ERft.hpp create mode 100644 tests/SPE1CASE1.RFT create mode 100644 tests/test_ERft.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b632a7b4..f7952244d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,6 +165,7 @@ if(ENABLE_ECL_INPUT) examples/test_util/EclOutput.cpp examples/test_util/EclUtil.cpp examples/test_util/EGrid.cpp + examples/test_util/ERft.cpp examples/test_util/summaryComparator.cpp examples/test_util/summaryIntegrationTest.cpp examples/test_util/summaryRegressionTest.cpp) @@ -176,7 +177,7 @@ if(ENABLE_ECL_INPUT) set(_libs testutil opmcommon ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) foreach(test test_compareSummary test_EclFilesComparator test_EclIO - test_EGrid) + test_EGrid test_ERft) opm_add_test(${test} CONDITION ENABLE_ECL_INPUT LIBRARIES ${_libs} WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/tests) diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 8410942c9..ac7c340f6 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -322,6 +322,7 @@ if(ENABLE_ECL_INPUT) tests/ECLFILE.INIT tests/ECLFILE.FINIT tests/SPE1CASE1.EGRID + tests/SPE1CASE1.RFT ) list (APPEND EXAMPLE_SOURCE_FILES examples/opmi.cpp diff --git a/examples/test_util/ERft.cpp b/examples/test_util/ERft.cpp new file mode 100644 index 000000000..342de035f --- /dev/null +++ b/examples/test_util/ERft.cpp @@ -0,0 +1,310 @@ +/* + 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 . + */ + +#include "ERft.hpp" + +#include +#include +#include +#include +#include +#include +#include + + +ERft::ERft(const std::string &filename) : EclFile(filename) +{ + loadData(); + std::vector first; + std::vector second; + + std::vector wellName; + std::vector dates; + + auto listOfArrays = getList(); + + for (size_t i = 0; i < listOfArrays.size(); i++) { + std::string name = std::get<0>(listOfArrays[i]); + + if (name == "TIME") { + first.push_back(i); + auto vect1 = get(i); + timeList.push_back(vect1[0]); + } + + if (name == "DATE") { + auto vect1 = get(i); + RftDate date(vect1[2],vect1[1],vect1[0]); + dateList.insert(date); + dates.push_back(date); + } + + if (name == "WELLETC"){ + auto vect1 = get(i); + wellList.insert(vect1[1]); + wellName.push_back(vect1[1]); + } + } + + for (size_t i = 0; i < first.size(); i++) { + std::pair range; + range.first = first[i]; + + if (i == first.size() - 1) { + range.second = listOfArrays.size(); + } else { + range.second = first[i+1]; + } + + arrIndexRange[i] = range; + } + + numReports = first.size(); + + for (size_t i = 0; i < wellName.size(); i++) { + std::pair wellDatePair(wellName[i],dates[i]); + reportIndex[wellDatePair] = i; + rftReportList.push_back(wellDatePair); + } +} + + +bool ERft::hasRft(const std::string& wellName, const RftDate& date) const +{ + return reportIndex.find({wellName, date}) != reportIndex.end(); +} + + +bool ERft::hasRft(const std::string& wellName, int year, int month, int day) const +{ + RftDate date(year, month, day); + return reportIndex.find({wellName,date}) != reportIndex.end(); +} + + +int ERft::getReportIndex(const std::string& wellName, const RftDate& date) const +{ + std::pair> wellDatePair(wellName,date); + auto rIndIt = reportIndex.find(wellDatePair); + + if (rIndIt == reportIndex.end()) { + int y = std::get<0>(date); + int m = std::get<1>(date); + int d = std::get<2>(date); + + std::string dateStr=std::to_string(y) + "/" + std::to_string(m) + "/" + std::to_string(d); + std::string message="RFT data not found for well " + wellName + " at date: " + dateStr; + OPM_THROW(std::invalid_argument, message); + } + + return rIndIt->second; +} + + +bool ERft::hasArray(const std::string& arrayName, const std::string& wellName, + const RftDate& date) const +{ + int reportInd = getReportIndex(wellName, date); + + auto searchInd = arrIndexRange.find(reportInd); + + int fromInd = searchInd->second.first; + int toInd = searchInd->second.second; + + auto it = std::find(array_name.begin()+fromInd,array_name.begin()+toInd,arrayName); + return it != array_name.begin() + toInd; +} + + +int ERft::getArrayIndex(const std::string& name, const std::string& wellName, + const RftDate& date) const +{ + int rInd= getReportIndex(wellName, date); + + auto searchInd = arrIndexRange.find(rInd); + + int fromInd =searchInd->second.first; + int toInd = searchInd->second.second; + auto it=std::find(array_name.begin()+fromInd,array_name.begin()+toInd,name); + + if (std::distance(array_name.begin(),it) == toInd) { + int y = std::get<0>(date); + int m = std::get<1>(date); + int d = std::get<2>(date); + + std::string dateStr = std::to_string(y) + "/" + std::to_string(m) + "/" + std::to_string(d); + std::string message = "Array " + name + " not found for RFT, well: " + wellName + " date: " + dateStr; + OPM_THROW(std::invalid_argument, message); + } + + return std::distance(array_name.begin(),it); +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string &wellName, + const RftDate& date) const +{ + int arrInd = getArrayIndex(name, wellName, date); + + if (array_type[arrInd] != EIOD::REAL) { + std::string message = "Array " + name + " found in RFT file for selected date and well, but called with wrong type"; + OPM_THROW(std::runtime_error, message); + } + + auto search_array = real_array.find(arrInd); + return search_array->second; +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string& wellName, + const RftDate& date) const +{ + int arrInd = getArrayIndex(name, wellName, date); + + if (array_type[arrInd] != EIOD::DOUB) { + std::string message = "Array " + name + " found in RFT file for selected date and well, but called with wrong type"; + OPM_THROW(std::runtime_error, message); + } + + auto search_array = doub_array.find(arrInd); + return search_array->second; +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string& wellName, + const RftDate& date) const +{ + int arrInd = getArrayIndex(name, wellName, date); + + if (array_type[arrInd] != EIOD::INTE) { + std::string message = "Array " + name + " found in RFT file for selected date and well, but called with wrong type"; + OPM_THROW(std::runtime_error, message); + } + + auto search_array = inte_array.find(arrInd); + return search_array->second; +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string& wellName, + const RftDate& date) const +{ + int arrInd = getArrayIndex(name, wellName, date); + + if (array_type[arrInd] != EIOD::LOGI) { + std::string message = "Array " + name + " found in RFT file for selected date and well, but called with wrong type"; + OPM_THROW(std::runtime_error, message); + } + + auto search_array = logi_array.find(arrInd); + return search_array->second; +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string& wellName, + const RftDate& date) const +{ + int arrInd = getArrayIndex(name, wellName, date); + + if (array_type[arrInd] != EIOD::CHAR) { + std::string message = "Array " + name + " found in RFT file for selected date and well, but called with wrong type"; + OPM_THROW(std::runtime_error, message); + } + + auto search_array = char_array.find(arrInd); + return search_array->second; +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string& wellName, + int year, int month, int day) const +{ + return getRft(name, wellName, RftDate{year, month, day}); +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string& wellName, + int year, int month, int day) const +{ + return getRft(name, wellName, RftDate{year, month, day}); +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string& wellName, + int year, int month, int day) const +{ + return getRft(name, wellName, RftDate{year, month, day}); +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string& wellName, + int year, int month, int day) const +{ + return getRft(name, wellName, RftDate{year, month, day}); +} + + +template<> const std::vector& +ERft::getRft(const std::string& name, const std::string& wellName, + int year, int month, int day) const +{ + return getRft(name, wellName, RftDate{year, month, day}); +} + + +std::vector ERft::listOfRftArrays(const std::string& wellName, + const RftDate& date) const +{ + std::vector list; + int rInd = getReportIndex(wellName, date); + + auto searchInd = arrIndexRange.find(rInd); + for (int i = searchInd->second.first; i < searchInd->second.second; i++) { + list.emplace_back(array_name[i], array_type[i], array_size[i]); + } + + return list; +} + + +std::vector ERft::listOfRftArrays(const std::string& wellName, + int year, int month, int day) const +{ + return listOfRftArrays(wellName, RftDate{year, month, day}); +} + + +std::vector ERft::listOfWells() const +{ + return { this->wellList.begin(), this->wellList.end() }; +} + + +std::vector ERft::listOfdates() const +{ + return { this->dateList.begin(), this->dateList.end() }; +} diff --git a/examples/test_util/ERft.hpp b/examples/test_util/ERft.hpp new file mode 100644 index 000000000..2c0144fe5 --- /dev/null +++ b/examples/test_util/ERft.hpp @@ -0,0 +1,83 @@ +/* + 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 . + */ + +#ifndef ERFT_HPP +#define ERFT_HPP + + +#include "EclFile.hpp" + +#include +#include +#include +#include +#include +#include +#include + + +class ERft : public EclFile +{ +public: + explicit ERft(const std::string &filename); + + using RftDate = std::tuple; + template + const std::vector& getRft(const std::string& name, const std::string& wellName, + const RftDate& date) const; + + template + const std::vector& getRft(const std::string& name, const std::string& wellName, + int year, int month, int day) const; + + std::vector listOfWells() const; + std::vector listOfdates() const; + + using RftReportList = std::vector>; + const RftReportList& listOfRftReports() const { return rftReportList; } + + bool hasRft(const std::string& wellName, const RftDate& date) const; + bool hasRft(const std::string& wellName, int year, int month, int day) const; + + std::vector listOfRftArrays(const std::string& wellName, + const RftDate& date) const; + + std::vector listOfRftArrays(const std::string& wellName, + int year, int month, int day) const; + + bool hasArray(const std::string& arrayName, const std::string& wellName, + const RftDate& date) const; + +private: + std::map> arrIndexRange; + int numReports; + std::vector timeList; + + std::set wellList; + std::set dateList; + RftReportList rftReportList; + + std::map,int> reportIndex; // mapping report index to wellName and date (tupe) + + int getReportIndex(const std::string& wellName, const RftDate& date) const; + int getArrayIndex(const std::string& name, const std::string& wellName, + const RftDate& date) const; +}; + +#endif + diff --git a/tests/SPE1CASE1.RFT b/tests/SPE1CASE1.RFT new file mode 100644 index 0000000000000000000000000000000000000000..f050db50dd45ae71493c929ef6135b20b75cb7a3 GIT binary patch literal 3652 zcmd^B&2G~`5Oxx(1k{5MAQcITy&(=&1Sf?j>-pUEiNPU1xJs>!7 zKz)E-ptlx8&y|pP0e;j602S_hv++7>6USCTEr?MjlihsYnVtPSJDR5HvAe<^#-l5dX_IB47&2zZ?TDL`Wf(KXqh7C#M;L=8 zI9U%viUF#d{?HBlh{iQ#FSO4KP_bWN1{E;N1(=3hr|(Cx6S@}pQgYFfL1VrJ)h!;x zeM}NgJp;SZ#nd>aAmmZB8dB~v82+3fV@xzML?-i?&X0qw6yq2;g0S9=WWW@08skknTNj8g$~w+ut?LEwqK zx0EwwBAVojZ+_L1oT}4=A)eX>=#Af*{TSEZu47K_XL%}bu5&mKLIasR0rP{axIF@-bc zR>{3^Uel`I3&!FNqOu}q#)MHoFEhAB zHD9X4{u|ud-}%7zkJk8`C10LdA-9eX-*t`;51|JswuoE3?Q6hDna!>B4Z?|gb4J}F zZZ+}w3|om?W&JGs5Bphg_{9CAwfEqnJSVI(wSTl. + + */ + + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define BOOST_TEST_MODULE Test EGrid +#include + +template +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 begin1(file1); + std::istreambuf_iterator begin2(file2); + + std::istreambuf_iterator end; + + return range_equal(begin1, end, begin2, end); +} + + +template +bool operator==(const std::vector & t1, const std::vector & 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(TestERft_1) { + using Date = std::tuple; + + std::vector ref_wellList= {"A-1H", "B-2H", "INJ", "PROD"}; + std::vector ref_dates= { + Date{2015,1, 1}, + Date{2015,9, 1}, + Date{2016,5,31}, + Date{2017,7,31}, + }; + + const std::vector> ref_rftList = { + {"PROD", Date{2015,1, 1}}, + {"INJ" , Date{2015,1, 1}}, + {"A-1H", Date{2015,9, 1}}, + {"B-2H", Date{2016,5,31}}, + {"PROD", Date{2017,7,31}} + }; + + std::string testFile="SPE1CASE1.RFT"; + + ERft rft1(testFile); + + std::vector wellList = rft1.listOfWells(); + std::vector rftDates = rft1.listOfdates(); + std::vector> rftList = rft1.listOfRftReports(); + + BOOST_CHECK_EQUAL(wellList==ref_wellList, true); + BOOST_CHECK_EQUAL(rftDates==ref_dates, true); + + BOOST_CHECK_EQUAL(rftList==ref_rftList, true); + + BOOST_CHECK_EQUAL(rft1.hasRft("PROD", Date{2015,1,1}), true); + BOOST_CHECK_EQUAL(rft1.hasRft("PROD",2015,1,1), true); + + BOOST_CHECK_EQUAL(rft1.hasRft("PROD", Date{2015,10,1}), false); + BOOST_CHECK_EQUAL(rft1.hasRft("XXXX", Date{2015,1,1}), false); + BOOST_CHECK_EQUAL(rft1.hasRft("PROD",2015,10,1), false); + BOOST_CHECK_EQUAL(rft1.hasRft("XXXX",2015,1,1), false); + + // test member function hasArray + + BOOST_CHECK_EQUAL(rft1.hasArray("SGAS","B-2H", Date{2016,5,31}), true); + BOOST_CHECK_EQUAL(rft1.hasArray("XXXX","B-2H", Date{2016,5,31}), false); + + BOOST_CHECK_THROW(rft1.hasArray("SGAS","C-2H", Date{2016,5,31}),std::invalid_argument); + BOOST_CHECK_THROW(rft1.hasArray("SGAS","B-2H", Date{2016,5,30}),std::invalid_argument); + BOOST_CHECK_THROW(rft1.hasArray("SGAS","C-2H", Date{2016,5,30}),std::invalid_argument); + BOOST_CHECK_THROW(rft1.hasArray("XXXX","C-2H", Date{2016,5,30}),std::invalid_argument); + + // test member function getRft + + std::vector vect1=rft1.getRft("CONIPOS","B-2H", Date{2016,5,31}); + std::vector vect2=rft1.getRft("PRESSURE","B-2H", Date{2016,5,31}); + std::vector vect3=rft1.getRft("WELLETC","B-2H", Date{2016,5,31}); + + BOOST_CHECK_EQUAL(vect1.size(), 3); + BOOST_CHECK_EQUAL(vect2.size(), 3); + BOOST_CHECK_EQUAL(vect3.size(), 16); + + // called with invalid argument, array not existing, wrong well name or wrong date + BOOST_CHECK_THROW(std::vector vect1=rft1.getRft("CONIPOS","C-2H", Date{2016,5,31}),std::invalid_argument); + BOOST_CHECK_THROW(std::vector vect1=rft1.getRft("CONIPOS","B-2H", Date{2016,5,30}),std::invalid_argument); + BOOST_CHECK_THROW(std::vector vect1=rft1.getRft("XXXXXXX","B-2H", Date{2016,5,31}),std::invalid_argument); + + // called with wrong type + BOOST_CHECK_THROW(std::vector vect1=rft1.getRft("SGAS","B-2H", Date{2016,5,31}),std::runtime_error); + BOOST_CHECK_THROW(std::vector vect1=rft1.getRft("CONIPOS","B-2H", Date{2016,5,31}),std::runtime_error); + BOOST_CHECK_THROW(std::vector vect1=rft1.getRft("CONIPOS","B-2H", Date{2016,5,31}), std::runtime_error); +} + + +BOOST_AUTO_TEST_CASE(TestERft_2) { + + std::string testFile="SPE1CASE1.RFT"; + + std::string outFile="TEST.RFT"; + + { + EclOutput eclTest(outFile, false); + + ERft rft1(testFile); + + auto rftList = rft1.listOfRftReports(); + + for (auto& rft : rftList) { + std::string wellName = std::get<0>(rft); + auto date = std::get<1>(rft); + + auto arrayList = rft1.listOfRftArrays(wellName, date); + + for (auto& array : arrayList) { + std::string arrName = std::get<0>(array); + EIOD::eclArrType arrType = std::get<1>(array); + + if (arrType == EIOD::INTE) { + std::vector vect = rft1.getRft(arrName, wellName, date); + eclTest.write(arrName, vect); + } else if (arrType == EIOD::REAL) { + std::vector vect = rft1.getRft(arrName, wellName, date); + eclTest.write(arrName, vect); + } else if (arrType == EIOD::DOUB) { + std::vector vect = rft1.getRft(arrName, wellName, date); + eclTest.write(arrName, vect); + } else if (arrType == EIOD::LOGI) { + std::vector vect = rft1.getRft(arrName, wellName, date); + eclTest.write(arrName, vect); + } else if (arrType == EIOD::CHAR) { + std::vector vect = rft1.getRft(arrName, wellName, date); + eclTest.write(arrName, vect); + } else if (arrType == EIOD::MESS) { + eclTest.write(arrName, std::vector()); + } else { + std::cout << "unknown type " << std::endl; + exit(1); + } + } + } + } + + BOOST_CHECK_EQUAL(compare_files(testFile, outFile), true); + + if (remove(outFile.c_str())==-1) { + std::cout << " > Warning! temporary file was not deleted" << std::endl; + }; +}