diff --git a/opm/io/eclipse/ERft.hpp b/opm/io/eclipse/ERft.hpp index 4c6f2c531..ac4fc876f 100644 --- a/opm/io/eclipse/ERft.hpp +++ b/opm/io/eclipse/ERft.hpp @@ -67,6 +67,8 @@ public: bool hasArray(const std::string& arrayName, const std::string& wellName, const RftDate& date) const; + bool hasArray(const std::string& arrayName, int reportInd) const; + int numberOfReports() { return numReports; } private: diff --git a/python/cxx/eclipse_io.cpp b/python/cxx/eclipse_io.cpp index 15105c5b7..4107df3a3 100644 --- a/python/cxx/eclipse_io.cpp +++ b/python/cxx/eclipse_io.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -191,11 +192,62 @@ py::array get_cellvolumes(Opm::EclIO::EGrid * file_ptr) return get_cellvolumes_mask(file_ptr, mask); } +npArray get_rft_vector_WellDate(Opm::EclIO::ERft * file_ptr,const std::string& name, + const std::string& well, int y, int m, int d) +{ + auto arrList = file_ptr->listOfRftArrays(well, y, m, d); + size_t array_index = get_array_index(arrList, name, 0); + Opm::EclIO::eclArrType array_type = std::get<1>(arrList[array_index]); + + if (array_type == Opm::EclIO::INTE) + return std::make_tuple (convert::numpy_array( file_ptr->getRft(name, well, y, m, d) ), array_type); + + if (array_type == Opm::EclIO::REAL) + return std::make_tuple (convert::numpy_array( file_ptr->getRft(name, well, y, m, d) ), array_type); + + if (array_type == Opm::EclIO::DOUB) + return std::make_tuple (convert::numpy_array( file_ptr->getRft(name, well, y, m, d) ), array_type); + + if (array_type == Opm::EclIO::CHAR) + return std::make_tuple (convert::numpy_string_array( file_ptr->getRft(name, well, y, m, d) ), array_type); + + if (array_type == Opm::EclIO::LOGI) + return std::make_tuple (convert::numpy_array( file_ptr->getRft(name, well, y, m, d) ), array_type); + + throw std::logic_error("Data type not supported"); +} + +npArray get_rft_vector_Index(Opm::EclIO::ERft * file_ptr,const std::string& name, int reportIndex) +{ + auto arrList = file_ptr->listOfRftArrays(reportIndex); + size_t array_index = get_array_index(arrList, name, 0); + Opm::EclIO::eclArrType array_type = std::get<1>(arrList[array_index]); + + if (array_type == Opm::EclIO::INTE) + return std::make_tuple (convert::numpy_array( file_ptr->getRft(name, reportIndex) ), array_type); + + if (array_type == Opm::EclIO::REAL) + return std::make_tuple (convert::numpy_array( file_ptr->getRft(name, reportIndex) ), array_type); + + if (array_type == Opm::EclIO::DOUB) + return std::make_tuple (convert::numpy_array( file_ptr->getRft(name, reportIndex) ), array_type); + + if (array_type == Opm::EclIO::CHAR) + return std::make_tuple (convert::numpy_string_array( file_ptr->getRft(name, reportIndex) ), array_type); + + if (array_type == Opm::EclIO::LOGI) + return std::make_tuple (convert::numpy_array( file_ptr->getRft(name, reportIndex) ), array_type); + + throw std::logic_error("Data type not supported"); +} + } + + void python::common::export_IO(py::module& m) { py::enum_(m, "eclArrType", py::arithmetic()) @@ -250,4 +302,25 @@ void python::common::export_IO(py::module& m) { .def("xyz_from_active_index", &get_xyz_from_active_index) .def("cellvolumes", &get_cellvolumes) .def("cellvolumes", &get_cellvolumes_mask); + + py::class_(m, "ERft") + .def(py::init()) + .def("__get_list_of_rfts", &Opm::EclIO::ERft::listOfRftReports) + + .def("__get_list_of_arrays", (std::vector< std::tuple > + (Opm::EclIO::ERft::*)(int) const) &Opm::EclIO::ERft::listOfRftArrays) + + .def("__get_list_of_arrays", (std::vector< std::tuple > + (Opm::EclIO::ERft::*)(const std::string&, int, int, int) const) + &Opm::EclIO::ERft::listOfRftArrays) + + .def("__get_data", &get_rft_vector_WellDate) + .def("__get_data", &get_rft_vector_Index) + + .def("__has_rft", (bool (Opm::EclIO::ERft::*)(const std::string&, int, int, int) const) &Opm::EclIO::ERft::hasRft) + .def("__has_array", (bool (Opm::EclIO::ERft::*)(const std::string&, int) const) &Opm::EclIO::ERft::hasArray) + .def("__has_array", (bool (Opm::EclIO::ERft::*)(const std::string&, const std::string&, const + std::tuple&) const) &Opm::EclIO::ERft::hasArray) + + .def("__len__", &Opm::EclIO::ERft::numberOfReports); } diff --git a/python/python/opm/_common.py b/python/python/opm/_common.py index daee9c319..14a8a7097 100644 --- a/python/python/opm/_common.py +++ b/python/python/opm/_common.py @@ -24,6 +24,7 @@ from .libopmcommon_python import EclFile, eclArrType from .libopmcommon_python import ERst from .libopmcommon_python import ESmry from .libopmcommon_python import EGrid +from .libopmcommon_python import ERft from .libopmcommon_python import SummaryState #from .schedule import Well, Connection, Schedule diff --git a/python/python/opm/io/ecl/__init__.py b/python/python/opm/io/ecl/__init__.py index add807a0c..f23985e0b 100644 --- a/python/python/opm/io/ecl/__init__.py +++ b/python/python/opm/io/ecl/__init__.py @@ -3,6 +3,7 @@ from opm._common import EclFile from opm._common import ERst from opm._common import ESmry from opm._common import EGrid +from opm._common import ERft import sys import datetime @@ -119,6 +120,63 @@ def getitem_esmry(self, arg): return self.__get_all(arg) +def contains_erft(self, arg): + + if isinstance(arg, tuple): + if len(arg) == 4: + return self.__has_rft(arg[0], arg[1], arg[2], arg[3]) + elif len(arg) == 5: + return self.__has_array(arg[0], arg[1], (arg[2], arg[3], arg[4])) + elif len(arg) == 2: + return self.__has_array(arg[0], arg[1]) + else: + raise ValueError("expecting tuple (wellname, year, month, day) or \ + (arrayName, wellname, year, month, day) or (arrayName, report_index)") + else: + raise ValueError("expecting tuple (wellname, year, month, day) or \ + (arrayName, wellname, year, month, day) or (arrayName, report_index)") + +@property +def erft_list_of_rfts(self): + + if sys.version_info.major==2: + data = self.__get_list_of_rfts() + return [ ( x[0].encode("utf-8"), x[1], x[2] ) for x in data ] + else: + return self.__get_list_of_rfts() + + +def erft_list_of_arrays(self, arg1, arg2 = None): + + if not arg2: + data = self.__get_list_of_arrays(int(arg1)) + else: + data = self.__get_list_of_arrays(str(arg1), int(arg2[0]), int(arg2[1]), int(arg2[2])) + + if sys.version_info.major==2: + return [ ( x[0].encode("utf-8"), x[1], x[2] ) for x in data ] + else: + return data + + +def getitem_erft(self, arg): + + if isinstance(arg, tuple): + if len(arg) == 2: + data, array_type = self.__get_data(arg[0], arg[1]) + elif len(arg) == 5: + data, array_type = self.__get_data(arg[0], arg[1], arg[2], arg[3], arg[4]) + else: + raise ValueError("ERft.__getitem__, expecting tuple (name, index) or (name, well, y, m, d)") + else: + raise ValueError("ERft.__getitem__, expecting tuple (name, index) or (name, well, y, m, d)") + + if array_type == eclArrType.CHAR: + return np.array([ x.decode("utf-8") for x in data ]) + else: + return data + + setattr(EclFile, "__getitem__", getitem_eclfile) setattr(EclFile, "arrays", eclfile_get_list_of_arrays) @@ -129,3 +187,8 @@ setattr(ERst, "__getitem__", getitem_erst) setattr(ESmry, "start_date", esmry_start_date) setattr(ESmry, "end_date", esmry_end_date) setattr(ESmry, "__getitem__", getitem_esmry) + +setattr(ERft, "__contains__", contains_erft) +setattr(ERft, "list_of_rfts", erft_list_of_rfts) +setattr(ERft, "arrays", erft_list_of_arrays) +setattr(ERft, "__getitem__",getitem_erft) diff --git a/python/tests/data/SPE1CASE1.RFT b/python/tests/data/SPE1CASE1.RFT new file mode 100644 index 000000000..f050db50d Binary files /dev/null and b/python/tests/data/SPE1CASE1.RFT differ diff --git a/python/tests/test_erft.py b/python/tests/test_erft.py new file mode 100755 index 000000000..a55261423 --- /dev/null +++ b/python/tests/test_erft.py @@ -0,0 +1,177 @@ +import unittest +import sys +import numpy as np +import datetime + +from opm.io.ecl import ERft, eclArrType +try: + from tests.utils import test_path +except ImportError: + from utils import test_path + + + +class TestEclFile(unittest.TestCase): + + def test_content(self): + + refContent = [ ('PROD', (2015, 1, 1), 0.0), + ('INJ', (2015, 1, 1), 0.0), + ('A-1H', (2015, 9, 1), 243.0), + ('B-2H', (2016, 5, 31), 516.0), + ('PROD', (2017, 7, 31), 942.0) ] + + + with self.assertRaises(ValueError): + ERft("/file/that/does_not_exists") + + rft1 = ERft(test_path("data/SPE1CASE1.RFT")) + self.assertEqual(len(rft1), 5) + + self.assertTrue( ("PROD", 2015, 1, 1) in rft1 ) + self.assertFalse( ("XXX", 2015, 1, 1) in rft1 ) + + self.assertTrue( ("PRESSURE", "PROD", 2015, 1, 1) in rft1 ) + self.assertFalse( ("XXX", "PROD", 2015, 1, 1) in rft1 ) + + self.assertTrue( ("PRESSURE", 0) in rft1 ) + self.assertTrue( ("PRESSURE", 1) in rft1 ) + + self.assertFalse( ("XXX", 0) in rft1 ) + + with self.assertRaises(ValueError): + self.assertTrue( ("PRESSURE", "XX", "XX") in rft1 ) + + rftlist = rft1.list_of_rfts + + self.assertEqual(len(rftlist), 5) + + for n, rftdata in enumerate(rftlist): + self.assertEqual(rftdata[0], refContent[n][0]) + self.assertEqual(rftdata[1], refContent[n][1]) + self.assertEqual(rftdata[2], refContent[n][2]) + + + def test_list_of_rfts(self): + + ref_rftlist = [] + ref_rftlist.append(('PROD', (2015, 1, 1), 0.0)) + ref_rftlist.append(('INJ', (2015, 1, 1), 0.0)) + ref_rftlist.append(('A-1H', (2015, 9, 1), 243.0)) + ref_rftlist.append(('B-2H', (2016, 5, 31), 516.0)) + ref_rftlist.append(('PROD', (2017, 7, 31), 942.0)) + + rft1 = ERft(test_path("data/SPE1CASE1.RFT")) + + for n, element in enumerate(rft1.list_of_rfts): + self.assertEqual(element, ref_rftlist[n]) + + + def test_list_of_array(self): + + refArrList = ["TIME", "DATE", "WELLETC", "CONIPOS", "CONJPOS", "CONKPOS", "HOSTGRID", "DEPTH", "PRESSURE", + "SWAT", "SGAS"] + + rft1 = ERft(test_path("data/SPE1CASE1.RFT")) + + rft_date = (2016, 5, 31) + arrList1 = rft1.arrays( "B-2H", rft_date ) + arrList2 = rft1.arrays( 3 ) + + self.assertEqual(len(arrList1), len(refArrList)) + + for n, (name, arrType, arrSize) in enumerate(arrList1): + + self.assertEqual(name, refArrList[n]) + + if arrType != eclArrType.MESS: + array = rft1[name, "B-2H", 2016, 5, 31] + self.assertEqual(len(array), arrSize) + + if arrType == eclArrType.INTE: + self.assertEqual(array.dtype, "int32") + elif arrType == eclArrType.REAL: + self.assertEqual(array.dtype, "float32") + elif arrType == eclArrType.DOUB: + self.assertEqual(array.dtype, "float64") + elif arrType == eclArrType.LOGI: + self.assertEqual(array.dtype, "bool") + elif arrType == eclArrType.CHAR: + self.assertTrue(array.dtype.kind in {'U', 'S'}) + + + self.assertEqual(len(arrList2), len(refArrList)) + + for n, (name, arrType, arrSize) in enumerate(arrList2): + + self.assertEqual(name, refArrList[n]) + + if arrType != eclArrType.MESS: + array = rft1[name, "B-2H", 2016, 5, 31 ] + self.assertEqual(len(array), arrSize) + + if arrType == eclArrType.INTE: + self.assertEqual(array.dtype, "int32") + elif arrType == eclArrType.REAL: + self.assertEqual(array.dtype, "float32") + elif arrType == eclArrType.DOUB: + self.assertEqual(array.dtype, "float64") + elif arrType == eclArrType.LOGI: + self.assertEqual(array.dtype, "bool") + elif arrType == eclArrType.CHAR: + self.assertTrue(array.dtype.kind in {'U', 'S'}) + + + def test_get(self): + + pref = [0.57886104E+04, 0.57946934E+04, 0.58056177E+04] + refI = [9, 9, 9] + refJ = [4, 4, 4] + refK = [1, 2, 3] + + rft1 = ERft(test_path("data/SPE1CASE1.RFT")) + + pres1a = rft1["PRESSURE", "A-1H", 2015, 9, 1 ] + pres1b = rft1["PRESSURE", 2 ] + + self.assertEqual(len(pres1a), len(pref)) + self.assertEqual(len(pres1b), len(pref)) + + for ref, v1, v2 in zip(pref, pres1a, pres1b): + self.assertAlmostEqual(ref, v1, 4) + self.assertAlmostEqual(ref, v2, 4) + + conI_1a = rft1["CONIPOS", "B-2H", 2016, 5, 31] + conJ_1a = rft1["CONJPOS", "B-2H", 2016, 5, 31] + conK_1a = rft1["CONKPOS", "B-2H", 2016, 5, 31] + + conI_1b = rft1["CONIPOS", 3] + conJ_1b = rft1["CONJPOS", 3] + conK_1b = rft1["CONKPOS", 3] + + self.assertEqual(len(refI), len(conI_1a)) + self.assertEqual(len(refI), len(conI_1b)) + + self.assertEqual(len(refJ), len(conJ_1a)) + self.assertEqual(len(refJ), len(conJ_1b)) + + self.assertEqual(len(refK), len(conK_1a)) + self.assertEqual(len(refK), len(conK_1b)) + + for ref, v1, v2 in zip(refI, conI_1a, conI_1b): + self.assertEqual(ref, v1) + self.assertEqual(ref, v2) + + for ref, v1, v2 in zip(refJ, conJ_1a, conJ_1b): + self.assertEqual(ref, v1) + self.assertEqual(ref, v2) + + for ref, v1, v2 in zip(refK, conK_1a, conK_1b): + self.assertEqual(ref, v1) + self.assertEqual(ref, v2) + + +if __name__ == "__main__": + + unittest.main() + diff --git a/src/opm/io/eclipse/ERft.cpp b/src/opm/io/eclipse/ERft.cpp index 7cab30024..25045baa7 100644 --- a/src/opm/io/eclipse/ERft.cpp +++ b/src/opm/io/eclipse/ERft.cpp @@ -131,6 +131,18 @@ bool ERft::hasArray(const std::string& arrayName, const std::string& wellName, } +bool ERft::hasArray(const std::string& arrayName, int reportInd) const +{ + auto searchInd = arrIndexRange.find(reportInd); + + int fromInd = std::get<0>(searchInd->second); + int toInd = std::get<1>(searchInd->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 {