new python bindings class EModel

This commit is contained in:
Torbjørn Skille
2021-04-11 09:11:35 +02:00
parent 7a372c2a43
commit 94e541ad60
11 changed files with 926 additions and 3 deletions

106
python/cxx/emodel_util.cpp Normal file
View File

@@ -0,0 +1,106 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <opm/utility/EModel.hpp>
#include "export.hpp"
#include "converters.hpp"
#include <opm/common/utility/numeric/calculateCellVol.hpp>
namespace py = pybind11;
namespace {
using EclEntry = std::tuple<std::string, Opm::EclIO::eclArrType, int>;
Opm::EclIO::eclArrType getArrayType(EModel * file_ptr, std::string key){
std::vector<std::string> inteVect = {"I", "J", "K", "ROW", "COLUMN", "LAYER"};
if(std::find(inteVect.begin(), inteVect.end(), key) != inteVect.end()) {
return Opm::EclIO::INTE;
}
auto arrayList = file_ptr->getListOfParameters();
size_t n = 0;
while (n < arrayList.size() ){
if (std::get<0>(arrayList[n]) == key){
return std::get<1>(arrayList[n]);
}
n++;
}
throw std::logic_error("Array not found in EModel");
}
py::array get_param(EModel * file_ptr, std::string key)
{
Opm::EclIO::eclArrType arrType = getArrayType(file_ptr, key);
if (arrType == Opm::EclIO::REAL){
std::vector<float> vect = file_ptr->getParam<float>(key);
return py::array(py::dtype("f"), {vect.size()}, {}, &vect[0]);
} else if (arrType == Opm::EclIO::INTE){
std::vector<int> vect = file_ptr->getParam<int>(key);
return py::array(py::dtype("i"), {vect.size()}, {}, &vect[0]);
} else
throw std::logic_error("Data type not supported");
}
void add_int_filter_1value(EModel * file_ptr, std::string key, std::string opr, int value)
{
file_ptr->addFilter<int>(key, opr, value);
}
void add_float_filter_1value(EModel * file_ptr, std::string key, std::string opr, float value)
{
file_ptr->addFilter<float>(key, opr, value);
}
void add_int_filter_2values(EModel * file_ptr, std::string key, std::string opr, int value1, int value2)
{
file_ptr->addFilter<int>(key, opr, value1, value2);
}
void add_float_filter_2values(EModel * file_ptr, std::string key, std::string opr, float value1, float value2)
{
file_ptr->addFilter<float>(key, opr, value1, value2);
}
} // name space
void python::common::export_EModel(py::module& m) {
m.def("calc_cell_vol",calculateCellVol);
py::class_<EModel>(m, "EModel")
.def(py::init<const std::string &>())
.def("__contains__", &EModel::hasParameter)
.def("grid_dims", &EModel::gridDims)
.def("active_cells", &EModel::getNumberOfActiveCells)
.def("set_depth_fwl", &EModel::setDepthfwl)
.def("add_hc_filter", &EModel::addHCvolFilter)
.def("get_list_of_arrays", &EModel::getListOfParameters)
.def("active_report_step", &EModel::getActiveReportStep)
.def("get_report_steps", &EModel::getListOfReportSteps)
.def("has_report_step", &EModel::hasReportStep)
.def("set_report_step", &EModel::setReportStep)
.def("reset_filter", &EModel::resetFilter)
.def("get", &get_param)
.def("__add_filter", &add_int_filter_1value)
.def("__add_filter", &add_float_filter_1value)
.def("__add_filter", &add_int_filter_2values)
.def("__add_filter", &add_float_filter_2values);
}

View File

@@ -19,6 +19,7 @@ void python::common::export_all(py::module& module) {
export_UnitSystem(module);
export_Log(module);
export_IO(module);
export_EModel(module);
export_SummaryState(module);
export_ParserKeywords(module);
}

View File

@@ -30,6 +30,7 @@ void export_TableManager(py::module& module);
void export_Well(py::module& module);
void export_Log(py::module& module);
void export_IO(py::module& module);
void export_EModel(py::module& module);
void export_SummaryState(py::module& module);
// The export_ParserKeywords() function is implemented in the source file

