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..2301fda7a 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; @@ -44,9 +53,9 @@ 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; + size_t offset; int report_step = 0; if (target_type == RD_SUMMARY_FILE) @@ -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 cdc743e3c..ea96bb4e8 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(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 @@ -217,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() @@ -384,13 +386,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/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 2727c3009..5be217c33 100644 --- a/lib/include/resdata/rd_file.hpp +++ b/lib/include/resdata/rd_file.hpp @@ -6,28 +6,25 @@ #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); 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); @@ -35,23 +32,20 @@ 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); bool rd_file_writable(const rd_file_type *rd_file); -bool rd_file_flags_set(const rd_file_type *rd_file, int 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, @@ -63,22 +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, int flags) { - return {rd_file_open(path.c_str(), flags), &rd_file_close}; +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_free}; } -inline rd_file_ptr open_rd_file(const std::filesystem::path &path, int flags) { - return {rd_file_open(path.string().c_str(), flags), &rd_file_close}; +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_free}; } 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 09ae066e4..ffa5327a5 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -1,121 +1,142 @@ -#ifndef ERT_RD_FILE_VIEW_H -#define ERT_RD_FILE_VIEW_H - +#pragma once #include -#include #include #include +#include +#include +#include +#include +#include +#include #include #include #include -#include #include +#include +#include -using inv_map_type = std::unordered_map; +namespace rd { -#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 - 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); - -rd_file_view_type *rd_file_view_alloc(ERT::FortIO *fortio, int *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, - 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 char *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); -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, - 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, int flag); -void rd_file_view_add_flag(rd_file_view_type *file_view, int 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, int *flags, - inv_map_type *inv_map, - FILE *istream); - -void rd_file_view_clear(rd_file_view_type *file_view); - -#ifdef __cplusplus -} -#include - -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); -#endif +using inv_map_type = std::unordered_map; -#endif +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. */ + 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, size_t offset); + + /** 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/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/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 d573d52b7..87b2b5cd0 100644 --- a/lib/include/resdata/well/well_rseg_loader.hpp +++ b/lib/include/resdata/well/well_rseg_loader.hpp @@ -1,23 +1,12 @@ -#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); +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 * well_rseg_loader_load_values(const well_rseg_loader_type *well_rseg_loader, int rseg_offset); - -#ifdef __cplusplus -} -#endif - -#endif 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 10d9500d8..9d79f7d4e 100644 --- a/lib/private-include/detail/resdata/cwrap_pybind.hpp +++ b/lib/private-include/detail/resdata/cwrap_pybind.hpp @@ -21,3 +21,4 @@ inline void register_exceptions(pybind11::module &m) { } pybind11::object CTime(); +pybind11::object ResdataKW(); 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..6ed6d1186 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; @@ -147,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 e1d006076..9549c1377 100644 --- a/lib/private-include/detail/resdata/rd_unsmry_loader.hpp +++ b/lib/private-include/detail/resdata/rd_unsmry_loader.hpp @@ -1,18 +1,20 @@ +#include +#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); - ~unsmry_loader(); + FileMode file_options = FileMode::DEFAULT); std::vector get_vector(int pos) const; std::vector sim_seconds() const; @@ -32,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/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..60be2522b 100644 --- a/lib/resdata/rd_file.cpp +++ b/lib/resdata/rd_file.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -6,12 +7,13 @@ #include #include +#include +#include -#include -#include #include -#include -#include +#include +#include +#include #include #include @@ -19,9 +21,10 @@ #include #include #include -#include #include #include +#include +#include /** This file implements functionality to load a file in @@ -97,16 +100,11 @@ 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; - int flags; - vector_type *map_stack; - inv_map_type *inv_view; }; /* @@ -135,18 +133,15 @@ 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) { - 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; 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); + size_t offset) { + rd_file->active_view->write(target, offset); } /** @@ -170,7 +165,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 +173,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 +181,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 +200,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 +240,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 +259,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 +268,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) { @@ -319,11 +287,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 ((flags & FileMode::WRITABLE) == FileMode::WRITABLE) return std::make_unique( filename, std::ios_base::in | std::ios_base::out, fmt_file); else @@ -333,20 +301,21 @@ 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) { - 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->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, RD_FILE_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 +323,19 @@ 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->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) - rd_file_view_free(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 +348,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 +377,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 +387,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 +399,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 +479,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, RD_FILE_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,41 +556,44 @@ 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; } 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; + 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, - RD_FILE_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 2d2f4739e..c016b4920 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) @@ -55,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)); @@ -70,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), @@ -81,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 acd7f20ea..07ac6b1e7 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -1,14 +1,13 @@ #include -#include #include -#include +#include #include #include -#include #include -#include #include +#include +#include #include #include @@ -18,164 +17,93 @@ #include #include #include -#include +#include #include #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; - int *flags; -}; - -bool rd_file_view_check_flags(int state_flags, int query_flags) { - if ((state_flags & query_flags) == query_flags) - return true; - else - return false; -} - -bool rd_file_view_flags_set(const rd_file_view_type *file_view, - int query_flags) { - return rd_file_view_check_flags(*file_view->flags, query_flags); -} - -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, - inv_map_type *inv_map) { - rd_file_view_type *rd_file_view = new rd_file_view_type(); +namespace rd { - rd_file_view->fortio = fortio; - rd_file_view->inv_map = inv_map; - rd_file_view->flags = flags; +void FileView::make_index() { + distinct_kw.clear(); + kw_index.clear(); - return rd_file_view; -} + 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); -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]; -} - -/** - 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, int 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, int 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()) { + if (context->fortio.assert_stream_open()) { + rd_kw = file_kw->get_kw(context->fortio); + context->inv_map[rd_kw] = file_kw.get(); - 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)) - 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; @@ -186,183 +114,102 @@ 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(); -} - -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, RD_FILE_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); -} - -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)) { - 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, 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); } } -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; - { - /* 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 = static_cast(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; } -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 = rd_file_view_alloc( - 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); +* They are organized in blocks; where each block starts with a + SEQNUM keyword, which contains the report step. - if (child) - file_view->child_list.emplace_back(child); +* 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. - return 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. -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); - - if (child) - rd_file_view->child_list.emplace_back(child); - - 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 ======================== @@ -423,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 @@ -433,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. @@ -449,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); @@ -473,275 +302,214 @@ 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; - std::unique_ptr seqnum_map( - rd_file_view_alloc_blockview(rd_file_view, SEQNUM_KW, seqnum_index), - &rd_file_view_free); + 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; - std::unique_ptr seqnum_map( - rd_file_view_alloc_blockview(rd_file_view, SEQNUM_KW, seqnum_index), - &rd_file_view_free); + 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)) /* 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; } } } -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++) { - std::unique_ptr - seqnum_map( - rd_file_view_alloc_blockview(parent_map, SEQNUM_KW, s_idx), - &rd_file_view_free); + 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; - bool sim = rd_file_view_has_sim_time(seqnum_map.get(), sim_time); - if (sim) - 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) { - std::unique_ptr - seqnum_map(rd_file_view_alloc_blockview(file_view, SEQNUM_KW, - seqnum_index), - &rd_file_view_free); + 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, int *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; - rd_file_view_ptr file_view(rd_file_view_alloc(fortio, flags, inv_map), - &rd_file_view_free); + 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 new file mode 100644 index 000000000..5a5bbb807 --- /dev/null +++ b/lib/resdata/rd_file_view_pybind.cpp @@ -0,0 +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::object parent) { + if (!kw) + return py::none(); + return ResdataKW().attr("createCReference")( + reinterpret_cast(kw), parent); +} +} // namespace + +template struct overload : Ts... { + using Ts::operator()...; +}; +template overload(Ts...) -> overload; + +PYBIND11_MODULE(rd_file_view, m) { + register_exceptions(m); + 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 a6e524937..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,18 +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_file_view_free); - 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 = @@ -2410,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) @@ -2537,7 +2534,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 +2762,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_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.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..ee5c46aaf 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,21 +27,22 @@ #include #include #include -#include #include #include #include +#include +#include #include "detail/resdata/rd_sum_file_data.hpp" 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 @@ -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); @@ -784,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. */ diff --git a/lib/resdata/rd_sum_file_data.cpp b/lib/resdata/rd_sum_file_data.cpp index 9615e55eb..092da1b8e 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; @@ -545,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) @@ -575,7 +588,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,10 +611,10 @@ 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())); + auto global_view = rd_file_get_global_view(rd_file.get()); + this->add_rd_file(report_step, *global_view); } } } @@ -618,8 +631,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); @@ -632,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_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..1d591ac21 100644 --- a/lib/resdata/rd_unsmry_loader.cpp +++ b/lib/resdata/rd_unsmry_loader.cpp @@ -1,48 +1,56 @@ -#include +#include +#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)), 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"); @@ -53,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 { @@ -73,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, RD_FILE_CLOSE_STREAM)) - rd_file_view_fclose_stream(file_view); + if (file_view->has_flags(FileMode::CLOSE_STREAM)) + file_view->close(); return data; } @@ -88,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; } @@ -106,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])); @@ -127,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_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..589a3c995 100644 --- a/lib/resdata/tests/rd_file.cpp +++ b/lib/resdata/tests/rd_file.cpp @@ -1,8 +1,8 @@ #include #include -#include #include +#include #include #include @@ -12,10 +12,10 @@ #include #include #include -#include #include #include #include +#include void test_writable(size_t data_size) { rd::util::TestArea ta("file_writable"); @@ -31,13 +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, RD_FILE_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", 0); - 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", 0); - 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", 0); - 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", 0); - 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 53d959b39..dbfd5c09a 100644 --- a/lib/resdata/tests/rd_file_equinor.cpp +++ b/lib/resdata/tests/rd_file_equinor.cpp @@ -1,64 +1,63 @@ #include #include +#include + #include #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); + 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, RD_FILE_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, RD_FILE_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, RD_FILE_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, RD_FILE_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, 0); - 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 1a4c2c2d9..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(), 0); - 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 aa0991ddd..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, 0); + 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 79ef930bd..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", 0); - 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", 0); - 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_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_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); -} diff --git a/lib/resdata/tests/rd_lgr_test.cpp b/lib/resdata/tests/rd_lgr_test.cpp index 83b7066d3..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, 0); + 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 9dcef4fda..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, 0); - 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_type *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, NNC1_KW)) { - rd_kw_type *nnc1_kw = - rd_file_view_iget_named_kw(nnc_view, NNC1_KW, 0); - rd_kw_type *nnc2_kw = - rd_file_view_iget_named_kw(nnc_view, 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, NNCG_KW)) { - rd_kw_type *nnchead_kw = - rd_file_view_iget_named_kw(nnc_view, NNCHEAD_KW, 0); - rd_kw_type *nncg_kw = - rd_file_view_iget_named_kw(nnc_view, NNCG_KW, 0); - rd_kw_type *nncl_kw = - rd_file_view_iget_named_kw(nnc_view, 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, NNCHEADA_KW)) { - rd_kw_type *nncheada_kw = - rd_file_view_iget_named_kw(nnc_view, NNCHEADA_KW, 0); - rd_kw_type *nnc1_kw = - rd_file_view_iget_named_kw(nnc_view, NNA1_KW, 0); - rd_kw_type *nnc2_kw = - rd_file_view_iget_named_kw(nnc_view, 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); @@ -129,14 +121,11 @@ void test_scan(const char *grid_filename) { } } } - - rd_file_view_free(nnc_view); } } 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_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..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 @@ -14,27 +16,29 @@ 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; + 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 fd957441a..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", 0); - 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 a6ca90fdc..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", 0); - 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, 0); - 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, 0); - 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 2e8c1be31..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, 0); - 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 57f068b52..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, 0); - 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 71d4d82f0..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, 0); - 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 30a3e0e06..15ae23b58 100644 --- a/lib/resdata/tests/well_state_load.cpp +++ b/lib/resdata/tests/well_state_load.cpp @@ -22,27 +22,28 @@ 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); - auto header = RSTHead::read(rd_file_get_global_view(rst_file), - rd_filename_report_nr(rst_file_name)); + rd_file_type *rst_file = rd_file_open(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 86df43e12..f348caa49 100644 --- a/lib/resdata/tests/well_state_load_missing_RSEG.cpp +++ b/lib/resdata/tests/well_state_load_missing_RSEG.cpp @@ -23,10 +23,10 @@ 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_view_type *rst_view = rd_file_get_active_view(rst_file); + rd_file_type *rst_file = rd_file_open(rst_file_name); + 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 2f861f4e0..6cefef51f 100644 --- a/lib/resdata/well_info.cpp +++ b/lib/resdata/well_info.cpp @@ -1,5 +1,4 @@ -#include - +#include #include #include #include @@ -8,49 +7,51 @@ #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) + explicit close_guard(rd::FileView *file_view) : file_view(file_view), - was_set(rd_file_view_drop_flag(file_view, RD_FILE_CLOSE_STREAM)) {} + was_set(file_view->drop_flags(FileMode::CLOSE_STREAM)) {} ~close_guard() { if (was_set) - rd_file_view_add_flag(file_view, RD_FILE_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); @@ -70,24 +71,26 @@ 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); } } 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..eee53583e 100644 --- a/lib/resdata/well_rseg_loader.cpp +++ b/lib/resdata/well_rseg_loader.cpp @@ -1,25 +1,23 @@ - +#include #include #include -#include #include #include #include #include - -#include +#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); @@ -41,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, RD_FILE_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); @@ -63,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 99e8fb35c..893d760e3 100644 --- a/lib/tests/test_geertsma.cpp +++ b/lib/tests/test_geertsma.cpp @@ -81,19 +81,19 @@ 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()), 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; @@ -132,22 +132,22 @@ 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()), 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; @@ -178,16 +178,16 @@ 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()), 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; @@ -215,20 +215,20 @@ 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()), 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; @@ -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()), @@ -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 54939822d..fe907c2b2 100644 --- a/lib/tests/test_rd_sum.cpp +++ b/lib/tests/test_rd_sum.cpp @@ -789,14 +789,13 @@ 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)); + 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 "); @@ -832,10 +831,10 @@ 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); - 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 smspec_file = open_rd_file(name + ".SMSPEC"); + 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); @@ -1422,8 +1421,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 +1522,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 +1784,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..6c7da3e9b 100644 --- a/lib/tests/test_well_info.cpp +++ b/lib/tests/test_well_info.cpp @@ -190,18 +190,18 @@ 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); - auto *view = rd_file_get_global_view(file.get()); + 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); - 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/_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/rd_util.py b/python/resdata/rd_util.py index 686487c91..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( @@ -109,8 +86,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) @@ -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/resfile/rd_file.py b/python/resdata/resfile/rd_file.py index 7f47bb2b4..f4d253ac4 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: @@ -524,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): diff --git a/python/resdata/resfile/rd_file_view.py b/python/resdata/resfile/rd_file_view.py deleted file mode 100644 index 28bc7817d..000000000 --- a/python/resdata/resfile/rd_file_view.py +++ /dev/null @@ -1,190 +0,0 @@ -from cwrap import BaseCClass -from six import string_types - -from resdata import ResdataPrototype -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) - - 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 self._iget_named_kw(kw_name, index).setParent(parent=self) - - 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 self._get_size() - - def __contains__(self, kw): - if self.num_keywords(kw) > 0: - return True - else: - return False - - def num_keywords(self, kw): - return self._get_num_named_kw(kw) - - def unique_size(self): - return self._get_unique_size() - - def unique_kw(self): - return [self._get_unique_kw(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) - - view = self._create_block_view2(start_kw, stop_kw, idx) - view.setParent(parent=self) - return view - - 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)) - - view = self._create_block_view(kw, kw_index) - view.setParent(parent=self) - return view - - 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 = self._restart_view(seqnum_index, report_step, CTime(sim_time), sim_days) - if view is None: - raise ValueError("No such restart block could be identified") - - view.setParent(parent=self) - return view 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: ... 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/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): 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