From 514e3a4a3536edbd66a22ade663377d845be97f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Skille?= Date: Sat, 21 Aug 2021 20:21:00 +0200 Subject: [PATCH] Adding python bindings for c++ class ExtESmry - Used for loading data from summary file ESMRY - python class ESmry supporting both SMSPEC/UNSMRY and ESMRY summary files. --- opm/io/eclipse/ExtESmry.hpp | 2 + python/cxx/eclipse_io.cpp | 138 ++++++++++++++++++++++++++++-------- python/opm/_common.py | 4 -- python/tests/test_esmry.py | 117 +++++++++++++++++++++++++++++- 4 files changed, 225 insertions(+), 36 deletions(-) diff --git a/opm/io/eclipse/ExtESmry.hpp b/opm/io/eclipse/ExtESmry.hpp index 067c7d816..3d93e9e7e 100644 --- a/opm/io/eclipse/ExtESmry.hpp +++ b/opm/io/eclipse/ExtESmry.hpp @@ -54,6 +54,8 @@ public: void loadData(); void loadData(const std::vector& stringVect); + time_point startdate() const { return m_startdat; } + bool hasKey(const std::string& key) const; size_t numberOfTimeSteps() const { return m_nTstep; } diff --git a/python/cxx/eclipse_io.cpp b/python/cxx/eclipse_io.cpp index 04a3ca4c8..d8833a211 100644 --- a/python/cxx/eclipse_io.cpp +++ b/python/cxx/eclipse_io.cpp @@ -2,15 +2,18 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include #include +#include #include @@ -25,6 +28,100 @@ namespace { using npArray = std::tuple; using EclEntry = std::tuple; +class ESmryBind { + +public: + + ESmryBind(const std::string& filename, bool loadBaseRunData) + { + filesystem::path m_inputFileName(filename); + + if (m_inputFileName.extension() == ".SMSPEC"){ + m_esmry = std::make_unique(m_inputFileName, loadBaseRunData); + } else if (m_inputFileName.extension()==".ESMRY") { + m_ext_esmry = std::make_unique(m_inputFileName, loadBaseRunData); + } else + throw std::invalid_argument("Input file should have extension .SMSPEC or .ESMRY"); + } + + bool hasKey(const std::string& key) + { + if (m_esmry != nullptr) + return m_esmry->hasKey(key); + else + return m_ext_esmry->hasKey(key); + } + + void make_esmry_file() + { + if (m_esmry == nullptr) + throw std::invalid_argument("make_esmry_file only available for SMSPEC input files"); + + m_esmry->make_esmry_file(); + } + + size_t numberOfTimeSteps() + { + if (m_esmry != nullptr) + return m_esmry->numberOfTimeSteps(); + else + return m_ext_esmry->numberOfTimeSteps(); + } + + py::array get_smry_vector(const std::string& key) + { + if (m_esmry != nullptr) + return convert::numpy_array( m_esmry->get(key) ); + else + return convert::numpy_array( m_ext_esmry->get(key) ); + } + + py::array get_smry_vector_at_rsteps(const std::string& key) + { + if (m_esmry != nullptr) + return convert::numpy_array( m_esmry->get_at_rstep(key) ); + else + return convert::numpy_array( m_ext_esmry->get_at_rstep(key) ); + } + + time_point smry_start_date() + { + time_point utc_chrono; + + if (m_esmry != nullptr) + utc_chrono = m_esmry->startdate(); + else + utc_chrono = m_ext_esmry->startdate(); + + auto utc_time_t = std::chrono::system_clock::to_time_t( utc_chrono ); + auto utc_ts = Opm::TimeStampUTC( utc_time_t ); + auto local_time_t = Opm::asLocalTimeT( utc_ts ); + return TimeService::from_time_t( local_time_t ); + } + + const std::vector& keywordList() const + { + if (m_esmry != nullptr) + return m_esmry->keywordList(); + else + return m_ext_esmry->keywordList(); + } + + std::vector keywordList(const std::string& pattern) const + { + if (m_esmry != nullptr) + return m_esmry->keywordList(pattern); + else + return m_ext_esmry->keywordList(pattern); + } + +private: + std::unique_ptr m_esmry; + std::unique_ptr m_ext_esmry; +}; + + + class EclOutputBind { public: @@ -166,18 +263,6 @@ npArray get_erst_vector(Opm::EclIO::ERst * file_ptr, const std::string& key, siz } -py::array get_smry_vector(Opm::EclIO::ESmry * file_ptr, const std::string& key) -{ - return convert::numpy_array( file_ptr->get(key) ); -} - - -py::array get_smry_vector_at_rsteps(Opm::EclIO::ESmry * file_ptr, const std::string& key) -{ - return convert::numpy_array( file_ptr->get_at_rstep(key) ); -} - - std::tuple, std::array, std::array> get_xyz_from_ijk(Opm::EclIO::EGrid * file_ptr,int i, int j, int k) { @@ -291,14 +376,6 @@ npArray get_rft_vector_Index(Opm::EclIO::ERft * file_ptr,const std::string& name the pybind11 conversion. */ -time_point esmry_start_date(const Opm::EclIO::ESmry * esmry) { - auto utc_chrono = esmry->startdate(); - auto utc_time_t = std::chrono::system_clock::to_time_t( utc_chrono ); - auto utc_ts = Opm::TimeStampUTC( utc_time_t ); - auto local_time_t = Opm::asLocalTimeT( utc_ts ); - return TimeService::from_time_t( local_time_t ); -} - } @@ -340,18 +417,19 @@ void python::common::export_IO(py::module& m) { .def("__get_data", &get_erst_by_index) .def("__get_data", &get_erst_vector); - py::class_(m, "ESmry") + py::class_(m, "ESmry") .def(py::init(), py::arg("filename"), py::arg("load_base_run") = false) - .def("__contains__", &Opm::EclIO::ESmry::hasKey) - .def("__len__", &Opm::EclIO::ESmry::numberOfTimeSteps) - .def("__get_all", &get_smry_vector) - .def("__get_at_rstep", &get_smry_vector_at_rsteps) - .def_property_readonly("start_date", &esmry_start_date) + .def("__contains__", &ESmryBind::hasKey) + .def("make_esmry_file", &ESmryBind::make_esmry_file) + .def("__len__", &ESmryBind::numberOfTimeSteps) + .def("__get_all", &ESmryBind::get_smry_vector) + .def("__get_at_rstep", &ESmryBind::get_smry_vector_at_rsteps) + .def_property_readonly("start_date", &ESmryBind::smry_start_date) + .def("keys", (const std::vector& (ESmryBind::*) (void) const) + &ESmryBind::keywordList) + .def("keys", (std::vector (ESmryBind::*) (const std::string&) const) + &ESmryBind::keywordList); - .def("keys", (const std::vector& (Opm::EclIO::ESmry::*) (void) const) - &Opm::EclIO::ESmry::keywordList) - .def("keys", (std::vector (Opm::EclIO::ESmry::*) (const std::string&) const) - &Opm::EclIO::ESmry::keywordList); py::class_(m, "EGrid") .def(py::init()) diff --git a/python/opm/_common.py b/python/opm/_common.py index 1e2483c3e..75b9c67ae 100644 --- a/python/opm/_common.py +++ b/python/opm/_common.py @@ -29,7 +29,3 @@ 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 -#from .config import EclipseConfig -#from .parser import parse, parse_string diff --git a/python/tests/test_esmry.py b/python/tests/test_esmry.py index 160f71baa..c6988c29a 100755 --- a/python/tests/test_esmry.py +++ b/python/tests/test_esmry.py @@ -10,15 +10,20 @@ except ImportError: from utils import test_path - class TestEclFile(unittest.TestCase): def test_base_runs(self): - with self.assertRaises(RuntimeError): + with self.assertRaises(ValueError): ESmry("/file/that/does_not_exists") smry1 = ESmry(test_path("data/SPE1CASE1.SMSPEC")) + smry1.make_esmry_file() + + smry2 = ESmry(test_path("data/SPE1CASE1.ESMRY")) + + with self.assertRaises(ValueError): + smry2.make_esmry_file() self.assertEqual(len(smry1), 67) self.assertEqual(smry1.start_date, datetime.datetime(2015,1,1) ) @@ -100,6 +105,114 @@ class TestEclFile(unittest.TestCase): for key, ref in zip(list_of_keys2, ref_keys_pattern): self.assertEqual(key, ref) + + def test_base_runs_ext(self): + + smry1 = ESmry(test_path("data/SPE1CASE1.SMSPEC")) + smry1.make_esmry_file() + + extsmry1 = ESmry(test_path("data/SPE1CASE1.ESMRY")) + + self.assertEqual(len(extsmry1), 67) + self.assertEqual(extsmry1.start_date, datetime.datetime(2015,1,1) ) + self.assertEqual(extsmry1.end_date, datetime.datetime(2020,4,29) ) + + self.assertTrue("TIME" in extsmry1) + self.assertTrue("BPR:10,10,3" in extsmry1) + self.assertFalse("XXXX" in extsmry1) + + with self.assertRaises(ValueError): + test = extsmry1["XXX"] + + time1a = extsmry1["TIME"] + + self.assertEqual(len(time1a), len(extsmry1)) + + time1b = extsmry1["TIME", True] + + self.assertEqual(len(time1b), 64) + + + def test_restart_runs_ext(self): + + base_smry = ESmry(test_path("data/SPE1CASE1.SMSPEC")) + base_smry.make_esmry_file() + + base_ext_smry = ESmry(test_path("data/SPE1CASE1.ESMRY")) + + time0 = base_ext_smry["TIME"] + self.assertEqual(time0[0], 1.0) + + rst_smry1 = ESmry(test_path("data/SPE1CASE1_RST60.SMSPEC")) + rst_smry1.make_esmry_file() + + rst_ext_smry1 = ESmry(test_path("data/SPE1CASE1_RST60.ESMRY")) + + time1 = rst_ext_smry1["TIME"] + gor1 = rst_ext_smry1["WGOR:PROD"] + + self.assertEqual(base_ext_smry.start_date, datetime.datetime(2015,1,1) ) + time0 = base_ext_smry["TIME"] + self.assertEqual(time0[0], 1.0) + + rst_ext_smry1 = ESmry(test_path("data/SPE1CASE1_RST60.ESMRY")) + time1 = rst_ext_smry1["TIME"] + gor1 = rst_ext_smry1["WGOR:PROD"] + + self.assertEqual(rst_smry1.start_date, datetime.datetime(2015,1,1) ) + self.assertEqual(len(rst_smry1), 60) + self.assertEqual(time1[0], 1856.0) + self.assertEqual(len(time1), 60) + self.assertEqual(len(gor1), 60) + + rst_ext_smry2 = ESmry(test_path("data/SPE1CASE1_RST60.ESMRY"), load_base_run = True) + time2 = rst_ext_smry2["TIME"] + gor2 = rst_ext_smry2["WGOR:PROD"] + + self.assertEqual(rst_ext_smry2.start_date, datetime.datetime(2015,1,1) ) + self.assertEqual(len(rst_ext_smry2), 123) + + self.assertEqual(time2[0], 1.0) + self.assertEqual(len(rst_ext_smry2), 123) + self.assertEqual(len(time2), 123) + self.assertEqual(len(gor2), 123) + + + def test_keylist_ext(self): + + ref_key_list = ["BPR:1,1,1", "BPR:10,10,3", "FGOR", "FOPR", "TIME", "WBHP:INJ", "WBHP:PROD", + "WGIR:INJ", "WGIR:PROD", "WGIT:INJ", "WGIT:PROD", "WGOR:PROD", "WGPR:INJ", + "WGPR:PROD", "WGPT:INJ", "WGPT:PROD", "WOIR:INJ", "WOIR:PROD", "WOIT:INJ", + "WOIT:PROD", "WOPR:INJ", "WOPR:PROD", "WOPT:INJ", "WOPT:PROD", "WWIR:INJ", + "WWIR:PROD", "WWIT:INJ", "WWIT:PROD", "WWPR:INJ", "WWPR:PROD", "WWPT:INJ", + "WWPT:PROD"] + + ref_keys_pattern = ["WGPR:INJ", "WGPR:PROD", "WOPR:INJ", "WOPR:PROD", "WWPR:INJ", "WWPR:PROD"] + + smry1 = ESmry(test_path("data/SPE1CASE1.SMSPEC")) + smry1.make_esmry_file() + + ext_smry1 = ESmry(test_path("data/SPE1CASE1.ESMRY")) + + list_of_keys = ext_smry1.keys() + self.assertEqual(len(list_of_keys), len(ref_key_list)) + + for key, ref_key in zip(list_of_keys, ref_key_list): + self.assertEqual(key, ref_key) + + for key in list_of_keys: + data = smry1[key] + self.assertEqual(len(smry1), len(data)) + + list_of_keys2 = ext_smry1.keys("W?PR:*") + + self.assertEqual(len(list_of_keys2), len(ref_keys_pattern)) + + for key, ref in zip(list_of_keys2, ref_keys_pattern): + self.assertEqual(key, ref) + + + if __name__ == "__main__": unittest.main()