python binding for EclFile
This commit is contained in:
parent
0b8a42fd1f
commit
7cacc734e8
@ -273,6 +273,20 @@ if (OPM_ENABLE_PYTHON)
|
||||
add_custom_target(opmcommon_python ALL DEPENDS python/python/opm/${python_lib_target})
|
||||
add_dependencies(opmcommon_python opmcommon)
|
||||
|
||||
|
||||
add_custom_command(OUTPUT python/python/opm/python${PYTHON_VER}/libopmioecl_python.so
|
||||
DEPENDS
|
||||
python/cxx/eclipse_io.cpp
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/python/ ${CMAKE_BINARY_DIR}/python
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python/setup.py
|
||||
build
|
||||
build_ext
|
||||
--build-lib=${CMAKE_BINARY_DIR}/python/python/opm/python${PYTHON_VER}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/python
|
||||
COMMENT "Building more python bindings")
|
||||
|
||||
|
||||
|
||||
# The install target is based on manually copying the python file tree to the
|
||||
# installation area with a small installation script 'install.py'. Would have
|
||||
# preferred to use standard setup.py install, but the setup.py based solution
|
||||
|
73
python/cxx/eclipse_io.cpp
Normal file
73
python/cxx/eclipse_io.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/numpy.h>
|
||||
|
||||
#include <src/opm/io/eclipse/EclFile.cpp>
|
||||
#include <opm/io/eclipse/EclIOdata.hpp>
|
||||
#include <src/opm/io/eclipse/EclUtil.cpp>
|
||||
|
||||
#include <src/opm/common/OpmLog/OpmLog.cpp>
|
||||
#include <src/opm/common/OpmLog/LogBackend.cpp>
|
||||
#include <src/opm/common/OpmLog/LogUtil.cpp>
|
||||
#include <src/opm/common/OpmLog/StreamLog.cpp>
|
||||
#include <src/opm/common/OpmLog/Logger.cpp>
|
||||
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
class EclFileTmp : public Opm::EclIO::EclFile {
|
||||
|
||||
public:
|
||||
EclFileTmp(const std::string& filename): Opm::EclIO::EclFile(filename) {};
|
||||
|
||||
py::array_t<float> getFloatNumpy(int arrIndex) {
|
||||
std::vector<float> tmp=get<float>(arrIndex);
|
||||
return py::array(py::dtype("f"), {tmp.size()}, {}, &tmp[0]);
|
||||
};
|
||||
|
||||
py::array_t<double> getDoubleNumpy(int arrIndex) {
|
||||
std::vector<double> tmp=get<double>(arrIndex);
|
||||
return py::array(py::dtype("d"), {tmp.size()}, {}, &tmp[0]);
|
||||
};
|
||||
|
||||
py::array_t<int> getIntegerNumpy(int arrIndex) {
|
||||
std::vector<int> tmp=get<int>(arrIndex);
|
||||
return py::array(py::dtype("i"), {tmp.size()}, {}, &tmp[0]);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
PYBIND11_MODULE(libopmioecl_python, m) {
|
||||
|
||||
py::enum_<Opm::EclIO::eclArrType>(m, "eclArrType", py::arithmetic())
|
||||
.value("INTE", Opm::EclIO::INTE)
|
||||
.value("REAL", Opm::EclIO::REAL)
|
||||
.value("DOUB", Opm::EclIO::DOUB)
|
||||
.value("CHAR", Opm::EclIO::CHAR)
|
||||
.value("LOGI", Opm::EclIO::LOGI)
|
||||
.value("MESS", Opm::EclIO::MESS)
|
||||
.export_values();
|
||||
|
||||
py::class_<std::vector<std::tuple<std::string,Opm::EclIO::eclArrType,int>>>(m, "EclEntry")
|
||||
.def(py::init<>())
|
||||
.def("__len__", [](const std::vector<std::tuple<std::string,Opm::EclIO::eclArrType,int>> &v) { return v.size(); })
|
||||
.def("__getitem__", [](std::vector<std::tuple<std::string,Opm::EclIO::eclArrType,int>> &v, int item) { return v[item];})
|
||||
.def("__iter__", [](std::vector<std::tuple<std::string,Opm::EclIO::eclArrType,int>> &v) {
|
||||
return py::make_iterator(v.begin(), v.end());
|
||||
}, py::keep_alive<0, 1>());
|
||||
|
||||
|
||||
py::class_<EclFileTmp>(m, "EclFileBind")
|
||||
.def(py::init<const std::string &>())
|
||||
.def("getList", &EclFileTmp::getList)
|
||||
.def("hasKey", &EclFileTmp::hasKey)
|
||||
|
||||
.def("loadAllData", (void (EclFileTmp::*)(void)) &EclFileTmp::loadData)
|
||||
.def("loadDataByIndex", (void (EclFileTmp::*)(int)) &EclFileTmp::loadData)
|
||||
|
||||
.def("getRealFromIndexNumpy", &EclFileTmp::getFloatNumpy)
|
||||
.def("getDoubFromIndexNumpy", &EclFileTmp::getDoubleNumpy)
|
||||
.def("getInteFromIndexNumpy", &EclFileTmp::getIntegerNumpy)
|
||||
.def("getLogiFromIndex", (const std::vector<bool>& (EclFileTmp::*)(int)) &EclFileTmp::get<bool>)
|
||||
.def("getCharFromIndex", (const std::vector<std::string>& (EclFileTmp::*)(int)) &EclFileTmp::get<std::string>);
|
||||
}
|
@ -19,6 +19,7 @@ from .libopmcommon_python import Schedule
|
||||
from .libopmcommon_python import OpmLog
|
||||
from .libopmcommon_python import SummaryConfig
|
||||
|
||||
from .libopmioecl_python import EclFileBind, eclArrType
|
||||
|
||||
#from .schedule import Well, Connection, Schedule
|
||||
#from .config import EclipseConfig
|
||||
|
71
python/python/opm/io/ecl/__init__.py
Normal file
71
python/python/opm/io/ecl/__init__.py
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
from opm._common import EclFileBind, eclArrType
|
||||
|
||||
|
||||
class EclFile:
|
||||
|
||||
def __init__(self, fileName):
|
||||
self.name = fileName
|
||||
self.arrayNameList=[]
|
||||
self.arrayTypeList=[]
|
||||
|
||||
self.eclfile = EclFileBind(fileName)
|
||||
|
||||
arrayList = self.eclfile.getList()
|
||||
|
||||
for name, type, size in arrayList:
|
||||
self.arrayNameList.append(name)
|
||||
|
||||
if type==eclArrType.INTE:
|
||||
self.arrayTypeList.append(eclArrType.INTE)
|
||||
elif type==eclArrType.REAL:
|
||||
self.arrayTypeList.append(eclArrType.REAL)
|
||||
elif type==eclArrType.DOUB:
|
||||
self.arrayTypeList.append(eclArrType.DOUB)
|
||||
elif type==eclArrType.CHAR:
|
||||
self.arrayTypeList.append(eclArrType.CHAR)
|
||||
elif type==eclArrType.LOGI:
|
||||
self.arrayTypeList.append(eclArrType.LOGI)
|
||||
elif type==eclArrType.MESS:
|
||||
self.arrayTypeList.append(eclArrType.MESS)
|
||||
else:
|
||||
message = "Unknown array type: %s for array: '%s' in file %s" % (repr(type),name, fileName)
|
||||
raise NameError(message)
|
||||
|
||||
def getListOfArrays(self):
|
||||
return self.arrayNameList
|
||||
|
||||
def getNumArrays(self):
|
||||
return len(self.arrayNameList)
|
||||
|
||||
def hasArray(self, name):
|
||||
return self.eclfile.hasKey(name)
|
||||
|
||||
def get(self, arg):
|
||||
|
||||
try:
|
||||
ind = int(arg)
|
||||
except:
|
||||
if not arg in self.arrayNameList:
|
||||
message = "Array '%s' not found in file %s" % (arg,self.name)
|
||||
raise NameError(message)
|
||||
|
||||
ind = self.arrayNameList.index(arg)
|
||||
|
||||
self.eclfile.loadDataByIndex(ind)
|
||||
|
||||
if self.arrayTypeList[ind]==eclArrType.INTE:
|
||||
array=self.eclfile.getInteFromIndexNumpy(ind)
|
||||
elif self.arrayTypeList[ind]==eclArrType.REAL:
|
||||
array=self.eclfile.getRealFromIndexNumpy(ind)
|
||||
elif self.arrayTypeList[ind]==eclArrType.DOUB:
|
||||
array=self.eclfile.getDoubFromIndexNumpy(ind)
|
||||
elif self.arrayTypeList[ind]==eclArrType.LOGI:
|
||||
array=self.eclfile.getLogiFromIndex(ind)
|
||||
elif self.arrayTypeList[ind]==eclArrType.CHAR:
|
||||
array=self.eclfile.getCharFromIndex(ind)
|
||||
elif self.arrayTypeList[ind]==eclArrType.MESS:
|
||||
array=[]
|
||||
|
||||
return array
|
||||
|
@ -56,6 +56,18 @@ ext_modules = [
|
||||
undef_macros=["NDEBUG"],
|
||||
include_dirs=["pybind11/include"]
|
||||
),
|
||||
|
||||
Extension(
|
||||
'libopmioecl_python',
|
||||
[
|
||||
'cxx/eclipse_io.cpp',
|
||||
],
|
||||
libraries=['opmcommon', 'boost_filesystem', 'boost_regex'],
|
||||
language='c++',
|
||||
undef_macros=["NDEBUG"],
|
||||
include_dirs=["pybind11/include"]
|
||||
)
|
||||
|
||||
]
|
||||
|
||||
setup(
|
||||
@ -68,10 +80,11 @@ setup(
|
||||
'opm.io.ecl_state',
|
||||
'opm.io.parser',
|
||||
'opm.io.schedule',
|
||||
'opm.io.ecl',
|
||||
'opm.tools'
|
||||
],
|
||||
ext_modules=ext_modules,
|
||||
package_data={'opm': ['libopmcommon_python{}'.format(suffix)]},
|
||||
package_data={'opm': ['libopmcommon_python{}'.format(suffix), 'libopmioecl_python'.format(suffix)]},
|
||||
include_package_data=True,
|
||||
license='Open Source',
|
||||
zip_safe=False,
|
||||
|
BIN
python/tests/data/9_EDITNNC.INIT
Normal file
BIN
python/tests/data/9_EDITNNC.INIT
Normal file
Binary file not shown.
BIN
python/tests/data/9_EDITNNC.SMSPEC
Normal file
BIN
python/tests/data/9_EDITNNC.SMSPEC
Normal file
Binary file not shown.
BIN
python/tests/data/9_EDITNNC.UNSMRY
Normal file
BIN
python/tests/data/9_EDITNNC.UNSMRY
Normal file
Binary file not shown.
40860
python/tests/data/SPE9.FINIT
Normal file
40860
python/tests/data/SPE9.FINIT
Normal file
File diff suppressed because it is too large
Load Diff
BIN
python/tests/data/SPE9.INIT
Normal file
BIN
python/tests/data/SPE9.INIT
Normal file
Binary file not shown.
125
python/tests/test_eclfile.py
Executable file
125
python/tests/test_eclfile.py
Executable file
@ -0,0 +1,125 @@
|
||||
import unittest
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
from opm.io.ecl import EclFile
|
||||
|
||||
|
||||
class TestEclFile(unittest.TestCase):
|
||||
|
||||
def test_getListOfArrays(self):
|
||||
|
||||
refList=["INTEHEAD","LOGIHEAD","DOUBHEAD","PORV","DEPTH","DX","DY","DZ","PORO",
|
||||
"PERMX","PERMY", "PERMZ","NTG","TRANX","TRANY","TRANZ","TABDIMS","TAB",
|
||||
"ACTNUM","EQLNUM","FIPNUM","PVTNUM","SATNUM","TRANNNC"]
|
||||
|
||||
self.assertRaises(ValueError, EclFile, "/file/that/does_not_exists")
|
||||
|
||||
file2uf = EclFile("tests/data/SPE9.INIT")
|
||||
self.assertEqual(file2uf.getNumArrays(), 24)
|
||||
|
||||
arrList = file2uf.getListOfArrays()
|
||||
self.assertEqual(arrList, refList)
|
||||
|
||||
file2f = EclFile("tests/data/SPE9.FINIT")
|
||||
self.assertEqual(file2f.getNumArrays(), 24)
|
||||
|
||||
def test_get_function(self):
|
||||
|
||||
file1 = EclFile("tests/data/SPE9.INIT")
|
||||
|
||||
first = file1.get(0)
|
||||
self.assertEqual(len(first), 95)
|
||||
|
||||
# get fourth array in file SPE9.INIT which is PORV
|
||||
test1 = file1.get(3)
|
||||
test2 = file1.get("PORV")
|
||||
|
||||
for val1, val2 in zip(test1, test2):
|
||||
self.assertEqual(val1, val2)
|
||||
|
||||
def test_get_function_float(self):
|
||||
|
||||
file1 = EclFile("tests/data/SPE9.INIT")
|
||||
|
||||
dzList=[20.0, 15.0, 26.0, 15.0, 16.0, 14.0, 8.0, 8.0, 18.0, 12.0, 19.0, 18.0, 20.0, 50.0, 100.0]
|
||||
poroList = [0.087, 0.097, 0.111, 0.16, 0.13, 0.17, 0.17, 0.08, 0.14, 0.13, 0.12, 0.105, 0.12, 0.116, 0.157]
|
||||
ft3_to_bbl = 0.1781076
|
||||
|
||||
refporv = []
|
||||
|
||||
for poro, dz in zip(dzList, poroList):
|
||||
for i in range(0,600):
|
||||
refporv.append(300.0*300.0*dz*poro*ft3_to_bbl)
|
||||
|
||||
self.assertTrue(file1.hasArray("PORV"))
|
||||
porv_np = file1.get("PORV")
|
||||
|
||||
self.assertEqual(len(porv_np), 9000)
|
||||
|
||||
self.assertTrue(isinstance(porv_np, np.ndarray))
|
||||
self.assertEqual(porv_np.dtype, "float32")
|
||||
|
||||
porv_list = file1.get("PORV")
|
||||
|
||||
for val1, val2 in zip(porv_np, refporv):
|
||||
self.assertLess(abs(1.0 - val1/val2), 1e-6)
|
||||
|
||||
|
||||
def test_get_function_double(self):
|
||||
|
||||
refTabData=[0.147E+02, 0.2E+21, 0.4E+03, 0.2E+21, 0.8E+03, 0.2E+21, 0.12E+04, 0.2E+21, 0.16E+04, 0.2E+21, 0.2E+04, 0.2E+21, 0.24E+04, 0.2E+21, 0.28E+04, 0.2E+21, 0.32E+04, 0.2E+21, 0.36E+04, 0.2E+21, 0.4E+04, 0.5E+04, 0.1E+01, 0.2E+21, 0.98814229249012E+00, 0.2E+21, 0.97513408093613E+00]
|
||||
|
||||
file1 = EclFile("tests/data/SPE9.INIT")
|
||||
|
||||
tab = file1.get("TAB")
|
||||
|
||||
self.assertTrue(isinstance(tab, np.ndarray))
|
||||
self.assertEqual(tab.dtype, "float64")
|
||||
|
||||
for i in range(0, len(refTabData)):
|
||||
self.assertLess(abs(1.0 - refTabData[i]/tab[i]), 1e-12 )
|
||||
|
||||
|
||||
def test_get_function_integer(self):
|
||||
|
||||
refTabdims = [ 885, 1, 1, 1, 1, 1, 1, 67, 11, 2, 1, 78, 1, 78, 78, 0, 0, 0, 83, 1, 686, 40, 1, 86, 40, 1,
|
||||
286, 1, 80, 1 ]
|
||||
|
||||
file1 = EclFile("tests/data/SPE9.INIT")
|
||||
tabdims = file1.get("TABDIMS")
|
||||
|
||||
self.assertTrue(isinstance(tabdims, np.ndarray))
|
||||
self.assertEqual(tabdims.dtype, "int32")
|
||||
|
||||
for i in range(0, len(refTabdims)):
|
||||
self.assertEqual(refTabdims[i], tabdims[i])
|
||||
|
||||
|
||||
def test_get_function_logi(self):
|
||||
|
||||
file1 = EclFile("tests/data/9_EDITNNC.INIT")
|
||||
|
||||
self.assertTrue(file1.hasArray("LOGIHEAD"))
|
||||
logih = file1.get("LOGIHEAD")
|
||||
|
||||
self.assertEqual(len(logih), 121)
|
||||
self.assertEqual(logih[0], True)
|
||||
self.assertEqual(logih[2], False)
|
||||
self.assertEqual(logih[8], True)
|
||||
|
||||
def test_get_function_char(self):
|
||||
|
||||
file1 = EclFile("tests/data/9_EDITNNC.SMSPEC")
|
||||
|
||||
self.assertTrue(file1.hasArray("KEYWORDS"))
|
||||
keyw = file1.get("KEYWORDS")
|
||||
|
||||
self.assertEqual(len(keyw), 312)
|
||||
self.assertEqual(keyw[0], "TIME")
|
||||
self.assertEqual(keyw[16], "FWCT")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user