Adding python bindings for C++ class ERft

This commit is contained in:
Torbjørn Skille
2020-03-23 10:57:49 +01:00
parent d258ce5a57
commit 1a39c07981
7 changed files with 328 additions and 0 deletions
+73
View File
@@ -7,6 +7,7 @@
#include <src/opm/io/eclipse/ERst.cpp>
#include <src/opm/io/eclipse/ESmry.cpp>
#include <src/opm/io/eclipse/EGrid.cpp>
#include <src/opm/io/eclipse/ERft.cpp>
#include <opm/common/utility/numeric/calculateCellVol.hpp>
@@ -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<int>(name, well, y, m, d) ), array_type);
if (array_type == Opm::EclIO::REAL)
return std::make_tuple (convert::numpy_array( file_ptr->getRft<float>(name, well, y, m, d) ), array_type);
if (array_type == Opm::EclIO::DOUB)
return std::make_tuple (convert::numpy_array( file_ptr->getRft<double>(name, well, y, m, d) ), array_type);
if (array_type == Opm::EclIO::CHAR)
return std::make_tuple (convert::numpy_string_array( file_ptr->getRft<std::string>(name, well, y, m, d) ), array_type);
if (array_type == Opm::EclIO::LOGI)
return std::make_tuple (convert::numpy_array( file_ptr->getRft<bool>(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<int>(name, reportIndex) ), array_type);
if (array_type == Opm::EclIO::REAL)
return std::make_tuple (convert::numpy_array( file_ptr->getRft<float>(name, reportIndex) ), array_type);
if (array_type == Opm::EclIO::DOUB)
return std::make_tuple (convert::numpy_array( file_ptr->getRft<double>(name, reportIndex) ), array_type);
if (array_type == Opm::EclIO::CHAR)
return std::make_tuple (convert::numpy_string_array( file_ptr->getRft<std::string>(name, reportIndex) ), array_type);
if (array_type == Opm::EclIO::LOGI)
return std::make_tuple (convert::numpy_array( file_ptr->getRft<bool>(name, reportIndex) ), array_type);
throw std::logic_error("Data type not supported");
}
}
void python::common::export_IO(py::module& m) {
py::enum_<Opm::EclIO::eclArrType>(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_<Opm::EclIO::ERft>(m, "ERft")
.def(py::init<const std::string &>())
.def("__get_list_of_rfts", &Opm::EclIO::ERft::listOfRftReports)
.def("__get_list_of_arrays", (std::vector< std::tuple<std::string, Opm::EclIO::eclArrType, long int> >
(Opm::EclIO::ERft::*)(int) const) &Opm::EclIO::ERft::listOfRftArrays)
.def("__get_list_of_arrays", (std::vector< std::tuple<std::string, Opm::EclIO::eclArrType, long int> >
(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<int,int,int>&) const) &Opm::EclIO::ERft::hasArray)
.def("__len__", &Opm::EclIO::ERft::numberOfReports);
}
+1
View File
@@ -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
+63
View File
@@ -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)
Binary file not shown.
+177
View File
@@ -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()