View File

@@ -26,6 +26,8 @@ from .libopmcommon_python import ESmry
from .libopmcommon_python import EGrid
from .libopmcommon_python import ERft
from .libopmcommon_python import EclOutput
from .libopmcommon_python import EModel
from .libopmcommon_python import calc_cell_vol
from .libopmcommon_python import SummaryState
#from .schedule import Well, Connection, Schedule

View File

@@ -0,0 +1,34 @@
from __future__ import absolute_import
from opm._common import EModel, eclArrType
from opm._common import calc_cell_vol
def emodel_add_filter(self, key, operator, val1, val2 = None):
if key in ["I", "J", "K", "ROW", "COLUMN", "LAYER"]:
arrType=eclArrType.INTE
else:
arrList = self.get_list_of_arrays()
arrNameList = [item[0] for item in arrList]
arrTypeList = [item[1] for item in arrList]
if key not in arrNameList:
raise ValueError("{} array not found in EModel".format(key))
ind = arrNameList.index(key)
arrType = arrTypeList[ind]
if not val2:
if arrType == eclArrType.INTE:
self.__add_filter(key, operator, int(val1))
elif arrType == eclArrType.REAL:
self.__add_filter(key, operator, float(val1))
else:
if arrType == eclArrType.INTE:
self.__add_filter(key, operator, int(val1), int(val2))
elif arrType == eclArrType.REAL:
self.__add_filter(key, operator, float(val1), float(val2))
setattr(EModel, "add_filter", emodel_add_filter)

View File

@@ -60,8 +60,9 @@ ext_modules = [
'cxx/summary_state.cpp',
'cxx/table_manager.cpp',
'cxx/well.cpp',
'cxx/export.cpp',
'cxx/builtin_pybind11.cpp'
'cxx/emodel_util.cpp',
'cxx/builtin_pybind11.cpp',
'cxx/export.cpp'
],
libraries=libs,
language='c++',
@@ -92,7 +93,8 @@ setup(
'opm.io.parser',
'opm.io.schedule',
'opm.io.ecl',
'opm.tools'
'opm.tools',
'opm.util'
],
ext_modules=ext_modules,
include_package_data=True,

Binary file not shown.

184
python/tests/test_emodel.py Executable file
View File

