From 070cebe84108519aea1ea83473396f2159c0ffe0 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Tue, 14 Jul 2026 08:28:04 +0200 Subject: [PATCH 01/20] Remove test that is not built This test was only set up to build on windows, but CI is not set up to run any tests on windows. --- lib/CMakeLists.txt | 7 ----- lib/resdata/tests/rd_lfs.cpp | 56 ------------------------------------ 2 files changed, 63 deletions(-) delete mode 100644 lib/resdata/tests/rd_lfs.cpp diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index cdc743e3c..0665ea574 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -384,13 +384,6 @@ add_test( ${CMAKE_CURRENT_SOURCE_DIR}/resdata/tests/data/num_cpu4 ${CMAKE_CURRENT_SOURCE_DIR}/resdata/tests/data/num_cpu5) -# The rd_win64 application is not built as a proper test integrated into the -# CTEST system. Should be invoked manually on Windows. -if(ERT_WINDOWS) - add_executable(rd_lfs resdata/tests/rd_lfs.cpp util/test_util.cpp) - target_link_libraries(rd_lfs resdata) -endif() - # # geometry # diff --git a/lib/resdata/tests/rd_lfs.cpp b/lib/resdata/tests/rd_lfs.cpp deleted file mode 100644 index 8b8bf925e..000000000 --- a/lib/resdata/tests/rd_lfs.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -int main(int argc, char **argv) { - int num_kw = 1000; // Total file size should roughly exceed 2GB - int kw_size = 600000; - rd_kw_type *kw = rd_kw_alloc("KW", kw_size, RD_INT); - int i; - offset_type file_size; - for (i = 0; i < kw_size; i++) - rd_kw_iset_int(kw, i, i); - - { - ERT::FortIO fortio("LARGE_FILE.UNRST", std::ios_base::out); - for (i = 0; i < num_kw; i++) { - printf("Writing keyword %d/%d to file:LARGE_FILE.UNRST \n", i + 1, - num_kw); - rd_kw_fwrite(kw, fortio); - } - } - - file_size = util_file_size("LARGE_FILE.UNRST"); - printf("File size: %lld \n", file_size); - { - ERT::FortIO fortio("LARGE_FILE.UNRST", std::ios_base::in); - printf("Seeking to file end: "); - fortio.fseek(file_size, SEEK_SET); - printf("Seek OK \n"); - } - - printf("Doing rd_file_open(..)\n"); - { - rd_file_type *file = rd_file_open("LARGE_FILE.UNRST", 0); - rd_kw_type *file_kw = rd_file_iget_named_kw(file, "KW", num_kw - 1); - if (rd_kw_equal(kw, file_kw)) - printf("Keyword read back from file correctly :-) \n"); - else - printf("Fatal error - keyword different on return ...\n"); - rd_file_close(file); - } - - remove("LARGE_FILE.UNRST"); - - exit(0); -} From b6582791c3229818bf50cb556bdc2bab5b97cff1 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 11:57:27 +0200 Subject: [PATCH 02/20] Use pybind for ResdataFileView --- lib/CMakeLists.txt | 1 + .../detail/resdata/cwrap_pybind.hpp | 2 + lib/resdata/rd_file_view_pybind.cpp | 90 +++++++++++++++++++ python/resdata/resfile/rd_file_view.py | 55 ++++-------- 4 files changed, 108 insertions(+), 40 deletions(-) create mode 100644 lib/resdata/rd_file_view_pybind.cpp diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 0665ea574..f6fa55939 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -210,6 +210,7 @@ add_resdata_pybind_module(_grid rd_grid_pybind.cpp resdata/grid) add_resdata_pybind_module(_kw rd_kw_pybind.cpp resdata/resfile) add_resdata_pybind_module(_rsthead rsthead_pybind.cpp resdata/resfile) add_resdata_pybind_module(_file rd_file_pybind.cpp resdata/resfile) +add_resdata_pybind_module(_file_view rd_file_view_pybind.cpp resdata/resfile) add_resdata_pybind_module(fortio fortio_pybind.cpp resdata/resfile) add_resdata_pybind_module(well well_pybind.cpp resdata) add_resdata_pybind_module(_subsidence rd_subsidence_pybind.cpp diff --git a/lib/private-include/detail/resdata/cwrap_pybind.hpp b/lib/private-include/detail/resdata/cwrap_pybind.hpp index 10d9500d8..c7ba862a4 100644 --- a/lib/private-include/detail/resdata/cwrap_pybind.hpp +++ b/lib/private-include/detail/resdata/cwrap_pybind.hpp @@ -21,3 +21,5 @@ inline void register_exceptions(pybind11::module &m) { } pybind11::object CTime(); +pybind11::object ResdataKW(); +pybind11::object ResdataFileView(); diff --git a/lib/resdata/rd_file_view_pybind.cpp b/lib/resdata/rd_file_view_pybind.cpp new file mode 100644 index 000000000..8f96879cd --- /dev/null +++ b/lib/resdata/rd_file_view_pybind.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +namespace py = pybind11; + +namespace { +py::object create_kw_reference(rd_kw_type *kw, py::handle parent) { + if (!kw) + return py::none(); + return ResdataKW().attr("createCReference")( + reinterpret_cast(kw), parent); +} + +py::object create_view_reference(rd_file_view_type *view, py::handle parent) { + if (!view) + return py::none(); + return ResdataFileView().attr("createCReference")( + reinterpret_cast(view), parent); +} +} // namespace + +PYBIND11_MODULE(_file_view, m) { + register_exceptions(m); + m.doc() = "pybind11 bindings for ResdataFileView"; + + m.def("_iget_kw", [](py::handle self, int index) { + return create_kw_reference( + rd_file_view_iget_kw(from_cwrap(self), index), + self); + }); + m.def("_iget_named_kw", [](py::handle self, std::string kw, int index) { + return create_kw_reference( + rd_file_view_iget_named_kw(from_cwrap(self), + kw.c_str(), index), + self); + }); + m.def("_get_unique_kw", [](py::handle self, int index) { + const char *kw = rd_file_view_iget_distinct_kw( + from_cwrap(self), index); + if (!kw) + return std::string(); + return std::string(kw); + }); + m.def("_get_size", [](py::handle self) { + return rd_file_view_get_size(from_cwrap(self)); + }); + m.def("_get_num_named_kw", [](py::handle self, std::string kw) { + return rd_file_view_get_num_named_kw( + from_cwrap(self), kw.c_str()); + }); + m.def("_get_unique_size", [](py::handle self) { + return rd_file_view_get_num_distinct_kw( + from_cwrap(self)); + }); + m.def("_create_block_view", [](py::handle self, std::string kw, int index) { + return create_view_reference( + rd_file_view_add_blockview(from_cwrap(self), + kw.c_str(), index), + self); + }); + m.def("_create_block_view2", + [](py::handle self, std::optional start_kw, + std::optional stop_kw, int index) { + return create_view_reference( + rd_file_view_add_blockview2( + from_cwrap(self), + start_kw ? start_kw->c_str() : nullptr, + stop_kw ? stop_kw->c_str() : nullptr, index), + self); + }); + m.def("_restart_view", + [](py::handle self, int seqnum_index, int report_step, + std::int64_t sim_time, double sim_days) { + return create_view_reference( + rd_file_view_add_restart_view( + from_cwrap(self), seqnum_index, + report_step, static_cast(sim_time), sim_days), + self); + }); +} diff --git a/python/resdata/resfile/rd_file_view.py b/python/resdata/resfile/rd_file_view.py index 28bc7817d..98467026f 100644 --- a/python/resdata/resfile/rd_file_view.py +++ b/python/resdata/resfile/rd_file_view.py @@ -1,43 +1,18 @@ from cwrap import BaseCClass from six import string_types -from resdata import ResdataPrototype +import resdata.resfile._file_view as _file_view from resdata.util.util import CTime class ResdataFileView(BaseCClass): TYPE_NAME = "rd_file_view" - _iget_kw = ResdataPrototype( - "rd_kw_ref rd_file_view_iget_kw( rd_file_view , int)" - ) - _iget_named_kw = ResdataPrototype( - "rd_kw_ref rd_file_view_iget_named_kw( rd_file_view , char* , int)" - ) - _get_unique_kw = ResdataPrototype( - "char* rd_file_view_iget_distinct_kw( rd_file_view, int )" - ) - _get_size = ResdataPrototype("int rd_file_view_get_size( rd_file_view )") - _get_num_named_kw = ResdataPrototype( - "int rd_file_view_get_num_named_kw( rd_file_view , char* )" - ) - _get_unique_size = ResdataPrototype( - "int rd_file_view_get_num_distinct_kw( rd_file_view )" - ) - _create_block_view = ResdataPrototype( - "rd_file_view_ref rd_file_view_add_blockview( rd_file_view , char*, int )" - ) - _create_block_view2 = ResdataPrototype( - "rd_file_view_ref rd_file_view_add_blockview2( rd_file_view , char*, char*, int )" - ) - _restart_view = ResdataPrototype( - "rd_file_view_ref rd_file_view_add_restart_view( rd_file_view , int, int, rd_time_t, double )" - ) def __init__(self): raise NotImplementedError("Can not instantiate directly") def __iget(self, index): - return self._iget_kw(index).setParent(parent=self) + return _file_view._iget_kw(self, index) def __repr__(self): return "ResdataFileView(size=%d) %s" % (len(self), self._ad_str()) @@ -49,7 +24,7 @@ def iget_named_kw(self, kw_name, index): if index >= self.num_keywords(kw_name): raise IndexError("Too large index: %d" % index) - return self._iget_named_kw(kw_name, index).setParent(parent=self) + return _file_view._iget_named_kw(self, kw_name, index) def __getitem__(self, index): """ @@ -111,7 +86,7 @@ def __getitem__(self, index): raise TypeError("Index must be integer or string (keyword)") def __len__(self): - return self._get_size() + return _file_view._get_size(self) def __contains__(self, kw): if self.num_keywords(kw) > 0: @@ -120,13 +95,16 @@ def __contains__(self, kw): return False def num_keywords(self, kw): - return self._get_num_named_kw(kw) + return _file_view._get_num_named_kw(self, kw) def unique_size(self): - return self._get_unique_size() + return _file_view._get_unique_size(self) def unique_kw(self): - return [self._get_unique_kw(index) for index in range(self.unique_size())] + return [ + _file_view._get_unique_kw(self, index) + for index in range(self.unique_size()) + ] def block_view2(self, start_kw, stop_kw, start_index): idx = start_index @@ -146,9 +124,7 @@ def block_view2(self, start_kw, stop_kw, start_index): if stop_kw not in self: raise KeyError("The keyword:%s is not in file" % stop_kw) - view = self._create_block_view2(start_kw, stop_kw, idx) - view.setParent(parent=self) - return view + return _file_view._create_block_view2(self, start_kw, stop_kw, idx) def block_view(self, kw, kw_index): num = self.num_keywords(kw) @@ -163,9 +139,7 @@ def block_view(self, kw, kw_index): if not (0 <= idx < num): raise IndexError("Index must be in [0, %d), was: %d." % (num, kw_index)) - view = self._create_block_view(kw, kw_index) - view.setParent(parent=self) - return view + return _file_view._create_block_view(self, kw, kw_index) def restart_view( self, seqnum_index=None, report_step=None, sim_time=None, sim_days=None @@ -182,9 +156,10 @@ def restart_view( if seqnum_index is None: seqnum_index = -1 - view = self._restart_view(seqnum_index, report_step, CTime(sim_time), sim_days) + view = _file_view._restart_view( + self, seqnum_index, report_step, CTime(sim_time).value(), sim_days + ) if view is None: raise ValueError("No such restart block could be identified") - view.setParent(parent=self) return view From 20b35f1d24d683471f291480f121d547f2a305ac Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 12:00:38 +0200 Subject: [PATCH 03/20] Remove extern "C" around rd_file_view.hpp --- lib/include/resdata/rd_file_view.hpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/lib/include/resdata/rd_file_view.hpp b/lib/include/resdata/rd_file_view.hpp index 09ae066e4..d4d58de01 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -1,10 +1,9 @@ -#ifndef ERT_RD_FILE_VIEW_H -#define ERT_RD_FILE_VIEW_H - +#pragma once #include #include #include #include +#include #include @@ -15,10 +14,6 @@ using inv_map_type = std::unordered_map; -#ifdef __cplusplus -extern "C" { -#endif - typedef enum { RD_FILE_CLOSE_STREAM = 1, /* This flag will close the underlying FILE object between each access; this is @@ -104,10 +99,6 @@ rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, int *flags, void rd_file_view_clear(rd_file_view_type *file_view); -#ifdef __cplusplus -} -#include - using rd_file_view_ptr = std::unique_ptr; @@ -116,6 +107,3 @@ rd_file_view_iget_file_kw(const rd_file_view_type *rd_file_view, int global_index); void rd_file_view_add_kw(rd_file_view_type *rd_file_view, std::shared_ptr file_kw); -#endif - -#endif From 13a5e929225ee890f33eda6a7278920aed28bb22 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 12:03:46 +0200 Subject: [PATCH 04/20] Use constructor for rd_file_view_alloc --- lib/resdata/rd_file_view.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index acd7f20ea..5793012be 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -33,6 +33,9 @@ struct rd_file_view_struct { *inv_map; /* Shared reference owned by the rd_file structure. */ std::vector> child_list; int *flags; + + rd_file_view_struct(ERT::FortIO *fortio, int *flags, inv_map_type *inv_map) + : fortio(fortio), inv_map(inv_map), flags(flags) {}; }; bool rd_file_view_check_flags(int state_flags, int query_flags) { @@ -53,13 +56,7 @@ const char *rd_file_view_get_src_file(const rd_file_view_type *file_view) { rd_file_view_type *rd_file_view_alloc(ERT::FortIO *fortio, int *flags, inv_map_type *inv_map) { - rd_file_view_type *rd_file_view = new rd_file_view_type(); - - rd_file_view->fortio = fortio; - rd_file_view->inv_map = inv_map; - rd_file_view->flags = flags; - - return rd_file_view; + return new rd_file_view_struct(fortio, flags, inv_map); } static int rd_file_view_get_global_index(const rd_file_view_type *rd_file_view, From f27afba6f54c0f06e9e05bda4262a222c143b963 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 12:06:32 +0200 Subject: [PATCH 05/20] Use std::string for iget_distinct_kw --- lib/include/resdata/rd_file_view.hpp | 5 +++-- lib/resdata/rd_file_view.cpp | 8 ++++---- lib/resdata/rd_file_view_pybind.cpp | 5 +---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/include/resdata/rd_file_view.hpp b/lib/include/resdata/rd_file_view.hpp index d4d58de01..31df1856d 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -43,8 +44,8 @@ void rd_file_view_index_fload_kw(const rd_file_view_type *rd_file_view, const char *kw, int index, const int_vector_type *index_map, char *buffer); -const char *rd_file_view_iget_distinct_kw(const rd_file_view_type *rd_file_view, - int index); +const std::string & +rd_file_view_iget_distinct_kw(const rd_file_view_type *rd_file_view, int index); int rd_file_view_get_num_distinct_kw(const rd_file_view_type *rd_file_view); int rd_file_view_get_size(const rd_file_view_type *rd_file_view); rd_kw_type *rd_file_view_iget_named_kw(const rd_file_view_type *rd_file_view, diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index 5793012be..0874c46ad 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -183,10 +183,10 @@ static int rd_file_view_find_kw_value(const rd_file_view_type *rd_file_view, return global_index; } -const char *rd_file_view_iget_distinct_kw(const rd_file_view_type *rd_file_view, - int index) { - const std::string &string = rd_file_view->distinct_kw[index]; - return string.c_str(); +const std::string & +rd_file_view_iget_distinct_kw(const rd_file_view_type *rd_file_view, + int index) { + return rd_file_view->distinct_kw[index]; } int rd_file_view_get_num_distinct_kw(const rd_file_view_type *rd_file_view) { diff --git a/lib/resdata/rd_file_view_pybind.cpp b/lib/resdata/rd_file_view_pybind.cpp index 8f96879cd..e55d84e71 100644 --- a/lib/resdata/rd_file_view_pybind.cpp +++ b/lib/resdata/rd_file_view_pybind.cpp @@ -45,11 +45,8 @@ PYBIND11_MODULE(_file_view, m) { self); }); m.def("_get_unique_kw", [](py::handle self, int index) { - const char *kw = rd_file_view_iget_distinct_kw( + return rd_file_view_iget_distinct_kw( from_cwrap(self), index); - if (!kw) - return std::string(); - return std::string(kw); }); m.def("_get_size", [](py::handle self) { return rd_file_view_get_size(from_cwrap(self)); From 733d47e6ae76567fdfcafc08c053be87b2ee1ca3 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 12:07:37 +0200 Subject: [PATCH 06/20] Simplify check_flags --- lib/resdata/rd_file_view.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index 0874c46ad..18504a324 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -39,10 +39,7 @@ struct rd_file_view_struct { }; bool rd_file_view_check_flags(int state_flags, int query_flags) { - if ((state_flags & query_flags) == query_flags) - return true; - else - return false; + return (state_flags & query_flags) == query_flags; } bool rd_file_view_flags_set(const rd_file_view_type *file_view, From 32fb6e20cd6aa999b621e762aac88a8c04f39e01 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 12:10:24 +0200 Subject: [PATCH 07/20] Change util_abort to thrown exception --- lib/resdata/rd_file_view.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index 18504a324..2f6294d3a 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -248,15 +249,13 @@ static int rd_file_view_iget_occurence(const rd_file_view_type *rd_file_view, const auto &index_vector = rd_file_view->kw_index.at(header); int occurence = -1; - { - /* Manual reverse lookup. */ - for (size_t i = 0; i < index_vector.size(); i++) { - if (index_vector[i] == global_index) - occurence = i; - } + for (size_t i = 0; i < index_vector.size(); i++) { + if (index_vector[i] == global_index) + occurence = i; } if (occurence < 0) - util_abort("%s: internal error ... \n", __func__); + throw std::out_of_range( + fmt::format("Could not find index {}", global_index)); return occurence; } From 79f77b28e4493e0ab68efd699936e30bad2adcc2 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 12:14:00 +0200 Subject: [PATCH 08/20] Remove unnecessary comments --- lib/resdata/rd_file_view.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index 2f6294d3a..5584bc6d8 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -596,17 +596,14 @@ static bool rd_file_view_has_sim_days(const rd_file_view_type *rd_file_view, double file_sim_days = rd_file_view_iget_restart_sim_days( rd_file_view, doubhead_index); - if (util_double_approx_equal(sim_days, - file_sim_days)) /* Perfect hit. */ + if (util_double_approx_equal(sim_days, file_sim_days)) return true; - if (file_sim_days > - sim_days) /* We have gone past the target_time - i.e. we do not have it. */ + if (file_sim_days > sim_days) return false; doubhead_index++; - if (doubhead_index == - num_DOUBHEAD) /* We have iterated through the whole thing without finding sim_time. */ + if (doubhead_index == num_DOUBHEAD) return false; } } From 5e98736e8a556328cd32a875b8a7477f7203a811 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 12:14:34 +0200 Subject: [PATCH 09/20] Inline sim --- lib/resdata/rd_file_view.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index 5584bc6d8..3a115b2b8 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -623,8 +623,7 @@ rd_file_view_seqnum_index_from_sim_time(rd_file_view_type *parent_map, if (!seqnum_map) continue; - bool sim = rd_file_view_has_sim_time(seqnum_map.get(), sim_time); - if (sim) + if (rd_file_view_has_sim_time(seqnum_map.get(), sim_time)) return s_idx; } return -1; From 1a80cea28f3977ee9bd4aac9a0eb5447b8d9286c Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 12:38:15 +0200 Subject: [PATCH 10/20] Fixed misspelled PARALLEL --- python/resdata/rd_util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/resdata/rd_util.py b/python/resdata/rd_util.py index 686487c91..5f8195a72 100644 --- a/python/resdata/rd_util.py +++ b/python/resdata/rd_util.py @@ -109,8 +109,8 @@ def get_num_cpu(datafile): """ Parse ECLIPSE datafile and determine how many CPUs are needed. - Will look for the "PARALLELL" keyword, and then read off the - number of CPUs required. Will return one if no PARALLELL keyword + Will look for the "PARALLEL" keyword, and then read off the + number of CPUs required. Will return one if no PARALLEL keyword is found. """ return ResdataUtil._get_num_cpu(datafile) From d8a0bdade3338bce6f081eb40c5d7678b7ca479e Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 13:00:38 +0200 Subject: [PATCH 11/20] Use pybind for FileMode enum Also introduces a default argument to rd_file_open to avoid calling it with flags=0 repeatedly. --- applications/resdata/rd_pack.cpp | 3 +- applications/resdata/rd_unpack.cpp | 2 +- lib/CMakeLists.txt | 1 + lib/include/resdata/rd_file.hpp | 22 +++---- lib/include/resdata/rd_file_flag.hpp | 51 ++++++++++++++ lib/include/resdata/rd_file_view.hpp | 29 +++----- lib/include/resdata/rd_sum.hpp | 9 ++- lib/include/resdata/rd_sum_data.hpp | 3 +- .../detail/resdata/rd_sum_file_data.hpp | 9 ++- .../detail/resdata/rd_unsmry_loader.hpp | 6 +- lib/resdata/file_mode_pybind.cpp | 29 ++++++++ lib/resdata/rd_file.cpp | 30 ++++----- lib/resdata/rd_file_pybind.cpp | 5 +- lib/resdata/rd_file_view.cpp | 27 ++++---- lib/resdata/rd_grid.cpp | 4 +- lib/resdata/rd_smspec.cpp | 2 +- lib/resdata/rd_sum.cpp | 16 ++--- lib/resdata/rd_sum_data.cpp | 13 ++-- lib/resdata/rd_sum_file_data.cpp | 30 +++++++-- lib/resdata/rd_sum_pybind.cpp | 5 +- lib/resdata/rd_unsmry_loader.cpp | 17 +++-- lib/resdata/tests/rd_coarse_test.cpp | 4 +- lib/resdata/tests/rd_dualp.cpp | 9 +-- lib/resdata/tests/rd_file.cpp | 14 ++-- lib/resdata/tests/rd_file_equinor.cpp | 20 +++--- lib/resdata/tests/rd_grid_dx_dy_dz.cpp | 2 +- lib/resdata/tests/rd_grid_export.cpp | 2 +- lib/resdata/tests/rd_grid_init_fwrite.cpp | 4 +- lib/resdata/tests/rd_grid_volume.cpp | 2 +- lib/resdata/tests/rd_lgr_test.cpp | 2 +- lib/resdata/tests/rd_nnc_test.cpp | 2 +- lib/resdata/tests/rd_restart_test.cpp | 2 +- lib/resdata/tests/rd_rsthead.cpp | 2 +- lib/resdata/tests/rdxx_kw.cpp | 2 +- lib/resdata/tests/test_rd_file_index.cpp | 6 +- lib/resdata/tests/well_conn_CF.cpp | 2 +- lib/resdata/tests/well_dualp.cpp | 2 +- lib/resdata/tests/well_segment_load.cpp | 2 +- lib/resdata/tests/well_state_load.cpp | 2 +- .../tests/well_state_load_missing_RSEG.cpp | 2 +- lib/resdata/well_info.cpp | 11 ++-- lib/resdata/well_rseg_loader.cpp | 8 +-- lib/tests/test_geertsma.cpp | 20 +++--- lib/tests/test_rd_sum.cpp | 13 ++-- lib/tests/test_well_info.cpp | 2 +- python/resdata/rd_util.py | 36 ++++------ python/resdata/summary/rd_sum.py | 13 ++-- tests/test_file_mode.py | 66 +++++++++++++++++++ 48 files changed, 359 insertions(+), 206 deletions(-) create mode 100644 lib/include/resdata/rd_file_flag.hpp create mode 100644 lib/resdata/file_mode_pybind.cpp create mode 100644 tests/test_file_mode.py diff --git a/applications/resdata/rd_pack.cpp b/applications/resdata/rd_pack.cpp index 85deca698..0bb5312b9 100644 --- a/applications/resdata/rd_pack.cpp +++ b/applications/resdata/rd_pack.cpp @@ -90,8 +90,7 @@ int main(int argc, char **argv) { filelist.at(i - 1).c_str(), filelist.at(i).c_str()); prev_report_step = report_step; - rd_file_ptr src_file(rd_file_open(filelist.at(i).c_str(), 0), - &rd_file_close); + rd_file_ptr src_file = open_rd_file(filelist.at(i)); if (target_type == RD_UNIFIED_RESTART_FILE) { /* Must insert the SEQNUM keyword first. */ rd_kw_iset_int(seqnum_kw.get(), 0, report_step); diff --git a/applications/resdata/rd_unpack.cpp b/applications/resdata/rd_unpack.cpp index 798b383f1..96d6d2ff1 100644 --- a/applications/resdata/rd_unpack.cpp +++ b/applications/resdata/rd_unpack.cpp @@ -44,7 +44,7 @@ static void unpack_file(const fs::path &filepath) { printf("** Warning: when unpacking unified summary files it as " "ambigous - starting with 0001 -> \n"); } - rd_file_ptr src_file(rd_file_open(filename.c_str(), 0), &rd_file_close); + rd_file_ptr src_file = open_rd_file(filename); int size; int offset; int report_step = 0; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f6fa55939..baf26dba1 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -218,6 +218,7 @@ add_resdata_pybind_module(_subsidence rd_subsidence_pybind.cpp add_resdata_pybind_module(_grav rd_grav_pybind.cpp resdata/gravimetry) add_resdata_pybind_module(_rd_sum rd_sum_pybind.cpp resdata/summary) add_resdata_pybind_module(_type rd_type_pybind.cpp resdata/types) +add_resdata_pybind_module(_file_mode file_mode_pybind.cpp resdata) if(NOT BUILD_TESTS) return() diff --git a/lib/include/resdata/rd_file.hpp b/lib/include/resdata/rd_file.hpp index 2727c3009..5aebf6d43 100644 --- a/lib/include/resdata/rd_file.hpp +++ b/lib/include/resdata/rd_file.hpp @@ -6,24 +6,20 @@ #include #include -#include #include #include #include -#include +#include #include "ert/util/type_macros.hpp" -#define RD_FILE_FLAGS_ENUM_DEFS \ - {.value = 1, .name = "RD_FILE_CLOSE_STREAM"}, \ - {.value = 2, .name = "RD_FILE_WRITABLE"} -#define RD_FILE_FLAGS_ENUM_SIZE 2 - typedef struct rd_file_struct rd_file_type; bool rd_file_load_all(rd_file_type *rd_file); -rd_file_type *rd_file_open(const char *filename, int flags); +rd_file_type *rd_file_open(const char *filename, + FileMode flags = FileMode::DEFAULT); rd_file_type *rd_file_fast_open(const char *filename, - const char *index_filename, int flags); + const char *index_filename, + FileMode flags = FileMode::DEFAULT); bool rd_file_write_index(const rd_file_type *rd_file, const char *index_filename); bool rd_file_index_valid(const char *file_name, const char *index_file_name); @@ -40,7 +36,7 @@ void rd_file_fwrite_fortio(const rd_file_type *ec_file, ERT::FortIO &fortio, int rd_file_get_phases(const rd_file_type *init_file); bool rd_file_writable(const rd_file_type *rd_file); -bool rd_file_flags_set(const rd_file_type *rd_file, int flags); +bool rd_file_flags_set(const rd_file_type *rd_file, FileMode flags); rd_kw_type *rd_file_iget_kw(const rd_file_type *file, int global_index); rd_kw_type *rd_file_iget_named_kw(const rd_file_type *file, const char *kw, @@ -76,9 +72,11 @@ bool rd_file_subselect_block(rd_file_type *rd_file, const char *kw, using rd_file_ptr = std::unique_ptr; -inline rd_file_ptr open_rd_file(const std::string &path, int flags) { +inline rd_file_ptr open_rd_file(const std::string &path, + FileMode flags = FileMode::DEFAULT) { return {rd_file_open(path.c_str(), flags), &rd_file_close}; } -inline rd_file_ptr open_rd_file(const std::filesystem::path &path, int flags) { +inline rd_file_ptr open_rd_file(const std::filesystem::path &path, + FileMode flags = FileMode::DEFAULT) { return {rd_file_open(path.string().c_str(), flags), &rd_file_close}; } diff --git a/lib/include/resdata/rd_file_flag.hpp b/lib/include/resdata/rd_file_flag.hpp new file mode 100644 index 000000000..3831a1f50 --- /dev/null +++ b/lib/include/resdata/rd_file_flag.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include + +enum class FileMode : int { + DEFAULT = 0, + CLOSE_STREAM = + 1, /* This flag will close the underlying FILE object between each access; + this is mainly to save filedescriptors in cases where many rd_file + instances are open at the same time. */ + WRITABLE = + 2 /* This flag opens the file in a mode where it can be updated and modified, + but it must still exist and be readable. I.e. this should not compared + with the normal: fopen(filename , "w") where an existing file is + truncated to zero upon successfull open. */ +}; + +constexpr FileMode operator|(FileMode lhs, FileMode rhs) { + using T = std::underlying_type_t; + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +constexpr FileMode operator&(FileMode lhs, FileMode rhs) { + using T = std::underlying_type_t; + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + +constexpr FileMode operator^(FileMode lhs, FileMode rhs) { + using T = std::underlying_type_t; + return static_cast(static_cast(lhs) ^ static_cast(rhs)); +} + +constexpr FileMode operator~(FileMode value) { + using T = std::underlying_type_t; + return static_cast(~static_cast(value)); +} + +constexpr FileMode &operator|=(FileMode &lhs, FileMode rhs) { + lhs = lhs | rhs; + return lhs; +} + +constexpr FileMode &operator&=(FileMode &lhs, FileMode rhs) { + lhs = lhs & rhs; + return lhs; +} + +constexpr FileMode &operator^=(FileMode &lhs, FileMode rhs) { + lhs = lhs ^ rhs; + return lhs; +} diff --git a/lib/include/resdata/rd_file_view.hpp b/lib/include/resdata/rd_file_view.hpp index 31df1856d..343346567 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include #include #include @@ -10,31 +9,18 @@ #include #include -#include #include +#include using inv_map_type = std::unordered_map; -typedef enum { - RD_FILE_CLOSE_STREAM = 1, /* - This flag will close the underlying FILE object between each access; this is - mainly to save filedescriptors in cases where many rd_file instances are open at - the same time. */ - RD_FILE_WRITABLE = 2 /* - This flag opens the file in a mode where it can be updated and modified, but it - must still exist and be readable. I.e. this should not compared with the normal: - fopen(filename , "w") where an existing file is truncated to zero upon successfull - open. - */ -} rd_file_flag_type; - typedef struct rd_file_view_struct rd_file_view_type; bool rd_file_view_flags_set(const rd_file_view_type *file_view, - int query_flags); -bool rd_file_view_check_flags(int state_flags, int query_flags); + FileMode query_flags); +bool rd_file_view_check_flags(FileMode state_flags, FileMode query_flags); -rd_file_view_type *rd_file_view_alloc(ERT::FortIO *fortio, int *flags, +rd_file_view_type *rd_file_view_alloc(ERT::FortIO *fortio, FileMode *flags, inv_map_type *inv_map); void rd_file_view_make_index(rd_file_view_type *rd_file_view); bool rd_file_view_has_kw(const rd_file_view_type *rd_file_view, const char *kw); @@ -73,8 +59,8 @@ rd_file_view_alloc_blockview2(const rd_file_view_type *rd_file_view, const char *start_kw, const char *end_kw, int occurence); -bool rd_file_view_drop_flag(rd_file_view_type *file_view, int flag); -void rd_file_view_add_flag(rd_file_view_type *file_view, int flag); +bool rd_file_view_drop_flag(rd_file_view_type *file_view, FileMode flag); +void rd_file_view_add_flag(rd_file_view_type *file_view, FileMode flag); bool rd_file_view_has_sim_time(const rd_file_view_type *rd_file_view, time_t sim_time); @@ -94,7 +80,8 @@ void rd_file_view_fclose_stream(rd_file_view_type *file_view); void rd_file_view_write_index(const rd_file_view_type *file_view, FILE *ostream); -rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, int *flags, +rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, + FileMode *flags, inv_map_type *inv_map, FILE *istream); diff --git a/lib/include/resdata/rd_sum.hpp b/lib/include/resdata/rd_sum.hpp index 3eee9d005..a562a585d 100644 --- a/lib/include/resdata/rd_sum.hpp +++ b/lib/include/resdata/rd_sum.hpp @@ -1,6 +1,4 @@ #pragma once - -#include #include #include #include @@ -18,6 +16,7 @@ #include #include #include "resdata/rd_util.hpp" +#include typedef struct rd_sum_vector_struct rd_sum_vector_type; @@ -42,10 +41,10 @@ int rd_sum_get_data_length(const rd_sum_type *rd_sum); rd_sum_type *rd_sum_fread_alloc(const char *, const stringlist_type *data_files, const char *key_join_string, bool include_restart, bool lazy_load, - int file_options); + FileMode file_options = FileMode::DEFAULT); rd_sum_type *rd_sum_fread_alloc_case(const char *, const char *key_join_string, bool include_restart, bool lazy_load, - int file_options); + FileMode file_options = FileMode::DEFAULT); rd_sum_ptr rd_sum_alloc_resample(const rd_sum_type *rd_sum, const char *rd_case, const time_t_vector_type *times, bool lower_extrapolation, @@ -164,7 +163,7 @@ UTIL_IS_INSTANCE_HEADER(rd_sum); rd_sum_ptr read_summary(const std::string &filename, const std::string &key_join_string = ":", bool lazy_load = true, bool include_restart = true, - int file_options = 0); + FileMode file_options = FileMode::DEFAULT); rd_sum_ptr make_summary_writer(std::string rd_case, bool fmt_output, bool unified, std::string key_join_string, time_t sim_start, diff --git a/lib/include/resdata/rd_sum_data.hpp b/lib/include/resdata/rd_sum_data.hpp index 31ae92a0f..b59a3fbe6 100644 --- a/lib/include/resdata/rd_sum_data.hpp +++ b/lib/include/resdata/rd_sum_data.hpp @@ -13,6 +13,7 @@ #include #include #include +#include typedef struct rd_sum_data_struct rd_sum_data_type; @@ -22,7 +23,7 @@ void rd_sum_data_fwrite(const rd_sum_data_type *data, const char *rd_case, bool fmt_case, bool unified); bool rd_sum_data_can_write(const rd_sum_data_type *data); bool rd_sum_data_fread(rd_sum_data_type *data, const stringlist_type *filelist, - bool lazy_load, int file_options); + bool lazy_load, FileMode file_options); rd_sum_data_type *rd_sum_data_alloc_writer(rd_smspec_type *smspec); rd_sum_data_type *rd_sum_data_alloc(rd_smspec_type *smspec); double rd_sum_data_time2days(const rd_sum_data_type *data, time_t sim_time); diff --git a/lib/private-include/detail/resdata/rd_sum_file_data.hpp b/lib/private-include/detail/resdata/rd_sum_file_data.hpp index 2725f452d..bd1cad15c 100644 --- a/lib/private-include/detail/resdata/rd_sum_file_data.hpp +++ b/lib/private-include/detail/resdata/rd_sum_file_data.hpp @@ -1,16 +1,21 @@ #include +#include +#include #include #include -#include #include #include #include #include +#include #include #include #include +#include +#include +#include namespace rd { @@ -133,7 +138,7 @@ class rd_sum_file_data { void fwrite_unified(ERT::FortIO &fortio) const; void fwrite_multiple(const std::string &rd_case, bool fmt_case) const; bool fread(const stringlist_type *filelist, bool lazy_load, - int file_options); + FileMode file_options = FileMode::DEFAULT); private: const rd_smspec_type *rd_smspec; diff --git a/lib/private-include/detail/resdata/rd_unsmry_loader.hpp b/lib/private-include/detail/resdata/rd_unsmry_loader.hpp index e1d006076..422c1cca8 100644 --- a/lib/private-include/detail/resdata/rd_unsmry_loader.hpp +++ b/lib/private-include/detail/resdata/rd_unsmry_loader.hpp @@ -1,17 +1,19 @@ +#include #include #include #include -#include #include #include +#include +#include namespace rd { class unsmry_loader { public: unsmry_loader(const rd_smspec_type *smspec, const std::string &filename, - int file_options); + FileMode file_options = FileMode::DEFAULT); ~unsmry_loader(); std::vector get_vector(int pos) const; diff --git a/lib/resdata/file_mode_pybind.cpp b/lib/resdata/file_mode_pybind.cpp new file mode 100644 index 000000000..57708c10a --- /dev/null +++ b/lib/resdata/file_mode_pybind.cpp @@ -0,0 +1,29 @@ +#include +#include + +#include + +namespace py = pybind11; + +namespace { +PYBIND11_MODULE(_file_mode, m) { + m.doc() = "pybind11 bindings for the FileMode enum from rd_file_flag.hpp"; + + py::enum_ file_mode(m, "FileMode", py::arithmetic()); + file_mode.value("DEFAULT", FileMode::DEFAULT) + .value("CLOSE_STREAM", FileMode::CLOSE_STREAM) + .value("WRITABLE", FileMode::WRITABLE); + + file_mode.def( + "__or__", [](FileMode a, FileMode b) { return a | b; }, + py::is_operator()); + file_mode.def( + "__and__", [](FileMode a, FileMode b) { return a & b; }, + py::is_operator()); + file_mode.def( + "__xor__", [](FileMode a, FileMode b) { return a ^ b; }, + py::is_operator()); + file_mode.def( + "__invert__", [](FileMode a) { return ~a; }, py::is_operator()); +} +} // namespace diff --git a/lib/resdata/rd_file.cpp b/lib/resdata/rd_file.cpp index c7166c43e..44cc35f7c 100644 --- a/lib/resdata/rd_file.cpp +++ b/lib/resdata/rd_file.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -7,11 +8,9 @@ #include #include -#include -#include #include -#include -#include +#include +#include #include #include @@ -19,9 +18,10 @@ #include #include #include -#include #include #include +#include +#include /** This file implements functionality to load a file in @@ -104,7 +104,7 @@ struct rd_file_struct { *global_view; /* The index of all the rd_kw instances in the file. */ rd_file_view_type *active_view; /* The currently active index. */ bool read_only; - int flags; + FileMode flags; vector_type *map_stack; inv_map_type *inv_view; }; @@ -135,7 +135,7 @@ struct rd_file_struct { UTIL_SAFE_CAST_FUNCTION(rd_file, RD_FILE_ID) UTIL_IS_INSTANCE_FUNCTION(rd_file, RD_FILE_ID) -static rd_file_type *rd_file_alloc_empty(int flags) { +static rd_file_type *rd_file_alloc_empty(FileMode flags) { rd_file_type *rd_file = (rd_file_type *)util_malloc(sizeof *rd_file); UTIL_TYPE_ID_INIT(rd_file, RD_FILE_ID); rd_file->map_stack = vector_alloc_new(); @@ -319,11 +319,11 @@ static void rd_file_select_global(rd_file_type *rd_file) { */ static std::unique_ptr rd_file_alloc_fortio(const char *filename, - int flags) { + FileMode flags) { bool fmt_file; rd_fmt_file(filename, &fmt_file); - if (rd_file_view_check_flags(flags, RD_FILE_WRITABLE)) + if (rd_file_view_check_flags(flags, FileMode::WRITABLE)) return std::make_unique( filename, std::ios_base::in | std::ios_base::out, fmt_file); else @@ -333,7 +333,7 @@ static std::unique_ptr rd_file_alloc_fortio(const char *filename, return nullptr; } -rd_file_type *rd_file_open(const char *filename, int flags) { +rd_file_type *rd_file_open(const char *filename, FileMode flags) { auto fortio = rd_file_alloc_fortio(filename, flags); if (fortio) { @@ -345,7 +345,7 @@ rd_file_type *rd_file_open(const char *filename, int flags) { rd_file_scan(rd_file.get()); rd_file_select_global(rd_file.get()); - if (rd_file_view_check_flags(rd_file->flags, RD_FILE_CLOSE_STREAM)) + if (rd_file_view_check_flags(rd_file->flags, FileMode::CLOSE_STREAM)) rd_file->fortio->fclose_stream(); return rd_file.release(); @@ -354,7 +354,7 @@ rd_file_type *rd_file_open(const char *filename, int flags) { } bool rd_file_writable(const rd_file_type *rd_file) { - return rd_file_view_check_flags(rd_file->flags, RD_FILE_WRITABLE); + return rd_file_view_check_flags(rd_file->flags, FileMode::WRITABLE); } /** @@ -527,7 +527,7 @@ bool rd_file_save_kw(const rd_file_type *rd_file, const rd_kw_type *rd_kw) { file_kw->inplace_write(*rd_file->fortio); - if (rd_file_view_check_flags(rd_file->flags, RD_FILE_CLOSE_STREAM)) + if (rd_file_view_check_flags(rd_file->flags, FileMode::CLOSE_STREAM)) rd_file->fortio->fclose_stream(); return true; @@ -611,7 +611,7 @@ bool rd_file_write_index(const rd_file_type *rd_file, } rd_file_type *rd_file_fast_open(const char *file_name, - const char *index_file_name, int flags) { + const char *index_file_name, FileMode flags) { if (!rd_file_index_valid0(file_name, index_file_name)) return NULL; @@ -631,7 +631,7 @@ rd_file_type *rd_file_fast_open(const char *file_name, if (rd_file->global_view) { rd_file_select_global(rd_file.get()); if (rd_file_view_check_flags(rd_file->flags, - RD_FILE_CLOSE_STREAM)) + FileMode::CLOSE_STREAM)) rd_file->fortio->fclose_stream(); return rd_file.release(); } diff --git a/lib/resdata/rd_file_pybind.cpp b/lib/resdata/rd_file_pybind.cpp index 2d2f4739e..963221481 100644 --- a/lib/resdata/rd_file_pybind.cpp +++ b/lib/resdata/rd_file_pybind.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -22,7 +23,7 @@ PYBIND11_MODULE(_file, m) { register_exceptions(m); m.doc() = "pybind11 bindings between rd_file.py and rd_file.cpp"; - m.def("_open", [](std::string filename, int flags) -> py::object { + m.def("_open", [](std::string filename, FileMode &flags) -> py::object { auto *file = rd_file_open(filename.c_str(), flags); if (file == nullptr) return py::none(); @@ -30,7 +31,7 @@ PYBIND11_MODULE(_file, m) { }); m.def("_fast_open", [](std::string filename, std::string index_filename, - int flags) -> py::object { + FileMode flags) -> py::object { auto *file = rd_file_fast_open(filename.c_str(), index_filename.c_str(), flags); if (file == nullptr) diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index 3a115b2b8..5f4507745 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -19,9 +18,9 @@ #include #include #include -#include #include #include +#include struct rd_file_view_struct { std::vector> kw_list; @@ -33,18 +32,19 @@ struct rd_file_view_struct { inv_map_type *inv_map; /* Shared reference owned by the rd_file structure. */ std::vector> child_list; - int *flags; + FileMode *flags; - rd_file_view_struct(ERT::FortIO *fortio, int *flags, inv_map_type *inv_map) + rd_file_view_struct(ERT::FortIO *fortio, FileMode *flags, + inv_map_type *inv_map) : fortio(fortio), inv_map(inv_map), flags(flags) {}; }; -bool rd_file_view_check_flags(int state_flags, int query_flags) { +bool rd_file_view_check_flags(FileMode state_flags, FileMode query_flags) { return (state_flags & query_flags) == query_flags; } bool rd_file_view_flags_set(const rd_file_view_type *file_view, - int query_flags) { + FileMode query_flags) { return rd_file_view_check_flags(*file_view->flags, query_flags); } @@ -52,7 +52,7 @@ const char *rd_file_view_get_src_file(const rd_file_view_type *file_view) { return file_view->fortio->filename_ref(); } -rd_file_view_type *rd_file_view_alloc(ERT::FortIO *fortio, int *flags, +rd_file_view_type *rd_file_view_alloc(ERT::FortIO *fortio, FileMode *flags, inv_map_type *inv_map) { return new rd_file_view_struct(fortio, flags, inv_map); } @@ -107,15 +107,15 @@ rd_file_view_iget_named_file_kw(const rd_file_view_type *rd_file_view, return rd_file_view_iget_file_kw(rd_file_view, global_index); } -bool rd_file_view_drop_flag(rd_file_view_type *file_view, int flag) { +bool rd_file_view_drop_flag(rd_file_view_type *file_view, FileMode flag) { bool flag_set = rd_file_view_flags_set(file_view, flag); if (flag_set) - *file_view->flags -= flag; + *file_view->flags &= ~flag; return flag_set; } -void rd_file_view_add_flag(rd_file_view_type *file_view, int flag) { +void rd_file_view_add_flag(rd_file_view_type *file_view, FileMode flag) { *file_view->flags |= flag; } @@ -128,7 +128,7 @@ static rd_kw_type *rd_file_view_get_kw(const rd_file_view_type *rd_file_view, rd_kw = file_kw->get_kw(*rd_file_view->fortio); (*rd_file_view->inv_map)[rd_kw] = file_kw.get(); - if (rd_file_view_flags_set(rd_file_view, RD_FILE_CLOSE_STREAM)) + if (rd_file_view_flags_set(rd_file_view, FileMode::CLOSE_STREAM)) rd_file_view->fortio->fclose_stream(); } } @@ -212,7 +212,7 @@ bool rd_file_view_load_all(rd_file_view_type *rd_file_view) { loadOK = true; } - if (rd_file_view_flags_set(rd_file_view, RD_FILE_CLOSE_STREAM)) + if (rd_file_view_flags_set(rd_file_view, FileMode::CLOSE_STREAM)) rd_file_view->fortio->fclose_stream(); return loadOK; @@ -705,7 +705,8 @@ void rd_file_view_write_index(const rd_file_view_type *file_view, } } -rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, int *flags, +rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, + FileMode *flags, inv_map_type *inv_map, FILE *istream) { diff --git a/lib/resdata/rd_grid.cpp b/lib/resdata/rd_grid.cpp index a6e524937..060fc7e02 100644 --- a/lib/resdata/rd_grid.cpp +++ b/lib/resdata/rd_grid.cpp @@ -2537,7 +2537,7 @@ static rd_grid_ptr rd_grid_alloc_EGRID_all_grids(const char *grid_file, throw std::invalid_argument(fmt::format( "{}: wrong file type - expected .EGRID file", grid_file)); { - auto rd_file = rd_file_ptr(rd_file_open(grid_file, 0), &rd_file_close); + auto rd_file = open_rd_file(std::string(grid_file)); if (rd_file) { int num_grid = rd_file_get_num_named_kw(rd_file.get(), GRIDHEAD_KW); auto main_grid = rd_grid_alloc_EGRID__(nullptr, rd_file.get(), 0, @@ -2765,7 +2765,7 @@ static rd_grid_ptr rd_grid_alloc_GRID(const char *grid_file, "{}: wrong file type - expected .GRID file", grid_file)); int cell_offset = 0; - rd_file_ptr rd_file{rd_file_open(grid_file, 0), &rd_file_close}; + rd_file_ptr rd_file = open_rd_file(std::string(grid_file)); int num_grid = rd_file_get_num_named_kw(rd_file.get(), DIMENS_KW); int grid_nr; int dualp_flag; diff --git a/lib/resdata/rd_smspec.cpp b/lib/resdata/rd_smspec.cpp index e39e6278b..cfd765844 100644 --- a/lib/resdata/rd_smspec.cpp +++ b/lib/resdata/rd_smspec.cpp @@ -855,7 +855,7 @@ static bool rd_smspec_check_header(rd_file_type *header) { static bool rd_smspec_fread_header(rd_smspec_type *rd_smspec, const std::string &header_file, bool include_restart) { - rd_file_ptr header(rd_file_open(header_file.c_str(), 0), &rd_file_close); + rd_file_ptr header = open_rd_file(header_file); if (header && rd_smspec_check_header(header.get())) { const char *names_alias = get_active_keyword_alias(header.get(), WGNAMES_KW); diff --git a/lib/resdata/rd_sum.cpp b/lib/resdata/rd_sum.cpp index 73219e91d..dab1c4cb6 100644 --- a/lib/resdata/rd_sum.cpp +++ b/lib/resdata/rd_sum.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #include @@ -149,14 +149,14 @@ static rd_sum_ptr rd_sum_alloc__(std::string input_arg, static bool rd_sum_fread_data(rd_sum_type *rd_sum, const stringlist_type *data_files, bool lazy_load, - int file_options) { + FileMode file_options) { rd_sum->data.reset(rd_sum_data_alloc(rd_sum->smspec.get())); return rd_sum_data_fread(rd_sum->data.get(), data_files, lazy_load, file_options); } static void rd_sum_fread_history(rd_sum_type *rd_sum, bool lazy_load, - int file_options) { + FileMode file_options) { const char *restart_header = rd_smspec_get_restart_case(rd_sum->smspec.get()); if (restart_header == nullptr) @@ -177,7 +177,7 @@ static void rd_sum_fread_history(rd_sum_type *rd_sum, bool lazy_load, static bool rd_sum_fread(rd_sum_type *rd_sum, const std::string &header_file, const stringlist_type *data_files, bool include_restart, bool lazy_load, - int file_options) { + FileMode file_options) { rd_sum->smspec = read_smspec(header_file, rd_sum->key_join_string, include_restart); if (rd_sum->smspec) { @@ -428,7 +428,7 @@ rd_alloc_summary_files(fs::path path, fs::path _base, std::string ext, } static bool rd_sum_fread_case(rd_sum_type *rd_sum, bool include_restart, - bool lazy_load, int file_options) { + bool lazy_load, FileMode file_options) { stringlist_ptr summary_file_list = make_stringlist(); bool caseOK = false; @@ -458,7 +458,7 @@ rd_sum_type *rd_sum_fread_alloc(const char *header_file, const stringlist_type *data_files, const char *key_join_string, bool include_restart, bool lazy_load, - int file_options) { + FileMode file_options) { rd_sum_ptr rd_sum = rd_sum_alloc__(header_file, key_join_string); if (rd_sum) { if (!rd_sum_fread(rd_sum.get(), header_file, data_files, @@ -578,7 +578,7 @@ void rd_sum_free(rd_sum_type *rd_sum) { delete rd_sum; } rd_sum_type *rd_sum_fread_alloc_case(const char *input_file, const char *key_join_string, bool include_restart, bool lazy_load, - int file_options) { + FileMode file_options) { rd_sum_ptr rd_sum = rd_sum_alloc__(input_file, key_join_string); if (!rd_sum) return nullptr; @@ -1139,7 +1139,7 @@ double rd_sum_get_first_value_gen_key(const rd_sum_type *rd_sum, rd_sum_ptr read_summary(const std::string &filename, const std::string &key_join_string, bool lazy_load, - bool include_restart, int file_options) { + bool include_restart, FileMode file_options) { return {rd_sum_fread_alloc_case(filename.c_str(), key_join_string.c_str(), include_restart, lazy_load, file_options), &rd_sum_free}; diff --git a/lib/resdata/rd_sum_data.cpp b/lib/resdata/rd_sum_data.cpp index da7c7547f..4e8814f80 100644 --- a/lib/resdata/rd_sum_data.cpp +++ b/lib/resdata/rd_sum_data.cpp @@ -1,7 +1,12 @@ +#include #include #include +#include #include +#include +#include +#include #include #include #include @@ -11,9 +16,8 @@ #include #include #include -#include #include -#include +#include #include @@ -23,10 +27,11 @@ #include #include #include -#include #include #include #include +#include +#include #include "detail/resdata/rd_sum_file_data.hpp" @@ -614,7 +619,7 @@ void rd_sum_data_add_case(rd_sum_data_type *self, */ bool rd_sum_data_fread(rd_sum_data_type *data, const stringlist_type *filelist, - bool lazy_load, int file_options) { + bool lazy_load, FileMode file_options) { auto file_data = std::make_shared(data->smspec); if (file_data->fread(filelist, lazy_load, file_options)) { data->data_files.push_back(file_data); diff --git a/lib/resdata/rd_sum_file_data.cpp b/lib/resdata/rd_sum_file_data.cpp index 9615e55eb..3b04e4452 100644 --- a/lib/resdata/rd_sum_file_data.cpp +++ b/lib/resdata/rd_sum_file_data.cpp @@ -1,17 +1,33 @@ +#include +#include +#include #include -#include #include #include #include #include +#include +#include +#include + +#include +#include +#include #include #include #include #include -#include "detail/resdata/rd_sum_file_data.hpp" -#include "detail/resdata/rd_unsmry_loader.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace fs = std::filesystem; @@ -575,7 +591,7 @@ void rd_sum_file_data::add_rd_file(int report_step, } bool rd_sum_file_data::fread(const stringlist_type *filelist, bool lazy_load, - int file_options) { + FileMode file_options) { if (stringlist_get_size(filelist) == 0) return false; @@ -598,7 +614,7 @@ bool rd_sum_file_data::fread(const stringlist_type *filelist, bool lazy_load, util_abort("%s: file:%s has wrong type \n", __func__, data_file); { - rd_file_ptr rd_file(rd_file_open(data_file, 0), &rd_file_close); + rd_file_ptr rd_file = open_rd_file(std::string(data_file)); if (rd_file && check_file(rd_file.get())) { this->add_rd_file(report_step, rd_file_get_global_view(rd_file.get())); @@ -618,8 +634,8 @@ bool rd_sum_file_data::fread(const stringlist_type *filelist, bool lazy_load, // Is this correct for a restarted chain of UNSMRY files? Looks like the // report step sequence will be restarted? - rd_file_ptr rd_file(rd_file_open(stringlist_iget(filelist, 0), 0), - &rd_file_close); + rd_file_ptr rd_file = + open_rd_file(std::string(stringlist_iget(filelist, 0))); if (rd_file && check_file(rd_file.get())) { int first_report_step = rd_smspec_get_first_step(this->rd_smspec); diff --git a/lib/resdata/rd_sum_pybind.cpp b/lib/resdata/rd_sum_pybind.cpp index d82affc21..472acff12 100644 --- a/lib/resdata/rd_sum_pybind.cpp +++ b/lib/resdata/rd_sum_pybind.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -31,7 +32,7 @@ PYBIND11_MODULE(_rd_sum, m) { m.def( "_fread_alloc_case", [](std::string load_case, std::string key_join_string, - bool include_restart, bool lazy_load, int file_options) { + bool include_restart, bool lazy_load, FileMode file_options) { return reinterpret_cast(rd_sum_fread_alloc_case( load_case.c_str(), key_join_string.c_str(), include_restart, lazy_load, file_options)); @@ -41,7 +42,7 @@ PYBIND11_MODULE(_rd_sum, m) { "_fread_alloc", [](std::string header_file, py::handle data_files, std::string key_join_string, bool include_restart, bool lazy_load, - int file_options) { + FileMode file_options) { return reinterpret_cast(rd_sum_fread_alloc( header_file.c_str(), from_cwrap(data_files), key_join_string.c_str(), include_restart, lazy_load, diff --git a/lib/resdata/rd_unsmry_loader.cpp b/lib/resdata/rd_unsmry_loader.cpp index 1fe402b43..ce82e002f 100644 --- a/lib/resdata/rd_unsmry_loader.cpp +++ b/lib/resdata/rd_unsmry_loader.cpp @@ -1,22 +1,27 @@ -#include +#include +#include +#include #include -#include -#include +#include #include +#include #include #include +#include #include #include +#include #include +#include -#include "detail/resdata/rd_unsmry_loader.hpp" +#include namespace rd { unsmry_loader::unsmry_loader(const rd_smspec_type *smspec, - const std::string &filename, int file_options) + const std::string &filename, FileMode file_options) : size(rd_smspec_get_params_size(smspec)), time_index(rd_smspec_get_time_index(smspec)), time_seconds(rd_smspec_get_time_seconds(smspec)), @@ -78,7 +83,7 @@ std::vector unsmry_loader::get_vector(int pos) const { data[index] = value; } - if (rd_file_view_flags_set(file_view, RD_FILE_CLOSE_STREAM)) + if (rd_file_view_flags_set(file_view, FileMode::CLOSE_STREAM)) rd_file_view_fclose_stream(file_view); return data; diff --git a/lib/resdata/tests/rd_coarse_test.cpp b/lib/resdata/tests/rd_coarse_test.cpp index ff24e9326..0fbe0509f 100644 --- a/lib/resdata/tests/rd_coarse_test.cpp +++ b/lib/resdata/tests/rd_coarse_test.cpp @@ -55,8 +55,8 @@ int main(int argc, char **argv) { rd::filename(case_path, RD_INIT_FILE, false, 0).string(); rd_grid_ptr GRID = read_grid(egrid_file); - rd_file_ptr RST_file(rd_file_open(rst_file.c_str(), 0), &rd_file_close); - rd_file_ptr INIT_file(rd_file_open(init_file.c_str(), 0), &rd_file_close); + rd_file_ptr RST_file = open_rd_file(rst_file); + rd_file_ptr INIT_file = open_rd_file(init_file); { test_assert_true(rd_grid_have_coarse_cells(GRID.get())); diff --git a/lib/resdata/tests/rd_dualp.cpp b/lib/resdata/tests/rd_dualp.cpp index 4e1a7e183..01b0f8709 100644 --- a/lib/resdata/tests/rd_dualp.cpp +++ b/lib/resdata/tests/rd_dualp.cpp @@ -20,12 +20,9 @@ int main(int argc, char **argv) { rd::filename(case_path, RD_RESTART_FILE, false, 0).string(); rd_grid_ptr rd_grid = read_grid(grid_file); - rd_file_ptr RST_file = - rd_file_ptr(rd_file_open(rst_file.c_str(), 0), &rd_file_close); - rd_file_ptr INIT_file = - rd_file_ptr(rd_file_open(init_file.c_str(), 0), &rd_file_close); - rd_file_ptr GRID_file = - rd_file_ptr(rd_file_open(grid_file.c_str(), 0), &rd_file_close); + rd_file_ptr RST_file = open_rd_file(rst_file); + rd_file_ptr INIT_file = open_rd_file(init_file); + rd_file_ptr GRID_file = open_rd_file(grid_file); { rd_kw_type *actnum = diff --git a/lib/resdata/tests/rd_file.cpp b/lib/resdata/tests/rd_file.cpp index 047efecac..6ffdeca92 100644 --- a/lib/resdata/tests/rd_file.cpp +++ b/lib/resdata/tests/rd_file.cpp @@ -1,6 +1,5 @@ #include #include -#include #include @@ -12,10 +11,10 @@ #include #include #include -#include #include #include #include +#include void test_writable(size_t data_size) { rd::util::TestArea ta("file_writable"); @@ -31,7 +30,8 @@ void test_writable(size_t data_size) { } for (int i = 0; i < 4; ++i) { - rd_file_type *rd_file = rd_file_open(data_file_name, RD_FILE_WRITABLE); + rd_file_type *rd_file = + rd_file_open(data_file_name, FileMode::WRITABLE); rd_kw_type *loaded_kw = rd_file_view_iget_kw(rd_file_get_global_view(rd_file), 0); test_assert_true(rd_kw_equal(kw, loaded_kw)); @@ -51,7 +51,7 @@ void test_truncated() { rd_grid_fwrite_EGRID2(grid.get(), "TEST.EGRID", RD_METRIC_UNITS); } { - rd_file_type *rd_file = rd_file_open("TEST.EGRID", 0); + rd_file_type *rd_file = rd_file_open("TEST.EGRID"); test_assert_true(rd_file_is_instance(rd_file)); num_kw = rd_file_get_size(rd_file); rd_file_close(rd_file); @@ -64,7 +64,7 @@ void test_truncated() { fclose(stream); } { - rd_file_type *rd_file = rd_file_open("TEST.EGRID", 0); + rd_file_type *rd_file = rd_file_open("TEST.EGRID"); test_assert_true(rd_file_get_size(rd_file) < num_kw); rd_file_close(rd_file); } @@ -78,7 +78,7 @@ void test_mixed_case() { rd_grid_fwrite_EGRID2(grid.get(), "TESTcase.EGRID", RD_METRIC_UNITS); } { - rd_file_type *rd_file = rd_file_open("TESTcase.EGRID", 0); + rd_file_type *rd_file = rd_file_open("TESTcase.EGRID"); test_assert_true(rd_file_is_instance(rd_file)); num_kw = rd_file_get_size(rd_file); rd_file_close(rd_file); @@ -91,7 +91,7 @@ void test_mixed_case() { fclose(stream); } { - rd_file_type *rd_file = rd_file_open("TESTcase.EGRID", 0); + rd_file_type *rd_file = rd_file_open("TESTcase.EGRID"); test_assert_true(rd_file_get_size(rd_file) < num_kw); rd_file_close(rd_file); } diff --git a/lib/resdata/tests/rd_file_equinor.cpp b/lib/resdata/tests/rd_file_equinor.cpp index 53d959b39..83691d540 100644 --- a/lib/resdata/tests/rd_file_equinor.cpp +++ b/lib/resdata/tests/rd_file_equinor.cpp @@ -5,15 +5,13 @@ #include #include -#include #include -#include -#include -#include +#include +#include void test_close_stream2(const char *src_file, const char *target_file) { util_copy_file(src_file, target_file); - rd_file_type *rd_file = rd_file_open(target_file, RD_FILE_CLOSE_STREAM); + rd_file_type *rd_file = rd_file_open(target_file, FileMode::CLOSE_STREAM); rd_file_load_all(rd_file); unlink(target_file); @@ -25,14 +23,16 @@ void test_close_stream2(const char *src_file, const char *target_file) { void test_loadall(const char *src_file, const char *target_file) { util_copy_file(src_file, target_file); { - rd_file_type *rd_file = rd_file_open(target_file, RD_FILE_CLOSE_STREAM); + rd_file_type *rd_file = + rd_file_open(target_file, FileMode::CLOSE_STREAM); test_assert_true(rd_file_load_all(rd_file)); rd_file_close(rd_file); } { - rd_file_type *rd_file = rd_file_open(target_file, RD_FILE_CLOSE_STREAM); + rd_file_type *rd_file = + rd_file_open(target_file, FileMode::CLOSE_STREAM); unlink(target_file); test_assert_false(rd_file_load_all(rd_file)); @@ -43,7 +43,7 @@ void test_loadall(const char *src_file, const char *target_file) { void test_close_stream1(const char *src_file, const char *target_file) { util_copy_file(src_file, target_file); - rd_file_type *rd_file = rd_file_open(target_file, RD_FILE_CLOSE_STREAM); + rd_file_type *rd_file = rd_file_open(target_file, FileMode::CLOSE_STREAM); rd_kw_type *kw0 = rd_file_iget_kw(rd_file, 0); rd_kw_type *kw1 = rd_file_iget_kw(rd_file, 1); unlink(target_file); @@ -67,7 +67,7 @@ void test_writable(const char *src_file) { ta.copy_file(src_file); { - rd_file_type *rd_file = rd_file_open(fname, RD_FILE_WRITABLE); + rd_file_type *rd_file = rd_file_open(fname, FileMode::WRITABLE); rd_kw_type *swat = rd_file_iget_named_kw(rd_file, "SWAT", 0); rd_kw_type *swat0 = rd_kw_alloc_copy(swat); test_assert_true(rd_kw_equal(swat, swat0)); @@ -76,7 +76,7 @@ void test_writable(const char *src_file) { test_assert_true(rd_file_writable(rd_file)); rd_file_close(rd_file); - rd_file = rd_file_open(fname, 0); + rd_file = rd_file_open(fname); swat = rd_file_iget_named_kw(rd_file, "SWAT", 0); test_assert_true( util_double_approx_equal(rd_kw_iget_float(swat, 0), 1000)); diff --git a/lib/resdata/tests/rd_grid_dx_dy_dz.cpp b/lib/resdata/tests/rd_grid_dx_dy_dz.cpp index 1a4c2c2d9..41c534138 100644 --- a/lib/resdata/tests/rd_grid_dx_dy_dz.cpp +++ b/lib/resdata/tests/rd_grid_dx_dy_dz.cpp @@ -25,7 +25,7 @@ void test_dxdydz(const std::string &grid_fname, const std::string &init_fname) { std::cerr << "Could not open " << grid_fname << std::endl; exit(-1); } - rd_file_type *init_file = rd_file_open(init_fname.c_str(), 0); + rd_file_type *init_file = rd_file_open(init_fname.c_str()); if (init_file == NULL) { std::cerr << "Could not open " << init_fname << std::endl; exit(-1); diff --git a/lib/resdata/tests/rd_grid_export.cpp b/lib/resdata/tests/rd_grid_export.cpp index aa0991ddd..999929aa3 100644 --- a/lib/resdata/tests/rd_grid_export.cpp +++ b/lib/resdata/tests/rd_grid_export.cpp @@ -95,7 +95,7 @@ int main(int argc, char **argv) { if (argc == 1) test_assert_true(rd_grid_get_unit_system(rd_grid.get()) == RD_METRIC_UNITS); - rd_file_type *rd_file = rd_file_open(grid_file, 0); + rd_file_type *rd_file = rd_file_open(grid_file); export_actnum(rd_grid.get(), rd_file); export_coord(rd_grid.get(), rd_file); diff --git a/lib/resdata/tests/rd_grid_init_fwrite.cpp b/lib/resdata/tests/rd_grid_init_fwrite.cpp index 79ef930bd..84661852c 100644 --- a/lib/resdata/tests/rd_grid_init_fwrite.cpp +++ b/lib/resdata/tests/rd_grid_init_fwrite.cpp @@ -36,7 +36,7 @@ void test_write_depth(rd_grid_type *grid) { rd_grid_fwrite_depth(grid, init_file, RD_METRIC_UNITS); } { - rd_file_type *init_file = rd_file_open("INIT", 0); + rd_file_type *init_file = rd_file_open("INIT"); rd_kw_type *depth = rd_file_iget_named_kw(init_file, "DEPTH", 0); test_assert_int_equal(rd_kw_get_size(depth), rd_grid_get_nactive(grid)); @@ -89,7 +89,7 @@ void test_write_dims(const rd_grid_type *grid) { rd_grid_fwrite_dims(grid, init_file, RD_METRIC_UNITS); } { - rd_file_type *init_file = rd_file_open("INIT", 0); + rd_file_type *init_file = rd_file_open("INIT"); rd_kw_type *DX = rd_file_iget_named_kw(init_file, "DX", 0); rd_kw_type *DY = rd_file_iget_named_kw(init_file, "DY", 0); rd_kw_type *DZ = rd_file_iget_named_kw(init_file, "DZ", 0); diff --git a/lib/resdata/tests/rd_grid_volume.cpp b/lib/resdata/tests/rd_grid_volume.cpp index cacd08a93..023ab322d 100644 --- a/lib/resdata/tests/rd_grid_volume.cpp +++ b/lib/resdata/tests/rd_grid_volume.cpp @@ -19,7 +19,7 @@ int main(int argc, char **argv) { std::string init_file = rd::filename(path_case, RD_INIT_FILE, false, 0).string(); - rd_file_ptr init(rd_file_open(init_file.c_str(), 0), &rd_file_close); + rd_file_ptr init = open_rd_file(init_file); rd_grid_ptr grid = read_grid(grid_file); const rd_kw_type *poro_kw = rd_file_iget_named_kw(init.get(), "PORO", 0); const rd_kw_type *porv_kw = rd_file_iget_named_kw(init.get(), "PORV", 0); diff --git a/lib/resdata/tests/rd_lgr_test.cpp b/lib/resdata/tests/rd_lgr_test.cpp index 83b7066d3..051598bba 100644 --- a/lib/resdata/tests/rd_lgr_test.cpp +++ b/lib/resdata/tests/rd_lgr_test.cpp @@ -10,7 +10,7 @@ int main(int argc, char **argv) { const char *grid_file = argv[1]; rd_grid_ptr rd_grid = read_grid(grid_file); - rd_file_type *rd_file = rd_file_open(grid_file, 0); + rd_file_type *rd_file = rd_file_open(grid_file); rd_grid_test_lgr_consistency(rd_grid.get()); diff --git a/lib/resdata/tests/rd_nnc_test.cpp b/lib/resdata/tests/rd_nnc_test.cpp index 9dcef4fda..ac5339a8d 100644 --- a/lib/resdata/tests/rd_nnc_test.cpp +++ b/lib/resdata/tests/rd_nnc_test.cpp @@ -28,7 +28,7 @@ template int vector_util_index(const std::vector &vec, T value) { void test_scan(const char *grid_filename) { rd_grid_type *rd_grid = rd_grid_alloc(grid_filename); - rd_file_type *grid_file = rd_file_open(grid_filename, 0); + rd_file_type *grid_file = rd_file_open(grid_filename); int block_nr; for (block_nr = 0; diff --git a/lib/resdata/tests/rd_restart_test.cpp b/lib/resdata/tests/rd_restart_test.cpp index f1997936f..a54eedea0 100644 --- a/lib/resdata/tests/rd_restart_test.cpp +++ b/lib/resdata/tests/rd_restart_test.cpp @@ -21,7 +21,7 @@ int main(int argc, char **argv) { bool OK = true; const char *unrst_file = argv[1]; - rd_file_type *rst_file = rd_file_open(unrst_file, 0); + rd_file_type *rst_file = rd_file_open(unrst_file); OK = OK && test_get(rst_file, 1, 1, 1998, -1); OK = OK && test_get(rst_file, 17, 9, 2003, -1); diff --git a/lib/resdata/tests/rd_rsthead.cpp b/lib/resdata/tests/rd_rsthead.cpp index 0c6325e45..e957645e8 100644 --- a/lib/resdata/tests/rd_rsthead.cpp +++ b/lib/resdata/tests/rd_rsthead.cpp @@ -14,7 +14,7 @@ void test_file(const char *filename, int occurence, bool exists, const RSTHead &true_header) { int report_step = rd_filename_report_nr(filename); - rd_file_type *rst_file = rd_file_open(filename, 0); + rd_file_type *rst_file = rd_file_open(filename); rd_file_enum file_type = rd_get_file_type(filename, NULL, NULL); rd_file_view_type *rst_view; diff --git a/lib/resdata/tests/rdxx_kw.cpp b/lib/resdata/tests/rdxx_kw.cpp index fd957441a..ce58f1adb 100644 --- a/lib/resdata/tests/rdxx_kw.cpp +++ b/lib/resdata/tests/rdxx_kw.cpp @@ -164,7 +164,7 @@ void test_read_write() { } { - rd_file_type *f = rd_file_open("test_file", 0); + rd_file_type *f = rd_file_open("test_file"); rd_kw_type *d_kw = rd_file_iget_named_kw(f, "DOUBLE", 0); rd_kw_type *f_kw = rd_file_iget_named_kw(f, "FLOAT", 0); rd_kw_type *i_kw = rd_file_iget_named_kw(f, "INT", 0); diff --git a/lib/resdata/tests/test_rd_file_index.cpp b/lib/resdata/tests/test_rd_file_index.cpp index a6ca90fdc..1a8854262 100644 --- a/lib/resdata/tests/test_rd_file_index.cpp +++ b/lib/resdata/tests/test_rd_file_index.cpp @@ -15,7 +15,7 @@ void test_load_nonexisting_file() { rd_file_type *rd_file = - rd_file_fast_open("base_file", "a_file_that_does_not_exist_2384623", 0); + rd_file_fast_open("base_file", "a_file_that_does_not_exist_2384623"); test_assert_NULL(rd_file); } @@ -43,7 +43,7 @@ void test_create_and_load_index_file() { //finished creating data file //creating rd_file - rd_file_type *rd_file = rd_file_open(file_name, 0); + rd_file_type *rd_file = rd_file_open(file_name); test_assert_true(rd_file_has_kw(rd_file, "TEST1_KW")); rd_file_write_index(rd_file, index_file_name); int rd_file_size = rd_file_get_size(rd_file); @@ -63,7 +63,7 @@ void test_create_and_load_index_file() { test_assert_true(rd_file_index_valid(file_name, index_file_name)); rd_file_type *rd_file_index = - rd_file_fast_open(file_name, index_file_name, 0); + rd_file_fast_open(file_name, index_file_name); test_assert_true(rd_file_is_instance(rd_file_index)); test_assert_true(rd_file_get_global_view(rd_file_index)); diff --git a/lib/resdata/tests/well_conn_CF.cpp b/lib/resdata/tests/well_conn_CF.cpp index 2e8c1be31..3bcfd2355 100644 --- a/lib/resdata/tests/well_conn_CF.cpp +++ b/lib/resdata/tests/well_conn_CF.cpp @@ -23,7 +23,7 @@ void well_conn_test_CF(const rd_kw_type *iwel_kw, const rd_kw_type *icon_kw, int main(int argc, char **argv) { const char *Xfile = argv[1]; - rd_file_type *rst_file = rd_file_open(Xfile, 0); + rd_file_type *rst_file = rd_file_open(Xfile); auto rst_head = RSTHead::read(rd_file_get_global_view(rst_file), rd_filename_report_nr(Xfile)); const rd_kw_type *iwel_kw = rd_file_iget_named_kw(rst_file, IWEL_KW, 0); diff --git a/lib/resdata/tests/well_dualp.cpp b/lib/resdata/tests/well_dualp.cpp index 57f068b52..8497fa4fc 100644 --- a/lib/resdata/tests/well_dualp.cpp +++ b/lib/resdata/tests/well_dualp.cpp @@ -12,7 +12,7 @@ #include void test_rstfile(const char *filename, bool fracture_connection) { - rd_file_type *rst_file = rd_file_open(filename, 0); + rd_file_type *rst_file = rd_file_open(filename); const rd_kw_type *iwel_kw = rd_file_iget_named_kw(rst_file, IWEL_KW, 0); auto header = RSTHead::read(rd_file_get_global_view(rst_file), rd_filename_report_nr(filename)); diff --git a/lib/resdata/tests/well_segment_load.cpp b/lib/resdata/tests/well_segment_load.cpp index 71d4d82f0..689008aec 100644 --- a/lib/resdata/tests/well_segment_load.cpp +++ b/lib/resdata/tests/well_segment_load.cpp @@ -16,7 +16,7 @@ int main(int argc, char **argv) { const char *Xfile = argv[1]; - rd_file_type *rst_file = rd_file_open(Xfile, 0); + rd_file_type *rst_file = rd_file_open(Xfile); rd_file_view_type *rst_view = rd_file_get_active_view(rst_file); auto rst_head = RSTHead::read(rst_view, rd_filename_report_nr(Xfile)); const rd_kw_type *iwel_kw = rd_file_iget_named_kw(rst_file, IWEL_KW, 0); diff --git a/lib/resdata/tests/well_state_load.cpp b/lib/resdata/tests/well_state_load.cpp index 30a3e0e06..1bbf25774 100644 --- a/lib/resdata/tests/well_state_load.cpp +++ b/lib/resdata/tests/well_state_load.cpp @@ -22,7 +22,7 @@ int main(int argc, char **argv) { const char *rst_file_name = argv[2]; rd_grid_type *grid = rd_grid_alloc(grid_file); - rd_file_type *rst_file = rd_file_open(rst_file_name, 0); + rd_file_type *rst_file = rd_file_open(rst_file_name); auto header = RSTHead::read(rd_file_get_global_view(rst_file), rd_filename_report_nr(rst_file_name)); const char *well_name = "WELL"; diff --git a/lib/resdata/tests/well_state_load_missing_RSEG.cpp b/lib/resdata/tests/well_state_load_missing_RSEG.cpp index 86df43e12..77bf7a459 100644 --- a/lib/resdata/tests/well_state_load_missing_RSEG.cpp +++ b/lib/resdata/tests/well_state_load_missing_RSEG.cpp @@ -23,7 +23,7 @@ int main(int argc, char **argv) { const char *rst_file_name = argv[2]; rd_grid_type *grid = rd_grid_alloc(grid_file); - rd_file_type *rst_file = rd_file_open(rst_file_name, 0); + rd_file_type *rst_file = rd_file_open(rst_file_name); rd_file_view_type *rst_view = rd_file_get_active_view(rst_file); auto header = RSTHead::read(rst_view, rd_filename_report_nr(rst_file_name)); diff --git a/lib/resdata/well_info.cpp b/lib/resdata/well_info.cpp index 2f861f4e0..fb9e05adb 100644 --- a/lib/resdata/well_info.cpp +++ b/lib/resdata/well_info.cpp @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -8,23 +6,24 @@ #include #include #include -#include #include #include #include #include #include #include +#include +#include namespace { struct close_guard { explicit close_guard(rd_file_view_type *file_view) : file_view(file_view), - was_set(rd_file_view_drop_flag(file_view, RD_FILE_CLOSE_STREAM)) {} + was_set(rd_file_view_drop_flag(file_view, FileMode::CLOSE_STREAM)) {} ~close_guard() { if (was_set) - rd_file_view_add_flag(file_view, RD_FILE_CLOSE_STREAM); + rd_file_view_add_flag(file_view, FileMode::CLOSE_STREAM); } close_guard(const close_guard &) = delete; close_guard &operator=(const close_guard &) = delete; @@ -87,7 +86,7 @@ void WellInfo::add_UNRST_wells(rd_file_type *rst_file, void WellInfo::load_rstfile(const std::string &filename, bool load_segment_information) { - rd_file_ptr rd_file(rd_file_open(filename.c_str(), 0), rd_file_close); + rd_file_ptr rd_file = open_rd_file(filename); load_rstfile(rd_file.get(), load_segment_information); } diff --git a/lib/resdata/well_rseg_loader.cpp b/lib/resdata/well_rseg_loader.cpp index af28fa37d..579a8496f 100644 --- a/lib/resdata/well_rseg_loader.cpp +++ b/lib/resdata/well_rseg_loader.cpp @@ -1,15 +1,13 @@ - +#include #include #include -#include #include #include #include #include - -#include +#include struct well_rseg_loader_struct { rd_file_view_type *rst_view; @@ -41,7 +39,7 @@ well_rseg_loader_type *well_rseg_loader_alloc(rd_file_view_type *rst_view) { void well_rseg_loader_free(well_rseg_loader_type *loader) { - if (rd_file_view_flags_set(loader->rst_view, RD_FILE_CLOSE_STREAM)) + if (rd_file_view_flags_set(loader->rst_view, FileMode::CLOSE_STREAM)) rd_file_view_fclose_stream(loader->rst_view); int_vector_free(loader->relative_index_map); diff --git a/lib/tests/test_geertsma.cpp b/lib/tests/test_geertsma.cpp index 99e8fb35c..ed085f8f6 100644 --- a/lib/tests/test_geertsma.cpp +++ b/lib/tests/test_geertsma.cpp @@ -81,8 +81,8 @@ TEST_CASE_METHOD(Tmpdir, "Geertsma kernel single cell") { write_subsidence_init(init_path, size); write_subsidence_restart(unrst_path, std::vector{1.0f}); - rd_file_ptr init = open_rd_file(init_path, 0); - rd_file_ptr restart = open_rd_file(unrst_path, 0); + rd_file_ptr init = open_rd_file(init_path); + rd_file_ptr restart = open_rd_file(unrst_path); std::unique_ptr subsidence(rd_subsidence_alloc(grid.get(), init.get()), @@ -132,8 +132,8 @@ TEST_CASE_METHOD(Tmpdir, "Geertsma kernel two source points two vintages") { write_subsidence_restart(unrst_path, std::vector{1.0f, 10.0f}, std::vector{10.0f, 20.0f}); - rd_file_ptr init = open_rd_file(init_path, 0); - rd_file_ptr restart = open_rd_file(unrst_path, 0); + rd_file_ptr init = open_rd_file(init_path); + rd_file_ptr restart = open_rd_file(unrst_path); std::unique_ptr subsidence(rd_subsidence_alloc(grid.get(), init.get()), @@ -178,8 +178,8 @@ TEST_CASE_METHOD(Tmpdir, "Geertsma kernel with seabed") { write_subsidence_init(init_path, rd_grid_get_active_size(grid.get())); write_subsidence_restart(unrst_path, std::vector{1.0f}); - rd_file_ptr init = open_rd_file(init_path, 0); - rd_file_ptr restart = open_rd_file(unrst_path, 0); + rd_file_ptr init = open_rd_file(init_path); + rd_file_ptr restart = open_rd_file(unrst_path); std::unique_ptr subsidence(rd_subsidence_alloc(grid.get(), init.get()), @@ -215,8 +215,8 @@ TEST_CASE_METHOD(Tmpdir, std::vector{1e5f, 1e5f}, std::vector{9e4f, 9e4f}); - rd_file_ptr init = open_rd_file(init_path, 0); - rd_file_ptr restart = open_rd_file(unrst_path, 0); + rd_file_ptr init = open_rd_file(init_path); + rd_file_ptr restart = open_rd_file(unrst_path); std::unique_ptr subsidence(rd_subsidence_alloc(grid.get(), init.get()), @@ -260,8 +260,8 @@ TEST_CASE_METHOD(Tmpdir, "Subsidence survey validation") { std::vector{1e5f, 1e5f}, std::vector{9e4f, 9e4f}); - rd_file_ptr init = open_rd_file(init_path, 0); - rd_file_ptr restart = open_rd_file(unrst_path, 0); + rd_file_ptr init = open_rd_file(init_path); + rd_file_ptr restart = open_rd_file(unrst_path); std::unique_ptr subsidence(rd_subsidence_alloc(grid.get(), init.get()), diff --git a/lib/tests/test_rd_sum.cpp b/lib/tests/test_rd_sum.cpp index 54939822d..aca1ae6f6 100644 --- a/lib/tests/test_rd_sum.cpp +++ b/lib/tests/test_rd_sum.cpp @@ -789,7 +789,7 @@ TEST_CASE_METHOD(Tmpdir, "Restart writer writes has restart kw") { } const std::string smspec_ext = fmt_output ? ".FSMSPEC" : ".SMSPEC"; - auto restart_file = open_rd_file(restart_name + smspec_ext, 0); + auto restart_file = open_rd_file(restart_name + smspec_ext); REQUIRE(restart_file != nullptr); rd_file_view_type *view = rd_file_get_global_view(restart_file.get()); REQUIRE(rd_file_view_has_kw(view, RESTART_KW)); @@ -832,7 +832,7 @@ TEST_CASE_METHOD(Tmpdir, "Restart case names are split across the 8 blocks") { rd_sum_fwrite(rd_sum.get()); } - auto smspec_file = open_rd_file(name + ".SMSPEC", 0); + auto smspec_file = open_rd_file(name + ".SMSPEC"); rd_file_view_type *view = rd_file_get_global_view(smspec_file.get()); REQUIRE(rd_file_view_has_kw(view, RESTART_KW)); rd_kw_type *restart_kw = rd_file_view_iget_named_kw(view, RESTART_KW, 0); @@ -1422,8 +1422,8 @@ SCENARIO_METHOD(Tmpdir, "Loading Restarts") { } WHEN("CASE3 is post-processed into CASE4 by appending a duplicate " "BPR keyword and a WTPRWI1 placeholder") { - auto smspec_in = open_rd_file(case3_path + ".SMSPEC", 0); - auto sum_in = open_rd_file(case3_path + ".UNSMRY", 0); + auto smspec_in = open_rd_file(case3_path + ".SMSPEC"); + auto sum_in = open_rd_file(case3_path + ".UNSMRY"); rd_kw_type *keywords = rd_file_iget_named_kw(smspec_in.get(), "KEYWORDS", 0); @@ -1523,7 +1523,7 @@ SCENARIO_METHOD(Tmpdir, "rd::unsmry_loader reads back values from a UNSMRY") { WHEN("A rd::unsmry_loader is constructed over the UNSMRY file") { auto loader = std::make_unique( - rd_sum_get_smspec(rd_sum.get()), case_path + ".UNSMRY", 0); + rd_sum_get_smspec(rd_sum.get()), case_path + ".UNSMRY"); THEN("get_vector returns the per-keyword series") { const std::vector fopt = loader->get_vector(1); @@ -1785,8 +1785,7 @@ TEST_CASE_METHOD(Tmpdir, "fread_alloc_case guesses base when given directory") { auto explicit_sum = rd_sum_ptr( rd_sum_fread_alloc(header_file.c_str(), data_files.get(), ":", /*include_restart=*/true, - /*lazy_load=*/true, - /*file_options=*/0), + /*lazy_load=*/true), &rd_sum_free); REQUIRE(explicit_sum.get() != nullptr); diff --git a/lib/tests/test_well_info.cpp b/lib/tests/test_well_info.cpp index d40b5c356..5b2a9f987 100644 --- a/lib/tests/test_well_info.cpp +++ b/lib/tests/test_well_info.cpp @@ -190,7 +190,7 @@ bool is_loaded(std::shared_ptr file_kw) { TEST_CASE_METHOD(Tmpdir, "keywords are lazily loaded", "[well][transaction]") { auto path = write_three_kw_file(dirname); - rd_file_ptr file(rd_file_open(path.c_str(), 0), rd_file_close); + rd_file_ptr file = open_rd_file(path); auto *view = rd_file_get_global_view(file.get()); auto fk0 = rd_file_view_iget_file_kw(view, 0); diff --git a/python/resdata/rd_util.py b/python/resdata/rd_util.py index 5f8195a72..f07067b33 100644 --- a/python/resdata/rd_util.py +++ b/python/resdata/rd_util.py @@ -15,6 +15,7 @@ from cwrap import BaseCEnum from resdata import ResdataPrototype +from resdata._file_mode import FileMode class FileType(BaseCEnum): @@ -45,9 +46,6 @@ class FileType(BaseCEnum): FileType.addEnum("DATA", 512) -# ----------------------------------------------------------------- - - class Phase(BaseCEnum): TYPE_NAME = "rd_phase_enum" OIL = None @@ -60,9 +58,6 @@ class Phase(BaseCEnum): Phase.addEnum("WATER", 4) -# ----------------------------------------------------------------- - - class UnitSystem(BaseCEnum): TYPE_NAME = "rd_unit_enum" @@ -78,24 +73,6 @@ class UnitSystem(BaseCEnum): UnitSystem.addEnum("PVT_M", 4) -# ----------------------------------------------------------------- - - -class FileMode(BaseCEnum): - TYPE_NAME = "rd_file_flag_enum" - DEFAULT = None - CLOSE_STREAM = None - WRITABLE = None - - -FileMode.addEnum("DEFAULT", 0) -FileMode.addEnum("CLOSE_STREAM", 1) -FileMode.addEnum("WRITABLE", 2) - - -# ----------------------------------------------------------------- - - class ResdataUtil: _get_num_cpu = ResdataPrototype("int rd_get_num_cpu(char*)", bind=False) _get_file_type = ResdataPrototype( @@ -157,3 +134,14 @@ def report_step(filename): get_num_cpu = ResdataUtil.get_num_cpu get_file_type = ResdataUtil.get_file_type get_start_date = ResdataUtil.get_start_date + +__all__ = [ + "FileMode", + "FileType", + "Phase", + "ResdataUtil", + "UnitSystem", + "get_file_type", + "get_num_cpu", + "get_start_date", +] diff --git a/python/resdata/summary/rd_sum.py b/python/resdata/summary/rd_sum.py index 83f5f927e..016c938e9 100644 --- a/python/resdata/summary/rd_sum.py +++ b/python/resdata/summary/rd_sum.py @@ -23,7 +23,7 @@ from cwrap import CFILE, BaseCClass import resdata.summary._rd_sum as _rd_sum -from resdata import UnitSystem +from resdata import FileMode, UnitSystem from resdata.util.util import ( CTime, DoubleVector, @@ -58,7 +58,7 @@ def __init__( join_string=":", include_restart=True, lazy_load=True, - file_options=0, + file_options=FileMode.DEFAULT, ): """Loads a new Summary instance with summary data. @@ -82,7 +82,7 @@ def __init__( whereas getting a vector will be slower. When the summary data is split over multiple CASE.Snnn files all the data will be loaded at construction time, and the @lazy_load option is ignored. If the - lazy_load functionality is used the file_options integer flag is passed + lazy_load functionality is used the file_options flag is passed when opening the UNSMRY file. """ @@ -110,7 +110,12 @@ def load(cls, smspec_file, unsmry_file, key_join_string=":", include_restart=Tru data_files = StringList() data_files.append(unsmry_file) c_ptr = _rd_sum._fread_alloc( - smspec_file, data_files, key_join_string, include_restart, False, 0 + smspec_file, + data_files, + key_join_string, + include_restart, + False, + FileMode.DEFAULT, ) if not c_ptr: raise OSError("Failed to create summary instance") diff --git a/tests/test_file_mode.py b/tests/test_file_mode.py new file mode 100644 index 000000000..20202e11a --- /dev/null +++ b/tests/test_file_mode.py @@ -0,0 +1,66 @@ +import pytest +from resdata import FileMode + + +def test_that_the_file_mode_enum_exposes_the_expected_members(): + assert set(FileMode.__members__) == {"DEFAULT", "CLOSE_STREAM", "WRITABLE"} + + +@pytest.mark.parametrize( + "mode, value", + [ + (FileMode.DEFAULT, 0), + (FileMode.CLOSE_STREAM, 1), + (FileMode.WRITABLE, 2), + ], +) +def test_that_file_mode_members_have_the_expected_integer_values(mode, value): + assert int(mode) == value + + +def test_that_or_combines_flags(): + combined = FileMode.CLOSE_STREAM | FileMode.WRITABLE + + assert isinstance(combined, FileMode) + assert int(combined) == 3 + + +def test_that_or_with_default_is_a_no_op(): + assert FileMode.WRITABLE | FileMode.DEFAULT == FileMode.WRITABLE + + +def test_that_and_extracts_a_set_flag(): + combined = FileMode.CLOSE_STREAM | FileMode.WRITABLE + + assert combined & FileMode.WRITABLE == FileMode.WRITABLE + assert combined & FileMode.CLOSE_STREAM == FileMode.CLOSE_STREAM + + +def test_that_and_of_disjoint_flags_is_default(): + assert FileMode.CLOSE_STREAM & FileMode.WRITABLE == FileMode.DEFAULT + + +def test_that_xor_toggles_flags(): + assert FileMode.CLOSE_STREAM ^ FileMode.CLOSE_STREAM == FileMode.DEFAULT + assert int(FileMode.CLOSE_STREAM ^ FileMode.WRITABLE) == 3 + + +def test_that_xor_can_clear_a_single_flag(): + combined = FileMode.CLOSE_STREAM | FileMode.WRITABLE + + assert combined ^ FileMode.WRITABLE == FileMode.CLOSE_STREAM + + +def test_that_invert_flips_all_bits(): + assert int(~FileMode.DEFAULT) == -1 + assert int(~FileMode.CLOSE_STREAM) == -2 + + +def test_that_inverting_twice_is_the_identity(): + assert ~~FileMode.WRITABLE == FileMode.WRITABLE + + +def test_that_a_flag_masks_out_of_a_combination_via_invert_and_and(): + combined = FileMode.CLOSE_STREAM | FileMode.WRITABLE + + assert combined & ~FileMode.WRITABLE == FileMode.CLOSE_STREAM From 8213663a4b431f1d9efae70856fbf8cbda36ef3c Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 14:14:00 +0200 Subject: [PATCH 12/20] Fix spelling mistakes in rd_sum_data.cpp docs --- lib/resdata/rd_sum_data.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/resdata/rd_sum_data.cpp b/lib/resdata/rd_sum_data.cpp index 4e8814f80..ee5c46aaf 100644 --- a/lib/resdata/rd_sum_data.cpp +++ b/lib/resdata/rd_sum_data.cpp @@ -38,11 +38,11 @@ namespace fs = std::filesystem; /* - This file implements the sruct rd_sum_data which manages the actual simulated + This file implements the struct rd_sum_data which manages the actual simulated values from a summary file, including all time-related information. In the case of restarted simulations the different summary cases will be internalized as separate rd_sum_file_data instances. The rd_sum_file_data class is an - internal implemenation detail which is not exported. More details about the + internal implementation detail which is not exported. More details about the internal storage of summary data can be found in that file. For this file the implementation mainly consists of maintaining an ordered @@ -789,7 +789,7 @@ double rd_sum_data_get_from_sim_time(const rd_sum_data_type *data, However - as indicated on the figure above there is a zero measure point right at the start which corresponds to - time_index == 0; this is to ensure that there is correspondance + time_index == 0; this is to ensure that there is correspondence with the simulator results if you ask for a value interpolated to the starting time. */ From 462a738e776aa28e83f7798bc5e799c63e56405c Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 14:49:54 +0200 Subject: [PATCH 13/20] Move rd_file_view_struct to header --- lib/include/resdata/rd_file_view.hpp | 18 ++++++++++++++++++ lib/resdata/rd_file_view.cpp | 19 ------------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/lib/include/resdata/rd_file_view.hpp b/lib/include/resdata/rd_file_view.hpp index 343346567..87e09ed41 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include @@ -15,6 +17,22 @@ using inv_map_type = std::unordered_map; typedef struct rd_file_view_struct rd_file_view_type; +struct rd_file_view_struct { + std::vector> kw_list; + std::map> kw_index; + std::vector + distinct_kw; /* A list of the keywords occuring in the file - each string occurs ONLY ONCE. */ + ERT::FortIO * + fortio; /* The same fortio instance pointer as in the rd_file styructure. */ + inv_map_type + *inv_map; /* Shared reference owned by the rd_file structure. */ + std::vector> child_list; + FileMode *flags; + + rd_file_view_struct(ERT::FortIO *fortio, FileMode *flags, + inv_map_type *inv_map) + : fortio(fortio), inv_map(inv_map), flags(flags) {}; +}; bool rd_file_view_flags_set(const rd_file_view_type *file_view, FileMode query_flags); diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index 5f4507745..3378e9ba1 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -4,9 +4,7 @@ #include #include -#include #include -#include #include #include @@ -22,23 +20,6 @@ #include #include -struct rd_file_view_struct { - std::vector> kw_list; - std::map> kw_index; - std::vector - distinct_kw; /* A list of the keywords occuring in the file - each string occurs ONLY ONCE. */ - ERT::FortIO * - fortio; /* The same fortio instance pointer as in the rd_file styructure. */ - inv_map_type - *inv_map; /* Shared reference owned by the rd_file structure. */ - std::vector> child_list; - FileMode *flags; - - rd_file_view_struct(ERT::FortIO *fortio, FileMode *flags, - inv_map_type *inv_map) - : fortio(fortio), inv_map(inv_map), flags(flags) {}; -}; - bool rd_file_view_check_flags(FileMode state_flags, FileMode query_flags) { return (state_flags & query_flags) == query_flags; } From b388ee91e3c7360d5e016b6a1a4ddb415f274dfe Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Thu, 9 Jul 2026 15:00:57 +0200 Subject: [PATCH 14/20] Use constructor and destructor for rd_file_view_struct --- lib/include/resdata/rd_file_view.hpp | 7 +------ lib/resdata/rd_file.cpp | 4 ++-- lib/resdata/rd_file_view.cpp | 30 ++++++++++------------------ lib/resdata/rd_grid.cpp | 3 +-- lib/resdata/tests/rd_nnc_test.cpp | 28 ++++++++++++-------------- 5 files changed, 28 insertions(+), 44 deletions(-) diff --git a/lib/include/resdata/rd_file_view.hpp b/lib/include/resdata/rd_file_view.hpp index 87e09ed41..8c0a929c8 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -37,9 +37,6 @@ struct rd_file_view_struct { bool rd_file_view_flags_set(const rd_file_view_type *file_view, FileMode query_flags); bool rd_file_view_check_flags(FileMode state_flags, FileMode query_flags); - -rd_file_view_type *rd_file_view_alloc(ERT::FortIO *fortio, FileMode *flags, - inv_map_type *inv_map); void rd_file_view_make_index(rd_file_view_type *rd_file_view); bool rd_file_view_has_kw(const rd_file_view_type *rd_file_view, const char *kw); rd_kw_type *rd_file_view_iget_kw(const rd_file_view_type *rd_file_view, @@ -55,7 +52,6 @@ int rd_file_view_get_size(const rd_file_view_type *rd_file_view); rd_kw_type *rd_file_view_iget_named_kw(const rd_file_view_type *rd_file_view, const char *kw, int ith); bool rd_file_view_load_all(rd_file_view_type *rd_file_view); -void rd_file_view_free(rd_file_view_type *rd_file_view); int rd_file_view_get_num_named_kw(const rd_file_view_type *rd_file_view, const char *kw); void rd_file_view_fwrite(const rd_file_view_type *rd_file_view, @@ -105,8 +101,7 @@ rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, void rd_file_view_clear(rd_file_view_type *file_view); -using rd_file_view_ptr = - std::unique_ptr; +using rd_file_view_ptr = std::unique_ptr; std::shared_ptr rd_file_view_iget_file_kw(const rd_file_view_type *rd_file_view, diff --git a/lib/resdata/rd_file.cpp b/lib/resdata/rd_file.cpp index 44cc35f7c..f1d5a9cda 100644 --- a/lib/resdata/rd_file.cpp +++ b/lib/resdata/rd_file.cpp @@ -339,7 +339,7 @@ rd_file_type *rd_file_open(const char *filename, FileMode flags) { if (fortio) { rd_file_ptr rd_file(rd_file_alloc_empty(flags), &rd_file_close); rd_file->fortio = fortio.release(); - rd_file->global_view = rd_file_view_alloc( + rd_file->global_view = new rd_file_view_struct( rd_file->fortio, &rd_file->flags, rd_file->inv_view); rd_file_scan(rd_file.get()); @@ -368,7 +368,7 @@ void rd_file_close(rd_file_type *rd_file) { delete rd_file->fortio; if (rd_file->global_view) - rd_file_view_free(rd_file->global_view); + delete rd_file->global_view; delete rd_file->inv_view; vector_free(rd_file->map_stack); diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index 3378e9ba1..f44f3feb4 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -204,8 +204,6 @@ void rd_file_view_add_kw(rd_file_view_type *rd_file_view, rd_file_view->kw_list.push_back(file_kw); } -void rd_file_view_free(rd_file_view_type *rd_file_view) { delete rd_file_view; } - int rd_file_view_get_num_named_kw(const rd_file_view_type *rd_file_view, const char *kw) { if (rd_file_view_has_kw(rd_file_view, kw)) { @@ -249,7 +247,7 @@ rd_file_view_alloc_blockview2(const rd_file_view_type *rd_file_view, rd_file_view_get_num_named_kw(rd_file_view, start_kw) <= occurence) return NULL; - rd_file_view_type *block_map = rd_file_view_alloc( + rd_file_view_type *block_map = new rd_file_view_struct( rd_file_view->fortio, rd_file_view->flags, rd_file_view->inv_map); size_t kw_index = 0; if (start_kw) @@ -450,9 +448,8 @@ static time_t rd_rsthead_date(const rd_kw_type *intehead_kw) { time_t rd_file_view_iget_restart_sim_date(const rd_file_view_type *rd_file_view, int seqnum_index) { time_t sim_time = -1; - std::unique_ptr seqnum_map( - rd_file_view_alloc_blockview(rd_file_view, SEQNUM_KW, seqnum_index), - &rd_file_view_free); + rd_file_view_ptr seqnum_map( + rd_file_view_alloc_blockview(rd_file_view, SEQNUM_KW, seqnum_index)); if (seqnum_map) { rd_kw_type *intehead_kw = @@ -466,9 +463,8 @@ time_t rd_file_view_iget_restart_sim_date(const rd_file_view_type *rd_file_view, double rd_file_view_iget_restart_sim_days(const rd_file_view_type *rd_file_view, int seqnum_index) { double sim_days = 0; - std::unique_ptr seqnum_map( - rd_file_view_alloc_blockview(rd_file_view, SEQNUM_KW, seqnum_index), - &rd_file_view_free); + rd_file_view_ptr seqnum_map( + rd_file_view_alloc_blockview(rd_file_view, SEQNUM_KW, seqnum_index)); if (seqnum_map) { rd_kw_type *doubhead_kw = @@ -596,10 +592,8 @@ rd_file_view_seqnum_index_from_sim_time(rd_file_view_type *parent_map, int num_seqnum = rd_file_view_get_num_named_kw(parent_map, SEQNUM_KW); for (int s_idx = 0; s_idx < num_seqnum; s_idx++) { - std::unique_ptr - seqnum_map( - rd_file_view_alloc_blockview(parent_map, SEQNUM_KW, s_idx), - &rd_file_view_free); + rd_file_view_ptr seqnum_map( + rd_file_view_alloc_blockview(parent_map, SEQNUM_KW, s_idx)); if (!seqnum_map) continue; @@ -616,10 +610,8 @@ static int rd_file_view_seqnum_index_from_sim_days(rd_file_view_type *file_view, int seqnum_index = 0; while (true) { - std::unique_ptr - seqnum_map(rd_file_view_alloc_blockview(file_view, SEQNUM_KW, - seqnum_index), - &rd_file_view_free); + rd_file_view_ptr seqnum_map( + rd_file_view_alloc_blockview(file_view, SEQNUM_KW, seqnum_index)); if (seqnum_map) { if (rd_file_view_has_sim_days(seqnum_map.get(), sim_days)) { @@ -694,8 +686,8 @@ rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, int index_size = util_fread_int(istream); if (index_size < 0) return NULL; - rd_file_view_ptr file_view(rd_file_view_alloc(fortio, flags, inv_map), - &rd_file_view_free); + auto file_view = + std::make_unique(fortio, flags, inv_map); try { file_view->kw_list = diff --git a/lib/resdata/rd_grid.cpp b/lib/resdata/rd_grid.cpp index 060fc7e02..381586d63 100644 --- a/lib/resdata/rd_grid.cpp +++ b/lib/resdata/rd_grid.cpp @@ -2389,8 +2389,7 @@ static void rd_grid_init_nnc(rd_grid_type *main_grid, rd_file_type *rd_file) { for (int i = 0; i < num_nnchead_kw; i++) { auto lgr_view = rd_file_view_ptr( - rd_file_alloc_global_blockview(rd_file, NNCHEAD_KW, i), - &rd_file_view_free); + rd_file_alloc_global_blockview(rd_file, NNCHEAD_KW, i)); rd_kw_type *nnchead_kw = rd_file_view_iget_named_kw(lgr_view.get(), NNCHEAD_KW, 0); int lgr_nr = rd_kw_iget_int(nnchead_kw, NNCHEAD_LGR_INDEX); diff --git a/lib/resdata/tests/rd_nnc_test.cpp b/lib/resdata/tests/rd_nnc_test.cpp index ac5339a8d..a89d12891 100644 --- a/lib/resdata/tests/rd_nnc_test.cpp +++ b/lib/resdata/tests/rd_nnc_test.cpp @@ -36,8 +36,8 @@ void test_scan(const char *grid_filename) { block_nr++) { rd_grid_type *lgr = rd_grid; int lgr_nr; - rd_file_view_type *nnc_view = - rd_file_alloc_global_blockview(grid_file, NNCHEAD_KW, block_nr); + rd_file_view_ptr nnc_view( + rd_file_alloc_global_blockview(grid_file, NNCHEAD_KW, block_nr)); { if (block_nr > 0) lgr = rd_grid_iget_lgr(rd_grid, block_nr - 1); @@ -45,11 +45,11 @@ void test_scan(const char *grid_filename) { /* Internal nnc */ { - if (rd_file_view_has_kw(nnc_view, NNC1_KW)) { + if (rd_file_view_has_kw(nnc_view.get(), NNC1_KW)) { rd_kw_type *nnc1_kw = - rd_file_view_iget_named_kw(nnc_view, NNC1_KW, 0); + rd_file_view_iget_named_kw(nnc_view.get(), NNC1_KW, 0); rd_kw_type *nnc2_kw = - rd_file_view_iget_named_kw(nnc_view, NNC2_KW, 0); + rd_file_view_iget_named_kw(nnc_view.get(), NNC2_KW, 0); int i; for (i = 0; i < rd_kw_get_size(nnc1_kw); i++) { const int g1 = rd_kw_iget_int(nnc1_kw, i) - 1; @@ -73,13 +73,13 @@ void test_scan(const char *grid_filename) { /* Global -> lgr */ { - if (rd_file_view_has_kw(nnc_view, NNCG_KW)) { + if (rd_file_view_has_kw(nnc_view.get(), NNCG_KW)) { rd_kw_type *nnchead_kw = - rd_file_view_iget_named_kw(nnc_view, NNCHEAD_KW, 0); + rd_file_view_iget_named_kw(nnc_view.get(), NNCHEAD_KW, 0); rd_kw_type *nncg_kw = - rd_file_view_iget_named_kw(nnc_view, NNCG_KW, 0); + rd_file_view_iget_named_kw(nnc_view.get(), NNCG_KW, 0); rd_kw_type *nncl_kw = - rd_file_view_iget_named_kw(nnc_view, NNCL_KW, 0); + rd_file_view_iget_named_kw(nnc_view.get(), NNCL_KW, 0); int i; int lgr_nr = rd_kw_iget_int(nnchead_kw, NNCHEAD_LGR_INDEX); for (i = 0; i < rd_kw_get_size(nncg_kw); i++) { @@ -103,13 +103,13 @@ void test_scan(const char *grid_filename) { /* Amalgamated: LGR -> LGR */ { - if (rd_file_view_has_kw(nnc_view, NNCHEADA_KW)) { + if (rd_file_view_has_kw(nnc_view.get(), NNCHEADA_KW)) { rd_kw_type *nncheada_kw = - rd_file_view_iget_named_kw(nnc_view, NNCHEADA_KW, 0); + rd_file_view_iget_named_kw(nnc_view.get(), NNCHEADA_KW, 0); rd_kw_type *nnc1_kw = - rd_file_view_iget_named_kw(nnc_view, NNA1_KW, 0); + rd_file_view_iget_named_kw(nnc_view.get(), NNA1_KW, 0); rd_kw_type *nnc2_kw = - rd_file_view_iget_named_kw(nnc_view, NNA2_KW, 0); + rd_file_view_iget_named_kw(nnc_view.get(), NNA2_KW, 0); int lgr_nr1 = rd_kw_iget_int(nncheada_kw, NNCHEADA_ILOC1_INDEX); int lgr_nr2 = rd_kw_iget_int(nncheada_kw, NNCHEADA_ILOC2_INDEX); @@ -129,8 +129,6 @@ void test_scan(const char *grid_filename) { } } } - - rd_file_view_free(nnc_view); } } From 3e3066446de723f9ec7c22b3501e29bba080183e Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Fri, 10 Jul 2026 06:26:41 +0200 Subject: [PATCH 15/20] Rename rd_file_struct to FileView --- lib/include/resdata/rd_file_view.hpp | 7 +++---- lib/resdata/rd_file.cpp | 4 ++-- lib/resdata/rd_file_view.cpp | 7 +++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/include/resdata/rd_file_view.hpp b/lib/include/resdata/rd_file_view.hpp index 8c0a929c8..c14b3fe7a 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -16,8 +16,8 @@ using inv_map_type = std::unordered_map; -typedef struct rd_file_view_struct rd_file_view_type; -struct rd_file_view_struct { +typedef struct FileView rd_file_view_type; +struct FileView { std::vector> kw_list; std::map> kw_index; std::vector @@ -29,8 +29,7 @@ struct rd_file_view_struct { std::vector> child_list; FileMode *flags; - rd_file_view_struct(ERT::FortIO *fortio, FileMode *flags, - inv_map_type *inv_map) + FileView(ERT::FortIO *fortio, FileMode *flags, inv_map_type *inv_map) : fortio(fortio), inv_map(inv_map), flags(flags) {}; }; diff --git a/lib/resdata/rd_file.cpp b/lib/resdata/rd_file.cpp index f1d5a9cda..c6b9ec258 100644 --- a/lib/resdata/rd_file.cpp +++ b/lib/resdata/rd_file.cpp @@ -339,8 +339,8 @@ rd_file_type *rd_file_open(const char *filename, FileMode flags) { if (fortio) { rd_file_ptr rd_file(rd_file_alloc_empty(flags), &rd_file_close); rd_file->fortio = fortio.release(); - rd_file->global_view = new rd_file_view_struct( - rd_file->fortio, &rd_file->flags, rd_file->inv_view); + rd_file->global_view = + new FileView(rd_file->fortio, &rd_file->flags, rd_file->inv_view); rd_file_scan(rd_file.get()); rd_file_select_global(rd_file.get()); diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index f44f3feb4..bf63ec534 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -35,7 +35,7 @@ const char *rd_file_view_get_src_file(const rd_file_view_type *file_view) { rd_file_view_type *rd_file_view_alloc(ERT::FortIO *fortio, FileMode *flags, inv_map_type *inv_map) { - return new rd_file_view_struct(fortio, flags, inv_map); + return new FileView(fortio, flags, inv_map); } static int rd_file_view_get_global_index(const rd_file_view_type *rd_file_view, @@ -247,7 +247,7 @@ rd_file_view_alloc_blockview2(const rd_file_view_type *rd_file_view, rd_file_view_get_num_named_kw(rd_file_view, start_kw) <= occurence) return NULL; - rd_file_view_type *block_map = new rd_file_view_struct( + rd_file_view_type *block_map = new FileView( rd_file_view->fortio, rd_file_view->flags, rd_file_view->inv_map); size_t kw_index = 0; if (start_kw) @@ -686,8 +686,7 @@ rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, int index_size = util_fread_int(istream); if (index_size < 0) return NULL; - auto file_view = - std::make_unique(fortio, flags, inv_map); + auto file_view = std::make_unique(fortio, flags, inv_map); try { file_view->kw_list = From be1339f0ef0addc56810d776aa946e53a917221c Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Mon, 13 Jul 2026 13:17:06 +0200 Subject: [PATCH 16/20] Remove extern "C" around well_rseg_loader --- lib/include/resdata/well/well_rseg_loader.hpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/lib/include/resdata/well/well_rseg_loader.hpp b/lib/include/resdata/well/well_rseg_loader.hpp index d573d52b7..f27e25052 100644 --- a/lib/include/resdata/well/well_rseg_loader.hpp +++ b/lib/include/resdata/well/well_rseg_loader.hpp @@ -1,12 +1,7 @@ -#ifndef ERT_WELL_RSEG_LOADER_H -#define ERT_WELL_RSEG_LOADER_H +#pragma once #include -#ifdef __cplusplus -extern "C" { -#endif - typedef struct well_rseg_loader_struct well_rseg_loader_type; well_rseg_loader_type *well_rseg_loader_alloc(rd_file_view_type *rst_view); @@ -15,9 +10,3 @@ void well_rseg_loader_free(well_rseg_loader_type *well_rseg_loader); double * well_rseg_loader_load_values(const well_rseg_loader_type *well_rseg_loader, int rseg_offset); - -#ifdef __cplusplus -} -#endif - -#endif From 6df9cb62901538d285a8401e29fcbb0743dee909 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Fri, 10 Jul 2026 12:52:07 +0200 Subject: [PATCH 17/20] Use pybind to define rd_file_view Since we now have better control over the integer type conversions, get_kw now takes size_t. This fixes a object life-time issue with ResdataFile where all read values would be cleaned up after close, meaning all use of kws read inside an open_rd_file context be use-after-free. --- applications/resdata/rd_unpack.cpp | 17 +- lib/CMakeLists.txt | 2 +- lib/include/resdata/FortIO.hpp | 1 + lib/include/resdata/rd_file.hpp | 27 +- lib/include/resdata/rd_file_view.hpp | 205 +++--- lib/include/resdata/rd_grav.hpp | 24 +- lib/include/resdata/rd_rsthead.hpp | 18 +- lib/include/resdata/rd_subsidence.hpp | 2 +- lib/include/resdata/well/well_info.hpp | 2 +- lib/include/resdata/well/well_rseg_loader.hpp | 2 +- lib/include/resdata/well/well_state.hpp | 24 +- .../detail/resdata/cwrap_pybind.hpp | 1 - .../detail/resdata/rd_sum_file_data.hpp | 2 +- .../detail/resdata/rd_unsmry_loader.hpp | 6 +- lib/resdata/cwrap_pybind.cpp | 14 - lib/resdata/rd_file.cpp | 207 +++--- lib/resdata/rd_file_pybind.cpp | 15 +- lib/resdata/rd_file_view.cpp | 596 ++++++------------ lib/resdata/rd_file_view_pybind.cpp | 297 +++++++-- lib/resdata/rd_grav.cpp | 95 ++- lib/resdata/rd_grav_pybind.cpp | 28 +- lib/resdata/rd_grid.cpp | 26 +- lib/resdata/rd_subsidence.cpp | 12 +- lib/resdata/rd_subsidence_pybind.cpp | 14 +- lib/resdata/rd_sum_file_data.cpp | 25 +- lib/resdata/rd_unsmry_loader.cpp | 47 +- lib/resdata/rsthead_pybind.cpp | 49 +- lib/resdata/tests/rd_file.cpp | 34 +- lib/resdata/tests/rd_file_equinor.cpp | 52 +- lib/resdata/tests/rd_grid_dx_dy_dz.cpp | 12 +- lib/resdata/tests/rd_grid_export.cpp | 13 +- lib/resdata/tests/rd_grid_init_fwrite.cpp | 16 +- lib/resdata/tests/rd_lgr_test.cpp | 12 +- lib/resdata/tests/rd_nnc_test.cpp | 51 +- lib/resdata/tests/rd_rsthead.cpp | 18 +- lib/resdata/tests/rdxx_kw.cpp | 14 +- lib/resdata/tests/test_rd_file_index.cpp | 37 +- lib/resdata/tests/well_conn_CF.cpp | 15 +- lib/resdata/tests/well_dualp.cpp | 11 +- lib/resdata/tests/well_segment_load.cpp | 17 +- lib/resdata/tests/well_state_load.cpp | 11 +- .../tests/well_state_load_missing_RSEG.cpp | 10 +- lib/resdata/well_info.cpp | 42 +- lib/resdata/well_rseg_loader.cpp | 11 +- lib/resdata/well_state.cpp | 89 ++- lib/tests/grid_fixtures.hpp | 6 + lib/tests/test_geertsma.cpp | 46 +- lib/tests/test_rd_sum.cpp | 13 +- lib/tests/test_well_info.cpp | 10 +- python/resdata/resfile/rd_file.py | 25 +- python/resdata/resfile/rd_file_view.py | 165 ----- tests/rd_tests/test_rd_file.py | 151 +++++ tests/rd_tests/test_rd_file_view.py | 12 + 53 files changed, 1291 insertions(+), 1360 deletions(-) delete mode 100644 python/resdata/resfile/rd_file_view.py diff --git a/applications/resdata/rd_unpack.cpp b/applications/resdata/rd_unpack.cpp index 96d6d2ff1..89af91926 100644 --- a/applications/resdata/rd_unpack.cpp +++ b/applications/resdata/rd_unpack.cpp @@ -16,6 +16,14 @@ for more details. */ +#include +#include + +#include +#include +#include +#include + #include #include @@ -23,7 +31,8 @@ #include #include #include -#include +#include +#include namespace fs = std::filesystem; @@ -55,7 +64,7 @@ static void unpack_file(const fs::path &filepath) { size = rd_file_get_num_named_kw(src_file.get(), "SEQNUM"); for (int block_index = 0; block_index < size; block_index++) { - rd_file_view_type *active_view; + std::shared_ptr active_view; if (target_type == RD_SUMMARY_FILE) { active_view = rd_file_get_global_blockview(src_file.get(), @@ -66,7 +75,7 @@ static void unpack_file(const fs::path &filepath) { rd_kw_type *seqnum_kw; active_view = rd_file_get_global_blockview(src_file.get(), SEQNUM_KW, block_index); - seqnum_kw = rd_file_view_iget_named_kw(active_view, SEQNUM_KW, 0); + seqnum_kw = active_view->get_kw(SEQNUM_KW, 0); report_step = rd_kw_iget_int(seqnum_kw, 0); offset = 1; } @@ -81,7 +90,7 @@ static void unpack_file(const fs::path &filepath) { fs::path target_file = rd::filename(filepath.stem(), target_type, fmt_file, report_step); ERT::FortIO fortio_target(target_file, std::ios_base::out, fmt_file); - rd_file_view_fwrite(active_view, fortio_target, offset); + active_view->write(fortio_target, offset); } } diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index baf26dba1..ea96bb4e8 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -210,7 +210,7 @@ add_resdata_pybind_module(_grid rd_grid_pybind.cpp resdata/grid) add_resdata_pybind_module(_kw rd_kw_pybind.cpp resdata/resfile) add_resdata_pybind_module(_rsthead rsthead_pybind.cpp resdata/resfile) add_resdata_pybind_module(_file rd_file_pybind.cpp resdata/resfile) -add_resdata_pybind_module(_file_view rd_file_view_pybind.cpp resdata/resfile) +add_resdata_pybind_module(rd_file_view rd_file_view_pybind.cpp resdata/resfile) add_resdata_pybind_module(fortio fortio_pybind.cpp resdata/resfile) add_resdata_pybind_module(well well_pybind.cpp resdata) add_resdata_pybind_module(_subsidence rd_subsidence_pybind.cpp diff --git a/lib/include/resdata/FortIO.hpp b/lib/include/resdata/FortIO.hpp index 98cb77834..36253f81b 100644 --- a/lib/include/resdata/FortIO.hpp +++ b/lib/include/resdata/FortIO.hpp @@ -71,6 +71,7 @@ class FortIO { void fflush() const; void rewind() const; [[nodiscard]] const char *filename_ref() const; + [[nodiscard]] const std::string &filename() const { return m_filename; }; [[nodiscard]] bool fmt_file() const; [[nodiscard]] offset_type ftell() const; bool fseek(offset_type offset, int whence); diff --git a/lib/include/resdata/rd_file.hpp b/lib/include/resdata/rd_file.hpp index 5aebf6d43..bb8b0ba5a 100644 --- a/lib/include/resdata/rd_file.hpp +++ b/lib/include/resdata/rd_file.hpp @@ -24,6 +24,7 @@ bool rd_file_write_index(const rd_file_type *rd_file, const char *index_filename); bool rd_file_index_valid(const char *file_name, const char *index_file_name); void rd_file_close(rd_file_type *rd_file); +void rd_file_free(rd_file_type *rd_file); rd_kw_type *rd_file_icopy_kw(const rd_file_type *rd_file, int index); bool rd_file_has_kw(const rd_file_type *rd_file, const char *kw); int rd_file_get_num_named_kw(const rd_file_type *rd_file, const char *kw); @@ -36,18 +37,15 @@ void rd_file_fwrite_fortio(const rd_file_type *ec_file, ERT::FortIO &fortio, int rd_file_get_phases(const rd_file_type *init_file); bool rd_file_writable(const rd_file_type *rd_file); -bool rd_file_flags_set(const rd_file_type *rd_file, FileMode flags); rd_kw_type *rd_file_iget_kw(const rd_file_type *file, int global_index); rd_kw_type *rd_file_iget_named_kw(const rd_file_type *file, const char *kw, int ith); -rd_file_view_type *rd_file_get_global_blockview(rd_file_type *rd_file, - const char *kw, int occurence); -rd_file_view_type *rd_file_alloc_global_blockview(rd_file_type *rd_file, - const char *kw, - int occurence); -rd_file_view_type *rd_file_get_global_view(rd_file_type *rd_file); -rd_file_view_type *rd_file_get_active_view(rd_file_type *rd_file); +std::shared_ptr +rd_file_get_global_blockview(rd_file_type *rd_file, const char *kw, + int occurence); +std::shared_ptr rd_file_get_global_view(rd_file_type *rd_file); +std::shared_ptr rd_file_get_active_view(rd_file_type *rd_file); bool rd_file_save_kw(const rd_file_type *rd_file, const rd_kw_type *rd_kw); double rd_file_iget_restart_sim_days(const rd_file_type *restart_file, @@ -59,24 +57,21 @@ int rd_file_get_restart_index(const rd_file_type *restart_file, bool rd_file_has_report_step(const rd_file_type *rd_file, int report_step); bool rd_file_has_sim_time(const rd_file_type *rd_file, time_t sim_time); -rd_file_view_type *rd_file_get_restart_view(rd_file_type *rd_file, - int input_index, int report_step, - time_t sim_time, double sim_days); -rd_file_view_type *rd_file_get_summary_view(rd_file_type *rd_file, - int report_step); +std::shared_ptr rd_file_get_summary_view(rd_file_type *rd_file, + int report_step); UTIL_IS_INSTANCE_HEADER(rd_file); bool rd_file_subselect_block(rd_file_type *rd_file, const char *kw, int occurence); -using rd_file_ptr = std::unique_ptr; +using rd_file_ptr = std::unique_ptr; inline rd_file_ptr open_rd_file(const std::string &path, FileMode flags = FileMode::DEFAULT) { - return {rd_file_open(path.c_str(), flags), &rd_file_close}; + return {rd_file_open(path.c_str(), flags), &rd_file_free}; } inline rd_file_ptr open_rd_file(const std::filesystem::path &path, FileMode flags = FileMode::DEFAULT) { - return {rd_file_open(path.string().c_str(), flags), &rd_file_close}; + return {rd_file_open(path.string().c_str(), flags), &rd_file_free}; } diff --git a/lib/include/resdata/rd_file_view.hpp b/lib/include/resdata/rd_file_view.hpp index c14b3fe7a..da26a4160 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -4,8 +4,10 @@ #include #include #include +#include #include #include +#include #include @@ -13,97 +15,128 @@ #include #include #include +#include + +namespace rd { using inv_map_type = std::unordered_map; -typedef struct FileView rd_file_view_type; -struct FileView { +struct FileContext { + ERT::FortIO fortio; + FileMode flags; + inv_map_type inv_map; + + FileContext(ERT::FortIO fortio, FileMode flags) + : fortio(std::move(fortio)), flags(flags) {} +}; + +class FileView { std::vector> kw_list; std::map> kw_index; std::vector distinct_kw; /* A list of the keywords occuring in the file - each string occurs ONLY ONCE. */ - ERT::FortIO * - fortio; /* The same fortio instance pointer as in the rd_file styructure. */ - inv_map_type - *inv_map; /* Shared reference owned by the rd_file structure. */ - std::vector> child_list; - FileMode *flags; - - FileView(ERT::FortIO *fortio, FileMode *flags, inv_map_type *inv_map) - : fortio(fortio), inv_map(inv_map), flags(flags) {}; -}; + std::shared_ptr context; + [[nodiscard]] std::shared_ptr get_file_kw(const std::string &kw, + size_t ith) const { + return get_file_kw(kw_index.at(kw).at(ith)); + } + [[nodiscard]] rd_kw_type *get_kw(const std::shared_ptr &file_kw); + [[nodiscard]] int find_kw_value(const std::string &kw, const void *value); + [[nodiscard]] int get_occurence(size_t global_index); + [[nodiscard]] bool has_sim_days(double sim_days); + +public: + explicit FileView(std::shared_ptr context) + : context(std::move(context)) {}; + + [[nodiscard]] bool has_flags(FileMode flags) const; + bool drop_flags(FileMode flags); + void add_flag(FileMode flag); + + [[nodiscard]] const std::string &filename() const; + [[nodiscard]] std::shared_ptr + get_file_kw(size_t global_index) const { + return kw_list.at(global_index); + } + [[nodiscard]] auto begin() { return kw_list.begin(); } + [[nodiscard]] auto end() { return kw_list.end(); } + [[nodiscard]] std::vector get_distinct_kw() const { + return distinct_kw; + } + [[nodiscard]] size_t num_distinct_kw() const { return distinct_kw.size(); } + [[nodiscard]] size_t size() const { return kw_list.size(); } + [[nodiscard]] size_t num_named_kw(const std::string &kw) const { + auto it = kw_index.find(kw); + return (it != kw_index.end()) ? it->second.size() : 0; + } + + void add_kw(std::shared_ptr file_kw) { + kw_list.push_back(std::move(file_kw)); + } + + /** Builds the internal index. + + Must be called every time the content of the kw_list vector is + modified (otherwise the rd_file instance will be in an + inconsistent state). */ + void make_index(); + + [[nodiscard]] bool has_kw(const std::string &kw) const { + return kw_index.find(kw) != kw_index.end(); + } + rd_kw_type *get_kw(size_t index) { return get_kw(get_file_kw(index)); } + rd_kw_type *get_kw(const std::string &kw, size_t ith) { + return get_kw(get_file_kw(kw, ith)); + } + + void index_fload_kw(const std::string &kw, int index, + const int_vector_type *index_map, char *io_buffer); + bool load_all(); + void write(ERT::FortIO &target, int offset); -bool rd_file_view_flags_set(const rd_file_view_type *file_view, - FileMode query_flags); -bool rd_file_view_check_flags(FileMode state_flags, FileMode query_flags); -void rd_file_view_make_index(rd_file_view_type *rd_file_view); -bool rd_file_view_has_kw(const rd_file_view_type *rd_file_view, const char *kw); -rd_kw_type *rd_file_view_iget_kw(const rd_file_view_type *rd_file_view, - int index); -void rd_file_view_index_fload_kw(const rd_file_view_type *rd_file_view, - const char *kw, int index, - const int_vector_type *index_map, - char *buffer); -const std::string & -rd_file_view_iget_distinct_kw(const rd_file_view_type *rd_file_view, int index); -int rd_file_view_get_num_distinct_kw(const rd_file_view_type *rd_file_view); -int rd_file_view_get_size(const rd_file_view_type *rd_file_view); -rd_kw_type *rd_file_view_iget_named_kw(const rd_file_view_type *rd_file_view, - const char *kw, int ith); -bool rd_file_view_load_all(rd_file_view_type *rd_file_view); -int rd_file_view_get_num_named_kw(const rd_file_view_type *rd_file_view, - const char *kw); -void rd_file_view_fwrite(const rd_file_view_type *rd_file_view, - ERT::FortIO &target, int offset); -rd_file_view_type *rd_file_view_add_blockview(rd_file_view_type *rd_file_view, - const char *header, - int occurence); -rd_file_view_type *rd_file_view_add_blockview2(rd_file_view_type *rd_file_view, - const char *start_kw, - const char *end_kw, - int occurence); -rd_file_view_type *rd_file_view_add_restart_view(rd_file_view_type *file_view, - int seqnum_index, - int report_step, - time_t sim_time, - double sim_days); -rd_file_view_type * -rd_file_view_alloc_blockview2(const rd_file_view_type *rd_file_view, - const char *start_kw, const char *end_kw, - int occurence); - -bool rd_file_view_drop_flag(rd_file_view_type *file_view, FileMode flag); -void rd_file_view_add_flag(rd_file_view_type *file_view, FileMode flag); - -bool rd_file_view_has_sim_time(const rd_file_view_type *rd_file_view, - time_t sim_time); -int rd_file_view_find_sim_time(const rd_file_view_type *rd_file_view, - time_t sim_time); -double rd_file_view_iget_restart_sim_days(const rd_file_view_type *rd_file_view, - int seqnum_index); -time_t rd_file_view_iget_restart_sim_date(const rd_file_view_type *rd_file_view, - int seqnum_index); -bool rd_file_view_has_report_step(const rd_file_view_type *rd_file_view, - int report_step); - -rd_file_view_type *rd_file_view_add_summary_view(rd_file_view_type *file_view, - int report_step); -const char *rd_file_view_get_src_file(const rd_file_view_type *file_view); -void rd_file_view_fclose_stream(rd_file_view_type *file_view); - -void rd_file_view_write_index(const rd_file_view_type *file_view, - FILE *ostream); -rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, - FileMode *flags, - inv_map_type *inv_map, - FILE *istream); - -void rd_file_view_clear(rd_file_view_type *file_view); - -using rd_file_view_ptr = std::unique_ptr; - -std::shared_ptr -rd_file_view_iget_file_kw(const rd_file_view_type *rd_file_view, - int global_index); -void rd_file_view_add_kw(rd_file_view_type *rd_file_view, - std::shared_ptr file_kw); + /** Creates a FileView with keywords from @start_kw to @end_kw. + + Will go from the ith=@occurence keyword named @start_kw to the + the first keyword named @end_kw. Returns nullptr if there is no such + start keyword. + + If start_kw==nullopt, goes from the start of the FileView. + If end_kw==nullopt, goes to the end of the FileView. */ + std::shared_ptr + blockview(const std::optional &start_kw = std::nullopt, + const std::optional &end_kw = std::nullopt, + size_t occurence = 0); + + bool has_report_step(int report_step) { + return find_kw_value(SEQNUM_KW, &report_step) >= 0; + } + /** The sim_date of the ith=@seqnum_index step in a restart file. + + returns -1 if there is no such step */ + time_t restart_sim_date(int seqnum_index); + /** The number of days since start of the ith=@seqnum_index step in a restart file. + + returns 0.0 if there is no such step */ + double restart_sim_days(int seqnum_index); + /** The index of the step with the given sim_time + + returns -1 if there is no such step */ + int find_sim_time(time_t sim_time); + bool has_sim_time(time_t sim_time); + + std::shared_ptr restart_view_from_seqnum_index(size_t index); + std::shared_ptr restart_view_from_report_step(int report_step); + std::shared_ptr restart_view_from_sim_time(time_t sim_time); + std::shared_ptr restart_view_from_sim_days(double sim_days); + + std::shared_ptr summary_view(int report_step); + + void close(); + void write_index(FILE *ostream) const; + + static std::shared_ptr read(std::shared_ptr context, + FILE *istream); + + void clear(); +}; +} // namespace rd diff --git a/lib/include/resdata/rd_grav.hpp b/lib/include/resdata/rd_grav.hpp index 2cf6670ad..f45c5013a 100644 --- a/lib/include/resdata/rd_grav.hpp +++ b/lib/include/resdata/rd_grav.hpp @@ -17,21 +17,21 @@ void rd_grav_free(rd_grav_type *rd_grav_config); rd_grav_type *rd_grav_alloc(rd_grid_type *rd_grid, const rd_file_type *init_file); -rd_grav_survey_type * -rd_grav_add_survey_FIP(rd_grav_type *grav, const std::string &name, - const rd_file_view_type *restart_file); +rd_grav_survey_type *rd_grav_add_survey_FIP(rd_grav_type *grav, + const std::string &name, + rd::FileView *restart_file); -rd_grav_survey_type * -rd_grav_add_survey_PORMOD(rd_grav_type *grav, const std::string &name, - const rd_file_view_type *restart_file); +rd_grav_survey_type *rd_grav_add_survey_PORMOD(rd_grav_type *grav, + const std::string &name, + rd::FileView *restart_file); -rd_grav_survey_type * -rd_grav_add_survey_RPORV(rd_grav_type *grav, const std::string &name, - const rd_file_view_type *restart_file); +rd_grav_survey_type *rd_grav_add_survey_RPORV(rd_grav_type *grav, + const std::string &name, + rd::FileView *restart_file); -rd_grav_survey_type * -rd_grav_add_survey_RFIP(rd_grav_type *grav, const std::string &name, - const rd_file_view_type *restart_file); +rd_grav_survey_type *rd_grav_add_survey_RFIP(rd_grav_type *grav, + const std::string &name, + rd::FileView *restart_file); double rd_grav_eval(const rd_grav_type *grav, const std::string &base, const std::optional &monitor, diff --git a/lib/include/resdata/rd_rsthead.hpp b/lib/include/resdata/rd_rsthead.hpp index fa8178d4f..455803564 100644 --- a/lib/include/resdata/rd_rsthead.hpp +++ b/lib/include/resdata/rd_rsthead.hpp @@ -123,20 +123,16 @@ struct RSTHead { this->dualp = false; } - inline static RSTHead read(const rd_file_view_type *rst_view, - int report_step) { - const rd_kw_type *intehead_kw = - rd_file_view_iget_named_kw(rst_view, INTEHEAD_KW, 0); - const rd_kw_type *doubhead_kw = - rd_file_view_iget_named_kw(rst_view, DOUBHEAD_KW, 0); + inline static RSTHead read(rd::FileView *rst_view, int report_step) { + const rd_kw_type *intehead_kw = rst_view->get_kw(INTEHEAD_KW, 0); + const rd_kw_type *doubhead_kw = rst_view->get_kw(DOUBHEAD_KW, 0); const rd_kw_type *logihead_kw = NULL; - if (rd_file_view_has_kw(rst_view, LOGIHEAD_KW)) - logihead_kw = rd_file_view_iget_named_kw(rst_view, LOGIHEAD_KW, 0); + if (rst_view->has_kw(LOGIHEAD_KW)) + logihead_kw = rst_view->get_kw(LOGIHEAD_KW, 0); - if (rd_file_view_has_kw(rst_view, SEQNUM_KW)) { - const rd_kw_type *seqnum_kw = - rd_file_view_iget_named_kw(rst_view, SEQNUM_KW, 0); + if (rst_view->has_kw(SEQNUM_KW)) { + const rd_kw_type *seqnum_kw = rst_view->get_kw(SEQNUM_KW, 0); report_step = rd_kw_iget_int(seqnum_kw, 0); } diff --git a/lib/include/resdata/rd_subsidence.hpp b/lib/include/resdata/rd_subsidence.hpp index 88d4c9feb..d7f4531dd 100644 --- a/lib/include/resdata/rd_subsidence.hpp +++ b/lib/include/resdata/rd_subsidence.hpp @@ -17,7 +17,7 @@ rd_subsidence_type *rd_subsidence_alloc(rd_grid_type *rd_grid, rd_subsidence_survey_type * rd_subsidence_add_survey_PRESSURE(rd_subsidence_type *subsidence, const std::string &name, - const rd_file_view_type *restart_view); + rd::FileView *restart_view); bool rd_subsidence_has_survey(const rd_subsidence_type *subsidence, const std::string &name); diff --git a/lib/include/resdata/well/well_info.hpp b/lib/include/resdata/well/well_info.hpp index e0b3677eb..39c3d936e 100644 --- a/lib/include/resdata/well/well_info.hpp +++ b/lib/include/resdata/well/well_info.hpp @@ -197,7 +197,7 @@ class WellInfo { WellState for each well.*/ void add_wells(rd_file_type *rst_file, int report_nr, bool load_segment_information); - void add_wells(rd_file_view_type *rst_view, int report_nr, + void add_wells(rd::FileView *rst_view, int report_nr, bool load_segment_information); /** Will fail if the rst_file instance is a non-unified restart file, because these files do not have the SEQNUM keyword. */ diff --git a/lib/include/resdata/well/well_rseg_loader.hpp b/lib/include/resdata/well/well_rseg_loader.hpp index f27e25052..87b2b5cd0 100644 --- a/lib/include/resdata/well/well_rseg_loader.hpp +++ b/lib/include/resdata/well/well_rseg_loader.hpp @@ -4,7 +4,7 @@ typedef struct well_rseg_loader_struct well_rseg_loader_type; -well_rseg_loader_type *well_rseg_loader_alloc(rd_file_view_type *rst_view); +well_rseg_loader_type *well_rseg_loader_alloc(rd::FileView *rst_view); void well_rseg_loader_free(well_rseg_loader_type *well_rseg_loader); double * diff --git a/lib/include/resdata/well/well_state.hpp b/lib/include/resdata/well/well_state.hpp index f146e2984..c0af14043 100644 --- a/lib/include/resdata/well/well_state.hpp +++ b/lib/include/resdata/well/well_state.hpp @@ -125,14 +125,12 @@ class WellState { void add_wellhead(const RSTHead &header, const rd_kw_type *iwel_kw, int well_nr, const std::string &grid_name, int grid_nr); - bool add_rates(rd_file_view_type *rst_view, int well_nr); - int get_lgr_well_nr(const rd_file_view_type *file_view); - void add_connections(const rd_file_view_type *rst_view, - const std::string &grid_name, int grid_nr, - int well_nr); - void add_global_connections(const rd_file_view_type *rst_view, int well_nr); - void add_LGR_connections(const rd_grid_type *grid, - rd_file_view_type *file_view); + bool add_rates(rd::FileView *rst_view, int well_nr); + int get_lgr_well_nr(rd::FileView *file_view); + void add_connections(rd::FileView *rst_view, const std::string &grid_name, + int grid_nr, int well_nr); + void add_global_connections(rd::FileView *rst_view, int well_nr); + void add_LGR_connections(const rd_grid_type *grid, rd::FileView *file_view); std::shared_ptr get_wellhead(const std::string &grid_name) { const auto it = name_wellhead.find(grid_name); return it != name_wellhead.end() ? it->second : nullptr; @@ -185,9 +183,9 @@ class WellState { [[nodiscard]] bool has_global_connections() const { return has_grid_connections(RD_GRID_GLOBAL_GRID); } - void add_connections(const rd_grid_type *grid, rd_file_view_type *rst_view, + void add_connections(const rd_grid_type *grid, rd::FileView *rst_view, int well_nr); - bool add_MSW(rd_file_view_type *rst_view, int well_nr, + bool add_MSW(rd::FileView *rst_view, int well_nr, bool load_segment_information); static std::shared_ptr @@ -195,9 +193,9 @@ class WellState { int report_nr, int global_well_nr, bool load_segment_information); static std::shared_ptr - read_wells_in_restart(rd_file_view_type *file_view, - const rd_grid_type *grid, int report_nr, - int global_well_nr, bool load_segment_information); + read_wells_in_restart(rd::FileView *file_view, const rd_grid_type *grid, + int report_nr, int global_well_nr, + bool load_segment_information); std::vector> * get_grid_connections(const std::string &grid_name) { auto it = connections.find(grid_name); diff --git a/lib/private-include/detail/resdata/cwrap_pybind.hpp b/lib/private-include/detail/resdata/cwrap_pybind.hpp index c7ba862a4..9d79f7d4e 100644 --- a/lib/private-include/detail/resdata/cwrap_pybind.hpp +++ b/lib/private-include/detail/resdata/cwrap_pybind.hpp @@ -22,4 +22,3 @@ inline void register_exceptions(pybind11::module &m) { pybind11::object CTime(); pybind11::object ResdataKW(); -pybind11::object ResdataFileView(); diff --git a/lib/private-include/detail/resdata/rd_sum_file_data.hpp b/lib/private-include/detail/resdata/rd_sum_file_data.hpp index bd1cad15c..6ed6d1186 100644 --- a/lib/private-include/detail/resdata/rd_sum_file_data.hpp +++ b/lib/private-include/detail/resdata/rd_sum_file_data.hpp @@ -152,7 +152,7 @@ class rd_sum_file_data { void build_index(); void fwrite_report(int report_step, ERT::FortIO &fortio) const; bool check_file(rd_file_type *rd_file); - void add_rd_file(int report_step, const rd_file_view_type *summary_view); + void add_rd_file(int report_step, rd::FileView &summary_view); }; } // namespace rd diff --git a/lib/private-include/detail/resdata/rd_unsmry_loader.hpp b/lib/private-include/detail/resdata/rd_unsmry_loader.hpp index 422c1cca8..9549c1377 100644 --- a/lib/private-include/detail/resdata/rd_unsmry_loader.hpp +++ b/lib/private-include/detail/resdata/rd_unsmry_loader.hpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -14,7 +15,6 @@ class unsmry_loader { public: unsmry_loader(const rd_smspec_type *smspec, const std::string &filename, FileMode file_options = FileMode::DEFAULT); - ~unsmry_loader(); std::vector get_vector(int pos) const; std::vector sim_seconds() const; @@ -34,8 +34,8 @@ class unsmry_loader { int m_length; //Number of PARAMS in the UNSMRY file std::array date_index; - rd_file_type *file; - rd_file_view_type *file_view; + rd_file_ptr file{nullptr, &rd_file_free}; + std::shared_ptr file_view; }; } // namespace rd diff --git a/lib/resdata/cwrap_pybind.cpp b/lib/resdata/cwrap_pybind.cpp index eceaeb51f..c518ee574 100644 --- a/lib/resdata/cwrap_pybind.cpp +++ b/lib/resdata/cwrap_pybind.cpp @@ -208,20 +208,6 @@ template <> rd_file_type *from_cwrap(py::handle obj) { return cast_cwrap(obj); } -py::object ResdataFileView() { - static py::object cls; - if (!cls) { - cls = py::module_::import("resdata.resfile").attr("ResdataFileView"); - } - return cls; -} - -template <> rd_file_view_type *from_cwrap(py::handle obj) { - if (!py::isinstance(obj, ResdataFileView())) - throw py::type_error("Expected ResdataFileView, got " + - static_cast(py::repr(obj))); - return cast_cwrap(obj); -} py::object ResdataSubsidence() { static py::object cls; if (!cls) { diff --git a/lib/resdata/rd_file.cpp b/lib/resdata/rd_file.cpp index c6b9ec258..e719b0f1e 100644 --- a/lib/resdata/rd_file.cpp +++ b/lib/resdata/rd_file.cpp @@ -7,10 +7,13 @@ #include #include +#include +#include #include #include #include +#include #include #include @@ -97,16 +100,13 @@ struct rd_file_struct { UTIL_TYPE_ID_DECLARATION; - ERT::FortIO *fortio; /* The source of all the keywords - must be retained - open for reading for the entire lifetime of the - rd_file object. */ - rd_file_view_type - *global_view; /* The index of all the rd_kw instances in the file. */ - rd_file_view_type *active_view; /* The currently active index. */ + std::shared_ptr context; + std::shared_ptr + global_view; /* The index of all the rd_kw instances in the file. */ + std::shared_ptr active_view; /* The currently active index. */ bool read_only; - FileMode flags; - vector_type *map_stack; - inv_map_type *inv_view; + std::unique_ptr map_stack{ + nullptr, &vector_free}; }; /* @@ -135,18 +135,16 @@ struct rd_file_struct { UTIL_SAFE_CAST_FUNCTION(rd_file, RD_FILE_ID) UTIL_IS_INSTANCE_FUNCTION(rd_file, RD_FILE_ID) -static rd_file_type *rd_file_alloc_empty(FileMode flags) { - rd_file_type *rd_file = (rd_file_type *)util_malloc(sizeof *rd_file); +static rd_file_type *rd_file_alloc_empty() { + rd_file_type *rd_file = new rd_file_type(); UTIL_TYPE_ID_INIT(rd_file, RD_FILE_ID); - rd_file->map_stack = vector_alloc_new(); - rd_file->inv_view = new inv_map_type(); - rd_file->flags = flags; + rd_file->map_stack.reset(vector_alloc_new()); return rd_file; } void rd_file_fwrite_fortio(const rd_file_type *rd_file, ERT::FortIO &target, int offset) { - rd_file_view_fwrite(rd_file->active_view, target, offset); + rd_file->active_view->write(target, offset); } /** @@ -170,7 +168,7 @@ void rd_file_fwrite_fortio(const rd_file_type *rd_file, ERT::FortIO &target, */ int rd_file_get_num_named_kw(const rd_file_type *rd_file, const char *kw) { - return rd_file_view_get_num_named_kw(rd_file->active_view, kw); + return rd_file->active_view->num_named_kw(kw); } /** @@ -178,7 +176,7 @@ int rd_file_get_num_named_kw(const rd_file_type *rd_file, const char *kw) { instance. */ int rd_file_get_size(const rd_file_type *rd_file) { - return rd_file_view_get_size(rd_file->active_view); + return rd_file->active_view->size(); } /** @@ -186,15 +184,15 @@ int rd_file_get_size(const rd_file_type *rd_file) { rd_kw 'kw'. */ bool rd_file_has_kw(const rd_file_type *rd_file, const char *kw) { - return rd_file_view_has_kw(rd_file->active_view, kw); + return rd_file->active_view->has_kw(kw); } const char *rd_file_get_src_file(const rd_file_type *rd_file) { - return rd_file->fortio->filename_ref(); + return rd_file->context->fortio.filename_ref(); } rd_kw_type *rd_file_iget_kw(const rd_file_type *file, int global_index) { - return rd_file_view_iget_kw(file->active_view, global_index); + return file->active_view->get_kw(global_index); } /* @@ -205,53 +203,26 @@ rd_kw_type *rd_file_iget_kw(const rd_file_type *file, int global_index) { rd_kw_type *rd_file_iget_named_kw(const rd_file_type *file, const char *kw, int ith) { - return rd_file_view_iget_named_kw(file->active_view, kw, ith); + return file->active_view->get_kw(kw, ith); } -rd_file_view_type *rd_file_get_global_view(rd_file_type *rd_file) { +std::shared_ptr rd_file_get_global_view(rd_file_type *rd_file) { return rd_file->global_view; } -// Very deprecated ... -rd_file_view_type *rd_file_get_active_view(rd_file_type *rd_file) { +std::shared_ptr rd_file_get_active_view(rd_file_type *rd_file) { return rd_file->active_view; } -rd_file_view_type *rd_file_get_global_blockview(rd_file_type *rd_file, - const char *kw, int occurence) { - rd_file_view_type *view = - rd_file_view_add_blockview(rd_file->global_view, kw, occurence); - return view; -} - -static rd_file_view_type *rd_file_alloc_global_blockview2(rd_file_type *rd_file, - const char *start_kw, - const char *end_kw, - int occurence) { - rd_file_view_type *view = rd_file_view_alloc_blockview2( - rd_file->global_view, start_kw, end_kw, occurence); - return view; -} - -rd_file_view_type *rd_file_alloc_global_blockview(rd_file_type *rd_file, - const char *kw, - int occurence) { - return rd_file_alloc_global_blockview2(rd_file, kw, kw, occurence); -} - -rd_file_view_type *rd_file_get_restart_view(rd_file_type *rd_file, - int input_index, int report_step, - time_t sim_time, double sim_days) { - rd_file_view_type *view = rd_file_view_add_restart_view( - rd_file->global_view, input_index, report_step, sim_time, sim_days); - return view; +std::shared_ptr +rd_file_get_global_blockview(rd_file_type *rd_file, const char *kw, + int occurence) { + return rd_file->global_view->blockview(kw, kw, occurence); } -rd_file_view_type *rd_file_get_summary_view(rd_file_type *rd_file, - int report_step) { - rd_file_view_type *view = - rd_file_view_add_summary_view(rd_file->global_view, report_step); - return view; +std::shared_ptr rd_file_get_summary_view(rd_file_type *rd_file, + int report_step) { + return rd_file->global_view->summary_view(report_step); } /* @@ -272,18 +243,18 @@ rd_file_view_type *rd_file_get_summary_view(rd_file_type *rd_file, */ static void rd_file_scan(rd_file_type *rd_file) { - rd_file->fortio->fseek(0, SEEK_SET); + rd_file->context->fortio.fseek(0, SEEK_SET); { rd_kw_ptr work_kw = make_rd_kw("WORK-KW", 0, RD_INT, nullptr); while (true) { - if (rd_file->fortio->read_at_eof()) + if (rd_file->context->fortio.read_at_eof()) break; { - offset_type current_offset = rd_file->fortio->ftell(); + offset_type current_offset = rd_file->context->fortio.ftell(); rd_read_status_enum read_status = - rd_kw_fread_header(work_kw.get(), *rd_file->fortio); + rd_kw_fread_header(work_kw.get(), rd_file->context->fortio); if (read_status == RD_KW_READ_FAIL) break; @@ -291,8 +262,8 @@ static void rd_file_scan(rd_file_type *rd_file) { auto file_kw = std::make_shared(work_kw.get(), current_offset); - if (file_kw->skip_data(*rd_file->fortio)) { - rd_file_view_add_kw(rd_file->global_view, file_kw); + if (file_kw->skip_data(rd_file->context->fortio)) { + rd_file->global_view->add_kw(file_kw); } else { break; } @@ -300,7 +271,7 @@ static void rd_file_scan(rd_file_type *rd_file) { } } } - rd_file_view_make_index(rd_file->global_view); + rd_file->global_view->make_index(); } static void rd_file_select_global(rd_file_type *rd_file) { @@ -323,7 +294,7 @@ static std::unique_ptr rd_file_alloc_fortio(const char *filename, bool fmt_file; rd_fmt_file(filename, &fmt_file); - if (rd_file_view_check_flags(flags, FileMode::WRITABLE)) + if ((flags & FileMode::WRITABLE) == FileMode::WRITABLE) return std::make_unique( filename, std::ios_base::in | std::ios_base::out, fmt_file); else @@ -337,16 +308,17 @@ rd_file_type *rd_file_open(const char *filename, FileMode flags) { auto fortio = rd_file_alloc_fortio(filename, flags); if (fortio) { - rd_file_ptr rd_file(rd_file_alloc_empty(flags), &rd_file_close); - rd_file->fortio = fortio.release(); - rd_file->global_view = - new FileView(rd_file->fortio, &rd_file->flags, rd_file->inv_view); + rd_file_ptr rd_file(rd_file_alloc_empty(), &rd_file_free); + rd_file->context = + std::make_shared(std::move(*fortio), flags); + rd_file->global_view = std::make_shared(rd_file->context); rd_file_scan(rd_file.get()); rd_file_select_global(rd_file.get()); - if (rd_file_view_check_flags(rd_file->flags, FileMode::CLOSE_STREAM)) - rd_file->fortio->fclose_stream(); + if ((rd_file->context->flags & FileMode::CLOSE_STREAM) == + FileMode::CLOSE_STREAM) + rd_file->context->fortio.fclose_stream(); return rd_file.release(); } else @@ -354,29 +326,19 @@ rd_file_type *rd_file_open(const char *filename, FileMode flags) { } bool rd_file_writable(const rd_file_type *rd_file) { - return rd_file_view_check_flags(rd_file->flags, FileMode::WRITABLE); + return (rd_file->context->flags & FileMode::WRITABLE) == FileMode::WRITABLE; } -/** - The rd_file_close() function will close the fortio instance and - free all the data created by the rd_file instance; this includes - the rd_kw instances which have been loaded on demand. -*/ - +/** The rd_file_close() function will close the fortio instance */ void rd_file_close(rd_file_type *rd_file) { - if (rd_file->fortio != NULL) - delete rd_file->fortio; - - if (rd_file->global_view) - delete rd_file->global_view; - - delete rd_file->inv_view; - vector_free(rd_file->map_stack); - free(rd_file); + if (rd_file->context) + rd_file->context->fortio.fclose_stream(); } +void rd_file_free(rd_file_type *rd_file) { delete rd_file; } + bool rd_file_load_all(rd_file_type *rd_file) { - return rd_file_view_load_all(rd_file->active_view); + return rd_file->active_view->load_all(); } /* Functions specialized to work with restart files. */ @@ -389,7 +351,7 @@ bool rd_file_load_all(rd_file_type *rd_file) { */ bool rd_file_has_sim_time(const rd_file_type *rd_file, time_t sim_time) { - return rd_file_view_has_sim_time(rd_file->active_view, sim_time); + return rd_file->active_view->has_sim_time(sim_time); } /* @@ -418,9 +380,7 @@ bool rd_file_has_sim_time(const rd_file_type *rd_file, time_t sim_time) { */ int rd_file_get_restart_index(const rd_file_type *rd_file, time_t sim_time) { - int active_index = - rd_file_view_find_sim_time(rd_file->active_view, sim_time); - return active_index; + return rd_file->active_view->find_sim_time(sim_time); } /** @@ -430,7 +390,7 @@ int rd_file_get_restart_index(const rd_file_type *rd_file, time_t sim_time) { */ bool rd_file_has_report_step(const rd_file_type *rd_file, int report_step) { - return rd_file_view_has_report_step(rd_file->active_view, report_step); + return rd_file->active_view->has_report_step(report_step); } /** @@ -442,12 +402,12 @@ bool rd_file_has_report_step(const rd_file_type *rd_file, int report_step) { time_t rd_file_iget_restart_sim_date(const rd_file_type *restart_file, int index) { - return rd_file_view_iget_restart_sim_date(restart_file->active_view, index); + return restart_file->active_view->restart_sim_date(index); } double rd_file_iget_restart_sim_days(const rd_file_type *restart_file, int index) { - return rd_file_view_iget_restart_sim_days(restart_file->active_view, index); + return restart_file->active_view->restart_sim_days(index); } /* @@ -522,33 +482,31 @@ bool rd_file_writable( const rd_file_type * rd_file ) { */ bool rd_file_save_kw(const rd_file_type *rd_file, const rd_kw_type *rd_kw) { - FileKW *file_kw = rd_file->inv_view->at(rd_kw); - if (rd_file->fortio->assert_stream_open()) { + FileKW *file_kw = rd_file->context->inv_map.at(rd_kw); + if (rd_file->context->fortio.assert_stream_open()) { - file_kw->inplace_write(*rd_file->fortio); + file_kw->inplace_write(rd_file->context->fortio); - if (rd_file_view_check_flags(rd_file->flags, FileMode::CLOSE_STREAM)) - rd_file->fortio->fclose_stream(); + if ((rd_file->context->flags & FileMode::CLOSE_STREAM) == + FileMode::CLOSE_STREAM) + rd_file->context->fortio.fclose_stream(); return true; } else return false; } -static rd_file_view_type *rd_file_get_relative_blockview(rd_file_type *rd_file, - const char *kw, - int occurence) { - rd_file_view_type *view = - rd_file_view_add_blockview(rd_file->active_view, kw, occurence); - return view; +static std::shared_ptr +rd_file_get_relative_blockview(rd_file_type *rd_file, const char *kw, + int occurence) { + return rd_file->active_view->blockview(kw, kw, occurence); } bool rd_file_subselect_block(rd_file_type *rd_file, const char *kw, int occurence) { - rd_file_view_type *blockmap = - rd_file_get_relative_blockview(rd_file, kw, occurence); - if (blockmap != NULL) { - rd_file->active_view = blockmap; + if (auto blockmap = + rd_file_get_relative_blockview(rd_file, kw, occurence)) { + rd_file->active_view = std::move(blockmap); return true; } else return false; @@ -601,11 +559,11 @@ bool rd_file_write_index(const rd_file_type *rd_file, return false; { char *filename = - util_split_alloc_filename(rd_file->fortio->filename_ref()); + util_split_alloc_filename(rd_file->context->fortio.filename_ref()); util_fwrite_string(filename, ostream); free(filename); } - rd_file_view_write_index(rd_file->global_view, ostream); + rd_file->global_view->write_index(ostream); fclose(ostream); return true; } @@ -613,29 +571,32 @@ bool rd_file_write_index(const rd_file_type *rd_file, rd_file_type *rd_file_fast_open(const char *file_name, const char *index_file_name, FileMode flags) { if (!rd_file_index_valid0(file_name, index_file_name)) - return NULL; + return nullptr; std::unique_ptr istream( fopen(index_file_name, "rb"), fclose); if (!istream) - return NULL; + return nullptr; if (rd_file_index_valid1(file_name, istream.get())) { auto fortio = rd_file_alloc_fortio(file_name, flags); if (fortio) { - rd_file_ptr rd_file(rd_file_alloc_empty(flags), &rd_file_close); - rd_file->fortio = fortio.release(); - rd_file->global_view = - rd_file_view_fread_alloc(rd_file->fortio, &rd_file->flags, - rd_file->inv_view, istream.get()); + rd_file_ptr rd_file(rd_file_alloc_empty(), &rd_file_free); + rd_file->context = + std::make_shared(std::move(*fortio), flags); + auto global_view = + rd::FileView::read(rd_file->context, istream.get()); + if (!global_view) + return nullptr; + rd_file->global_view = std::move(global_view); if (rd_file->global_view) { rd_file_select_global(rd_file.get()); - if (rd_file_view_check_flags(rd_file->flags, - FileMode::CLOSE_STREAM)) - rd_file->fortio->fclose_stream(); + if ((rd_file->context->flags & FileMode::CLOSE_STREAM) == + FileMode::CLOSE_STREAM) + rd_file->context->fortio.fclose_stream(); return rd_file.release(); } } } - return NULL; + return nullptr; } diff --git a/lib/resdata/rd_file_pybind.cpp b/lib/resdata/rd_file_pybind.cpp index 963221481..d266dd04a 100644 --- a/lib/resdata/rd_file_pybind.cpp +++ b/lib/resdata/rd_file_pybind.cpp @@ -23,7 +23,7 @@ PYBIND11_MODULE(_file, m) { register_exceptions(m); m.doc() = "pybind11 bindings between rd_file.py and rd_file.cpp"; - m.def("_open", [](std::string filename, FileMode &flags) -> py::object { + m.def("_open", [](std::string filename, FileMode flags) -> py::object { auto *file = rd_file_open(filename.c_str(), flags); if (file == nullptr) return py::none(); @@ -56,6 +56,9 @@ PYBIND11_MODULE(_file, m) { m.def("_close", [](py::handle self) { rd_file_close(from_cwrap(self)); }); + m.def("_free", [](py::handle self) { + rd_file_free(from_cwrap(self)); + }); m.def("_iget_restart_time", [](py::handle self, int index) { return static_cast(rd_file_iget_restart_sim_date( from_cwrap(self), index)); @@ -82,13 +85,9 @@ PYBIND11_MODULE(_file, m) { return rd_file_has_sim_time(from_cwrap(self), static_cast(sim_time)); }); - m.def( - "_get_global_view", - [](py::handle self) { - return reinterpret_cast( - rd_file_get_global_view(from_cwrap(self))); - }, - py::return_value_policy::reference); + m.def("_get_global_view", [](py::handle self) { + return rd_file_get_global_view(from_cwrap(self)); + }); m.def("_write_index", [](py::handle self, std::string index_filename) { return rd_file_write_index(from_cwrap(self), index_filename.c_str()); diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index bf63ec534..1d19c62ab 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -1,11 +1,12 @@ #include #include -#include +#include #include #include #include #include +#include #include #include @@ -16,142 +17,93 @@ #include #include #include +#include #include #include #include -bool rd_file_view_check_flags(FileMode state_flags, FileMode query_flags) { - return (state_flags & query_flags) == query_flags; -} - -bool rd_file_view_flags_set(const rd_file_view_type *file_view, - FileMode query_flags) { - return rd_file_view_check_flags(*file_view->flags, query_flags); -} +namespace rd { -const char *rd_file_view_get_src_file(const rd_file_view_type *file_view) { - return file_view->fortio->filename_ref(); -} +void FileView::make_index() { + distinct_kw.clear(); + kw_index.clear(); -rd_file_view_type *rd_file_view_alloc(ERT::FortIO *fortio, FileMode *flags, - inv_map_type *inv_map) { - return new FileView(fortio, flags, inv_map); -} - -static int rd_file_view_get_global_index(const rd_file_view_type *rd_file_view, - const char *kw, int ith) { - const auto &index_vector = rd_file_view->kw_index.at(kw); - return index_vector[ith]; -} + int global_index = 0; + for (const auto &file_kw : kw_list) { + const std::string &header = file_kw->get_header(); + if (kw_index.find(header) == kw_index.end()) + distinct_kw.push_back(header); -/** - This function iterates over the kw_list vector and builds the - internal index fields 'kw_index' and 'distinct_kw'. This function - must be called every time the content of the kw_list vector is - modified (otherwise the rd_file instance will be in an - inconsistent state). -*/ - -void rd_file_view_make_index(rd_file_view_type *rd_file_view) { - rd_file_view->distinct_kw.clear(); - rd_file_view->kw_index.clear(); - { - int global_index = 0; - for (const auto &file_kw : rd_file_view->kw_list) { - const std::string &header = file_kw->get_header(); - if (rd_file_view->kw_index.find(header) == - rd_file_view->kw_index.end()) - rd_file_view->distinct_kw.push_back(header); - - auto &index_vector = rd_file_view->kw_index[header]; - index_vector.push_back(global_index); - global_index++; - } + auto &index_vector = kw_index[header]; + index_vector.push_back(global_index); + global_index++; } } -bool rd_file_view_has_kw(const rd_file_view_type *rd_file_view, - const char *kw) { - return (rd_file_view->kw_index.find(kw) != rd_file_view->kw_index.end()); +bool FileView::has_flags(FileMode flags) const { + return (context->flags & flags) == flags; } -std::shared_ptr -rd_file_view_iget_file_kw(const rd_file_view_type *rd_file_view, - int global_index) { - return rd_file_view->kw_list[global_index]; -} +void FileView::add_flag(FileMode flag) { context->flags |= flag; } -static std::shared_ptr -rd_file_view_iget_named_file_kw(const rd_file_view_type *rd_file_view, - const char *kw, int ith) { - int global_index = rd_file_view_get_global_index(rd_file_view, kw, ith); - return rd_file_view_iget_file_kw(rd_file_view, global_index); +const std::string &FileView::filename() const { + return context->fortio.filename(); } -bool rd_file_view_drop_flag(rd_file_view_type *file_view, FileMode flag) { - bool flag_set = rd_file_view_flags_set(file_view, flag); +void FileView::close() { context->fortio.fclose_stream(); } + +bool FileView::drop_flags(FileMode flag) { + bool flag_set = has_flags(flag); if (flag_set) - *file_view->flags &= ~flag; + context->flags &= ~flag; return flag_set; } -void rd_file_view_add_flag(rd_file_view_type *file_view, FileMode flag) { - *file_view->flags |= flag; -} - -static rd_kw_type *rd_file_view_get_kw(const rd_file_view_type *rd_file_view, - const std::shared_ptr &file_kw) { +rd_kw_type *FileView::get_kw(const std::shared_ptr &file_kw) { rd_kw_type *rd_kw = file_kw->get_kw_ptr(); if (!rd_kw) { - if (rd_file_view->fortio->assert_stream_open()) { - - rd_kw = file_kw->get_kw(*rd_file_view->fortio); - (*rd_file_view->inv_map)[rd_kw] = file_kw.get(); + if (context->fortio.assert_stream_open()) { + rd_kw = file_kw->get_kw(context->fortio); + context->inv_map[rd_kw] = file_kw.get(); - if (rd_file_view_flags_set(rd_file_view, FileMode::CLOSE_STREAM)) - rd_file_view->fortio->fclose_stream(); + if (has_flags(FileMode::CLOSE_STREAM)) + context->fortio.fclose_stream(); } } return rd_kw; } -rd_kw_type *rd_file_view_iget_kw(const rd_file_view_type *rd_file_view, - int index) { - auto file_kw = rd_file_view_iget_file_kw(rd_file_view, index); - return rd_file_view_get_kw(rd_file_view, file_kw); -} +void FileView::index_fload_kw(const std::string &kw, int index, + const int_vector_type *index_map, + char *io_buffer) { + if (index < 0) + throw std::invalid_argument( + fmt::format("Got negative index in index_fload_kw: {}", index)); -void rd_file_view_index_fload_kw(const rd_file_view_type *rd_file_view, - const char *kw, int index, - const int_vector_type *index_map, - char *io_buffer) { - auto file_kw = rd_file_view_iget_named_file_kw(rd_file_view, kw, index); + auto file_kw = get_file_kw(kw, static_cast(index)); if (!file_kw) throw std::invalid_argument(std::string("Keyword '") + kw + "' index " + std::to_string(index) + " not found in file view"); - - if (rd_file_view->fortio->assert_stream_open()) { + if (context->fortio.assert_stream_open()) { offset_type offset = file_kw->get_offset(); rd_data_type data_type = file_kw->get_data_type(); int element_count = file_kw->get_size(); - rd_kw_fread_indexed_data(*rd_file_view->fortio, offset, data_type, + rd_kw_fread_indexed_data(context->fortio, offset, data_type, element_count, index_map, io_buffer); } } -static int rd_file_view_find_kw_value(const rd_file_view_type *rd_file_view, - const char *kw, const void *value) { +int FileView::find_kw_value(const std::string &kw, const void *value) { int global_index = -1; - if (rd_file_view_has_kw(rd_file_view, kw)) { - const auto &index_list = rd_file_view->kw_index.at(kw); + if (has_kw(kw)) { + const auto &index_list = kw_index.at(kw); size_t index = 0; while (index < index_list.size()) { - const rd_kw_type *rd_kw = - rd_file_view_iget_kw(rd_file_view, index_list[index]); + rd_kw_type *rd_kw = get_kw(index_list[index]); if (rd_kw_data_equal(rd_kw, value)) { global_index = index_list[index]; break; @@ -162,75 +114,39 @@ static int rd_file_view_find_kw_value(const rd_file_view_type *rd_file_view, return global_index; } -const std::string & -rd_file_view_iget_distinct_kw(const rd_file_view_type *rd_file_view, - int index) { - return rd_file_view->distinct_kw[index]; -} - -int rd_file_view_get_num_distinct_kw(const rd_file_view_type *rd_file_view) { - return rd_file_view->distinct_kw.size(); -} - -int rd_file_view_get_size(const rd_file_view_type *rd_file_view) { - return rd_file_view->kw_list.size(); -} - -rd_kw_type *rd_file_view_iget_named_kw(const rd_file_view_type *rd_file_view, - const char *kw, int ith) { - auto file_kw = rd_file_view_iget_named_file_kw(rd_file_view, kw, ith); - return rd_file_view_get_kw(rd_file_view, file_kw); -} - -bool rd_file_view_load_all(rd_file_view_type *rd_file_view) { +bool FileView::load_all() { bool loadOK = false; - if (rd_file_view->fortio->assert_stream_open()) { - for (auto &file_kw : rd_file_view->kw_list) { - auto rd_kw = file_kw->get_kw(*rd_file_view->fortio); - (*rd_file_view->inv_map)[rd_kw] = file_kw.get(); + if (context->fortio.assert_stream_open()) { + for (auto &file_kw : kw_list) { + auto rd_kw = file_kw->get_kw(context->fortio); + context->inv_map[rd_kw] = file_kw.get(); } loadOK = true; } - if (rd_file_view_flags_set(rd_file_view, FileMode::CLOSE_STREAM)) - rd_file_view->fortio->fclose_stream(); + if (has_flags(FileMode::CLOSE_STREAM)) + context->fortio.fclose_stream(); return loadOK; } -void rd_file_view_add_kw(rd_file_view_type *rd_file_view, - std::shared_ptr file_kw) { - rd_file_view->kw_list.push_back(file_kw); -} - -int rd_file_view_get_num_named_kw(const rd_file_view_type *rd_file_view, - const char *kw) { - if (rd_file_view_has_kw(rd_file_view, kw)) { - const auto &index_vector = rd_file_view->kw_index.at(kw); - return index_vector.size(); - } else - return 0; -} - -void rd_file_view_fwrite(const rd_file_view_type *rd_file_view, - ERT::FortIO &target, int offset) { - for (size_t index = offset; index < rd_file_view->kw_list.size(); index++) { - rd_kw_type *rd_kw = rd_file_view_iget_kw(rd_file_view, index); +void FileView::write(ERT::FortIO &target, int offset) { + for (size_t index = offset; index < kw_list.size(); index++) { + rd_kw_type *rd_kw = get_kw(index); rd_kw_fwrite(rd_kw, target); } } -static int rd_file_view_iget_occurence(const rd_file_view_type *rd_file_view, - int global_index) { - const auto &file_kw = rd_file_view->kw_list[global_index]; +int FileView::get_occurence(size_t global_index) { + const auto &file_kw = kw_list[global_index]; const std::string &header = file_kw->get_header(); - const auto &index_vector = rd_file_view->kw_index.at(header); + const auto &index_vector = kw_index.at(header); int occurence = -1; for (size_t i = 0; i < index_vector.size(); i++) { if (index_vector[i] == global_index) - occurence = i; + occurence = static_cast(i); } if (occurence < 0) throw std::out_of_range( @@ -239,102 +155,61 @@ static int rd_file_view_iget_occurence(const rd_file_view_type *rd_file_view, return occurence; } -rd_file_view_type * -rd_file_view_alloc_blockview2(const rd_file_view_type *rd_file_view, - const char *start_kw, const char *end_kw, - int occurence) { - if ((start_kw != NULL) && - rd_file_view_get_num_named_kw(rd_file_view, start_kw) <= occurence) - return NULL; - - rd_file_view_type *block_map = new FileView( - rd_file_view->fortio, rd_file_view->flags, rd_file_view->inv_map); - size_t kw_index = 0; +std::shared_ptr +FileView::blockview(const std::optional &start_kw, + const std::optional &end_kw, + size_t occurence) { + if (start_kw && num_named_kw(*start_kw) <= occurence) + return {nullptr}; + + auto block_map = std::make_shared(context); + size_t index = 0; if (start_kw) - kw_index = - rd_file_view_get_global_index(rd_file_view, start_kw, occurence); + index = kw_index.at(*start_kw).at(occurence); { - auto file_kw = rd_file_view->kw_list[kw_index]; + auto file_kw = kw_list[index]; while (true) { - rd_file_view_add_kw(block_map, file_kw); + block_map->add_kw(file_kw); - kw_index++; - if (kw_index == rd_file_view->kw_list.size()) + index++; + if (index == kw_list.size()) break; else { if (end_kw) { - file_kw = rd_file_view->kw_list[kw_index]; - if (strcmp(end_kw, file_kw->get_header().c_str()) == 0) + file_kw = kw_list[index]; + if (*end_kw == file_kw->get_header()) break; } } } } - rd_file_view_make_index(block_map); + block_map->make_index(); return block_map; } -/** - Will return NULL if the block which is asked for is not present. -*/ -static rd_file_view_type * -rd_file_view_alloc_blockview(const rd_file_view_type *rd_file_view, - const char *header, int occurence) { - return rd_file_view_alloc_blockview2(rd_file_view, header, header, - occurence); -} +/* There is no special datastructure for working with restart files, +they are 100% stock rd_file instances with the following limited +structure: -rd_file_view_type *rd_file_view_add_blockview(rd_file_view_type *file_view, - const char *header, - int occurence) { - rd_file_view_type *child = - rd_file_view_alloc_blockview2(file_view, header, header, occurence); - - if (child) - file_view->child_list.emplace_back(child); - - return child; -} +* They are organized in blocks; where each block starts with a + SEQNUM keyword, which contains the report step. -rd_file_view_type *rd_file_view_add_blockview2(rd_file_view_type *rd_file_view, - const char *start_kw, - const char *end_kw, - int occurence) { - rd_file_view_type *child = rd_file_view_alloc_blockview2( - rd_file_view, start_kw, end_kw, occurence); +* Each block contains an INTEHEAD keyword, immediately after the + SEQNUM keyword, which contains the true simulation date of of the + block, and also some other data. Observe that also INIT files and + GRID files contain an INTEHEAD keyword; and that for files with + LGRs there is one INTEHEAD keyword for each LGR. This creates an + extra level of mess. - if (child) - rd_file_view->child_list.emplace_back(child); +The natural time ordering when working with the file data is just +the running index in the file; however from a user perspective the +natural way to indicate time coordinate is through the report step +or the true simulation time (i.e. 22.th of October 2009). This file +is all about converting the natural input unit time and report_step +to the internal indexing. This is achieved by consulting the value +of the INTEHEAD and SEQNUM keywords respectively. - return child; -} - -/* - There is no special datastructure for working with restart files, - they are 100% stock rd_file instances with the following limited - structure: - - * They are organized in blocks; where each block starts with a - SEQNUM keyword, which contains the report step. - - * Each block contains an INTEHEAD keyword, immediately after the - SEQNUM keyword, which contains the true simulation date of of the - block, and also some other data. Observe that also INIT files and - GRID files contain an INTEHEAD keyword; and that for files with - LGRs there is one INTEHEAD keyword for each LGR. This creates an - extra level of mess. - - The natural time ordering when working with the file data is just - the running index in the file; however from a user perspective the - natural way to indicate time coordinate is through the report step - or the true simulation time (i.e. 22.th of October 2009). This file - is all about converting the natural input unit time and report_step - to the internal indexing. This is achieved by consulting the value - of the INTEHEAD and SEQNUM keywords respectively. -*/ - -/* About the time-direction ======================== @@ -395,9 +270,6 @@ we have introduced the following concepts: i.e. to perform queries based on the report_step we must load the SEQNUM keyword and read its value. - rd_file_get_unrstmap_report_step( rd_file , 0 ) => A - rd_file_get_unrstmap_report_step( rd_file , 1 ) => NULL - rd_file_has_report_step( rd_file , 5 ) => True rd_file_has_report_step( rd_file , 2 ) => False @@ -405,10 +277,7 @@ we have introduced the following concepts: step. The simulation time is stored as integers DAY, MONTH, YEAR in the INTEHEAD keyword; the function INTEHEAD_date() will extract the DAY, MONTH and YEAR values from an INTEHEAD keyword instance - and convert to a time_t instance. The functions: - - rd_file_get_unrstmap_sim_time() and rd_file_has_has_sim_time() - + and convert to a time_t instance. The functions rd_file_has_has_sim_time() can be used to query for simulation times and get the corresponding block maps. @@ -421,19 +290,7 @@ we have introduced the following concepts: SEQNUM. Instead of occurrence, xxxx_index is also used to indicate the occurrence of keyword xxxx. The occurrence number is the integer argument to the xxx_iget_named_kw() function, and also the final - call to create blockmaps. - -*/ - -bool rd_file_view_has_report_step(const rd_file_view_type *rd_file_view, - int report_step) { - int global_index = - rd_file_view_find_kw_value(rd_file_view, SEQNUM_KW, &report_step); - if (global_index >= 0) - return true; - else - return false; -} + call to create blockmaps. */ static time_t rsthead_date(int day, int month, int year) { return rd_make_date(day, month, year); @@ -445,133 +302,109 @@ static time_t rd_rsthead_date(const rd_kw_type *intehead_kw) { rd_kw_iget_int(intehead_kw, INTEHEAD_YEAR_INDEX)); } -time_t rd_file_view_iget_restart_sim_date(const rd_file_view_type *rd_file_view, - int seqnum_index) { +time_t FileView::restart_sim_date(int seqnum_index) { time_t sim_time = -1; - rd_file_view_ptr seqnum_map( - rd_file_view_alloc_blockview(rd_file_view, SEQNUM_KW, seqnum_index)); + std::shared_ptr seqnum_map = + blockview(SEQNUM_KW, SEQNUM_KW, seqnum_index); if (seqnum_map) { - rd_kw_type *intehead_kw = - rd_file_view_iget_named_kw(seqnum_map.get(), INTEHEAD_KW, 0); + rd_kw_type *intehead_kw = seqnum_map->get_kw(INTEHEAD_KW, 0); sim_time = rd_rsthead_date(intehead_kw); } return sim_time; } -double rd_file_view_iget_restart_sim_days(const rd_file_view_type *rd_file_view, - int seqnum_index) { +double FileView::restart_sim_days(int seqnum_index) { double sim_days = 0; - rd_file_view_ptr seqnum_map( - rd_file_view_alloc_blockview(rd_file_view, SEQNUM_KW, seqnum_index)); + std::shared_ptr seqnum_map = + blockview(SEQNUM_KW, SEQNUM_KW, seqnum_index); if (seqnum_map) { - rd_kw_type *doubhead_kw = - rd_file_view_iget_named_kw(seqnum_map.get(), DOUBHEAD_KW, 0); + rd_kw_type *doubhead_kw = seqnum_map->get_kw(DOUBHEAD_KW, 0); sim_days = rd_kw_iget_double(doubhead_kw, DOUBHEAD_DAYS_INDEX); } return sim_days; } -int rd_file_view_find_sim_time(const rd_file_view_type *rd_file_view, - time_t sim_time) { +/* Will scan through the rd_file looking for INTEHEAD +headers corresponding to sim_time. If sim_time is found the +function will return the INTEHEAD occurence number, i.e. for a +unified restart file like: + +INTEHEAD / 01.01.2000 +... +PRESSURE +SWAT +... +INTEHEAD / 01.03.2000 +... +PRESSURE +SWAT +... +INTEHEAD / 01.05.2000 +... +PRESSURE +SWAT +.... + +find_sim_time with time_t of "01.03.2000" will return 1. This will +in general NOT agree with the DATES step number. + +If the sim_time can not be found the function will return -1. + +Observe that the function requires on-the-second-equality; which is +of course quite strict. + +Each report step only has one occurence of SEQNUM, but one INTEHEAD +for each LGR; i.e. one should call iselect_rstblock() prior to +calling this function. */ +int FileView::find_sim_time(time_t sim_time) { int seqnum_index = -1; - if (rd_file_view_has_kw(rd_file_view, INTEHEAD_KW)) { - const auto &intehead_index_list = - rd_file_view->kw_index.at(INTEHEAD_KW); - size_t index = 0; - while (index < intehead_index_list.size()) { - const rd_kw_type *intehead_kw = - rd_file_view_iget_kw(rd_file_view, intehead_index_list[index]); + if (has_kw(INTEHEAD_KW)) { + const auto &intehead_index_list = kw_index.at(INTEHEAD_KW); + for (size_t index = 0; index < intehead_index_list.size(); index++) { + const rd_kw_type *intehead_kw = get_kw(intehead_index_list[index]); if (rd_rsthead_date(intehead_kw) == sim_time) { - seqnum_index = index; + seqnum_index = static_cast(index); break; } - index++; } } return seqnum_index; } -/** - This function will scan through the rd_file looking for INTEHEAD - headers corresponding to sim_time. If sim_time is found the - function will return the INTEHEAD occurence number, i.e. for a - unified restart file like: - - INTEHEAD / 01.01.2000 - ... - PRESSURE - SWAT - ... - INTEHEAD / 01.03.2000 - ... - PRESSURE - SWAT - ... - INTEHEAD / 01.05.2000 - ... - PRESSURE - SWAT - .... - - The function call: - - rd_file_get_restart_index( restart_file , (time_t) "01.03.2000") - - will return 1. Observe that this will in general NOT agree with the - DATES step number. - - If the sim_time can not be found the function will return -1, that - includes the case when the file in question is not a restart file - at all, and no INTEHEAD headers can be found. - - Observe that the function requires on-the-second-equality; which is - of course quite strict. - - Each report step only has one occurence of SEQNUM, but one INTEHEAD - for each LGR; i.e. one should call iselect_rstblock() prior to - calling this function. -*/ - -bool rd_file_view_has_sim_time(const rd_file_view_type *rd_file_view, - time_t sim_time) { - int num_INTEHEAD = rd_file_view_get_num_named_kw(rd_file_view, INTEHEAD_KW); +bool FileView::has_sim_time(time_t sim_time) { + size_t num_INTEHEAD = num_named_kw(INTEHEAD_KW); if (num_INTEHEAD == 0) return false; /* We have no INTEHEAD headers - probably not a restart file at all. */ else { int intehead_index = 0; while (true) { - time_t itime = rd_file_view_iget_restart_sim_date(rd_file_view, - intehead_index); + time_t itime = restart_sim_date(intehead_index); if (itime == sim_time) /* Perfect hit. */ return true; - if (itime > - sim_time) /* We have gone past the target_time - i.e. we do not have it. */ - return false; + if (itime > sim_time) + return false; /* We have gone past the target_time - i.e. we do not have it. */ intehead_index++; - if (intehead_index == - num_INTEHEAD) /* We have iterated through the whole thing without finding sim_time. */ - return false; + if (intehead_index == num_INTEHEAD) + return false; /* We have iterated through the whole thing without finding sim_time. */ } } } -static bool rd_file_view_has_sim_days(const rd_file_view_type *rd_file_view, - double sim_days) { - int num_DOUBHEAD = rd_file_view_get_num_named_kw(rd_file_view, DOUBHEAD_KW); +bool FileView::has_sim_days(double sim_days) { + size_t num_DOUBHEAD = num_named_kw(DOUBHEAD_KW); if (num_DOUBHEAD == 0) return false; /* We have no DOUBHEAD headers - probably not a restart file at all. */ else { int doubhead_index = 0; while (true) { - double file_sim_days = rd_file_view_iget_restart_sim_days( - rd_file_view, doubhead_index); + double file_sim_days = restart_sim_days(doubhead_index); if (util_double_approx_equal(sim_days, file_sim_days)) return true; @@ -586,124 +419,97 @@ static bool rd_file_view_has_sim_days(const rd_file_view_type *rd_file_view, } } -static int -rd_file_view_seqnum_index_from_sim_time(rd_file_view_type *parent_map, - time_t sim_time) { - int num_seqnum = rd_file_view_get_num_named_kw(parent_map, SEQNUM_KW); +std::shared_ptr +FileView::restart_view_from_seqnum_index(size_t index) { + return blockview(SEQNUM_KW, SEQNUM_KW, index); +} +std::shared_ptr +FileView::restart_view_from_report_step(int report_step) { + int global_index = find_kw_value(SEQNUM_KW, &report_step); + if (global_index < 0) + throw std::invalid_argument( + fmt::format("No such restart block could be identified")); + return restart_view_from_seqnum_index(get_occurence(global_index)); +} + +std::shared_ptr +FileView::restart_view_from_sim_time(time_t sim_time) { + size_t num_seqnum = num_named_kw(SEQNUM_KW); - for (int s_idx = 0; s_idx < num_seqnum; s_idx++) { - rd_file_view_ptr seqnum_map( - rd_file_view_alloc_blockview(parent_map, SEQNUM_KW, s_idx)); + for (size_t s_idx = 0; s_idx < num_seqnum; s_idx++) { + std::shared_ptr seqnum_map = + blockview(SEQNUM_KW, SEQNUM_KW, s_idx); if (!seqnum_map) continue; - if (rd_file_view_has_sim_time(seqnum_map.get(), sim_time)) - return s_idx; + if (seqnum_map->has_sim_time(sim_time)) + return seqnum_map; } - return -1; + throw std::invalid_argument( + fmt::format("No such restart block could be identified")); } -static int rd_file_view_seqnum_index_from_sim_days(rd_file_view_type *file_view, - double sim_days) { - int num_seqnum = rd_file_view_get_num_named_kw(file_view, SEQNUM_KW); - int seqnum_index = 0; +std::shared_ptr +FileView::restart_view_from_sim_days(double sim_days) { + size_t num_seqnum = num_named_kw(SEQNUM_KW); + size_t seqnum_index = 0; while (true) { - rd_file_view_ptr seqnum_map( - rd_file_view_alloc_blockview(file_view, SEQNUM_KW, seqnum_index)); + std::shared_ptr seqnum_map = + blockview(SEQNUM_KW, SEQNUM_KW, seqnum_index); if (seqnum_map) { - if (rd_file_view_has_sim_days(seqnum_map.get(), sim_days)) { - return seqnum_index; + if (seqnum_map->has_sim_days(sim_days)) { + return seqnum_map; } else { seqnum_index++; } } if (num_seqnum == seqnum_index) - return -1; + throw std::invalid_argument( + fmt::format("No such restart block could be identified")); } } -/* - Will mulitplex on the four input arguments. -*/ -rd_file_view_type *rd_file_view_add_restart_view(rd_file_view_type *file_view, - int input_index, - int report_step, - time_t sim_time, - double sim_days) { - rd_file_view_type *child = NULL; - int seqnum_index = -1; - - if (input_index >= 0) - seqnum_index = input_index; - else if (report_step >= 0) { - int global_index = - rd_file_view_find_kw_value(file_view, SEQNUM_KW, &report_step); - if (global_index >= 0) - seqnum_index = rd_file_view_iget_occurence(file_view, global_index); - } else if (sim_time != -1) - seqnum_index = - rd_file_view_seqnum_index_from_sim_time(file_view, sim_time); - else if (sim_days >= 0) - seqnum_index = - rd_file_view_seqnum_index_from_sim_days(file_view, sim_days); - - if (seqnum_index >= 0) - child = rd_file_view_add_blockview(file_view, SEQNUM_KW, seqnum_index); - - return child; -} - -rd_file_view_type *rd_file_view_add_summary_view(rd_file_view_type *file_view, - int report_step) { - rd_file_view_type *child = - rd_file_view_add_blockview(file_view, SEQHDR_KW, report_step); - return child; -} - -void rd_file_view_fclose_stream(rd_file_view_type *file_view) { - file_view->fortio->fclose_stream(); +std::shared_ptr FileView::summary_view(int report_step) { + return blockview(SEQHDR_KW, SEQHDR_KW, report_step); } -void rd_file_view_write_index(const rd_file_view_type *file_view, - FILE *ostream) { - int size = rd_file_view_get_size(file_view); - util_fwrite_int(size, ostream); +void FileView::write_index(FILE *ostream) const { + util_fwrite_int(static_cast(size()), ostream); - for (const auto &file_kw : file_view->kw_list) { + for (const auto &file_kw : kw_list) { file_kw->write_header(ostream); } } -rd_file_view_type *rd_file_view_fread_alloc(ERT::FortIO *fortio, - FileMode *flags, - inv_map_type *inv_map, - FILE *istream) { +std::shared_ptr FileView::read(std::shared_ptr context, + FILE *istream) { int index_size = util_fread_int(istream); if (index_size < 0) - return NULL; - auto file_view = std::make_unique(fortio, flags, inv_map); + return {nullptr}; + auto file_view = std::make_shared(std::move(context)); try { file_view->kw_list = FileKW::read(istream, static_cast(index_size)); } catch (const std::exception &e) { - fprintf(stderr, "%s\n", e.what()); - return NULL; + std::cerr << e.what() << std::endl; + return nullptr; } - rd_file_view_make_index(file_view.get()); - return file_view.release(); + file_view->make_index(); + return file_view; } -void rd_file_view_clear(rd_file_view_type *file_view) { - for (const auto &file_kw : file_view->kw_list) { +void FileView::clear() { + for (const auto &file_kw : kw_list) { if (auto *rd_kw = file_kw->get_kw_ptr()) - file_view->inv_map->erase(rd_kw); + context->inv_map.erase(rd_kw); file_kw->clear(); } } +} // namespace rd diff --git a/lib/resdata/rd_file_view_pybind.cpp b/lib/resdata/rd_file_view_pybind.cpp index e55d84e71..5a5bbb807 100644 --- a/lib/resdata/rd_file_view_pybind.cpp +++ b/lib/resdata/rd_file_view_pybind.cpp @@ -1,87 +1,260 @@ +#include +#include #include #include +#include #include +#include #include +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include +#include #include namespace py = pybind11; namespace { -py::object create_kw_reference(rd_kw_type *kw, py::handle parent) { +py::object create_kw_reference(rd_kw_type *kw, py::object parent) { if (!kw) return py::none(); return ResdataKW().attr("createCReference")( reinterpret_cast(kw), parent); } - -py::object create_view_reference(rd_file_view_type *view, py::handle parent) { - if (!view) - return py::none(); - return ResdataFileView().attr("createCReference")( - reinterpret_cast(view), parent); -} } // namespace -PYBIND11_MODULE(_file_view, m) { +template struct overload : Ts... { + using Ts::operator()...; +}; +template overload(Ts...) -> overload; + +PYBIND11_MODULE(rd_file_view, m) { register_exceptions(m); - m.doc() = "pybind11 bindings for ResdataFileView"; - - m.def("_iget_kw", [](py::handle self, int index) { - return create_kw_reference( - rd_file_view_iget_kw(from_cwrap(self), index), - self); - }); - m.def("_iget_named_kw", [](py::handle self, std::string kw, int index) { - return create_kw_reference( - rd_file_view_iget_named_kw(from_cwrap(self), - kw.c_str(), index), - self); - }); - m.def("_get_unique_kw", [](py::handle self, int index) { - return rd_file_view_iget_distinct_kw( - from_cwrap(self), index); - }); - m.def("_get_size", [](py::handle self) { - return rd_file_view_get_size(from_cwrap(self)); - }); - m.def("_get_num_named_kw", [](py::handle self, std::string kw) { - return rd_file_view_get_num_named_kw( - from_cwrap(self), kw.c_str()); - }); - m.def("_get_unique_size", [](py::handle self) { - return rd_file_view_get_num_distinct_kw( - from_cwrap(self)); - }); - m.def("_create_block_view", [](py::handle self, std::string kw, int index) { - return create_view_reference( - rd_file_view_add_blockview(from_cwrap(self), - kw.c_str(), index), - self); - }); - m.def("_create_block_view2", - [](py::handle self, std::optional start_kw, - std::optional stop_kw, int index) { - return create_view_reference( - rd_file_view_add_blockview2( - from_cwrap(self), - start_kw ? start_kw->c_str() : nullptr, - stop_kw ? stop_kw->c_str() : nullptr, index), - self); - }); - m.def("_restart_view", - [](py::handle self, int seqnum_index, int report_step, - std::int64_t sim_time, double sim_days) { - return create_view_reference( - rd_file_view_add_restart_view( - from_cwrap(self), seqnum_index, - report_step, static_cast(sim_time), sim_days), - self); - }); + py::class_>(m, + "ResdataFileView") + .def(py::init([]() -> std::shared_ptr { + py::set_error(PyExc_NotImplementedError, + "Class can not be instantiated directly"); + throw py::error_already_set(); + })) + .def("__repr__", + [](rd::FileView &self) { + return fmt::format("ResdataFileView(size={})", self.size()); + }) + .def( + "iget_named_kw", + [](py::object py_self, std::string kw, py::int_ index) { + auto &self = py_self.cast(); + if (!self.has_kw(kw)) + throw py::key_error(fmt::format("No such keyword: {}", kw)); + if (index < py::int_(0)) + throw py::index_error(fmt::format( + "Index of iget_named_kw for {} was negative: {}", kw, + py::str(index).cast())); + if (index >= py::int_(self.num_named_kw(kw))) + throw py::index_error( + fmt::format("Too large index: {}", + py::str(index).cast())); + return create_kw_reference( + self.get_kw(kw, index.cast()), py_self); + }, + py::arg("kw_name"), py::arg("index")) + .def( + "__getitem__", + [](py::object py_self, + std::variant index) + -> std::variant> { + auto &self = py_self.cast(); + return std::visit( + overload{ + [&self, &py_self](std::string si) { + if (!self.has_kw(si)) + throw py::key_error(fmt::format( + "Unrecognized keyword: {}", si)); + std::vector result; + size_t n = self.num_named_kw(si); + result.reserve(n); + size_t i = 0; + std::generate_n(std::back_inserter(result), n, + [&self, &py_self, &i, &si]() { + return create_kw_reference( + self.get_kw(si, i++), + py_self); + }); + return std::variant>{ + result}; + }, + [&self, &py_self](py::int_ start_index) { + py::int_ ls(self.size()); + py::int_ index(start_index); + if (index < py::int_(0)) + index += ls; + + if (index < py::int_(0) || index >= ls) + throw py::index_error(fmt::format( + "Index must be in [0, {}), was: {}.", + py::str(ls).cast(), + py::str(index).cast())); + + return std::variant>{ + create_kw_reference( + self.get_kw(index.cast()), + py_self)}; + }, + [&self, &py_self](py::slice s) { + size_t size = self.size(); + if (size > (size_t)PY_SSIZE_T_MAX) + throw std::invalid_argument( + "Size overflowed in slice calculation"); + auto ssize = static_cast(self.size()); + + py::ssize_t start, stop, step, slicelength; + if (!s.compute(ssize, &start, &stop, &step, + &slicelength)) { + throw py::index_error("slice out of range"); + } + + std::vector result; + result.reserve(slicelength); + for (py::ssize_t i = 0; i < slicelength; ++i) { + py::ssize_t idx = start + i * step; + if (idx < 0) + throw py::index_error( + fmt::format("Negative index {} in " + "FileView::__getitem__", + idx)); + result.push_back(create_kw_reference( + self.get_kw(static_cast(idx)), + py_self)); + } + return std::variant>{ + result}; + }, + }, + index); + }, + py::arg("index"), + "Look up ResdataKW instances from the current ResdataFile.\n" + "\n" + "The index argument can either be an integer, in\n" + "which case the method will return ResdataKW number index, or\n" + "alternatively a keyword string, in which case the method will\n" + "return a list of ResdataKW instances with that keyword:\n" + "\n" + " restart_file = rd_file.ResdataFile(\"CASE.UNRST\")\n" + " kw9 = restart_file[9]\n" + " swat_list = restart_file[\"SWAT\"]\n" + "\n" + "The keyword based lookup can be combined with an extra [] to\n" + "get ResdataKW instance nr:\n" + "\n" + " swat9 = restart_file[\"SWAT\"][9]\n" + "\n" + "Will return the 10'th SWAT keyword from the restart file. The\n" + "following example will iterate over all the SWAT keywords in a\n" + "restart file:\n" + "\n" + " restart_file = rd_file.ResdataFile(\"CASE.UNRST\")\n" + " for swat in restart_file[\"SWAT\"]:\n" + " ....\n") + .def("__len__", &rd::FileView::size) + .def("__contains__", &rd::FileView::has_kw) + .def("num_keywords", &rd::FileView::num_named_kw, py::arg("kw")) + .def("unique_size", &rd::FileView::num_distinct_kw) + .def("unique_kw", &rd::FileView::get_distinct_kw) + .def( + "block_view2", + [](rd::FileView *self, std::optional start_kw, + std::optional stop_kw, py::int_ start_index) { + size_t occurence = 0; + if (start_kw) { + size_t num_start = self->num_named_kw(*start_kw); + if (num_start == 0) + throw py::key_error(fmt::format( + "The keyword:{} is not in file", *start_kw)); + py::int_ index(start_index); + py::int_ ls(num_start); + if (index < py::int_(0)) + index += ls; + + if (index < py::int_(0) || index >= ls) + throw py::index_error(fmt::format( + "Index must be in [0, {}), was: {}.", + py::str(ls).cast(), + py::str(start_index).cast())); + occurence = index.cast(); + } + if (stop_kw && !self->has_kw(*stop_kw)) + throw py::key_error( + fmt::format("The keyword:{} is not in file", *stop_kw)); + + return self->blockview(start_kw, stop_kw, occurence); + }, + py::arg("start_kw"), py::arg("stop_kw"), py::arg("start_index")) + .def( + "block_view", + [](rd::FileView *self, std::string kw, py::int_ start_index) { + size_t num = self->num_named_kw(kw); + + if (num == 0) + throw py::key_error(fmt::format("Unknown keyword: {}", kw)); + + py::int_ ls(num); + py::int_ index(start_index); + if (index < py::int_(0)) + index += ls; + + if (index < py::int_(0) || index >= ls) + throw py::index_error( + fmt::format("Index must be in [0, {}), was: {}.", num, + py::str(index).cast())); + + return self->blockview(kw, kw, index.cast()); + }, + py::arg("kw"), py::arg("kw_index")) + .def( + "restart_view", + [](rd::FileView &self, std::optional seqnum_index, + std::optional report_step, py::object sim_time, + std::optional sim_days) { + std::shared_ptr view(nullptr); + if (seqnum_index.has_value()) { + if (*seqnum_index < py::int_(0)) + throw std::invalid_argument( + "seqnum_index cannot be negative"); + view = self.restart_view_from_seqnum_index( + (*seqnum_index).cast()); + } else if (report_step.has_value()) + view = self.restart_view_from_report_step(*report_step); + else if (!sim_time.is_none()) + view = self.restart_view_from_sim_time( + CTime()(sim_time).attr("value")().cast()); + else if (sim_days.has_value()) + view = self.restart_view_from_sim_days(*sim_days); + + if (!view) + throw py::value_error( + "No such restart block could be identified"); + return view; + }, + py::arg("seqnum_index") = py::none(), + py::arg("report_step") = py::none(), + py::arg("sim_time") = py::none(), py::arg("sim_days") = py::none()); } diff --git a/lib/resdata/rd_grav.cpp b/lib/resdata/rd_grav.cpp index af19e8ec7..18478a6ab 100644 --- a/lib/resdata/rd_grav.cpp +++ b/lib/resdata/rd_grav.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -107,7 +108,7 @@ static void rd_grav_survey_free(rd_grav_survey_type *grav_survey) { delete grav_survey; } -static const char *get_den_kw(rd_phase_enum phase, rd_version_enum rd_version) { +static std::string get_den_kw(rd_phase_enum phase, rd_version_enum rd_version) { if (rd_version == ECLIPSE100) { switch (phase) { case (RD_OIL_PHASE): @@ -197,10 +198,11 @@ static double rd_grav_phase_eval(rd_grav_phase_type *base_phase, } } -static rd_grav_phase_type * -rd_grav_phase_alloc(rd_grav_type *rd_grav, rd_grav_survey_type *survey, - rd_phase_enum phase, const rd_file_view_type *restart_file, - grav_calc_type calc_type) { +static rd_grav_phase_type *rd_grav_phase_alloc(rd_grav_type *rd_grav, + rd_grav_survey_type *survey, + rd_phase_enum phase, + rd::FileView *restart_file, + grav_calc_type calc_type) { const rd_file_type *init_file = rd_grav->init_file; const rd::rd_grid_cache *grid_cache = rd_grav->grid_cache; @@ -226,11 +228,11 @@ rd_grav_phase_alloc(rd_grav_type *rd_grav, rd_grav_survey_type *survey, rd_kw_type *fip_kw; if (phase == RD_OIL_PHASE) - fip_kw = rd_file_view_iget_named_kw(restart_file, FIPOIL_KW, 0); + fip_kw = restart_file->get_kw(FIPOIL_KW, 0); else if (phase == RD_GAS_PHASE) - fip_kw = rd_file_view_iget_named_kw(restart_file, FIPGAS_KW, 0); + fip_kw = restart_file->get_kw(FIPGAS_KW, 0); else - fip_kw = rd_file_view_iget_named_kw(restart_file, FIPWAT_KW, 0); + fip_kw = restart_file->get_kw(FIPWAT_KW, 0); for (int iactive = 0; iactive < size; iactive++) { double fip = rd_kw_iget_as_double(fip_kw, iactive); @@ -243,21 +245,17 @@ rd_grav_phase_alloc(rd_grav_type *rd_grav, rd_grav_survey_type *survey, } } else { rd_version_enum rd_version = rd_file_get_rd_version(init_file); - const char *den_kw_name = get_den_kw(phase, rd_version); - const rd_kw_type *den_kw = - rd_file_view_iget_named_kw(restart_file, den_kw_name, 0); + const std::string den_kw_name = get_den_kw(phase, rd_version); + const rd_kw_type *den_kw = restart_file->get_kw(den_kw_name, 0); if (calc_type == GRAV_CALC_RFIP) { rd_kw_type *rfip_kw; if (phase == RD_OIL_PHASE) - rfip_kw = - rd_file_view_iget_named_kw(restart_file, RFIPOIL_KW, 0); + rfip_kw = restart_file->get_kw(RFIPOIL_KW, 0); else if (phase == RD_GAS_PHASE) - rfip_kw = - rd_file_view_iget_named_kw(restart_file, RFIPGAS_KW, 0); + rfip_kw = restart_file->get_kw(RFIPGAS_KW, 0); else - rfip_kw = - rd_file_view_iget_named_kw(restart_file, RFIPWAT_KW, 0); + rfip_kw = restart_file->get_kw(RFIPWAT_KW, 0); { int iactive; @@ -271,20 +269,18 @@ rd_grav_phase_alloc(rd_grav_type *rd_grav, rd_grav_survey_type *survey, /* (calc_type == GRAV_CALC_RPORV) || (calc_type == GRAV_CALC_PORMOD) */ rd_kw_type *sat_kw; bool private_sat_kw = false; - if (rd_file_view_has_kw(restart_file, sat_kw_name)) - sat_kw = rd_file_view_iget_named_kw(restart_file, - sat_kw_name, 0); + if (restart_file->has_kw(std::string(sat_kw_name))) + sat_kw = restart_file->get_kw(sat_kw_name, 0); else { /* We are targeting the residual phase, e.g. the OIL phase in a three phase system. */ - const rd_kw_type *swat_kw = - rd_file_view_iget_named_kw(restart_file, "SWAT", 0); + const rd_kw_type *swat_kw = restart_file->get_kw("SWAT", 0); sat_kw = rd_kw_alloc_copy(swat_kw); rd_kw_scalar_set_float(sat_kw, 1.0); rd_kw_inplace_sub(sat_kw, swat_kw); /* sat = 1 - SWAT */ - if (rd_file_view_has_kw(restart_file, "SGAS")) { + if (restart_file->has_kw("SGAS")) { const rd_kw_type *sgas_kw = - rd_file_view_iget_named_kw(restart_file, "SGAS", 0); + restart_file->get_kw("SGAS", 0); rd_kw_inplace_sub(sat_kw, sgas_kw); /* sat -= SGAS */ } private_sat_kw = true; @@ -318,7 +314,7 @@ static void rd_grav_survey_add_phase(rd_grav_survey_type *survey, static bool rd_grav_survey_add_phases(rd_grav_type *rd_grav, rd_grav_survey_type *survey, - const rd_file_view_type *restart_file, + rd::FileView *restart_file, grav_calc_type calc_type) { int phases = rd_file_get_phases(rd_grav->init_file); if (phases & RD_OIL_PHASE) { @@ -453,15 +449,13 @@ static void rd_grav_survey_assert_RPORV(const rd_grav_survey_type *survey, */ static rd_grav_survey_type * -rd_grav_survey_alloc_RPORV(rd_grav_type *rd_grav, - const rd_file_view_type *restart_file, +rd_grav_survey_alloc_RPORV(rd_grav_type *rd_grav, rd::FileView *restart_file, const std::string &name) { rd_grav_survey_type *survey = rd_grav_survey_alloc_empty(rd_grav, name, GRAV_CALC_RPORV); - if (rd_file_view_has_kw(restart_file, RPORV_KW)) { - rd_kw_type *rporv_kw = - rd_file_view_iget_named_kw(restart_file, RPORV_KW, 0); + if (restart_file->has_kw(RPORV_KW)) { + rd_kw_type *rporv_kw = restart_file->get_kw(RPORV_KW, 0); int iactive; for (iactive = 0; iactive < rd_kw_get_size(rporv_kw); iactive++) survey->porv[iactive] = rd_kw_iget_as_double(rporv_kw, iactive); @@ -483,8 +477,7 @@ rd_grav_survey_alloc_RPORV(rd_grav_type *rd_grav, } static rd_grav_survey_type * -rd_grav_survey_alloc_PORMOD(rd_grav_type *rd_grav, - const rd_file_view_type *restart_file, +rd_grav_survey_alloc_PORMOD(rd_grav_type *rd_grav, rd::FileView *restart_file, const std::string &name) { rd::rd_grid_cache &grid_cache = *(rd_grav->grid_cache); rd_grav_survey_type *survey = @@ -492,8 +485,8 @@ rd_grav_survey_alloc_PORMOD(rd_grav_type *rd_grav, rd_kw_type *init_porv_kw = rd_file_iget_named_kw( rd_grav->init_file, PORV_KW, 0); /* Global indexing */ - rd_kw_type *pormod_kw = rd_file_view_iget_named_kw(restart_file, PORMOD_KW, - 0); /* Active indexing */ + rd_kw_type *pormod_kw = + restart_file->get_kw(PORMOD_KW, 0); /* Active indexing */ const int size = grid_cache.size(); const auto &global_index = grid_cache.global_index(); int active_index; @@ -518,10 +511,9 @@ rd_grav_survey_alloc_PORMOD(rd_grav_type *rd_grav, possibly also the rd_grav_add_std_density() functions. */ -static rd_grav_survey_type * -rd_grav_survey_alloc_FIP(rd_grav_type *rd_grav, - const rd_file_view_type *restart_file, - const std::string &name) { +static rd_grav_survey_type *rd_grav_survey_alloc_FIP(rd_grav_type *rd_grav, + rd::FileView *restart_file, + const std::string &name) { rd_grav_survey_type *survey = rd_grav_survey_alloc_empty(rd_grav, name, GRAV_CALC_FIP); @@ -536,8 +528,7 @@ rd_grav_survey_alloc_FIP(rd_grav_type *rd_grav, } static rd_grav_survey_type * -rd_grav_survey_alloc_RFIP(rd_grav_type *rd_grav, - const rd_file_view_type *restart_file, +rd_grav_survey_alloc_RFIP(rd_grav_type *rd_grav, rd::FileView *restart_file, const std::string &name) { rd_grav_survey_type *survey = @@ -598,9 +589,9 @@ static void rd_grav_add_survey__(rd_grav_type *grav, const std::string &name, grav->surveys[name] = survey; } -rd_grav_survey_type * -rd_grav_add_survey_RPORV(rd_grav_type *grav, const std::string &name, - const rd_file_view_type *restart_file) { +rd_grav_survey_type *rd_grav_add_survey_RPORV(rd_grav_type *grav, + const std::string &name, + rd::FileView *restart_file) { rd_grav_survey_type *survey = rd_grav_survey_alloc_RPORV(grav, restart_file, name); @@ -611,9 +602,9 @@ rd_grav_add_survey_RPORV(rd_grav_type *grav, const std::string &name, return survey; } -rd_grav_survey_type * -rd_grav_add_survey_FIP(rd_grav_type *grav, const std::string &name, - const rd_file_view_type *restart_file) { +rd_grav_survey_type *rd_grav_add_survey_FIP(rd_grav_type *grav, + const std::string &name, + rd::FileView *restart_file) { rd_grav_survey_type *survey = rd_grav_survey_alloc_FIP(grav, restart_file, name); if (survey == NULL) @@ -622,9 +613,9 @@ rd_grav_add_survey_FIP(rd_grav_type *grav, const std::string &name, return survey; } -rd_grav_survey_type * -rd_grav_add_survey_RFIP(rd_grav_type *grav, const std::string &name, - const rd_file_view_type *restart_file) { +rd_grav_survey_type *rd_grav_add_survey_RFIP(rd_grav_type *grav, + const std::string &name, + rd::FileView *restart_file) { rd_grav_survey_type *survey = rd_grav_survey_alloc_RFIP(grav, restart_file, name); if (survey == NULL) @@ -633,9 +624,9 @@ rd_grav_add_survey_RFIP(rd_grav_type *grav, const std::string &name, return survey; } -rd_grav_survey_type * -rd_grav_add_survey_PORMOD(rd_grav_type *grav, const std::string &name, - const rd_file_view_type *restart_file) { +rd_grav_survey_type *rd_grav_add_survey_PORMOD(rd_grav_type *grav, + const std::string &name, + rd::FileView *restart_file) { rd_grav_survey_type *survey = rd_grav_survey_alloc_PORMOD(grav, restart_file, name); if (survey == NULL) diff --git a/lib/resdata/rd_grav_pybind.cpp b/lib/resdata/rd_grav_pybind.cpp index 83ca229c4..8f6aa3f34 100644 --- a/lib/resdata/rd_grav_pybind.cpp +++ b/lib/resdata/rd_grav_pybind.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -38,34 +39,25 @@ PYBIND11_MODULE(_grav, m) { m.def("_add_survey_RPORV", [](py::handle self, const std::string &name, - py::handle restart_file) -> py::object { + rd::FileView *restart_file) -> py::object { auto *grav = from_cwrap(self); - auto *restart_file_ptr = - from_cwrap(restart_file); - - auto *survey = - rd_grav_add_survey_RPORV(grav, name, restart_file_ptr); + auto *survey = rd_grav_add_survey_RPORV(grav, name, restart_file); if (survey == nullptr) return py::none(); return py::int_(reinterpret_cast(survey)); }); m.def("_add_survey_PORMOD", [](py::handle self, const std::string &name, - py::handle restart_file) { + rd::FileView *restart_file) { auto *grav = from_cwrap(self); - auto *restart_file_ptr = from_cwrap(restart_file); - rd_grav_add_survey_PORMOD(grav, name, restart_file_ptr); + rd_grav_add_survey_PORMOD(grav, name, restart_file); }); m.def("_add_survey_FIP", [](py::handle self, const std::string &name, - py::handle restart_file) -> py::object { + rd::FileView *restart_file) -> py::object { auto *grav = from_cwrap(self); - auto *restart_file_ptr = - from_cwrap(restart_file); - - auto *survey = - rd_grav_add_survey_FIP(grav, name, restart_file_ptr); + auto *survey = rd_grav_add_survey_FIP(grav, name, restart_file); if (survey == nullptr) { return py::none(); @@ -75,11 +67,9 @@ PYBIND11_MODULE(_grav, m) { }); m.def("_add_survey_RFIP", [](py::handle self, const std::string &name, - py::handle restart_file) { + rd::FileView *restart_file) { auto *grav = from_cwrap(self); - auto *restart_file_ptr = from_cwrap(restart_file); - - rd_grav_add_survey_RFIP(grav, name, restart_file_ptr); + rd_grav_add_survey_RFIP(grav, name, restart_file); }); m.def("_eval", diff --git a/lib/resdata/rd_grid.cpp b/lib/resdata/rd_grid.cpp index 381586d63..d3ba8026f 100644 --- a/lib/resdata/rd_grid.cpp +++ b/lib/resdata/rd_grid.cpp @@ -37,6 +37,7 @@ #include #include #include +#include namespace fs = std::filesystem; @@ -2388,17 +2389,16 @@ static void rd_grid_init_nnc(rd_grid_type *main_grid, rd_file_type *rd_file) { */ for (int i = 0; i < num_nnchead_kw; i++) { - auto lgr_view = rd_file_view_ptr( - rd_file_alloc_global_blockview(rd_file, NNCHEAD_KW, i)); - rd_kw_type *nnchead_kw = - rd_file_view_iget_named_kw(lgr_view.get(), NNCHEAD_KW, 0); + auto lgr_view = rd_file_get_global_view(rd_file)->blockview( + NNCHEAD_KW, NNCHEAD_KW, i); + if (!lgr_view) + throw std::runtime_error("Could not find NNC section of grid file"); + rd_kw_type *nnchead_kw = lgr_view->get_kw(NNCHEAD_KW, 0); int lgr_nr = rd_kw_iget_int(nnchead_kw, NNCHEAD_LGR_INDEX); - if (rd_file_view_has_kw(lgr_view.get(), NNC1_KW)) { - const rd_kw_type *nnc1 = - rd_file_view_iget_named_kw(lgr_view.get(), NNC1_KW, 0); - const rd_kw_type *nnc2 = - rd_file_view_iget_named_kw(lgr_view.get(), NNC2_KW, 0); + if (lgr_view->has_kw(NNC1_KW)) { + const rd_kw_type *nnc1 = lgr_view->get_kw(NNC1_KW, 0); + const rd_kw_type *nnc2 = lgr_view->get_kw(NNC2_KW, 0); { rd_grid_type *grid = @@ -2409,11 +2409,9 @@ static void rd_grid_init_nnc(rd_grid_type *main_grid, rd_file_type *rd_file) { } } - if (rd_file_view_has_kw(lgr_view.get(), NNCL_KW)) { - const rd_kw_type *nncl = - rd_file_view_iget_named_kw(lgr_view.get(), NNCL_KW, 0); - const rd_kw_type *nncg = - rd_file_view_iget_named_kw(lgr_view.get(), NNCG_KW, 0); + if (lgr_view->has_kw(NNCL_KW)) { + const rd_kw_type *nncl = lgr_view->get_kw(NNCL_KW, 0); + const rd_kw_type *nncg = lgr_view->get_kw(NNCG_KW, 0); { rd_grid_type *grid = (lgr_nr > 0) diff --git a/lib/resdata/rd_subsidence.cpp b/lib/resdata/rd_subsidence.cpp index 67a30ddc1..a96daa081 100644 --- a/lib/resdata/rd_subsidence.cpp +++ b/lib/resdata/rd_subsidence.cpp @@ -69,7 +69,7 @@ struct rd_subsidence_survey_struct { static std::unique_ptr rd_subsidence_survey_alloc_PRESSURE(rd_subsidence_type *rd_subsidence, - const rd_file_view_type *restart_view, + rd::FileView *restart_view, const std::string &name) { auto survey( @@ -80,14 +80,14 @@ rd_subsidence_survey_alloc_PRESSURE(rd_subsidence_type *rd_subsidence, rd_kw_type *init_porv_kw = rd_file_iget_named_kw( rd_subsidence->init_file, PORV_KW, 0); /*Global indexing*/ - rd_kw_type *pressure_kw = rd_file_view_iget_named_kw( - restart_view, PRESSURE_KW, 0); /*Active indexing*/ + rd_kw_type *pressure_kw = + restart_view->get_kw(PRESSURE_KW, 0); /*Active indexing*/ rd_kw_type *rporv_kw = nullptr; - if (rd_file_view_has_kw(restart_view, RPORV_KW)) { + if (restart_view->has_kw(RPORV_KW)) { survey->dynamic_porevolume = std::vector(rd_subsidence->grid_cache->size(), 0.0); - rporv_kw = rd_file_view_iget_named_kw(restart_view, RPORV_KW, 0); + rporv_kw = restart_view->get_kw(RPORV_KW, 0); } for (int active_index = 0; active_index < size; active_index++) { @@ -219,7 +219,7 @@ rd_subsidence_type *rd_subsidence_alloc(rd_grid_type *rd_grid, rd_subsidence_survey_type * rd_subsidence_add_survey_PRESSURE(rd_subsidence_type *subsidence, const std::string &name, - const rd_file_view_type *restart_view) { + rd::FileView *restart_view) { auto survey = rd_subsidence_survey_alloc_PRESSURE(subsidence, restart_view, name); rd_subsidence_survey_type *ret = survey.get(); diff --git a/lib/resdata/rd_subsidence_pybind.cpp b/lib/resdata/rd_subsidence_pybind.cpp index 5f21c6204..bdea80c9e 100644 --- a/lib/resdata/rd_subsidence_pybind.cpp +++ b/lib/resdata/rd_subsidence_pybind.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -34,12 +35,13 @@ PYBIND11_MODULE(_subsidence, m) { rd_subsidence_free(from_cwrap(self)); }); - m.def("_add_survey_PRESSURE", [](py::handle self, std::string survey_name, - py::handle restart_file_view) { - rd_subsidence_add_survey_PRESSURE( - from_cwrap(self), survey_name, - from_cwrap(restart_file_view)); - }); + m.def("_add_survey_PRESSURE", + [](py::handle self, std::string survey_name, + std::shared_ptr restart_file_view) { + rd_subsidence_add_survey_PRESSURE( + from_cwrap(self), survey_name, + restart_file_view.get()); + }); m.def("_eval", [](py::handle self, std::string base, std::optional monitor, py::object region, diff --git a/lib/resdata/rd_sum_file_data.cpp b/lib/resdata/rd_sum_file_data.cpp index 3b04e4452..092da1b8e 100644 --- a/lib/resdata/rd_sum_file_data.cpp +++ b/lib/resdata/rd_sum_file_data.cpp @@ -561,26 +561,23 @@ bool rd_sum_file_data::check_file(rd_file_type *rd_file) { */ void rd_sum_file_data::add_rd_file(int report_step, - const rd_file_view_type *summary_view) { + rd::FileView &summary_view) { validate_report_step(report_step); - int num_ministep = rd_file_view_get_num_named_kw(summary_view, PARAMS_KW); + size_t num_ministep = summary_view.num_named_kw(PARAMS_KW); if (num_ministep > 0) { - int ikw; - for (ikw = 0; ikw < num_ministep; ikw++) { - rd_kw_type *ministep_kw = - rd_file_view_iget_named_kw(summary_view, MINISTEP_KW, ikw); - rd_kw_type *params_kw = - rd_file_view_iget_named_kw(summary_view, PARAMS_KW, ikw); + for (size_t ikw = 0; ikw < num_ministep; ikw++) { + rd_kw_type *ministep_kw = summary_view.get_kw(MINISTEP_KW, ikw); + rd_kw_type *params_kw = summary_view.get_kw(PARAMS_KW, ikw); { int ministep_nr = rd_kw_iget_int(ministep_kw, 0); + std::string filename = summary_view.filename(); std::unique_ptr tstep(rd_sum_tstep_alloc_from_file( report_step, ministep_nr, params_kw, - rd_file_view_get_src_file(summary_view), - this->rd_smspec), + filename.c_str(), this->rd_smspec), &rd_sum_tstep_free); if (tstep) @@ -616,8 +613,8 @@ bool rd_sum_file_data::fread(const stringlist_type *filelist, bool lazy_load, { rd_file_ptr rd_file = open_rd_file(std::string(data_file)); if (rd_file && check_file(rd_file.get())) { - this->add_rd_file(report_step, - rd_file_get_global_view(rd_file.get())); + auto global_view = rd_file_get_global_view(rd_file.get()); + this->add_rd_file(report_step, *global_view); } } } @@ -648,11 +645,11 @@ bool rd_sum_file_data::fread(const stringlist_type *filelist, bool lazy_load, SEQHDR block in the unified summary file is block zero (in ert counting). */ - rd_file_view_type *summary_view = + auto summary_view = rd_file_get_summary_view(rd_file.get(), block_index); if (summary_view) { this->add_rd_file(block_index + first_report_step, - summary_view); + *summary_view); block_index++; } else break; diff --git a/lib/resdata/rd_unsmry_loader.cpp b/lib/resdata/rd_unsmry_loader.cpp index ce82e002f..1d591ac21 100644 --- a/lib/resdata/rd_unsmry_loader.cpp +++ b/lib/resdata/rd_unsmry_loader.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -26,28 +28,29 @@ unsmry_loader::unsmry_loader(const rd_smspec_type *smspec, time_index(rd_smspec_get_time_index(smspec)), time_seconds(rd_smspec_get_time_seconds(smspec)), sim_start(rd_smspec_get_start_time(smspec)) { - rd_file_ptr file = open_rd_file(filename, file_options); - if (!file) - throw std::bad_alloc(); - - if (!rd_file_has_kw(file.get(), PARAMS_KW)) { + { + rd_file_ptr file = open_rd_file(filename, file_options); + if (!file) + throw std::bad_alloc(); + this->file = std::move(file); + } + if (!rd_file_has_kw(this->file.get(), PARAMS_KW)) { throw std::bad_alloc(); } - if (rd_file_get_num_named_kw(file.get(), PARAMS_KW) != - rd_file_get_num_named_kw(file.get(), MINISTEP_KW)) { + if (rd_file_get_num_named_kw(this->file.get(), PARAMS_KW) != + rd_file_get_num_named_kw(this->file.get(), MINISTEP_KW)) { throw std::bad_alloc(); } this->date_index = {{rd_smspec_get_date_day_index(smspec), rd_smspec_get_date_month_index(smspec), rd_smspec_get_date_year_index(smspec)}}; - rd_file_view_type *file_view = rd_file_get_global_view(file.get()); - int length = rd_file_view_get_num_named_kw(file_view, PARAMS_KW); + auto file_view = rd_file_get_global_view(this->file.get()); + int length = file_view->num_named_kw(PARAMS_KW); if (length > 0) { - const rd_kw_type *params_kw = - rd_file_view_iget_named_kw(file_view, PARAMS_KW, 0); + const rd_kw_type *params_kw = file_view->get_kw(PARAMS_KW, 0); if (params_kw == nullptr) throw std::invalid_argument( "Malformed summary file: missing PARAMS keyword entry"); @@ -58,13 +61,10 @@ unsmry_loader::unsmry_loader(const rd_smspec_type *smspec, "Malformed summary file: PARAMS keyword is not float"); } - this->file = file.release(); this->file_view = file_view; this->m_length = length; } -unsmry_loader::~unsmry_loader() { rd_file_close(file); } - int unsmry_loader::length() const { return this->m_length; } std::vector unsmry_loader::get_vector(int pos) const { @@ -78,13 +78,13 @@ std::vector unsmry_loader::get_vector(int pos) const { float value; for (int index = 0; index < this->length(); index++) { - rd_file_view_index_fload_kw(file_view, PARAMS_KW, index, - index_map.get(), (char *)&value); + file_view->index_fload_kw(PARAMS_KW, index, index_map.get(), + (char *)&value); data[index] = value; } - if (rd_file_view_flags_set(file_view, FileMode::CLOSE_STREAM)) - rd_file_view_fclose_stream(file_view); + if (file_view->has_flags(FileMode::CLOSE_STREAM)) + file_view->close(); return data; } @@ -93,8 +93,8 @@ std::vector unsmry_loader::get_vector(int pos) const { double unsmry_loader::iget(int time_index, int params_index) const { auto index_map = make_int_vector(1, params_index); float value; - rd_file_view_index_fload_kw(this->file_view, PARAMS_KW, time_index, - index_map.get(), (char *)&value); + file_view->index_fload_kw(PARAMS_KW, time_index, index_map.get(), + (char *)&value); return value; } @@ -111,8 +111,8 @@ time_t unsmry_loader::iget_sim_time(int time_index) const { int_vector_iset(index_map.get(), 2, this->date_index[2]); float values[3]; - rd_file_view_index_fload_kw(this->file_view, PARAMS_KW, time_index, - index_map.get(), (char *)&values); + file_view->index_fload_kw(PARAMS_KW, time_index, index_map.get(), + (char *)&values); return rd_make_date(util_roundf(values[0]), util_roundf(values[1]), util_roundf(values[2])); @@ -132,8 +132,7 @@ double unsmry_loader::iget_sim_seconds(int time_index) const { std::vector unsmry_loader::report_steps(int offset) const { std::vector report_steps; int current_step = offset; - for (int i = 0; i < rd_file_view_get_size(this->file_view); i++) { - const auto file_kw = rd_file_view_iget_file_kw(this->file_view, i); + for (const auto &file_kw : *file_view) { if (SEQHDR_KW == file_kw->get_header()) current_step++; diff --git a/lib/resdata/rsthead_pybind.cpp b/lib/resdata/rsthead_pybind.cpp index 4303d2789..d48c3ba07 100644 --- a/lib/resdata/rsthead_pybind.cpp +++ b/lib/resdata/rsthead_pybind.cpp @@ -19,32 +19,31 @@ PYBIND11_MODULE(_rsthead, m) { register_exceptions(m); m.doc() = "pybind11 bindings for rd_rsthead.hpp"; py::class_(m, "ResdataRestartHead") - .def(py::init([](std::optional>> - kw_arg, - std::optional rst_view) { - if (kw_arg == std::nullopt && rst_view == std::nullopt) - throw std::invalid_argument( - "Cannot construct ResdataRestartHead without one of " - "kw_arg " - "and rst_view, both were None!"); + .def( + py::init([](std::optional>> + kw_arg, + std::optional> rst_view) { + if (kw_arg == std::nullopt && rst_view == std::nullopt) + throw std::invalid_argument( + "Cannot construct ResdataRestartHead without one of " + "kw_arg " + "and rst_view, both were None!"); - if (kw_arg.has_value()) { - return new RSTHead( - std::get<0>(*kw_arg), - from_cwrap(std::get<1>(*kw_arg)), - from_cwrap(std::get<2>(*kw_arg)), - from_cwrap(std::get<3>(*kw_arg))); - } else { - return std::make_unique( - RSTHead::read( - from_cwrap(*rst_view), - -1)) - .release(); - } - }), - py::arg("kw_arg") = std::nullopt, - py::arg("rst_view") = std::nullopt) + if (kw_arg.has_value()) { + return new RSTHead( + std::get<0>(*kw_arg), + from_cwrap(std::get<1>(*kw_arg)), + from_cwrap(std::get<2>(*kw_arg)), + from_cwrap(std::get<3>(*kw_arg))); + } else { + return std::make_unique( + RSTHead::read(rst_view->get(), -1)) + .release(); + } + }), + py::arg("kw_arg") = std::nullopt, + py::arg("rst_view") = std::nullopt) .def("get_report_step", [](RSTHead &self) { return self.report_step; }) .def("get_sim_date", [](RSTHead &self) { diff --git a/lib/resdata/tests/rd_file.cpp b/lib/resdata/tests/rd_file.cpp index 6ffdeca92..589a3c995 100644 --- a/lib/resdata/tests/rd_file.cpp +++ b/lib/resdata/tests/rd_file.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -30,14 +31,13 @@ void test_writable(size_t data_size) { } for (int i = 0; i < 4; ++i) { - rd_file_type *rd_file = - rd_file_open(data_file_name, FileMode::WRITABLE); + auto rd_file = + open_rd_file(std::string(data_file_name), FileMode::WRITABLE); rd_kw_type *loaded_kw = - rd_file_view_iget_kw(rd_file_get_global_view(rd_file), 0); + rd_file_get_global_view(rd_file.get())->get_kw(0); test_assert_true(rd_kw_equal(kw, loaded_kw)); - rd_file_save_kw(rd_file, loaded_kw); - rd_file_close(rd_file); + rd_file_save_kw(rd_file.get(), loaded_kw); } rd_kw_free(kw); @@ -51,10 +51,9 @@ void test_truncated() { rd_grid_fwrite_EGRID2(grid.get(), "TEST.EGRID", RD_METRIC_UNITS); } { - rd_file_type *rd_file = rd_file_open("TEST.EGRID"); - test_assert_true(rd_file_is_instance(rd_file)); - num_kw = rd_file_get_size(rd_file); - rd_file_close(rd_file); + auto rd_file = open_rd_file(std::string("TEST.EGRID")); + test_assert_true(rd_file_is_instance(rd_file.get())); + num_kw = rd_file_get_size(rd_file.get()); } { @@ -64,9 +63,8 @@ void test_truncated() { fclose(stream); } { - rd_file_type *rd_file = rd_file_open("TEST.EGRID"); - test_assert_true(rd_file_get_size(rd_file) < num_kw); - rd_file_close(rd_file); + auto rd_file = open_rd_file(std::string("TEST.EGRID")); + test_assert_true(rd_file_get_size(rd_file.get()) < num_kw); } } @@ -78,10 +76,9 @@ void test_mixed_case() { rd_grid_fwrite_EGRID2(grid.get(), "TESTcase.EGRID", RD_METRIC_UNITS); } { - rd_file_type *rd_file = rd_file_open("TESTcase.EGRID"); - test_assert_true(rd_file_is_instance(rd_file)); - num_kw = rd_file_get_size(rd_file); - rd_file_close(rd_file); + auto rd_file = open_rd_file(std::string("TESTcase.EGRID")); + test_assert_true(rd_file_is_instance(rd_file.get())); + num_kw = rd_file_get_size(rd_file.get()); } { @@ -91,9 +88,8 @@ void test_mixed_case() { fclose(stream); } { - rd_file_type *rd_file = rd_file_open("TESTcase.EGRID"); - test_assert_true(rd_file_get_size(rd_file) < num_kw); - rd_file_close(rd_file); + auto rd_file = open_rd_file(std::string("TESTcase.EGRID")); + test_assert_true(rd_file_get_size(rd_file.get()) < num_kw); } } diff --git a/lib/resdata/tests/rd_file_equinor.cpp b/lib/resdata/tests/rd_file_equinor.cpp index 83691d540..dbfd5c09a 100644 --- a/lib/resdata/tests/rd_file_equinor.cpp +++ b/lib/resdata/tests/rd_file_equinor.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include #include #include @@ -11,54 +13,51 @@ void test_close_stream2(const char *src_file, const char *target_file) { util_copy_file(src_file, target_file); - rd_file_type *rd_file = rd_file_open(target_file, FileMode::CLOSE_STREAM); + auto rd_file = + open_rd_file(std::string(target_file), FileMode::CLOSE_STREAM); - rd_file_load_all(rd_file); + rd_file_load_all(rd_file.get()); unlink(target_file); - rd_kw_type *kw2 = rd_file_iget_kw(rd_file, 2); + rd_kw_type *kw2 = rd_file_iget_kw(rd_file.get(), 2); test_assert_not_NULL(kw2); - rd_file_close(rd_file); } void test_loadall(const char *src_file, const char *target_file) { util_copy_file(src_file, target_file); { - rd_file_type *rd_file = - rd_file_open(target_file, FileMode::CLOSE_STREAM); + auto rd_file = + open_rd_file(std::string(target_file), FileMode::CLOSE_STREAM); - test_assert_true(rd_file_load_all(rd_file)); - rd_file_close(rd_file); + test_assert_true(rd_file_load_all(rd_file.get())); } { - rd_file_type *rd_file = - rd_file_open(target_file, FileMode::CLOSE_STREAM); + auto rd_file = + open_rd_file(std::string(target_file), FileMode::CLOSE_STREAM); unlink(target_file); - test_assert_false(rd_file_load_all(rd_file)); - rd_file_close(rd_file); + test_assert_false(rd_file_load_all(rd_file.get())); } } void test_close_stream1(const char *src_file, const char *target_file) { util_copy_file(src_file, target_file); - rd_file_type *rd_file = rd_file_open(target_file, FileMode::CLOSE_STREAM); - rd_kw_type *kw0 = rd_file_iget_kw(rd_file, 0); - rd_kw_type *kw1 = rd_file_iget_kw(rd_file, 1); + auto rd_file = + open_rd_file(std::string(target_file), FileMode::CLOSE_STREAM); + rd_kw_type *kw0 = rd_file_iget_kw(rd_file.get(), 0); + rd_kw_type *kw1 = rd_file_iget_kw(rd_file.get(), 1); unlink(target_file); - rd_kw_type *kw1b = rd_file_iget_kw(rd_file, 1); + rd_kw_type *kw1b = rd_file_iget_kw(rd_file.get(), 1); test_assert_not_NULL(kw0); test_assert_not_NULL(kw1); test_assert_ptr_equal(kw1, kw1b); - rd_kw_type *kw2 = rd_file_iget_kw(rd_file, 2); + rd_kw_type *kw2 = rd_file_iget_kw(rd_file.get(), 2); test_assert_NULL(kw2); - test_assert_false(rd_file_writable(rd_file)); - - rd_file_close(rd_file); + test_assert_false(rd_file_writable(rd_file.get())); } void test_writable(const char *src_file) { @@ -67,17 +66,16 @@ void test_writable(const char *src_file) { ta.copy_file(src_file); { - rd_file_type *rd_file = rd_file_open(fname, FileMode::WRITABLE); - rd_kw_type *swat = rd_file_iget_named_kw(rd_file, "SWAT", 0); + auto rd_file = open_rd_file(std::string(fname), FileMode::WRITABLE); + rd_kw_type *swat = rd_file_iget_named_kw(rd_file.get(), "SWAT", 0); rd_kw_type *swat0 = rd_kw_alloc_copy(swat); test_assert_true(rd_kw_equal(swat, swat0)); rd_kw_iset_float(swat, 0, 1000.0); - rd_file_save_kw(rd_file, swat); - test_assert_true(rd_file_writable(rd_file)); - rd_file_close(rd_file); + rd_file_save_kw(rd_file.get(), swat); + test_assert_true(rd_file_writable(rd_file.get())); - rd_file = rd_file_open(fname); - swat = rd_file_iget_named_kw(rd_file, "SWAT", 0); + auto rd_file2 = open_rd_file(std::string(fname)); + swat = rd_file_iget_named_kw(rd_file2.get(), "SWAT", 0); test_assert_true( util_double_approx_equal(rd_kw_iget_float(swat, 0), 1000)); } diff --git a/lib/resdata/tests/rd_grid_dx_dy_dz.cpp b/lib/resdata/tests/rd_grid_dx_dy_dz.cpp index 41c534138..7bb83ef97 100644 --- a/lib/resdata/tests/rd_grid_dx_dy_dz.cpp +++ b/lib/resdata/tests/rd_grid_dx_dy_dz.cpp @@ -11,6 +11,7 @@ #include #include +#include namespace fs = std::filesystem; @@ -25,14 +26,14 @@ void test_dxdydz(const std::string &grid_fname, const std::string &init_fname) { std::cerr << "Could not open " << grid_fname << std::endl; exit(-1); } - rd_file_type *init_file = rd_file_open(init_fname.c_str()); - if (init_file == NULL) { + auto init_file = open_rd_file(init_fname); + if (!init_file) { std::cerr << "Could not open " << init_fname << std::endl; exit(-1); } - rd_kw_type *dx = rd_file_iget_named_kw(init_file, "DX", 0); - rd_kw_type *dy = rd_file_iget_named_kw(init_file, "DY", 0); - rd_kw_type *dz = rd_file_iget_named_kw(init_file, "DZ", 0); + rd_kw_type *dx = rd_file_iget_named_kw(init_file.get(), "DX", 0); + rd_kw_type *dy = rd_file_iget_named_kw(init_file.get(), "DY", 0); + rd_kw_type *dz = rd_file_iget_named_kw(init_file.get(), "DZ", 0); for (int a = 0; a < rd_grid_get_active_size(grid.get()); a += 100) { int g = rd_grid_get_global_index1A(grid.get(), a); @@ -52,7 +53,6 @@ void test_dxdydz(const std::string &grid_fname, const std::string &init_fname) { test_assert_true(err_y < eps_y); test_assert_true(err_z < eps_z); } - rd_file_close(init_file); } int main(int argc, char **argv) { diff --git a/lib/resdata/tests/rd_grid_export.cpp b/lib/resdata/tests/rd_grid_export.cpp index 999929aa3..8c9d3431c 100644 --- a/lib/resdata/tests/rd_grid_export.cpp +++ b/lib/resdata/tests/rd_grid_export.cpp @@ -1,5 +1,7 @@ #include +#include + #include #include @@ -95,13 +97,12 @@ int main(int argc, char **argv) { if (argc == 1) test_assert_true(rd_grid_get_unit_system(rd_grid.get()) == RD_METRIC_UNITS); - rd_file_type *rd_file = rd_file_open(grid_file); + auto rd_file = open_rd_file(std::string(grid_file)); - export_actnum(rd_grid.get(), rd_file); - export_coord(rd_grid.get(), rd_file); - export_zcorn(rd_grid.get(), rd_file); - export_mapaxes(rd_grid.get(), rd_file); - rd_file_close(rd_file); + export_actnum(rd_grid.get(), rd_file.get()); + export_coord(rd_grid.get(), rd_file.get()); + export_zcorn(rd_grid.get(), rd_file.get()); + export_mapaxes(rd_grid.get(), rd_file.get()); } } } diff --git a/lib/resdata/tests/rd_grid_init_fwrite.cpp b/lib/resdata/tests/rd_grid_init_fwrite.cpp index 84661852c..870362e65 100644 --- a/lib/resdata/tests/rd_grid_init_fwrite.cpp +++ b/lib/resdata/tests/rd_grid_init_fwrite.cpp @@ -14,6 +14,7 @@ #include #include #include +#include static void rd_grid_fwrite_depth(rd_grid_type *grid, ERT::FortIO &init_file, ert_rd_unit_enum output_unit) { @@ -36,15 +37,13 @@ void test_write_depth(rd_grid_type *grid) { rd_grid_fwrite_depth(grid, init_file, RD_METRIC_UNITS); } { - rd_file_type *init_file = rd_file_open("INIT"); - rd_kw_type *depth = rd_file_iget_named_kw(init_file, "DEPTH", 0); + auto init_file = open_rd_file(std::string("INIT")); + rd_kw_type *depth = rd_file_iget_named_kw(init_file.get(), "DEPTH", 0); test_assert_int_equal(rd_kw_get_size(depth), rd_grid_get_nactive(grid)); for (int i = 0; i < rd_grid_get_nactive(grid); i++) test_assert_double_equal(rd_kw_iget_as_double(depth, i), rd_grid_get_cdepth1A(grid, i)); - - rd_file_close(init_file); } } @@ -89,10 +88,10 @@ void test_write_dims(const rd_grid_type *grid) { rd_grid_fwrite_dims(grid, init_file, RD_METRIC_UNITS); } { - rd_file_type *init_file = rd_file_open("INIT"); - rd_kw_type *DX = rd_file_iget_named_kw(init_file, "DX", 0); - rd_kw_type *DY = rd_file_iget_named_kw(init_file, "DY", 0); - rd_kw_type *DZ = rd_file_iget_named_kw(init_file, "DZ", 0); + auto init_file = open_rd_file(std::string("INIT")); + rd_kw_type *DX = rd_file_iget_named_kw(init_file.get(), "DX", 0); + rd_kw_type *DY = rd_file_iget_named_kw(init_file.get(), "DY", 0); + rd_kw_type *DZ = rd_file_iget_named_kw(init_file.get(), "DZ", 0); test_assert_int_equal(rd_kw_get_size(DX), rd_grid_get_nactive(grid)); test_assert_int_equal(rd_kw_get_size(DY), rd_grid_get_nactive(grid)); @@ -105,7 +104,6 @@ void test_write_dims(const rd_grid_type *grid) { test_assert_double_equal(rd_kw_iget_as_double(DZ, i), rd_grid_get_cell_dz1A(grid, i)); } - rd_file_close(init_file); } } diff --git a/lib/resdata/tests/rd_lgr_test.cpp b/lib/resdata/tests/rd_lgr_test.cpp index 051598bba..301460529 100644 --- a/lib/resdata/tests/rd_lgr_test.cpp +++ b/lib/resdata/tests/rd_lgr_test.cpp @@ -1,5 +1,7 @@ #include +#include + #include #include @@ -10,13 +12,13 @@ int main(int argc, char **argv) { const char *grid_file = argv[1]; rd_grid_ptr rd_grid = read_grid(grid_file); - rd_file_type *rd_file = rd_file_open(grid_file); + auto rd_file = open_rd_file(std::string(grid_file)); rd_grid_test_lgr_consistency(rd_grid.get()); - if (rd_file_get_num_named_kw(rd_file, COORD_KW)) - test_assert_int_equal(rd_file_get_num_named_kw(rd_file, COORD_KW) - 1, - rd_grid_get_num_lgr(rd_grid.get())); - rd_file_close(rd_file); + if (rd_file_get_num_named_kw(rd_file.get(), COORD_KW)) + test_assert_int_equal( + rd_file_get_num_named_kw(rd_file.get(), COORD_KW) - 1, + rd_grid_get_num_lgr(rd_grid.get())); exit(0); } diff --git a/lib/resdata/tests/rd_nnc_test.cpp b/lib/resdata/tests/rd_nnc_test.cpp index a89d12891..0e4ff430c 100644 --- a/lib/resdata/tests/rd_nnc_test.cpp +++ b/lib/resdata/tests/rd_nnc_test.cpp @@ -1,6 +1,9 @@ +#include #include +#include #include +#include #include #include @@ -11,9 +14,7 @@ #include #include #include - -#include -#include +#include template int vector_util_index(const std::vector &vec, T value) { @@ -28,16 +29,15 @@ template int vector_util_index(const std::vector &vec, T value) { void test_scan(const char *grid_filename) { rd_grid_type *rd_grid = rd_grid_alloc(grid_filename); - rd_file_type *grid_file = rd_file_open(grid_filename); - int block_nr; + rd_file_ptr grid_file = open_rd_file(std::string(grid_filename)); - for (block_nr = 0; - block_nr < rd_file_get_num_named_kw(grid_file, NNCHEAD_KW); + for (int block_nr = 0; + block_nr < rd_file_get_num_named_kw(grid_file.get(), NNCHEAD_KW); block_nr++) { rd_grid_type *lgr = rd_grid; int lgr_nr; - rd_file_view_ptr nnc_view( - rd_file_alloc_global_blockview(grid_file, NNCHEAD_KW, block_nr)); + auto nnc_view = rd_file_get_global_view(grid_file.get()) + ->blockview(NNCHEAD_KW, NNCHEAD_KW, block_nr); { if (block_nr > 0) lgr = rd_grid_iget_lgr(rd_grid, block_nr - 1); @@ -45,11 +45,9 @@ void test_scan(const char *grid_filename) { /* Internal nnc */ { - if (rd_file_view_has_kw(nnc_view.get(), NNC1_KW)) { - rd_kw_type *nnc1_kw = - rd_file_view_iget_named_kw(nnc_view.get(), NNC1_KW, 0); - rd_kw_type *nnc2_kw = - rd_file_view_iget_named_kw(nnc_view.get(), NNC2_KW, 0); + if (nnc_view->has_kw(NNC1_KW)) { + rd_kw_type *nnc1_kw = nnc_view->get_kw(NNC1_KW, 0); + rd_kw_type *nnc2_kw = nnc_view->get_kw(NNC2_KW, 0); int i; for (i = 0; i < rd_kw_get_size(nnc1_kw); i++) { const int g1 = rd_kw_iget_int(nnc1_kw, i) - 1; @@ -73,13 +71,10 @@ void test_scan(const char *grid_filename) { /* Global -> lgr */ { - if (rd_file_view_has_kw(nnc_view.get(), NNCG_KW)) { - rd_kw_type *nnchead_kw = - rd_file_view_iget_named_kw(nnc_view.get(), NNCHEAD_KW, 0); - rd_kw_type *nncg_kw = - rd_file_view_iget_named_kw(nnc_view.get(), NNCG_KW, 0); - rd_kw_type *nncl_kw = - rd_file_view_iget_named_kw(nnc_view.get(), NNCL_KW, 0); + if (nnc_view->has_kw(NNCG_KW)) { + rd_kw_type *nnchead_kw = nnc_view->get_kw(NNCHEAD_KW, 0); + rd_kw_type *nncg_kw = nnc_view->get_kw(NNCG_KW, 0); + rd_kw_type *nncl_kw = nnc_view->get_kw(NNCL_KW, 0); int i; int lgr_nr = rd_kw_iget_int(nnchead_kw, NNCHEAD_LGR_INDEX); for (i = 0; i < rd_kw_get_size(nncg_kw); i++) { @@ -103,13 +98,10 @@ void test_scan(const char *grid_filename) { /* Amalgamated: LGR -> LGR */ { - if (rd_file_view_has_kw(nnc_view.get(), NNCHEADA_KW)) { - rd_kw_type *nncheada_kw = - rd_file_view_iget_named_kw(nnc_view.get(), NNCHEADA_KW, 0); - rd_kw_type *nnc1_kw = - rd_file_view_iget_named_kw(nnc_view.get(), NNA1_KW, 0); - rd_kw_type *nnc2_kw = - rd_file_view_iget_named_kw(nnc_view.get(), NNA2_KW, 0); + if (nnc_view->has_kw(NNCHEADA_KW)) { + rd_kw_type *nncheada_kw = nnc_view->get_kw(NNCHEADA_KW, 0); + rd_kw_type *nnc1_kw = nnc_view->get_kw(NNA1_KW, 0); + rd_kw_type *nnc2_kw = nnc_view->get_kw(NNA2_KW, 0); int lgr_nr1 = rd_kw_iget_int(nncheada_kw, NNCHEADA_ILOC1_INDEX); int lgr_nr2 = rd_kw_iget_int(nncheada_kw, NNCHEADA_ILOC2_INDEX); @@ -133,8 +125,7 @@ void test_scan(const char *grid_filename) { } int main(int argc, char **argv) { - int iarg; - for (iarg = 1; iarg < argc; iarg++) { + for (int iarg = 1; iarg < argc; iarg++) { printf("Checking file: %s \n", argv[iarg]); test_scan(argv[iarg]); } diff --git a/lib/resdata/tests/rd_rsthead.cpp b/lib/resdata/tests/rd_rsthead.cpp index e957645e8..040b855c6 100644 --- a/lib/resdata/tests/rd_rsthead.cpp +++ b/lib/resdata/tests/rd_rsthead.cpp @@ -1,6 +1,8 @@ #include - #include + +#include + #include #include @@ -16,25 +18,27 @@ void test_file(const char *filename, int occurence, bool exists, int report_step = rd_filename_report_nr(filename); rd_file_type *rst_file = rd_file_open(filename); rd_file_enum file_type = rd_get_file_type(filename, NULL, NULL); - rd_file_view_type *rst_view; + std::shared_ptr rst_view; if (file_type == RD_RESTART_FILE) rst_view = rd_file_get_global_view(rst_file); else - rst_view = rd_file_get_restart_view(rst_file, occurence, -1, -1, -1); + rst_view = + rd_file_get_global_view(rst_file)->restart_view_from_seqnum_index( + occurence); if (exists) { - test_assert_not_NULL(rst_view); - auto rst_head = RSTHead::read(rst_view, report_step); + test_assert_not_NULL(rst_view.get()); + auto rst_head = RSTHead::read(rst_view.get(), report_step); if (occurence == 0) { - auto rst_head0 = RSTHead::read(rst_view, report_step); + auto rst_head0 = RSTHead::read(rst_view.get(), report_step); test_assert_true(rst_head == rst_head0); } test_assert_true(rst_head == true_header); } else - test_assert_NULL(rst_view); + test_assert_NULL(rst_view.get()); } int main(int argc, char **argv) { diff --git a/lib/resdata/tests/rdxx_kw.cpp b/lib/resdata/tests/rdxx_kw.cpp index ce58f1adb..75fc440eb 100644 --- a/lib/resdata/tests/rdxx_kw.cpp +++ b/lib/resdata/tests/rdxx_kw.cpp @@ -164,12 +164,12 @@ void test_read_write() { } { - rd_file_type *f = rd_file_open("test_file"); - rd_kw_type *d_kw = rd_file_iget_named_kw(f, "DOUBLE", 0); - rd_kw_type *f_kw = rd_file_iget_named_kw(f, "FLOAT", 0); - rd_kw_type *i_kw = rd_file_iget_named_kw(f, "INT", 0); - rd_kw_type *b_kw = rd_file_iget_named_kw(f, "BOOL", 0); - rd_kw_type *s_kw = rd_file_iget_named_kw(f, "STRING", 0); + auto f = open_rd_file(std::string("test_file")); + rd_kw_type *d_kw = rd_file_iget_named_kw(f.get(), "DOUBLE", 0); + rd_kw_type *f_kw = rd_file_iget_named_kw(f.get(), "FLOAT", 0); + rd_kw_type *i_kw = rd_file_iget_named_kw(f.get(), "INT", 0); + rd_kw_type *b_kw = rd_file_iget_named_kw(f.get(), "BOOL", 0); + rd_kw_type *s_kw = rd_file_iget_named_kw(f.get(), "STRING", 0); for (size_t i = 0; i < d_data.size(); i++) test_assert_true(d_data[i] == rd_kw_iget_double(d_kw, i)); @@ -189,8 +189,6 @@ void test_read_write() { s8.erase(s8.find_last_not_of(' ') + 1); test_assert_true(s_data[i] == s8); } - - rd_file_close(f); } } } diff --git a/lib/resdata/tests/test_rd_file_index.cpp b/lib/resdata/tests/test_rd_file_index.cpp index 1a8854262..438ecb4fc 100644 --- a/lib/resdata/tests/test_rd_file_index.cpp +++ b/lib/resdata/tests/test_rd_file_index.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include @@ -14,9 +16,10 @@ #include void test_load_nonexisting_file() { - rd_file_type *rd_file = - rd_file_fast_open("base_file", "a_file_that_does_not_exist_2384623"); - test_assert_NULL(rd_file); + rd_file_ptr rd_file{ + rd_file_fast_open("base_file", "a_file_that_does_not_exist_2384623"), + &rd_file_free}; + test_assert_NULL(rd_file.get()); } void test_create_and_load_index_file() { @@ -43,11 +46,10 @@ void test_create_and_load_index_file() { //finished creating data file //creating rd_file - rd_file_type *rd_file = rd_file_open(file_name); - test_assert_true(rd_file_has_kw(rd_file, "TEST1_KW")); - rd_file_write_index(rd_file, index_file_name); - int rd_file_size = rd_file_get_size(rd_file); - rd_file_close(rd_file); + auto rd_file = open_rd_file(std::string(file_name)); + test_assert_true(rd_file_has_kw(rd_file.get(), "TEST1_KW")); + rd_file_write_index(rd_file.get(), index_file_name); + int rd_file_size = rd_file_get_size(rd_file.get()); //finished using rd_file test_assert_false(rd_file_index_valid(file_name, "nofile")); @@ -62,29 +64,28 @@ void test_create_and_load_index_file() { utime(index_file_name, &tm2); test_assert_true(rd_file_index_valid(file_name, index_file_name)); - rd_file_type *rd_file_index = - rd_file_fast_open(file_name, index_file_name); - test_assert_true(rd_file_is_instance(rd_file_index)); - test_assert_true(rd_file_get_global_view(rd_file_index)); + rd_file_ptr rd_file_index{rd_file_fast_open(file_name, index_file_name), + &rd_file_free}; + test_assert_true(rd_file_is_instance(rd_file_index.get())); - test_assert_int_equal(rd_file_size, rd_file_get_size(rd_file_index)); + test_assert_int_equal(rd_file_size, + rd_file_get_size(rd_file_index.get())); - test_assert_true(rd_file_has_kw(rd_file_index, "TEST1_KW")); - test_assert_true(rd_file_has_kw(rd_file_index, "TEST2_KW")); + test_assert_true(rd_file_has_kw(rd_file_index.get(), "TEST1_KW")); + test_assert_true(rd_file_has_kw(rd_file_index.get(), "TEST2_KW")); - rd_kw_type *kwi1 = rd_file_iget_kw(rd_file_index, 0); + rd_kw_type *kwi1 = rd_file_iget_kw(rd_file_index.get(), 0); test_assert_true(rd_kw_equal(kw1, kwi1)); test_assert_double_equal(537.0, rd_kw_iget_as_double(kwi1, 0)); test_assert_double_equal(546.0, rd_kw_iget_as_double(kwi1, 9)); - rd_kw_type *kwi2 = rd_file_iget_kw(rd_file_index, 1); + rd_kw_type *kwi2 = rd_file_iget_kw(rd_file_index.get(), 1); test_assert_true(rd_kw_equal(kw2, kwi2)); test_assert_double_equal(0.15, rd_kw_iget_as_double(kwi2, 1)); test_assert_double_equal(0.60, rd_kw_iget_as_double(kwi2, 4)); rd_kw_free(kw1); rd_kw_free(kw2); - rd_file_close(rd_file_index); } } diff --git a/lib/resdata/tests/well_conn_CF.cpp b/lib/resdata/tests/well_conn_CF.cpp index 3bcfd2355..49807ab40 100644 --- a/lib/resdata/tests/well_conn_CF.cpp +++ b/lib/resdata/tests/well_conn_CF.cpp @@ -23,12 +23,15 @@ void well_conn_test_CF(const rd_kw_type *iwel_kw, const rd_kw_type *icon_kw, int main(int argc, char **argv) { const char *Xfile = argv[1]; - rd_file_type *rst_file = rd_file_open(Xfile); - auto rst_head = RSTHead::read(rd_file_get_global_view(rst_file), + auto rst_file = open_rd_file(std::string(Xfile)); + auto rst_head = RSTHead::read(rd_file_get_global_view(rst_file.get()).get(), rd_filename_report_nr(Xfile)); - const rd_kw_type *iwel_kw = rd_file_iget_named_kw(rst_file, IWEL_KW, 0); - const rd_kw_type *icon_kw = rd_file_iget_named_kw(rst_file, ICON_KW, 0); - const rd_kw_type *scon_kw = rd_file_iget_named_kw(rst_file, SCON_KW, 0); + const rd_kw_type *iwel_kw = + rd_file_iget_named_kw(rst_file.get(), IWEL_KW, 0); + const rd_kw_type *icon_kw = + rd_file_iget_named_kw(rst_file.get(), ICON_KW, 0); + const rd_kw_type *scon_kw = + rd_file_iget_named_kw(rst_file.get(), SCON_KW, 0); const rd_kw_type *xcon_kw = 0; well_conn_test_CF(iwel_kw, icon_kw, scon_kw, xcon_kw, rst_head, 0, 0, @@ -51,7 +54,5 @@ int main(int argc, char **argv) { 55.195); well_conn_test_CF(iwel_kw, icon_kw, scon_kw, xcon_kw, rst_head, 2, 2, 18.032); - - rd_file_close(rst_file); exit(0); } diff --git a/lib/resdata/tests/well_dualp.cpp b/lib/resdata/tests/well_dualp.cpp index 8497fa4fc..2dbcf567c 100644 --- a/lib/resdata/tests/well_dualp.cpp +++ b/lib/resdata/tests/well_dualp.cpp @@ -8,13 +8,16 @@ #include #include #include +#include #include +#include void test_rstfile(const char *filename, bool fracture_connection) { - rd_file_type *rst_file = rd_file_open(filename); - const rd_kw_type *iwel_kw = rd_file_iget_named_kw(rst_file, IWEL_KW, 0); - auto header = RSTHead::read(rd_file_get_global_view(rst_file), + auto rst_file = open_rd_file(std::string(filename)); + const rd_kw_type *iwel_kw = + rd_file_iget_named_kw(rst_file.get(), IWEL_KW, 0); + auto header = RSTHead::read(rd_file_get_global_view(rst_file.get()).get(), rd_filename_report_nr(filename)); auto wellhead = WellConnection::read_wellhead(iwel_kw, header, 0); @@ -28,8 +31,6 @@ void test_rstfile(const char *filename, bool fracture_connection) { } test_assert_true(wellhead->get_k() < header.nz); - - rd_file_close(rst_file); } int main(int argc, char **argv) { diff --git a/lib/resdata/tests/well_segment_load.cpp b/lib/resdata/tests/well_segment_load.cpp index 689008aec..b7f4439b9 100644 --- a/lib/resdata/tests/well_segment_load.cpp +++ b/lib/resdata/tests/well_segment_load.cpp @@ -16,15 +16,17 @@ int main(int argc, char **argv) { const char *Xfile = argv[1]; - rd_file_type *rst_file = rd_file_open(Xfile); - rd_file_view_type *rst_view = rd_file_get_active_view(rst_file); - auto rst_head = RSTHead::read(rst_view, rd_filename_report_nr(Xfile)); - const rd_kw_type *iwel_kw = rd_file_iget_named_kw(rst_file, IWEL_KW, 0); - const rd_kw_type *iseg_kw = rd_file_iget_named_kw(rst_file, ISEG_KW, 0); - well_rseg_loader_type *rseg_loader = well_rseg_loader_alloc(rst_view); + auto rst_file = open_rd_file(std::string(Xfile)); + auto rst_view = rd_file_get_active_view(rst_file.get()); + auto rst_head = RSTHead::read(rst_view.get(), rd_filename_report_nr(Xfile)); + const rd_kw_type *iwel_kw = + rd_file_iget_named_kw(rst_file.get(), IWEL_KW, 0); + const rd_kw_type *iseg_kw = + rd_file_iget_named_kw(rst_file.get(), ISEG_KW, 0); + well_rseg_loader_type *rseg_loader = well_rseg_loader_alloc(rst_view.get()); test_install_SIGNALS(); - test_assert_not_NULL(rst_file); + test_assert_not_NULL(rst_file.get()); for (int well_nr = 0; well_nr < rst_head.nwells; well_nr++) { int iwel_offset = rst_head.niwelz * well_nr; @@ -80,6 +82,5 @@ int main(int argc, char **argv) { well_segment_collection_free(segments2); } } - rd_file_close(rst_file); exit(0); } diff --git a/lib/resdata/tests/well_state_load.cpp b/lib/resdata/tests/well_state_load.cpp index 1bbf25774..15ae23b58 100644 --- a/lib/resdata/tests/well_state_load.cpp +++ b/lib/resdata/tests/well_state_load.cpp @@ -23,26 +23,27 @@ int main(int argc, char **argv) { rd_grid_type *grid = rd_grid_alloc(grid_file); rd_file_type *rst_file = rd_file_open(rst_file_name); - auto header = RSTHead::read(rd_file_get_global_view(rst_file), - rd_filename_report_nr(rst_file_name)); + auto rst_view = rd_file_get_global_view(rst_file); + auto header = + RSTHead::read(rst_view.get(), rd_filename_report_nr(rst_file_name)); const char *well_name = "WELL"; int report_nr = 100; time_t valid_from = -1; bool open = false; auto type = WellType::GAS_INJECTOR; bool load_segment_information = true; - rd_file_view_type *rst_view = rd_file_get_global_view(rst_file); for (int global_well_nr = 0; global_well_nr < header.nwells; global_well_nr++) { WellState well_state(well_name, global_well_nr, open, type, report_nr, valid_from); - well_state.add_connections(grid, rst_view, 0); + well_state.add_connections(grid, rst_view.get(), 0); test_assert_true(well_state.has_grid_connections(RD_GRID_GLOBAL_GRID)); test_assert_false(well_state.has_grid_connections("???")); - well_state.add_MSW(rst_view, global_well_nr, load_segment_information); + well_state.add_MSW(rst_view.get(), global_well_nr, + load_segment_information); { const well_segment_collection_type *segments = well_state.get_segments(); diff --git a/lib/resdata/tests/well_state_load_missing_RSEG.cpp b/lib/resdata/tests/well_state_load_missing_RSEG.cpp index 77bf7a459..f348caa49 100644 --- a/lib/resdata/tests/well_state_load_missing_RSEG.cpp +++ b/lib/resdata/tests/well_state_load_missing_RSEG.cpp @@ -24,9 +24,9 @@ int main(int argc, char **argv) { rd_grid_type *grid = rd_grid_alloc(grid_file); rd_file_type *rst_file = rd_file_open(rst_file_name); - rd_file_view_type *rst_view = rd_file_get_active_view(rst_file); + auto rst_view = rd_file_get_active_view(rst_file); auto header = - RSTHead::read(rst_view, rd_filename_report_nr(rst_file_name)); + RSTHead::read(rst_view.get(), rd_filename_report_nr(rst_file_name)); const char *well_name = "WELL"; int report_nr = 100; time_t valid_from = -1; @@ -38,15 +38,15 @@ int main(int argc, char **argv) { global_well_nr++) { WellState well_state(well_name, global_well_nr, open, type, report_nr, valid_from); - well_state.add_connections(grid, rst_view, 0); - well_state.add_MSW(rst_view, global_well_nr, + well_state.add_connections(grid, rst_view.get(), 0); + well_state.add_MSW(rst_view.get(), global_well_nr, load_segment_information); { const well_segment_collection_type *segments = well_state.get_segments(); - if (!rd_file_view_has_kw(rst_view, RSEG_KW)) + if (!rst_view->has_kw(RSEG_KW)) test_assert_int_equal( 0, well_segment_collection_get_size(segments)); } diff --git a/lib/resdata/well_info.cpp b/lib/resdata/well_info.cpp index fb9e05adb..6cefef51f 100644 --- a/lib/resdata/well_info.cpp +++ b/lib/resdata/well_info.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -17,39 +18,40 @@ namespace { struct close_guard { - explicit close_guard(rd_file_view_type *file_view) + explicit close_guard(rd::FileView *file_view) : file_view(file_view), - was_set(rd_file_view_drop_flag(file_view, FileMode::CLOSE_STREAM)) {} + was_set(file_view->drop_flags(FileMode::CLOSE_STREAM)) {} ~close_guard() { if (was_set) - rd_file_view_add_flag(file_view, FileMode::CLOSE_STREAM); + file_view->add_flag(FileMode::CLOSE_STREAM); } close_guard(const close_guard &) = delete; close_guard &operator=(const close_guard &) = delete; - rd_file_view_type *file_view; + rd::FileView *file_view; bool was_set; }; struct clear_guard { - explicit clear_guard(rd_file_view_type *file_view) : file_view(file_view) {} + explicit clear_guard(std::shared_ptr file_view) + : file_view(file_view) {} - ~clear_guard() { rd_file_view_clear(file_view); } + ~clear_guard() { file_view->clear(); } clear_guard(const clear_guard &) = delete; clear_guard &operator=(const clear_guard &) = delete; - rd_file_view_type *file_view; + std::shared_ptr file_view; }; } // namespace void WellInfo::add_wells(rd_file_type *rst_file, int report_nr, bool load_segment_information) { - rd_file_view_type *rst_view = rd_file_get_active_view(rst_file); - add_wells(rst_view, report_nr, load_segment_information); + auto rst_view = rd_file_get_active_view(rst_file); + add_wells(rst_view.get(), report_nr, load_segment_information); } -void WellInfo::add_wells(rd_file_view_type *rst_view, int report_nr, +void WellInfo::add_wells(rd::FileView *rst_view, int report_nr, bool load_segment_information) { close_guard close_stream_guard(rst_view); auto global_header = RSTHead::read(rst_view, report_nr); @@ -69,18 +71,20 @@ void WellInfo::add_wells(rd_file_view_type *rst_view, int report_nr, void WellInfo::add_UNRST_wells(rd_file_type *rst_file, bool load_segment_information) { - rd_file_view_type *rst_view = rd_file_get_global_view(rst_file); - int num_blocks = rd_file_view_get_num_named_kw(rst_view, SEQNUM_KW); - for (int block_nr = 0; block_nr < num_blocks; block_nr++) { - - rd_file_view_type *step_view = - rd_file_view_add_restart_view(rst_view, block_nr, -1, -1, -1); - const rd_kw_type *seqnum_kw = - rd_file_view_iget_named_kw(step_view, SEQNUM_KW, 0); + auto rst_view = rd_file_get_global_view(rst_file); + size_t num_blocks = rst_view->num_named_kw(SEQNUM_KW); + for (size_t block_nr = 0; block_nr < num_blocks; block_nr++) { + + auto step_view = rst_view->restart_view_from_seqnum_index(block_nr); + if (!step_view) + throw std::runtime_error( + fmt::format("Could not find restart step: {}", block_nr)); + + const rd_kw_type *seqnum_kw = step_view->get_kw(SEQNUM_KW, 0); int report_nr = rd_kw_iget_int(seqnum_kw, 0); clear_guard clear(rst_view); - add_wells(step_view, report_nr, load_segment_information); + add_wells(step_view.get(), report_nr, load_segment_information); } } diff --git a/lib/resdata/well_rseg_loader.cpp b/lib/resdata/well_rseg_loader.cpp index 579a8496f..eee53583e 100644 --- a/lib/resdata/well_rseg_loader.cpp +++ b/lib/resdata/well_rseg_loader.cpp @@ -10,14 +10,14 @@ #include struct well_rseg_loader_struct { - rd_file_view_type *rst_view; + rd::FileView *rst_view; int_vector_type *relative_index_map; int_vector_type *absolute_index_map; char *buffer; const char *kw; }; -well_rseg_loader_type *well_rseg_loader_alloc(rd_file_view_type *rst_view) { +well_rseg_loader_type *well_rseg_loader_alloc(rd::FileView *rst_view) { well_rseg_loader_type *loader = (well_rseg_loader_type *)util_malloc(sizeof *loader); @@ -39,8 +39,8 @@ well_rseg_loader_type *well_rseg_loader_alloc(rd_file_view_type *rst_view) { void well_rseg_loader_free(well_rseg_loader_type *loader) { - if (rd_file_view_flags_set(loader->rst_view, FileMode::CLOSE_STREAM)) - rd_file_view_fclose_stream(loader->rst_view); + if (loader->rst_view->has_flags(FileMode::CLOSE_STREAM)) + loader->rst_view->close(); int_vector_free(loader->relative_index_map); int_vector_free(loader->absolute_index_map); @@ -61,8 +61,7 @@ double *well_rseg_loader_load_values(const well_rseg_loader_type *loader, int_vector_iset(index_map, index, relative_index + rseg_offset); } - rd_file_view_index_fload_kw(loader->rst_view, loader->kw, 0, index_map, - loader->buffer); + loader->rst_view->index_fload_kw(loader->kw, 0, index_map, loader->buffer); return (double *)loader->buffer; } diff --git a/lib/resdata/well_state.cpp b/lib/resdata/well_state.cpp index 796978f6c..8196d33b2 100644 --- a/lib/resdata/well_state.cpp +++ b/lib/resdata/well_state.cpp @@ -51,12 +51,11 @@ void WellState::add_wellhead(const RSTHead &header, const rd_kw_type *iwel_kw, } } -bool WellState::add_rates(rd_file_view_type *rst_view, int well_nr) { +bool WellState::add_rates(rd::FileView *rst_view, int well_nr) { - bool has_xwel_kw = rd_file_view_has_kw(rst_view, XWEL_KW); + bool has_xwel_kw = rst_view->has_kw(XWEL_KW); if (has_xwel_kw) { - const rd_kw_type *xwel_kw = - rd_file_view_iget_named_kw(rst_view, XWEL_KW, 0); + const rd_kw_type *xwel_kw = rst_view->get_kw(XWEL_KW, 0); auto header = RSTHead::read(rst_view, -1); int offset = header.nxwelz * well_nr; @@ -80,13 +79,12 @@ bool WellState::add_rates(rd_file_view_type *rst_view, int well_nr) { all. */ -int WellState::get_lgr_well_nr(const rd_file_view_type *file_view) { +int WellState::get_lgr_well_nr(rd::FileView *file_view) { int well_nr = -1; - if (rd_file_view_has_kw(file_view, ZWEL_KW)) { + if (file_view->has_kw(ZWEL_KW)) { auto header = RSTHead::read(file_view, -1); - const rd_kw_type *zwel_kw = - rd_file_view_iget_named_kw(file_view, ZWEL_KW, 0); + const rd_kw_type *zwel_kw = file_view->get_kw(ZWEL_KW, 0); int num_wells = header.nwells; well_nr = 0; while (true) { @@ -143,30 +141,28 @@ WellType well_state_translate_rd_type_int(int int_type) { to one LGR block with the rd_file_subselect_block() function. */ -void WellState::add_connections(const rd_file_view_type *rst_view, +void WellState::add_connections(rd::FileView *rst_view, const std::string &grid_name, int grid_nr, int well_nr) { auto header = RSTHead::read(rst_view, -1); - const rd_kw_type *iwel_kw = - rd_file_view_iget_named_kw(rst_view, IWEL_KW, 0); + const rd_kw_type *iwel_kw = rst_view->get_kw(IWEL_KW, 0); add_wellhead(header, iwel_kw, well_nr, grid_name, grid_nr); - if (rd_file_view_has_kw(rst_view, ICON_KW)) { - const rd_kw_type *icon_kw = - rd_file_view_iget_named_kw(rst_view, ICON_KW, 0); + if (rst_view->has_kw(ICON_KW)) { + const rd_kw_type *icon_kw = rst_view->get_kw(ICON_KW, 0); if (!has_grid_connections(grid_name)) this->connections[grid_name]; { rd_kw_type *scon_kw = nullptr; - if (rd_file_view_has_kw(rst_view, SCON_KW)) - scon_kw = rd_file_view_iget_named_kw(rst_view, SCON_KW, 0); + if (rst_view->has_kw(SCON_KW)) + scon_kw = rst_view->get_kw(SCON_KW, 0); rd_kw_type *xcon_kw = nullptr; - if (rd_file_view_has_kw(rst_view, XCON_KW)) { - xcon_kw = rd_file_view_iget_named_kw(rst_view, XCON_KW, 0); + if (rst_view->has_kw(XCON_KW)) { + xcon_kw = rst_view->get_kw(XCON_KW, 0); } const int iwel_offset = header.niwelz * well_nr; @@ -188,56 +184,51 @@ void WellState::add_connections(const rd_file_view_type *rst_view, } } -void WellState::add_global_connections(const rd_file_view_type *rst_view, - int well_nr) { +void WellState::add_global_connections(rd::FileView *rst_view, int well_nr) { add_connections(rst_view, RD_GRID_GLOBAL_GRID, 0, well_nr); } void WellState::add_LGR_connections(const rd_grid_type *grid, - rd_file_view_type *file_view) { + rd::FileView *file_view) { // Go through all the LGRs and add connections; both in the bulk // grid and as wellhead. int num_lgr = rd_grid_get_num_lgr(grid); for (int lgr_index = 0; lgr_index < num_lgr; lgr_index++) { - rd_file_view_type *lgr_view = - rd_file_view_add_blockview(file_view, LGR_KW, lgr_index); - /* - Even though the grid has LGR information the restart file is not required - to have corresponding LGR information. This has for a long time been - unchecked, and there might be bugs lurking based on the incorrect - assumption that if the grid has LGR information then the corresponding LGR - information can also be found in the restart file. - */ + auto lgr_view = file_view->blockview(LGR_KW, LGR_KW, lgr_index); + /* Even though the grid has LGR information the restart file is not required + to have corresponding LGR information. This has for a long time been + unchecked, and there might be bugs lurking based on the incorrect + assumption that if the grid has LGR information then the corresponding LGR + information can also be found in the restart file. */ if (lgr_view) { const char *grid_name = rd_grid_iget_lgr_name(grid, lgr_index); - int well_nr = get_lgr_well_nr(lgr_view); + int well_nr = get_lgr_well_nr(lgr_view.get()); if (well_nr >= 0) - add_connections(lgr_view, grid_name, lgr_index + 1, well_nr); + add_connections(lgr_view.get(), grid_name, lgr_index + 1, + well_nr); } } } void WellState::add_connections(const rd_grid_type *grid, - rd_file_view_type *rst_view, int well_nr) { + rd::FileView *rst_view, int well_nr) { add_global_connections(rst_view, well_nr); add_LGR_connections(grid, rst_view); } -bool WellState::add_MSW(rd_file_view_type *rst_view, int well_nr, +bool WellState::add_MSW(rd::FileView *rst_view, int well_nr, bool load_segment_information) { - if (rd_file_view_has_kw(rst_view, ISEG_KW)) { + if (rst_view->has_kw(ISEG_KW)) { auto rst_head = RSTHead::read(rst_view, -1); - const rd_kw_type *iwel_kw = - rd_file_view_iget_named_kw(rst_view, IWEL_KW, 0); - const rd_kw_type *iseg_kw = - rd_file_view_iget_named_kw(rst_view, ISEG_KW, 0); + const rd_kw_type *iwel_kw = rst_view->get_kw(IWEL_KW, 0); + const rd_kw_type *iseg_kw = rst_view->get_kw(ISEG_KW, 0); std::unique_ptr rseg_loader(nullptr, well_rseg_loader_free); - if (rd_file_view_has_kw(rst_view, RSEG_KW)) { + if (rst_view->has_kw(RSEG_KW)) { if (load_segment_information) rseg_loader.reset(well_rseg_loader_alloc(rst_view)); @@ -268,20 +259,18 @@ bool WellState::add_MSW(rd_file_view_type *rst_view, int well_nr, std::shared_ptr WellState::read_wells_in_restart( rd_file_type *rd_file, const rd_grid_type *grid, int report_nr, int global_well_nr, bool load_segment_information) { - return read_wells_in_restart(rd_file_get_active_view(rd_file), grid, - report_nr, global_well_nr, - load_segment_information); + auto active_view = rd_file_get_active_view(rd_file); + return read_wells_in_restart(active_view.get(), grid, report_nr, + global_well_nr, load_segment_information); } std::shared_ptr WellState::read_wells_in_restart( - rd_file_view_type *file_view, const rd_grid_type *grid, int report_nr, + rd::FileView *file_view, const rd_grid_type *grid, int report_nr, int global_well_nr, bool load_segment_information) { - if (rd_file_view_has_kw(file_view, IWEL_KW)) { + if (file_view->has_kw(IWEL_KW)) { auto global_header = RSTHead::read(file_view, -1); - const rd_kw_type *global_iwel_kw = - rd_file_view_iget_named_kw(file_view, IWEL_KW, 0); - const rd_kw_type *global_zwel_kw = - rd_file_view_iget_named_kw(file_view, ZWEL_KW, 0); + const rd_kw_type *global_iwel_kw = file_view->get_kw(IWEL_KW, 0); + const rd_kw_type *global_zwel_kw = file_view->get_kw(ZWEL_KW, 0); const int iwel_offset = global_header.niwelz * global_well_nr; @@ -305,7 +294,7 @@ std::shared_ptr WellState::read_wells_in_restart( report_nr, global_header.sim_time); well_state->add_connections(grid, file_view, global_well_nr); - if (rd_file_view_has_kw(file_view, ISEG_KW)) + if (file_view->has_kw(ISEG_KW)) well_state->add_MSW(file_view, global_well_nr, load_segment_information); diff --git a/lib/tests/grid_fixtures.hpp b/lib/tests/grid_fixtures.hpp index b6a496230..eb147dcc3 100644 --- a/lib/tests/grid_fixtures.hpp +++ b/lib/tests/grid_fixtures.hpp @@ -83,6 +83,12 @@ inline void write_int_kw(ERT::FortIO &fortio, const char *name, write_int_kw(fortio, name, values.data(), static_cast(values.size())); } +inline void write_int_kw(ERT::FortIO &fortio, const std::string &name, + const std::vector &values) { + write_int_kw(fortio, name.c_str(), values.data(), + static_cast(values.size())); +} + inline void write_float_kw(ERT::FortIO &fortio, const char *name, const float *values, int size) { auto kw = make_rd_kw(name, size, RD_FLOAT); diff --git a/lib/tests/test_geertsma.cpp b/lib/tests/test_geertsma.cpp index ed085f8f6..893d760e3 100644 --- a/lib/tests/test_geertsma.cpp +++ b/lib/tests/test_geertsma.cpp @@ -88,12 +88,12 @@ TEST_CASE_METHOD(Tmpdir, "Geertsma kernel single cell") { subsidence(rd_subsidence_alloc(grid.get(), init.get()), rd_subsidence_free); - rd_file_view_type *view1 = - rd_file_get_restart_view(restart.get(), 0, -1, -1, -1); - REQUIRE(view1 != nullptr); + auto view1 = rd_file_get_global_view(restart.get()) + ->restart_view_from_seqnum_index(0); + REQUIRE(view1); - rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1); - rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S2", view1); + rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1.get()); + rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S2", view1.get()); const double youngs_modulus = 5e8; const double poisson_ratio = 0.3; @@ -139,15 +139,15 @@ TEST_CASE_METHOD(Tmpdir, "Geertsma kernel two source points two vintages") { subsidence(rd_subsidence_alloc(grid.get(), init.get()), rd_subsidence_free); - rd_file_view_type *view1 = - rd_file_get_restart_view(restart.get(), 0, -1, -1, -1); - rd_file_view_type *view2 = - rd_file_get_restart_view(restart.get(), 1, -1, -1, -1); + auto view1 = rd_file_get_global_view(restart.get()) + ->restart_view_from_seqnum_index(0); + auto view2 = rd_file_get_global_view(restart.get()) + ->restart_view_from_seqnum_index(1); REQUIRE(view1 != nullptr); REQUIRE(view2 != nullptr); - rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1); - rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S2", view2); + rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1.get()); + rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S2", view2.get()); const double youngs_modulus = 5e8; const double poisson_ratio = 0.3; @@ -185,9 +185,9 @@ TEST_CASE_METHOD(Tmpdir, "Geertsma kernel with seabed") { subsidence(rd_subsidence_alloc(grid.get(), init.get()), rd_subsidence_free); - rd_file_view_type *view1 = - rd_file_get_restart_view(restart.get(), 0, -1, -1, -1); - rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1); + auto view1 = rd_file_get_global_view(restart.get()) + ->restart_view_from_seqnum_index(0); + rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1.get()); const double youngs_modulus = 5e8; const double poisson_ratio = 0.3; @@ -222,13 +222,13 @@ TEST_CASE_METHOD(Tmpdir, subsidence(rd_subsidence_alloc(grid.get(), init.get()), rd_subsidence_free); - rd_file_view_type *view1 = - rd_file_get_restart_view(restart.get(), 0, -1, -1, -1); - rd_file_view_type *view2 = - rd_file_get_restart_view(restart.get(), 1, -1, -1, -1); + auto view1 = rd_file_get_global_view(restart.get()) + ->restart_view_from_seqnum_index(0); + auto view2 = rd_file_get_global_view(restart.get()) + ->restart_view_from_seqnum_index(1); - rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1); - rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S2", view2); + rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1.get()); + rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S2", view2.get()); const double youngs_modulus = 5e8; const double poisson_ratio = 0.3; @@ -286,9 +286,9 @@ TEST_CASE_METHOD(Tmpdir, "Subsidence survey validation") { } SECTION("unknown monitor survey throws") { - rd_file_view_type *view1 = - rd_file_get_restart_view(restart.get(), 0, -1, -1, -1); - rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1); + auto view1 = rd_file_get_global_view(restart.get()) + ->restart_view_from_seqnum_index(0); + rd_subsidence_add_survey_PRESSURE(subsidence.get(), "S1", view1.get()); REQUIRE(rd_subsidence_has_survey(subsidence.get(), "S1")); REQUIRE_THROWS_AS(rd_subsidence_eval_geertsma_rporv( diff --git a/lib/tests/test_rd_sum.cpp b/lib/tests/test_rd_sum.cpp index aca1ae6f6..fe907c2b2 100644 --- a/lib/tests/test_rd_sum.cpp +++ b/lib/tests/test_rd_sum.cpp @@ -791,12 +791,11 @@ TEST_CASE_METHOD(Tmpdir, "Restart writer writes has restart kw") { const std::string smspec_ext = fmt_output ? ".FSMSPEC" : ".SMSPEC"; auto restart_file = open_rd_file(restart_name + smspec_ext); REQUIRE(restart_file != nullptr); - rd_file_view_type *view = rd_file_get_global_view(restart_file.get()); - REQUIRE(rd_file_view_has_kw(view, RESTART_KW)); + auto view = rd_file_get_global_view(restart_file.get()); + REQUIRE(view->has_kw(RESTART_KW)); SECTION("Parent case name is padded across 8-char blocks") { - rd_kw_type *restart_kw = - rd_file_view_iget_named_kw(view, RESTART_KW, 0); + rd_kw_type *restart_kw = view->get_kw(RESTART_KW, 0); REQUIRE(rd_kw_get_size(restart_kw) == 8); REQUIRE(std::string(static_cast( rd_kw_iget_ptr(restart_kw, 0))) == "CASE1 "); @@ -833,9 +832,9 @@ TEST_CASE_METHOD(Tmpdir, "Restart case names are split across the 8 blocks") { } auto smspec_file = open_rd_file(name + ".SMSPEC"); - rd_file_view_type *view = rd_file_get_global_view(smspec_file.get()); - REQUIRE(rd_file_view_has_kw(view, RESTART_KW)); - rd_kw_type *restart_kw = rd_file_view_iget_named_kw(view, RESTART_KW, 0); + auto view = rd_file_get_global_view(smspec_file.get()); + REQUIRE(view->has_kw(RESTART_KW)); + rd_kw_type *restart_kw = view->get_kw(RESTART_KW, 0); REQUIRE(rd_kw_get_size(restart_kw) == 8); for (int n = 0; n < 8; ++n) { const std::string expected = "WWWWGGG" + std::to_string(n); diff --git a/lib/tests/test_well_info.cpp b/lib/tests/test_well_info.cpp index 5b2a9f987..6c7da3e9b 100644 --- a/lib/tests/test_well_info.cpp +++ b/lib/tests/test_well_info.cpp @@ -191,17 +191,17 @@ bool is_loaded(std::shared_ptr file_kw) { TEST_CASE_METHOD(Tmpdir, "keywords are lazily loaded", "[well][transaction]") { auto path = write_three_kw_file(dirname); rd_file_ptr file = open_rd_file(path); - auto *view = rd_file_get_global_view(file.get()); + auto view = rd_file_get_global_view(file.get()); - auto fk0 = rd_file_view_iget_file_kw(view, 0); - auto fk1 = rd_file_view_iget_file_kw(view, 1); - auto fk2 = rd_file_view_iget_file_kw(view, 2); + auto fk0 = view->get_file_kw(0); + auto fk1 = view->get_file_kw(1); + auto fk2 = view->get_file_kw(2); REQUIRE_FALSE(is_loaded(fk0)); REQUIRE_FALSE(is_loaded(fk1)); REQUIRE_FALSE(is_loaded(fk2)); - rd_file_view_iget_kw(view, 0); + view->get_kw(0); REQUIRE(is_loaded(fk0)); REQUIRE_FALSE(is_loaded(fk1)); diff --git a/python/resdata/resfile/rd_file.py b/python/resdata/resfile/rd_file.py index 7f47bb2b4..26b0e341d 100644 --- a/python/resdata/resfile/rd_file.py +++ b/python/resdata/resfile/rd_file.py @@ -152,9 +152,7 @@ def __init__(self, filename, flags=FileMode.DEFAULT, index_filename=None): raise OSError('Failed to open file "%s"' % filename) else: super().__init__(c_ptr) - self.global_view: ResdataFileView = ResdataFileView.createCReference( - _file._get_global_view(self), self - ) + self.global_view: ResdataFileView = _file._get_global_view(self) def save_kw(self, kw): """ @@ -191,12 +189,25 @@ def __len__(self): return len(self.global_view) def close(self): - if self: - _file._close(self) - self._invalidateCPointer() + """Closes the file handle used to read data. + + There are two caveats: + + 1. Stale cached ResdataKW instances: A ResdataKW that was already + read before ``close()`` keeps the data it held at that time. It is + a snapshot: it is not refreshed and will not reflect any later + modifications made to the file. + + 2. Lazy re-opening of ResdataFileView: Keyword data is loaded lazily, + so a keyword that was *not* yet read when ``close()`` was called is + read on first access. Accessing such a keyword through a + ResdataFileView (or through this ResdataFile) + re-opens the file on disk to read it. + """ + _file._close(self) def free(self): - self.close() + _file._free(self) def block_view(self, kw, kw_index): if kw not in self: diff --git a/python/resdata/resfile/rd_file_view.py b/python/resdata/resfile/rd_file_view.py deleted file mode 100644 index 98467026f..000000000 --- a/python/resdata/resfile/rd_file_view.py +++ /dev/null @@ -1,165 +0,0 @@ -from cwrap import BaseCClass -from six import string_types - -import resdata.resfile._file_view as _file_view -from resdata.util.util import CTime - - -class ResdataFileView(BaseCClass): - TYPE_NAME = "rd_file_view" - - def __init__(self): - raise NotImplementedError("Can not instantiate directly") - - def __iget(self, index): - return _file_view._iget_kw(self, index) - - def __repr__(self): - return "ResdataFileView(size=%d) %s" % (len(self), self._ad_str()) - - def iget_named_kw(self, kw_name, index): - if kw_name not in self: - raise KeyError("No such keyword: %s" % kw_name) - - if index >= self.num_keywords(kw_name): - raise IndexError("Too large index: %d" % index) - - return _file_view._iget_named_kw(self, kw_name, index) - - def __getitem__(self, index): - """ - Implements [] operator; index can be integer or key. - - Will look up ResdataKW instances from the current ResdataFile - instance. The @index argument can either be an integer, in - which case the method will return ResdataKW number @index, or - alternatively a keyword string, in which case the method will - return a list of ResdataKW instances with that keyword: - - restart_file = rd_file.ResdataFile("CASE.UNRST") - kw9 = restart_file[9] - swat_list = restart_file["SWAT"] - - The keyword based lookup can be combined with an extra [] to - get ResdataKW instance nr: - - swat9 = restart_file["SWAT"][9] - - Will return the 10'th SWAT keyword from the restart file. The - following example will iterate over all the SWAT keywords in a - restart file: - - restart_file = rd_file.ResdataFile("CASE.UNRST") - for swat in restart_file["SWAT"]: - .... - """ - - if isinstance(index, int): - ls = len(self) - idx = index - if idx < 0: - idx += ls - if 0 <= idx < ls: - return self.__iget(idx) - else: - raise IndexError("Index must be in [0, %d), was: %d." % (ls, index)) - - if isinstance(index, slice): - indices = index.indices(len(self)) - kw_list = [] - for i in range(*indices): - kw_list.append(self[i]) - return kw_list - else: - if isinstance(index, bytes): - index = index.decode("ascii") - if isinstance(index, string_types): - if index in self: - kw_index = index - kw_list = [] - for index in range(self.num_keywords(kw_index)): - kw_list.append(self.iget_named_kw(kw_index, index)) - return kw_list - else: - raise KeyError("Unrecognized keyword:'%s'" % index) - else: - raise TypeError("Index must be integer or string (keyword)") - - def __len__(self): - return _file_view._get_size(self) - - def __contains__(self, kw): - if self.num_keywords(kw) > 0: - return True - else: - return False - - def num_keywords(self, kw): - return _file_view._get_num_named_kw(self, kw) - - def unique_size(self): - return _file_view._get_unique_size(self) - - def unique_kw(self): - return [ - _file_view._get_unique_kw(self, index) - for index in range(self.unique_size()) - ] - - def block_view2(self, start_kw, stop_kw, start_index): - idx = start_index - if start_kw: - if start_kw not in self: - raise KeyError("The keyword:%s is not in file" % start_kw) - - ls = self.num_keywords(start_kw) - if idx < 0: - idx += ls - if not (0 <= idx < ls): - raise IndexError( - "Index must be in [0, %d), was: %d." % (ls, start_index) - ) - - if stop_kw: - if stop_kw not in self: - raise KeyError("The keyword:%s is not in file" % stop_kw) - - return _file_view._create_block_view2(self, start_kw, stop_kw, idx) - - def block_view(self, kw, kw_index): - num = self.num_keywords(kw) - - if num == 0: - raise KeyError("Unknown keyword: %s" % kw) - - idx = kw_index - if idx < 0: - idx += num - - if not (0 <= idx < num): - raise IndexError("Index must be in [0, %d), was: %d." % (num, kw_index)) - - return _file_view._create_block_view(self, kw, kw_index) - - def restart_view( - self, seqnum_index=None, report_step=None, sim_time=None, sim_days=None - ): - if report_step is None: - report_step = -1 - - if sim_time is None: - sim_time = -1 - - if sim_days is None: - sim_days = -1 - - if seqnum_index is None: - seqnum_index = -1 - - view = _file_view._restart_view( - self, seqnum_index, report_step, CTime(sim_time).value(), sim_days - ) - if view is None: - raise ValueError("No such restart block could be identified") - - return view diff --git a/tests/rd_tests/test_rd_file.py b/tests/rd_tests/test_rd_file.py index c2c5f86b7..9d9d1607e 100644 --- a/tests/rd_tests/test_rd_file.py +++ b/tests/rd_tests/test_rd_file.py @@ -423,3 +423,154 @@ def test_save_kw_on_read_only_file_raises(tmpdir): with pytest.raises(OSError, match="opened read only"): read_only.save_kw(loaded_kw) + + +def _restart_kw(name, dtype, values): + kw = ResdataKW(name, len(values), dtype) + for index, value in enumerate(values): + kw[index] = value + return kw + + +def _restart_intehead(day, month, year): + header = ResdataKW("INTEHEAD", 67, ResDataType.RD_INT) + header[64] = day + header[65] = month + header[66] = year + return header + + +def _write_restart_file(path): + """Write a minimal, valid restart file with two report steps. + + Layout per block: SEQNUM, INTEHEAD, PRESSURE, SWAT. The two INTEHEADs + encode the simulation dates 2000-01-01 and 2010-01-01 so that the + date/restart lookups return meaningful values. Two blocks are written so + that the first block can be extracted with an explicit ``end_kw`` of + ``SEQNUM`` (working around bug #1247 in ``block_view``, which mishandles a + ``None`` end keyword). + """ + with openFortIO(path, mode=FortIO.WRITE_MODE) as f: + _restart_kw("SEQNUM", ResDataType.RD_INT, [10]).fwrite(f) + _restart_intehead(1, 1, 2000).fwrite(f) + _restart_kw("PRESSURE", ResDataType.RD_FLOAT, [1.0, 2.0, 3.0]).fwrite(f) + _restart_kw("SWAT", ResDataType.RD_FLOAT, [0.1, 0.2, 0.3]).fwrite(f) + _restart_kw("SEQNUM", ResDataType.RD_INT, [20]).fwrite(f) + _restart_intehead(1, 1, 2010).fwrite(f) + _restart_kw("PRESSURE", ResDataType.RD_FLOAT, [4.0, 5.0, 6.0]).fwrite(f) + _restart_kw("SWAT", ResDataType.RD_FLOAT, [0.4, 0.5, 0.6]).fwrite(f) + + +@pytest.fixture +def objects_from_closed_file(tmp_path): + """Return (rd_file, view, kw) read inside an ``open_rd_file`` context that + has since been closed. + """ + path = str(tmp_path / "R.UNRST") + _write_restart_file(path) + + with open_rd_file(path) as rd_file: + # The first restart block is delimited by the next SEQNUM keyword + view = rd_file.block_view2("SEQNUM", "SEQNUM", 0) + kw = view["PRESSURE"][0] + assert list(kw) == pytest.approx([1.0, 2.0, 3.0]) + + # The context manager has now closed the file + return rd_file, view, kw + + +def test_that_resdata_file_is_usable_after_close(objects_from_closed_file): + rd_file, _, _ = objects_from_closed_file + + assert rd_file + assert rd_file.get_filename().endswith("R.UNRST") + assert len(rd_file) == 8 + assert rd_file.size == 8 + assert rd_file.unique_size == 4 + assert set(rd_file.keys()) == {"SEQNUM", "INTEHEAD", "PRESSURE", "SWAT"} + assert len(rd_file.headers) == 8 + + assert rd_file.has_kw("PRESSURE") + assert "SWAT" in rd_file + assert rd_file.num_named_kw("PRESSURE") == 2 + + assert rd_file.iget_kw(2).name == "PRESSURE" + assert rd_file.iget_named_kw("SWAT", 0).name == "SWAT" + assert list(rd_file["PRESSURE"][0]) == pytest.approx([1.0, 2.0, 3.0]) + + assert rd_file.report_steps == [10, 20] + assert rd_file.report_list == [10, 20] + assert rd_file.num_report_steps() == 2 + assert rd_file.has_report_step(10) + assert not rd_file.has_report_step(99) + assert rd_file.has_sim_time(datetime.datetime(2000, 1, 1)) + assert rd_file.dates == [ + datetime.datetime(2000, 1, 1), + datetime.datetime(2010, 1, 1), + ] + + assert len(rd_file.block_view2("SEQNUM", "SEQNUM", 0)) == 4 + assert len(rd_file.restart_view(report_step=10)) >= 1 + + +def test_that_resdata_file_view_is_usable_after_close( + objects_from_closed_file, +): + _, view, _ = objects_from_closed_file + + assert "ResdataFileView" in repr(view) + assert len(view) == 4 + assert "PRESSURE" in view + assert view.num_keywords("PRESSURE") == 1 + assert view.unique_size() == 4 + assert set(view.unique_kw()) == {"SEQNUM", "INTEHEAD", "PRESSURE", "SWAT"} + + assert view.iget_named_kw("PRESSURE", 0).name == "PRESSURE" + assert view[2].name == "PRESSURE" + + # reading SWAT now forces a lazy reopen + assert list(view["SWAT"][0]) == pytest.approx([0.1, 0.2, 0.3]) + + assert "PRESSURE" in view.block_view2("PRESSURE", "SWAT", 0) + assert view.block_view("PRESSURE", 0)["PRESSURE"][0].name == "PRESSURE" + assert len(view.restart_view(report_step=10)) >= 1 + + +def test_that_resdata_kw_is_usable_after_context_close(objects_from_closed_file): + _, _, kw = objects_from_closed_file + + assert kw.name == "PRESSURE" + assert kw.get_name() == "PRESSURE" + assert len(kw) == 3 + assert kw[0] == pytest.approx(1.0) + assert list(kw) == pytest.approx([1.0, 2.0, 3.0]) + + assert kw.data_type.is_float() + assert kw.header == ("PRESSURE", 3, kw.type_name()) + + assert kw.get_min() == pytest.approx(1.0) + assert kw.get_max() == pytest.approx(3.0) + assert kw.get_min_max() == pytest.approx((1.0, 3.0)) + assert kw.sum() == pytest.approx(6.0) + + assert list(kw.numpy_view()) == pytest.approx([1.0, 2.0, 3.0]) + assert list(kw.numpy_copy()) == pytest.approx([1.0, 2.0, 3.0]) + + kw_copy = kw.copy() + assert kw.equal(kw_copy) + assert kw == kw_copy + assert "PRESSURE" in str(kw) + + +def test_that_kws_are_valid_after_closing_the_file(tmp_path): + path = str(tmp_path / "R.UNRST") + _write_restart_file(path) + + rd_file = ResdataFile(path) + kw = rd_file["PRESSURE"][0] + assert list(kw) == pytest.approx([1.0, 2.0, 3.0]) + + rd_file.close() + + assert kw.name == "PRESSURE" + assert list(kw) == pytest.approx([1.0, 2.0, 3.0]) diff --git a/tests/rd_tests/test_rd_file_view.py b/tests/rd_tests/test_rd_file_view.py index 93f078cdc..335cdadd0 100644 --- a/tests/rd_tests/test_rd_file_view.py +++ b/tests/rd_tests/test_rd_file_view.py @@ -118,6 +118,12 @@ def test_iget_named_kw_with_out_of_range_index_raises_indexerror(sample_file): rd_file.global_view.iget_named_kw("PRESSURE", 2) +def test_iget_named_kw_with_negative_index_raises_indexerror(sample_file): + with open_rd_file(sample_file) as rd_file: + with pytest.raises(IndexError): + rd_file.global_view.iget_named_kw("PRESSURE", -1) + + def test_getitem_by_index(sample_file): with open_rd_file(sample_file) as rd_file: view = rd_file.global_view @@ -199,6 +205,12 @@ def test_that_block_view_with_out_of_range_index_raises_indexerror(sample_file): rd_file.global_view.block_view("PRESSURE", 5) +def test_block_view_with_negative_index_counts_from_end(sample_file): + with open_rd_file(sample_file) as rd_file: + block = rd_file.global_view.block_view("PRESSURE", -1) + assert list(block[0]) == pytest.approx([4.0, 5.0, 6.0]) + + def test_block_view_with_out_of_range_negative_index_raises_indexerror(sample_file): with open_rd_file(sample_file) as rd_file: with pytest.raises(IndexError): From acfb6c56b6a47db0662a47d35821965f0c1699e0 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Tue, 14 Jul 2026 08:15:45 +0200 Subject: [PATCH 18/20] Use size_t for rd_file_fwrite_fortio --- applications/resdata/rd_unpack.cpp | 2 +- lib/include/resdata/rd_file.hpp | 2 +- lib/include/resdata/rd_file_view.hpp | 2 +- lib/resdata/rd_file.cpp | 2 +- lib/resdata/rd_file_pybind.cpp | 4 ++-- lib/resdata/rd_file_view.cpp | 2 +- python/resdata/resfile/rd_file.py | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/applications/resdata/rd_unpack.cpp b/applications/resdata/rd_unpack.cpp index 89af91926..2301fda7a 100644 --- a/applications/resdata/rd_unpack.cpp +++ b/applications/resdata/rd_unpack.cpp @@ -55,7 +55,7 @@ static void unpack_file(const fs::path &filepath) { } rd_file_ptr src_file = open_rd_file(filename); int size; - int offset; + size_t offset; int report_step = 0; if (target_type == RD_SUMMARY_FILE) diff --git a/lib/include/resdata/rd_file.hpp b/lib/include/resdata/rd_file.hpp index bb8b0ba5a..5be217c33 100644 --- a/lib/include/resdata/rd_file.hpp +++ b/lib/include/resdata/rd_file.hpp @@ -32,7 +32,7 @@ int rd_file_get_size(const rd_file_type *rd_file); const char *rd_file_get_src_file(const rd_file_type *rd_file); rd_version_enum rd_file_get_rd_version(const rd_file_type *file); void rd_file_fwrite_fortio(const rd_file_type *ec_file, ERT::FortIO &fortio, - int offset); + size_t offset); int rd_file_get_phases(const rd_file_type *init_file); diff --git a/lib/include/resdata/rd_file_view.hpp b/lib/include/resdata/rd_file_view.hpp index da26a4160..ffa5327a5 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -92,7 +92,7 @@ class FileView { void index_fload_kw(const std::string &kw, int index, const int_vector_type *index_map, char *io_buffer); bool load_all(); - void write(ERT::FortIO &target, int offset); + void write(ERT::FortIO &target, size_t offset); /** Creates a FileView with keywords from @start_kw to @end_kw. diff --git a/lib/resdata/rd_file.cpp b/lib/resdata/rd_file.cpp index e719b0f1e..6b25f1e94 100644 --- a/lib/resdata/rd_file.cpp +++ b/lib/resdata/rd_file.cpp @@ -143,7 +143,7 @@ static rd_file_type *rd_file_alloc_empty() { } void rd_file_fwrite_fortio(const rd_file_type *rd_file, ERT::FortIO &target, - int offset) { + size_t offset) { rd_file->active_view->write(target, offset); } diff --git a/lib/resdata/rd_file_pybind.cpp b/lib/resdata/rd_file_pybind.cpp index d266dd04a..c016b4920 100644 --- a/lib/resdata/rd_file_pybind.cpp +++ b/lib/resdata/rd_file_pybind.cpp @@ -74,8 +74,8 @@ PYBIND11_MODULE(_file, m) { m.def("_get_src_file", [](py::handle self) { return rd_file_get_src_file(from_cwrap(self)); }); - m.def("_fwrite", [](py::handle self, ERT::FortIO &fortio, int offset) { - rd_file_fwrite_fortio(from_cwrap(self), fortio, offset); + m.def("_fwrite", [](py::handle self, ERT::FortIO &fortio) { + rd_file_fwrite_fortio(from_cwrap(self), fortio, 0); }); m.def("_has_report_step", [](py::handle self, int report_step) { return rd_file_has_report_step(from_cwrap(self), diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index 1d19c62ab..07ac6b1e7 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -131,7 +131,7 @@ bool FileView::load_all() { return loadOK; } -void FileView::write(ERT::FortIO &target, int offset) { +void FileView::write(ERT::FortIO &target, size_t offset) { for (size_t index = offset; index < kw_list.size(); index++) { rd_kw_type *rd_kw = get_kw(index); rd_kw_fwrite(rd_kw, target); diff --git a/python/resdata/resfile/rd_file.py b/python/resdata/resfile/rd_file.py index 26b0e341d..f4d253ac4 100644 --- a/python/resdata/resfile/rd_file.py +++ b/python/resdata/resfile/rd_file.py @@ -535,7 +535,7 @@ def fwrite(self, fortio): >>> fortio.close() """ - _file._fwrite(self, fortio, 0) + _file._fwrite(self, fortio) def write_index(self, index_file_name): if not self or not _file._write_index(self, index_file_name): From 290c771d57d95291d5dc5b4aa6c2eb2e661e7e10 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Tue, 14 Jul 2026 08:42:07 +0200 Subject: [PATCH 19/20] Remove unused map_stack --- lib/resdata/rd_file.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/resdata/rd_file.cpp b/lib/resdata/rd_file.cpp index 6b25f1e94..60be2522b 100644 --- a/lib/resdata/rd_file.cpp +++ b/lib/resdata/rd_file.cpp @@ -105,8 +105,6 @@ struct rd_file_struct { global_view; /* The index of all the rd_kw instances in the file. */ std::shared_ptr active_view; /* The currently active index. */ bool read_only; - std::unique_ptr map_stack{ - nullptr, &vector_free}; }; /* @@ -138,7 +136,6 @@ UTIL_IS_INSTANCE_FUNCTION(rd_file, RD_FILE_ID) static rd_file_type *rd_file_alloc_empty() { rd_file_type *rd_file = new rd_file_type(); UTIL_TYPE_ID_INIT(rd_file, RD_FILE_ID); - rd_file->map_stack.reset(vector_alloc_new()); return rd_file; } From cacc8a6bc0a5ef2cbbdfbfb9443255ec6cba7c62 Mon Sep 17 00:00:00 2001 From: Eivind Jahren Date: Tue, 14 Jul 2026 10:00:53 +0200 Subject: [PATCH 20/20] Add .pyi files for FileMode and ResdataFileView --- python/resdata/_file_mode.pyi | 29 ++++++++++++++++++++++ python/resdata/resfile/rd_file_view.pyi | 32 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 python/resdata/_file_mode.pyi create mode 100644 python/resdata/resfile/rd_file_view.pyi diff --git a/python/resdata/_file_mode.pyi b/python/resdata/_file_mode.pyi new file mode 100644 index 000000000..7e1432d54 --- /dev/null +++ b/python/resdata/_file_mode.pyi @@ -0,0 +1,29 @@ +import typing + +__all__ = ["FileMode"] + +class FileMode: + CLOSE_STREAM: typing.ClassVar[FileMode] + DEFAULT: typing.ClassVar[FileMode] + WRITABLE: typing.ClassVar[FileMode] + __members__: typing.ClassVar[dict[str, FileMode]] + def __and__(self, arg0: FileMode) -> FileMode: ... + def __eq__(self, other: object) -> bool: ... + def __ge__(self, other: typing.Any) -> bool: ... + def __getstate__(self) -> int: ... + def __gt__(self, other: typing.Any) -> bool: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __init__(self, value: typing.SupportsInt) -> None: ... + def __int__(self) -> int: ... + def __invert__(self) -> FileMode: ... + def __le__(self, other: typing.Any) -> bool: ... + def __lt__(self, other: typing.Any) -> bool: ... + def __ne__(self, other: object) -> bool: ... + def __or__(self, arg0: FileMode) -> FileMode: ... + def __setstate__(self, state: typing.SupportsInt) -> None: ... + def __xor__(self, arg0: FileMode) -> FileMode: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... diff --git a/python/resdata/resfile/rd_file_view.pyi b/python/resdata/resfile/rd_file_view.pyi new file mode 100644 index 000000000..9de0ddaf1 --- /dev/null +++ b/python/resdata/resfile/rd_file_view.pyi @@ -0,0 +1,32 @@ +import datetime +from typing import SupportsFloat, SupportsInt, overload + +from .rd_kw import ResdataKW + +__all__ = ["ResdataFileView"] + +class ResdataFileView: + def __contains__(self, arg0: str) -> bool: ... + @overload + def __getitem__(self, index: str) -> list[ResdataKW]: ... + @overload + def __getitem__(self, index: SupportsInt) -> ResdataKW: ... + @overload + def __getitem__(self, index: slice) -> list[ResdataKW]: ... + def __init__(self) -> None: ... + def __len__(self) -> int: ... + def block_view(self, kw: str, kw_index: SupportsInt) -> ResdataFileView: ... + def block_view2( + self, start_kw: str | None, stop_kw: str | None, start_index: SupportsInt + ) -> ResdataFileView: ... + def iget_named_kw(self, kw_name: str, index: SupportsInt) -> ResdataKW: ... + def num_keywords(self, kw: str) -> int: ... + def restart_view( + self, + seqnum_index: SupportsInt | None = None, + report_step: SupportsInt | None = None, + sim_time: datetime.date | datetime.datetime | None = None, + sim_days: SupportsFloat | None = None, + ) -> ResdataFileView: ... + def unique_kw(self) -> list[str]: ... + def unique_size(self) -> int: ...