@@ -0,0 +1,184 @@
import unittest
import sys
import numpy as np
from opm.util import EModel
try:
from tests.utils import test_path
except ImportError:
from utils import test_path
class TestEModel(unittest.TestCase):
def test_open_model(self):
refArrList = ["PORV", "CELLVOL", "DEPTH", "DX", "DY", "DZ", "PORO", "PERMX", "PERMY", "PERMZ", "NTG", "TRANX",
"TRANY", "TRANZ", "ACTNUM", "ENDNUM", "EQLNUM", "FIPNUM", "FLUXNUM", "IMBNUM", "PVTNUM",
"SATNUM", "SWL", "SWCR", "SGL", "SGU", "ISWL", "ISWCR", "ISGL", "ISGU", "PPCW", "PRESSURE",
"RS", "RV", "SGAS", "SWAT", "SOMAX", "SGMAX"]
self.assertRaises(RuntimeError, EModel, "/file/that/does_not_exists")
self.assertRaises(ValueError, EModel, test_path("data/9_EDITNNC.EGRID"))
self.assertRaises(ValueError, EModel, test_path("data/9_EDITNNC.UNRST"))
mod1 = EModel(test_path("data/9_EDITNNC.INIT"))
arrayList = mod1.get_list_of_arrays()
for n, element in enumerate(arrayList):
self.assertEqual(element[0], refArrList[n])
celvol1 = mod1.get("CELLVOL")
self.assertEqual(len(celvol1), 2794)
def test_add_filter(self):
mod1 = EModel(test_path("data/9_EDITNNC.INIT"))
celvol1 = mod1.get("CELLVOL")
depth1 = mod1.get("DEPTH")
self.assertTrue(isinstance(celvol1, np.ndarray))
self.assertEqual(celvol1.dtype, "float32")
refVol1 = 2.79083e8
self.assertTrue( abs((sum(celvol1) - refVol1)/refVol1) < 1.0e-5)
mod1.add_filter("EQLNUM","eq", 1);
mod1.add_filter("DEPTH","lt", 2645.21);
refVol2 = 1.08876e8
refPorvVol2 = 2.29061e7
porv2 = mod1.get("PORV")
celvol2 = mod1.get("CELLVOL")
self.assertTrue( abs((sum(celvol2) - refVol2)/refVol2) < 1.0e-5)
self.assertTrue( abs((sum(porv2) - refPorvVol2)/refPorvVol2) < 1.0e-5)
mod1.reset_filter()
mod1.add_filter("EQLNUM","eq", 2);
mod1.add_filter("DEPTH","in", 2584.20, 2685.21);
refPorvVol3 = 3.34803e7
porv3 = mod1.get("PORV")
self.assertTrue( abs((sum(porv3) - refPorvVol3)/refPorvVol3) < 1.0e-5)
mod1.reset_filter()
mod1.add_filter("I","lt", 10);
mod1.add_filter("J","between", 3, 15);
mod1.add_filter("K","between", 2, 9);
poro = mod1.get("PORO")
self.assertEqual(len(poro), 495)
def test_paramers(self):
mod1 = EModel(test_path("data/9_EDITNNC.INIT"))
self.assertFalse("XXX" in mod1)
self.assertTrue("PORV" in mod1)
self.assertTrue("PRESSURE" in mod1)
self.assertTrue("RS" in mod1)
self.assertTrue("RV" in mod1)
self.assertEqual(mod1.active_report_step(), 0)
rsteps = mod1.get_report_steps()
self.assertEqual(rsteps, [0, 4, 7, 10, 15, 20, 27, 32, 36, 39])
mod1.set_report_step(7)
# parameter RS and RV is missing in report step number 7
self.assertFalse("RS" in mod1)
self.assertFalse("RV" in mod1)
mod1.set_report_step(15)
self.assertTrue("RS" in mod1)
self.assertTrue("RV" in mod1)
arrayList = mod1.get_list_of_arrays()
def test_rsteps_steps(self):
pres_ref_4_1_10 = [272.608, 244.461, 228.503, 214.118, 201.147, 194.563, 178.02, 181.839, 163.465, 148.677]
mod1 = EModel(test_path("data/9_EDITNNC.INIT"))
mod1.add_filter("I","eq", 4);
mod1.add_filter("J","eq", 1);
mod1.add_filter("K","eq", 10);
self.assertTrue(mod1.has_report_step(4))
self.assertFalse(mod1.has_report_step(2))
rsteps = mod1.get_report_steps()
for n, step in enumerate(rsteps):
mod1.set_report_step(step)
pres = mod1.get("PRESSURE")
self.assertTrue(abs(pres[0] - pres_ref_4_1_10[n])/pres_ref_4_1_10[n] < 1.0e-5)
def test_grid_props(self):
mod1 = EModel(test_path("data/9_EDITNNC.INIT"))
nI,nJ,nK = mod1.grid_dims()
self.assertEqual((nI,nJ,nK), (13, 22, 11))
nAct = mod1.active_cells()
self.assertEqual(nAct, 2794)
def test_hc_filter(self):
nAct_hc_eqln1 = 1090
nAct_hc_eqln2 = 1694
mod1 = EModel(test_path("data/9_EDITNNC.INIT"))
porv = mod1.get("PORV")
mod1.set_depth_fwl([2645.21, 2685.21])
mod1.add_hc_filter()
porv = mod1.get("PORV")
self.assertEqual(len(porv), nAct_hc_eqln1 + nAct_hc_eqln2)
mod1.reset_filter()
mod1.add_filter("EQLNUM","eq", 1);
mod1.add_filter("DEPTH","lt", 2645.21);
porv1 = mod1.get("PORV")
self.assertEqual(len(porv1), nAct_hc_eqln1)
mod1.reset_filter()
mod1.add_filter("EQLNUM","eq", 2);
mod1.add_filter("DEPTH","lt", 2685.21);
porv2 = mod1.get("PORV")
self.assertEqual(len(porv2), nAct_hc_eqln2)
ivect = mod1.get("I")
if __name__ == "__main__":
unittest.main()