diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f9998786..357f6777a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,12 +205,15 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) "MinSizeRel" "RelWithDebInfo") endif() -# Treat warnings as errors if not on Windows if(NOT ERT_WINDOWS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wno-unknown-pragmas ") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wfatal-errors -Wall -Wno-unknown-pragmas -Wno-unused-result -Wno-unused-parameter" ) + # Treat warnings as errors if gcc + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + endif() endif() if(MSVC) diff --git a/applications/CMakeLists.txt b/applications/CMakeLists.txt index b4de2550b..c11f15eee 100644 --- a/applications/CMakeLists.txt +++ b/applications/CMakeLists.txt @@ -1,7 +1,7 @@ project(resdata-applications) function(target_link_resdata target) - target_link_libraries(${target} resdata) + target_link_libraries(${target} resdata fmt::fmt) if(SKBUILD) set_target_properties(${target} PROPERTIES INSTALL_RPATH "$ORIGIN/../.libs") endif() diff --git a/applications/resdata/rd_pack.cpp b/applications/resdata/rd_pack.cpp index abbea0434..7e6ea805b 100644 --- a/applications/resdata/rd_pack.cpp +++ b/applications/resdata/rd_pack.cpp @@ -72,12 +72,11 @@ int main(int argc, char **argv) { std::vector filelist(argv + 1, argv + argc); std::sort(filelist.begin(), filelist.end(), fname_cmp); - rd_kw_ptr seqnum_kw(nullptr, &rd_kw_free); + std::unique_ptr seqnum_kw{nullptr}; ERT::FortIO target(target_file, std::ios_base::out, fmt_file); if (target_type == FileType::UNIFIED_RESTART) { - int dummy; - seqnum_kw.reset(rd_kw_alloc_new("SEQNUM", 1, RD_INT, &dummy)); + seqnum_kw = std::make_unique("SEQNUM", 1, RD_INT); } int prev_report_step = -1; @@ -97,8 +96,8 @@ int main(int argc, char **argv) { rd::File::open(filelist.at(i)); if (target_type == FileType::UNIFIED_RESTART) { /* Must insert the SEQNUM keyword first. */ - rd_kw_iset_int(seqnum_kw.get(), 0, report_step); - rd_kw_fwrite(seqnum_kw.get(), target); + seqnum_kw->at(0) = report_step; + seqnum_kw->fwrite(target); } src_file->write(target, 0); } /* Else skipping file of incorrect type. */ diff --git a/applications/resdata/rd_unpack.cpp b/applications/resdata/rd_unpack.cpp index 0ffae1557..a8903edf6 100644 --- a/applications/resdata/rd_unpack.cpp +++ b/applications/resdata/rd_unpack.cpp @@ -71,10 +71,10 @@ static void unpack_file(const fs::path &filepath) { report_step += 1; offset = 0; } else { - rd_kw_type *seqnum_kw; + rd::KW *seqnum_kw; active_view = src_file->blockview(SEQNUM_KW, block_index); seqnum_kw = active_view->get_kw(SEQNUM_KW, 0); - report_step = rd_kw_iget_int(seqnum_kw, 0); + report_step = seqnum_kw->at(0); offset = 1; } diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 605ab2758..67ecb93f6 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -257,7 +257,7 @@ add_executable( target_compile_features(rd_test_suite PUBLIC cxx_std_17) target_include_directories(rd_test_suite PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/private-include) -target_link_libraries(rd_test_suite resdata Catch2::Catch2) +target_link_libraries(rd_test_suite resdata fmt::fmt Catch2::Catch2) add_test(NAME rd_test_suite COMMAND rd_test_suite) foreach( @@ -317,8 +317,6 @@ foreach( rd_grid_init_fwrite rd_grid_reset_actnum rd_kw_space_pad - rd_kw_cmp_string - rd_kw_equal rd_kw_fread rd_kw_init rd_layer @@ -336,7 +334,7 @@ foreach( well_segment_collection test_rd_file) add_executable(${name} resdata/tests/${name}.cpp util/test_util.cpp) - target_link_libraries(${name} resdata) + target_link_libraries(${name} resdata fmt::fmt) target_include_directories( ${name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/private-include) add_test(NAME ${name} COMMAND ${name}) @@ -361,9 +359,9 @@ add_test( ${CMAKE_CURRENT_SOURCE_DIR}/resdata/tests/data/num_cpu4 ${CMAKE_CURRENT_SOURCE_DIR}/resdata/tests/data/num_cpu5) -foreach(test rdxx_kw rdxx_types) +foreach(test rdxx_types) add_executable(${test} resdata/tests/${test}.cpp util/test_util.cpp) - target_link_libraries(${test} resdata) + target_link_libraries(${test} resdata fmt::fmt) add_test(NAME ${test} COMMAND ${test}) endforeach() @@ -395,7 +393,7 @@ foreach( well_lgr_load) add_executable(${name} resdata/tests/${name}.cpp util/test_util.cpp) - target_link_libraries(${name} resdata) + target_link_libraries(${name} resdata fmt::fmt) target_include_directories( ${name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/private-include) endforeach() diff --git a/lib/include/ert/util/util.hpp b/lib/include/ert/util/util.hpp index ce8cb89ab..9f77ec858 100644 --- a/lib/include/ert/util/util.hpp +++ b/lib/include/ert/util/util.hpp @@ -116,7 +116,6 @@ bool util_copy_file__(const char *src_file, const char *target_file, char *util_alloc_cwd(void); char *util_alloc_realpath(const char *); char *util_alloc_realpath__(const char *input_path); -bool util_ftruncate(FILE *stream, long size); int util_roundf(float x); int util_round(double x); diff --git a/lib/include/resdata/FortIO.hpp b/lib/include/resdata/FortIO.hpp index ece76f2cd..bfeba9ef6 100644 --- a/lib/include/resdata/FortIO.hpp +++ b/lib/include/resdata/FortIO.hpp @@ -1,6 +1,10 @@ #pragma once +#include #include +#include +#include +#include #include #include #include @@ -46,8 +50,6 @@ class FortIO { FortIO() = delete; FortIO(const std::string &filename, std::ios_base::openmode mode, bool fmt_file = false, bool endian_flip_header = RD_ENDIAN_FLIP); - FortIO(const std::string &filename, bool fmt_file, bool writable, - FILE *stream, bool endian_flip_header = RD_ENDIAN_FLIP); ~FortIO(); FortIO(FortIO &&other) noexcept; @@ -67,7 +69,8 @@ class FortIO { int fskip_record(); bool fread_buffer(char *buffer, int buffer_size); void fwrite_record(const char *buffer, int buffer_size); - [[nodiscard]] FILE *get_FILE() const; + [[nodiscard]] std::istream &get_istream(); + [[nodiscard]] std::ostream &get_ostream(); void fflush() const; void rewind() const; [[nodiscard]] const char *filename_ref() const; @@ -75,10 +78,11 @@ class FortIO { [[nodiscard]] bool fmt_file() const; [[nodiscard]] offset_type ftell() const; bool fseek(offset_type offset, int whence); - bool data_fskip(int element_size, int element_count, int block_count); + bool data_fskip(size_t element_size, size_t element_count, + size_t block_count); void data_fseek(offset_type data_offset, size_t data_element, - size_t element_size, int element_count, int block_size); - bool ftruncate(offset_type size); + size_t element_size, int element_count, size_t block_size); + bool ftruncate(std::uintmax_t size); int fclean(); bool fclose_stream(); bool fopen_stream(); @@ -90,12 +94,11 @@ class FortIO { private: bool fseek_(offset_type offset, int whence); - FILE *m_stream = nullptr; + mutable std::fstream m_stream; std::string m_filename; bool m_endian_flip_header = false; bool m_fmt_file = false; - const char *m_fopen_mode = nullptr; - bool m_stream_owner = false; + std::ios_base::openmode m_open_mode = std::ios_base::openmode{}; /* The internal variable m_read_size is used in the functions fseek() and diff --git a/lib/include/resdata/ResdataKW.hpp b/lib/include/resdata/ResdataKW.hpp deleted file mode 100644 index 0ecc92db1..000000000 --- a/lib/include/resdata/ResdataKW.hpp +++ /dev/null @@ -1,242 +0,0 @@ -#ifndef OPM_ERT_RD_KW -#define OPM_ERT_RD_KW - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace ERT { -template struct rd_type {}; - -template <> struct rd_type { - static const rd_type_enum type{RD_FLOAT_TYPE}; -}; - -template <> struct rd_type { - static const rd_type_enum type{RD_DOUBLE_TYPE}; -}; - -template <> struct rd_type { - static const rd_type_enum type{RD_INT_TYPE}; -}; - -template <> struct rd_type { - static const rd_type_enum type{RD_BOOL_TYPE}; -}; - -template <> struct rd_type { - static const rd_type_enum type{RD_CHAR_TYPE}; -}; - -template <> struct rd_type { - static const rd_type_enum type{RD_CHAR_TYPE}; -}; - -/* - Both std::string and char* are mapped to the eight character string type - RD_CHAR_TYPE. That implies that the variable length string type - RD_STRING is invisible from this API. - */ - -template <> struct rd_type { - static const rd_type_enum type{RD_CHAR_TYPE}; -}; - -template <> struct rd_type { - static const rd_type_enum type{RD_CHAR_TYPE}; -}; - -template class ResdataKW_ref { -public: - explicit ResdataKW_ref(rd_kw_type *kw) : m_kw(kw) { - if (rd_type_get_type(rd_kw_get_data_type(kw)) != rd_type::type) - throw std::invalid_argument("Type error"); - } - - ResdataKW_ref() noexcept = default; - - const char *name() const { return rd_kw_get_header(this->m_kw); } - - size_t size() const { return size_t(rd_kw_get_size(this->m_kw)); } - - void fwrite(FortIO &fortio) const { rd_kw_fwrite(this->m_kw, fortio); } - - T at(size_t i) const { - return *static_cast(rd_kw_iget_ptr(this->m_kw, i)); - } - - T &operator[](size_t i) { - return *static_cast(rd_kw_iget_ptr(this->m_kw, i)); - } - - const typename std::remove_pointer::type *data() const { - using Tp = const typename std::remove_pointer::type *; - return static_cast(rd_kw_get_ptr(this->m_kw)); - } - - rd_kw_type *get() const { return this->m_kw; } - - void resize(size_t new_size) { rd_kw_resize(this->m_kw, new_size); } - -protected: - rd_kw_type *m_kw = nullptr; -}; - -template <> inline bool ResdataKW_ref::at(size_t i) const { - return rd_kw_iget_bool(this->m_kw, i); -} - -template <> inline const char *ResdataKW_ref::at(size_t i) const { - return rd_kw_iget_char_ptr(this->m_kw, i); -} - -template <> inline std::string ResdataKW_ref::at(size_t i) const { - return rd_kw_iget_char_ptr(this->m_kw, i); -} - -/* - The current implementation of "string" and "bool" storage in the underlying C - rd_kw structure does not lend itself to easily implement operator[]. We have - therefore explicitly deleted them here. -*/ - -template <> -const char *&ResdataKW_ref::operator[](size_t i) = delete; - -template <> bool &ResdataKW_ref::operator[](size_t i) = delete; - -template class ResdataKW : public ResdataKW_ref { -private: - using base = ResdataKW_ref; - -public: - using ResdataKW_ref::ResdataKW_ref; - - ResdataKW(const ResdataKW &) = delete; - ResdataKW(ResdataKW &&rhs) : base(rhs.m_kw) { rhs.m_kw = nullptr; } - - ~ResdataKW() { - if (this->m_kw) - rd_kw_free(this->m_kw); - } - - ResdataKW(const std::string &kw, int size_) - : base(rd_kw_alloc(kw.c_str(), size_, - rd_type_create_from_type(rd_type::type))) {} - - ResdataKW(const std::string &kw, const std::vector &data) - : ResdataKW(kw, data.size()) { - rd_kw_set_memcpy_data(this->m_kw, data.data()); - } - - template - ResdataKW(const std::string &kw, const std::vector &data) - : ResdataKW(kw, data.size()) { - T *target = static_cast(rd_kw_get_ptr(this->m_kw)); - - for (size_t i = 0; i < data.size(); ++i) - target[i] = T(data[i]); - } - - std::vector data() const { - const T *ptr = static_cast(rd_kw_get_ptr(this->m_kw)); - std::vector vector; - vector.assign(ptr, ptr + this->size()); - return vector; - } - - static ResdataKW load(FortIO &fortio) { - rd_kw_type *c_ptr = rd_kw_fread_alloc(fortio); - - if (!c_ptr) - throw std::invalid_argument("fread kw failed - EOF?"); - - return ResdataKW(c_ptr); - } -}; - -template <> -inline ResdataKW::ResdataKW(const std::string &kw, - const std::vector &data) - : ResdataKW(kw, data.size()) { - auto *ptr = this->get(); - for (size_t i = 0; i < data.size(); ++i) { - if (strlen(data[i]) > 8) - throw std::range_error("Strings must be maximum 8 characters long"); - rd_kw_iset_string8(ptr, i, data[i]); - } -} - -template <> -inline ResdataKW::ResdataKW(const std::string &kw, - const std::vector &data) - : ResdataKW(kw, data.size()) { - auto *ptr = this->get(); - for (size_t i = 0; i < data.size(); ++i) { - if (data[i].size() > 8) - throw std::range_error("Strings must be maximum 8 characters long"); - rd_kw_iset_string8(ptr, i, data[i].c_str()); - } -} - -template <> -template <> -inline ResdataKW::ResdataKW(const std::string &kw, - const std::vector &data) - : ResdataKW(kw, data.size()) { - auto *ptr = this->get(); - for (size_t i = 0; i < data.size(); ++i) { - if (strlen(data[i]) > 8) - throw std::range_error("Strings must be maximum 8 characters long"); - rd_kw_iset_string8(ptr, i, data[i]); - } -} - -template <> -inline ResdataKW::ResdataKW(const std::string &kw, - const std::vector &data) - : ResdataKW(kw, data.size()) { - for (size_t i = 0; i < data.size(); i++) - rd_kw_iset_bool(this->m_kw, i, data[i]); -} - -template <> -inline std::vector ResdataKW::data() const { - std::vector strings; - auto *ptr = this->get(); - for (size_t i = 0; i < this->size(); ++i) { - std::string s8 = rd_kw_iget_char_ptr(ptr, i); - s8.erase(s8.find_last_not_of(' ') + 1); - strings.push_back(s8); - } - return strings; -} - -/* - Will write an rd_kw instance to the open Fortio file. -*/ -template -void write_kw(FortIO &fortio, const std::string &kw, - const std::vector &data) { - ResdataKW rd_kw(kw, data); - rd_kw_fwrite(rd_kw.get(), fortio); -} - -/* - Will write an empty rd_kw instance of type 'MESS' to the Fortio file. -*/ -inline void write_mess(FortIO &fortio, const std::string &kw) { - rd_kw_type *rd_kw = rd_kw_alloc(kw.c_str(), 0, RD_MESS); - rd_kw_fwrite(rd_kw, fortio); -} - -} // namespace ERT - -#endif diff --git a/lib/include/resdata/fault_block_layer.hpp b/lib/include/resdata/fault_block_layer.hpp index 289ab74e9..f6840a99c 100644 --- a/lib/include/resdata/fault_block_layer.hpp +++ b/lib/include/resdata/fault_block_layer.hpp @@ -36,16 +36,16 @@ int fault_block_layer_get_max_id(const fault_block_layer_type *layer); int fault_block_layer_get_next_id(const fault_block_layer_type *layer); int fault_block_layer_get_size(const fault_block_layer_type *layer); bool fault_block_layer_scan_kw(fault_block_layer_type *layer, - const rd_kw_type *fault_block_kw); + const rd::KW *fault_block_kw); bool fault_block_layer_load_kw(fault_block_layer_type *layer, - const rd_kw_type *fault_block_kw); + const rd::KW *fault_block_kw); int fault_block_layer_get_k(const fault_block_layer_type *layer); void fault_block_layer_scan_layer(fault_block_layer_type *fault_layer, layer_type *layer); void fault_block_layer_insert_block_content(fault_block_layer_type *layer, const FaultBlock &src_block); bool fault_block_layer_export(const fault_block_layer_type *layer, - rd_kw_type *faultblock_kw); + rd::KW *faultblock_kw); rd_grid_type *fault_block_layer_get_grid(const fault_block_layer_type *layer); layer_type *fault_block_layer_get_layer(const fault_block_layer_type *layer); diff --git a/lib/include/resdata/rd_file.hpp b/lib/include/resdata/rd_file.hpp index b11d7f9d5..0a41f76a9 100644 --- a/lib/include/resdata/rd_file.hpp +++ b/lib/include/resdata/rd_file.hpp @@ -49,7 +49,7 @@ class File { return global_view->num_named_kw(kw); } /** Will return the ith occurence of @kw the File. */ - [[nodiscard]] rd_kw_type *get_kw(const std::string &kw, size_t ith) const { + [[nodiscard]] rd::KW *get_kw(const std::string &kw, size_t ith) const { return global_view->get_kw(kw, ith); } /** The total number of rd_kws in the File. */ @@ -84,7 +84,7 @@ class File { std::runtime_error if there is a mismatch. 3. The File must have been opened with FileMode::WRITABLE. */ - bool save_kw(const rd_kw_type *rd_kw); + bool save_kw(const rd::KW *rd_kw); /// Functions specialized to work with restart files. diff --git a/lib/include/resdata/rd_file_kw.hpp b/lib/include/resdata/rd_file_kw.hpp index 8852941d4..387f0090e 100644 --- a/lib/include/resdata/rd_file_kw.hpp +++ b/lib/include/resdata/rd_file_kw.hpp @@ -24,7 +24,7 @@ class FileKW { rd_data_type data_type; int kw_size; std::string header; - rd_kw_ptr kw{nullptr, &rd_kw_free}; + std::unique_ptr kw{nullptr}; void assert_kw() const; void load_kw(ERT::FortIO &fortio); @@ -41,9 +41,9 @@ class FileKW { It is the users responsibility that the @offset argument comes from the same fortio instance as used when calling get_kw().*/ - FileKW(const rd_kw_type *rd_kw, offset_type offset) - : FileKW(offset, rd_kw_get_data_type(rd_kw), rd_kw_get_size(rd_kw), - rd_kw_get_header(rd_kw)) {} + FileKW(const rd::KW *rd_kw, offset_type offset) + : FileKW(offset, rd_kw->data_type(), rd::kw_get_size(rd_kw), + rd_kw->header()) {} [[nodiscard]] bool operator==(const FileKW &other) const { if (file_offset != other.file_offset) return false; @@ -62,11 +62,11 @@ class FileKW { [[nodiscard]] rd_data_type get_data_type() const { return data_type; }; /** The rd_kw, if one is read, otherwise returns nullptr. */ - [[nodiscard]] rd_kw_type *get_kw_ptr() const { return kw.get(); }; + [[nodiscard]] rd::KW *get_kw_ptr() const { return kw.get(); }; /** Return the rd_kw. If it is not loaded, the method will read it from @fortio. The kw is then cached. */ - rd_kw_type *get_kw(ERT::FortIO &fortio); + rd::KW *get_kw(ERT::FortIO &fortio); bool skip_data(ERT::FortIO &fortio) const; /** Read @num keyword headers from @stream. diff --git a/lib/include/resdata/rd_file_view.hpp b/lib/include/resdata/rd_file_view.hpp index 0f7611785..06d8ab6d6 100644 --- a/lib/include/resdata/rd_file_view.hpp +++ b/lib/include/resdata/rd_file_view.hpp @@ -18,10 +18,11 @@ #include #include #include +#include namespace rd { -using inv_map_type = std::unordered_map; +using inv_map_type = std::unordered_map; struct FileContext { ERT::FortIO fortio; @@ -42,7 +43,7 @@ class FileView { 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]] rd::KW *get_kw(const std::shared_ptr &file_kw); [[nodiscard]] size_t get_occurence(size_t global_index); /** Validates the arguments of index_fload_kw and returns the keyword. @@ -136,8 +137,8 @@ class FileView { [[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) { + rd::KW *get_kw(size_t index) { return get_kw(get_file_kw(index)); } + rd::KW *get_kw(const std::string &kw, size_t ith) { return get_kw(get_file_kw(kw, ith)); } @@ -163,10 +164,10 @@ class FileView { throw std::ios_base::failure("Failed to open FortIO file " + filename()); - rd_kw_fread_indexed_data(context->fortio, file_kw->get_offset(), - file_kw->get_data_type(), file_kw->get_size(), - index_map, - reinterpret_cast(out.data())); + rd::KW::fread_indexed_data(context->fortio, file_kw->get_offset(), + file_kw->get_data_type(), + file_kw->get_size(), index_map, + reinterpret_cast(out.data())); } void write(ERT::FortIO &target, size_t offset); @@ -185,8 +186,10 @@ class FileView { bool has_report_step(int report_step) { return find_block(SEQNUM_KW, - [&](const rd_kw_type *seqnum_kw) { - return rd_kw_data_equal(seqnum_kw, &report_step); + [&](const rd::KW *seqnum_kw) { + return seqnum_kw->size() > 0 && + rd_type_is_int(seqnum_kw->data_type()) && + seqnum_kw->at(0) == report_step; }) .has_value(); } diff --git a/lib/include/resdata/rd_grid.hpp b/lib/include/resdata/rd_grid.hpp index f5292f119..7625b519c 100644 --- a/lib/include/resdata/rd_grid.hpp +++ b/lib/include/resdata/rd_grid.hpp @@ -28,7 +28,7 @@ int rd_grid_get_num_coarse_groups(const rd_grid_type *main_grid); rd_coarse_cell_type *rd_grid_iget_coarse_group(const rd_grid_type *rd_grid, int coarse_nr); std::vector rd_grid_get_column_property(const rd_grid_type *rd_grid, - const rd_kw_type *rd_kw, int i, + const rd::KW *rd_kw, int i, int j); void rd_grid_get_cell_corner_xyz1(const rd_grid_type *grid, int global_index, int corner_nr, double *xpos, double *ypos, @@ -75,19 +75,21 @@ const nnc_info_type *rd_grid_get_cell_nnc_info1(const rd_grid_type *grid, int global_index); void rd_grid_add_self_nnc(rd_grid_type *grid1, int g1, int g2, int nnc_index); rd_grid_type *rd_grid_alloc_GRDECL_kw(int nx, int ny, int nz, - const rd_kw_type *zcorn_kw, - const rd_kw_type *coord_kw, - const rd_kw_type *actnum_kw, - const rd_kw_type *mapaxes_kw); + const rd::KW *zcorn_kw, + const rd::KW *coord_kw, + const rd::KW *actnum_kw, + const rd::KW *mapaxes_kw); rd_grid_type *rd_grid_alloc(const char *); rd_grid_type *rd_grid_load_case(const char *case_input); rd_grid_type *rd_grid_load_case__(const char *case_input, bool apply_mapaxes); rd_grid_type *rd_grid_alloc_rectangular(int nx, int ny, int nz, double dx, double dy, double dz, const int *actnum); -rd_kw_ptr rd_grid_alloc_volume_kw(const rd_grid_type *grid, bool active_size); -std::optional rd_grid_alloc_mapaxes_kw(const rd_grid_type *grid); -rd_kw_ptr rd_grid_alloc_coord_kw(const rd_grid_type *grid); +std::unique_ptr rd_grid_alloc_volume_kw(const rd_grid_type *grid, + bool active_size); +std::optional> +rd_grid_alloc_mapaxes_kw(const rd_grid_type *grid); +std::unique_ptr rd_grid_alloc_coord_kw(const rd_grid_type *grid); bool rd_grid_exists(const char *case_input); @@ -139,8 +141,8 @@ bool rd_grid_has_lgr_nr(const rd_grid_type *main_grid, int lgr_nr); const char *rd_grid_iget_lgr_name(const rd_grid_type *rd_grid, int lgr_index); const char *rd_grid_get_lgr_name(const rd_grid_type *rd_grid, int lgr_nr); -double rd_grid_get_property(const rd_grid_type *rd_grid, - const rd_kw_type *rd_kw, int i, int j, int k); +double rd_grid_get_property(const rd_grid_type *rd_grid, const rd::KW *rd_kw, + int i, int j, int k); bool rd_grid_test_lgr_consistency(const rd_grid_type *rd_grid); void rd_grid_fwrite_EGRID(rd_grid_type *grid, const char *filename, @@ -153,8 +155,8 @@ void rd_grid_fwrite_GRID2(const rd_grid_type *grid, const char *filename, int rd_grid_zcorn_index__(int nx, int ny, int i, int j, int k, int c); -rd_kw_ptr rd_grid_alloc_zcorn_kw(const rd_grid_type *grid); -rd_kw_ptr rd_grid_alloc_actnum_kw(const rd_grid_type *grid); +std::unique_ptr rd_grid_alloc_zcorn_kw(const rd_grid_type *grid); +std::unique_ptr rd_grid_alloc_actnum_kw(const rd_grid_type *grid); rd_grid_type *rd_grid_alloc_copy(const rd_grid_type *src_grid); bool rd_grid_dual_grid(const rd_grid_type *rd_grid); @@ -172,10 +174,10 @@ bool rd_grid_use_mapaxes(const rd_grid_type *grid); void rd_grid_init_mapaxes_data_double(const rd_grid_type *grid, double *mapaxes); void rd_grid_reset_actnum(rd_grid_type *grid, const int *actnum); -void rd_grid_compressed_kw_copy(const rd_grid_type *grid, rd_kw_type *target_kw, - const rd_kw_type *src_kw); -void rd_grid_global_kw_copy(const rd_grid_type *grid, rd_kw_type *target_kw, - const rd_kw_type *src_kw); +void rd_grid_compressed_kw_copy(const rd_grid_type *grid, rd::KW *target_kw, + const rd::KW *src_kw); +void rd_grid_global_kw_copy(const rd_grid_type *grid, rd::KW *target_kw, + const rd::KW *src_kw); void rd_grid_export_cell_corners1(const rd_grid_type *grid, int global_index, double *x, double *y, double *z); diff --git a/lib/include/resdata/rd_kw.hpp b/lib/include/resdata/rd_kw.hpp index ca561d139..9a55b0cd4 100644 --- a/lib/include/resdata/rd_kw.hpp +++ b/lib/include/resdata/rd_kw.hpp @@ -1,56 +1,308 @@ #pragma once +#include #include #include -#include #include +#include +#include +#include #include #include #include #include +#include +#include #include +#include +#include -#include #include #include #include #include -UTIL_IS_INSTANCE_HEADER(rd_kw); +namespace rd { +/** The data stored in the kw mirror the possible rd_type_enum values that carry + element-wise data: + + RD_INT_TYPE -> std::vector + RD_FLOAT_TYPE -> std::vector + RD_DOUBLE_TYPE -> std::vector + RD_CHAR_TYPE / RD_STRING_TYPE -> std::vector + RD_BOOL_TYPE -> std::vector (0/1 values)*/ +using kw_data = + std::variant, std::vector, std::vector, + std::vector, std::vector>; + +/* the rd::KW datastructure is tightly bound to the on-disk binary format + supplied by Eclipse, and there the number of elements is stored as a signed + 32 bit integer. Internally, size_t is used to denote size, however when + loaded or saved to disk, the size is validated to be no larger than the + std::numeric_limits::max */ + +class KW { +private: + size_t m_size; + rd_data_type m_data_type; + std::string m_header; + std::optional m_data; + void zero_init_data(); + static bool fread_data(rd::KW *rd_kw, ERT::FortIO &fortio); + static std::string strip_header(const std::string &header) { + if (header.size() > RD_STRING8_LENGTH) + return header; + const size_t start = header.find_first_not_of(' '); + if (start == std::string::npos) + return std::string(); + const size_t end = header.find_last_not_of(' '); + return header.substr(start, end - start + 1); + } -typedef struct rd_kw_struct rd_kw_type; +public: + template T at(size_t index) const { + if (index >= m_size) + throw std::invalid_argument(fmt::format( + "Invalid index lookup. kw:{} input_index:{} size:{}", + m_header, index, m_size)); + if (!m_data.has_value() || + !std::holds_alternative>(m_data.value())) + throw std::invalid_argument( + fmt::format("Keyword: {} is wrong type", m_header)); + return std::get>(m_data.value())[index]; + } + template T &at(size_t index) { + if (index >= m_size) + throw std::invalid_argument(fmt::format( + "Invalid index lookup. kw:{} input_index:{} size:{}", + m_header, index, m_size)); + if (!m_data.has_value() || + !std::holds_alternative>(m_data.value())) + throw std::invalid_argument( + fmt::format("Keyword: {} is wrong type", m_header)); + return std::get>(m_data.value())[index]; + } -typedef enum { RD_KW_READ_OK = 0, RD_KW_READ_FAIL = 1 } rd_read_status_enum; + /* Splits @s into ctype_size()-wide chunks (space-padded/truncated), + writing them into consecutive std::string elements starting at + @index. This mirrors the convention of storing strings longer + than 8 characters across consecutive RD_CHAR elements. */ + void set_string_array(size_t index, const std::string &s) { + size_t len = ctype_size() - 1; + size_t chunks = s.size() / len; + if ((s.size() % len) != 0) + chunks++; + for (size_t i = 0; i < chunks; i++) { + size_t offset = i * len; + size_t length = std::min(len, s.size() - offset); + set_padded(index + i, s.substr(offset, length)); + } + } -/* - The size of an rd_kw instance is denoted with an integer. The - choice of int to store the size obviously limits the maximum size to - INT_MAX elements. This choice is an historical mistake - it should - probably have been size_t; however the rd_kw datastructure is - tightly bound to the on-disk binary format supplied by Eclipse, and - there the number of elements is stored as a signed(?) 32 bit - integer - so using int for size does make some sense- -*/ + /** Inverse of set_string_array(): concatenates @count consecutive + ctype_size()-wide std::string elements starting at @index into a + single string. */ + [[nodiscard]] std::string get_string_array(size_t index, + size_t count) const { + std::string result; + size_t len = ctype_size() - 1; + result.reserve(count * len); + for (size_t i = 0; i < count; i++) + result += rd::pad_spaces(at(index + i), len); + return result; + } + double as_double(size_t index) const; -#define RD_KW_MAX_SIZE INT_MAX + KW(rd_data_type data_type) = delete; -/* - Character data in restart format files comes as an array of fixed-length - string. Each of these strings is 8 characters long. The type name, - i.e. 'REAL', 'INTE', ... , come as 4 character strings. -*/ -#define RD_KW_HEADER_DATA_SIZE RD_STRING8_LENGTH + RD_TYPE_LENGTH + 4 -#define RD_KW_HEADER_FORTIO_SIZE RD_KW_HEADER_DATA_SIZE + 8 + KW(const std::string &header, size_t size, rd_data_type data_type) + : m_size(size), m_data_type(data_type), m_header(strip_header(header)) { + zero_init_data(); + } -int rd_kw_first_different(const rd_kw_type *kw1, const rd_kw_type *kw2, - int offset, double abs_epsilon, double rel_epsilon); -size_t rd_kw_fortio_size(const rd_kw_type *rd_kw); -void *rd_kw_get_ptr(const rd_kw_type *rd_kw); -void rd_kw_set_data_ptr(rd_kw_type *rd_kw, void *data); -void rd_kw_fwrite_data(const rd_kw_type *_rd_kw, ERT::FortIO &fortio); + KW(const std::string &header, int size, rd_data_type data_type) + : m_data_type(data_type), m_header(strip_header(header)) { + if (size < 0) + throw std::invalid_argument( + fmt::format("rd_kw size was negative: {}", size)); + this->m_size = static_cast(size); + zero_init_data(); + } + + template + KW(const std::string &header, const std::vector &data) + : m_size(data.size()), m_data_type(datatype::tag), + m_header(strip_header(header)) { + m_data = data; + } + + KW(const std::string &header, + const std::initializer_list &data, + rd_data_type data_type = RD_CHAR) + : m_size(data.size()), m_data_type(data_type), + m_header(strip_header(header)) { + m_data = std::vector(m_size, ""); + size_t i = 0; + for (const auto &v : data) + set_padded(i++, v); + } + + KW(const KW &other) + : m_size(other.size()), m_data_type(other.data_type()), + m_header(other.header()) { + m_data = other.m_data; + } + KW(const KW &other, const std::optional &new_kw, size_t offset, + size_t count); + + KW(const rd::KW &other, size_t index1, size_t index2, size_t stride); + + static std::unique_ptr fread(ERT::FortIO &fortio); + /* Reads a selection of elements (given by @index_map) from the data + section of a single keyword, extracting them from m_data rather than + the legacy raw buffer. The @kw_offset argument is the byte offset of + the start of the keyword (i.e. its header) in the file, as stored by + rd_file_kw. */ + static void fread_indexed_data(ERT::FortIO &fortio, offset_type kw_offset, + rd_data_type data_type, int element_count, + const std::vector &index_map, + char *io_buffer); + static std::unique_ptr make_actnum(const rd::KW *porv_kw, + float porv_limit); + static std::unique_ptr global_copy(const rd::KW *src, + const rd::KW *actnum); + static std::unique_ptr fread_header(ERT::FortIO &); + [[nodiscard]] size_t size() const { return m_size; } + [[nodiscard]] rd_data_type data_type() const { return m_data_type; } + [[nodiscard]] size_t ctype_size() const { + return rd_type_get_sizeof_ctype(m_data_type); + }; + [[nodiscard]] size_t iotype_size() const { + return rd_type_get_sizeof_iotype(m_data_type); + }; + void resize(size_t new_size); + static bool fskip_data(rd_data_type data_type, const int element_count, + ERT::FortIO &fortio); + static void fskip_header(ERT::FortIO &fortio); + bool fwrite(ERT::FortIO &) const; + std::string header() const { return m_header; }; + void set_header(std::string header) { + this->m_header = strip_header(header); + } + [[nodiscard]] const std::optional &data() const { return m_data; } + + /* Checks that m_data holds a std::vector and returns a reference to + it. Throws std::invalid_argument otherwise (e.g. wrong type, or the + keyword's data isn't representable by rd_kw_data_variant, such as + RD_MESS_TYPE). */ + template + [[nodiscard]] const std::vector &get_vector() const { + if (!m_data.has_value() || + !std::holds_alternative>(m_data.value())) + throw std::invalid_argument( + fmt::format("Keyword: {} is wrong type", m_header)); + return std::get>(m_data.value()); + } + template [[nodiscard]] std::vector &get_vector() { + return const_cast &>( + const_cast(this)->get_vector()); + } + + /* Replaces this keyword's data with a copy of @src's data. Throws + std::invalid_argument if the size or type doesn't match. */ + void copy_data_from(const rd::KW &src) { + if (!rd_type_is_equal(m_data_type, src.data_type()) || + m_size != src.size()) + throw std::invalid_argument("type/size mismatch"); + m_data = src.m_data; + } + + /* Sets every element of the underlying std::vector in m_data to + @value. Throws std::invalid_argument if + there is a type mismatch between T and data_type(). */ + template void scalar_set(T value) { + auto &vec = get_vector(); + std::fill(vec.begin(), vec.end(), value); + } + + /** This function compares the data of two rd_kw instances, and + returns true if the relative numerical difference is less than + @rel_diff. */ + [[nodiscard]] bool approx_equal(const rd::KW &rd_kw2, double abs_diff, + double rel_diff) const; + + template void scale(T scale_factor) { + auto &vec = get_vector(); + std::transform(vec.begin(), vec.end(), vec.begin(), + [scale_factor](T x) { return x * scale_factor; }); + } + template void shift(T shift_value) { + auto &vec = get_vector(); + std::transform(vec.begin(), vec.end(), vec.begin(), + [shift_value](T x) { return x + shift_value; }); + } + + [[nodiscard]] size_t first_different(const rd::KW *kw2, size_t offset, + double abs_epsilon, + double rel_epsilon) const; + [[nodiscard]] size_t fortio_size() const; + void fwrite_data(ERT::FortIO &fortio) const; + + bool operator==(const KW &other) const; + void operator-=(const rd::KW &sub_kw); + bool size_and_type_equal(const rd::KW *rd_kw2) const; + bool size_and_numeric_type_equal(const rd::KW *kw2) const; + rd_type_enum get_type() const { return rd_type_get_type(data_type()); } + void fix_uninitialized(int nx, int ny, int nz, const int *actnum); + + void set_padded(size_t index, const std::string &v) { + size_t len = ctype_size() - 1; + if (v.size() > len) + throw std::invalid_argument(fmt::format( + "String of length {} cannot hold input string of length {}", + len, v.size())); + at(index) = rd::pad_spaces(v, len); + } +}; + +/* RD_BOOL_TYPE is stored as std::vector (0/1 values) in m_data - there + is no std::vector alternative. These specializations let callers use + at() like any other numeric type; the char/bool reference aliasing + is safe in practice since char values are always 0 or 1, a valid bool + bit-pattern. */ +template <> inline bool KW::at(size_t index) const { + if (index >= m_size) + throw std::invalid_argument( + fmt::format("Invalid index lookup. kw:{} input_index:{} size:{}", + m_header, index, m_size)); + if (!m_data.has_value() || + !std::holds_alternative>(m_data.value())) + throw std::invalid_argument( + fmt::format("Keyword: {} is wrong type", m_header)); + return std::get>(m_data.value())[index] != 0; +} + +template <> inline bool &KW::at(size_t index) { + if (index >= m_size) + throw std::invalid_argument( + fmt::format("Invalid index lookup. kw:{} input_index:{} size:{}", + m_header, index, m_size)); + if (!m_data.has_value() || + !std::holds_alternative>(m_data.value())) + throw std::invalid_argument( + fmt::format("Keyword: {} is wrong type", m_header)); + char &c = std::get>(m_data.value())[index]; + return reinterpret_cast(c); +} + +/* RD_BOOL_TYPE is stored as std::vector in m_data, so scalar_set + must fill the underlying std::vector instead of std::vector. */ +template <> inline void KW::scalar_set(bool value) { + auto &vec = get_vector(); + std::fill(vec.begin(), vec.end(), static_cast(value ? 1 : 0)); +} -namespace rd { /** Normalizes @x to a mantissa with absolute value in [0.1, 1.0) and a base-10 exponent, i.e. `x == mantissa * 10**exponent`. This matches Fortran's 'D'/'E' formatted output, which differs from the C/printf @@ -98,7 +350,7 @@ inline size_t format_kw_element_buf(char *buf, size_t buf_size, double value) { return static_cast(written); } -inline std::string format_kw_element_fmt(int width) { +inline std::string format_kw_element_fmt(size_t width) { return " '%-" + std::to_string(width) + "s'"; } @@ -133,225 +385,12 @@ inline std::string format_kw_element(double value) { return std::string(buffer, len); } -inline std::string format_kw_element(const char *value, int width = 8) { - std::vector buffer(static_cast(width) + 4); +inline std::string format_kw_element(const char *value, size_t width = 8) { + std::vector buffer(width + 4); const std::string fmt = format_kw_element_fmt(width); size_t len = format_kw_element_buf(buffer.data(), buffer.size(), value, fmt); return std::string(buffer.data(), len); } +int kw_get_size(const rd::KW *); } // namespace rd - -bool rd_kw_fread_realloc_data(rd_kw_type *rd_kw, ERT::FortIO &fortio); -rd_data_type rd_kw_get_data_type(const rd_kw_type *); -const char *rd_kw_get_header(const rd_kw_type *rd_kw); -rd_kw_type *rd_kw_alloc_empty(void); -rd_read_status_enum rd_kw_fread_header(rd_kw_type *, ERT::FortIO &); -void rd_kw_set_header_name(rd_kw_type *, const char *); -bool rd_kw_fseek_kw(const char *, bool, bool, ERT::FortIO &); -void rd_kw_fskip(ERT::FortIO &); -bool rd_kw_fread_realloc(rd_kw_type *, ERT::FortIO &); -rd_kw_type *rd_kw_fread_alloc(ERT::FortIO &); -rd_kw_type *rd_kw_alloc_actnum(const rd_kw_type *porv_kw, float porv_limit); -void rd_kw_fread_indexed_data(ERT::FortIO &fortio, offset_type kw_offset, - rd_data_type, int element_count, - const std::vector &index_map, char *buffer); -void rd_kw_free(rd_kw_type *); -rd_kw_type *rd_kw_alloc_copy(const rd_kw_type *); -rd_kw_type *rd_kw_alloc_sub_copy(const rd_kw_type *src, const char *new_kw, - int offset, int count); -rd_kw_type *rd_kw_alloc_slice_copy(const rd_kw_type *src, int index1, - int index2, int stride); -void rd_kw_resize(rd_kw_type *rd_kw, int new_size); -void rd_kw_memcpy(rd_kw_type *, const rd_kw_type *); -void rd_kw_get_memcpy_data(const rd_kw_type *, void *); -void rd_kw_set_memcpy_data(rd_kw_type *, const void *); -bool rd_kw_fwrite(const rd_kw_type *, ERT::FortIO &); -void rd_kw_iget(const rd_kw_type *, int, void *); -void rd_kw_iset(rd_kw_type *rd_kw, int i, const void *iptr); -void rd_kw_iset_char_ptr(rd_kw_type *rd_kw, int index, const char *s); -void rd_kw_iset_string8(rd_kw_type *rd_kw, int index, const char *s8); -void rd_kw_iset_string_ptr(rd_kw_type *, int, const char *); -const char *rd_kw_iget_string_ptr(const rd_kw_type *, int); -const char *rd_kw_iget_char_ptr(const rd_kw_type *rd_kw, int i); -void *rd_kw_iget_ptr(const rd_kw_type *, int); -int rd_kw_get_size(const rd_kw_type *); -rd_kw_type *rd_kw_alloc(const char *header, int size, rd_data_type); -rd_kw_type *rd_kw_alloc_new(const char *, int, rd_data_type, const void *); -rd_kw_type *rd_kw_alloc_new_shared(const char *, int, rd_data_type, void *); -rd_kw_type *rd_kw_alloc_global_copy(const rd_kw_type *src, - const rd_kw_type *actnum); -void rd_kw_summarize(const rd_kw_type *rd_kw); -double rd_kw_iget_as_double(const rd_kw_type *rd_kw, int i); -bool rd_kw_equal(const rd_kw_type *rd_kw1, const rd_kw_type *rd_kw2); -bool rd_kw_size_and_type_equal(const rd_kw_type *rd_kw1, - const rd_kw_type *rd_kw2); -bool rd_kw_icmp_string(const rd_kw_type *rd_kw, int index, - const char *other_string); -bool rd_kw_numeric_equal(const rd_kw_type *rd_kw1, const rd_kw_type *rd_kw2, - double abs_diff, double rel_diff); -bool rd_kw_data_equal(const rd_kw_type *rd_kw, const void *data); -bool rd_kw_content_equal(const rd_kw_type *rd_kw1, const rd_kw_type *rd_kw2); -bool rd_kw_fskip_data__(rd_data_type, int, ERT::FortIO &); -bool rd_kw_fskip_data(rd_kw_type *rd_kw, ERT::FortIO &fortio); -void rd_kw_fskip_header(ERT::FortIO &fortio); -bool rd_kw_size_and_numeric_type_equal(const rd_kw_type *kw1, - const rd_kw_type *kw2); -bool rd_kw_inplace_safe_div(rd_kw_type *target_kw, const rd_kw_type *divisor); -void rd_kw_inplace_sqrt(rd_kw_type *kw); - -int rd_kw_element_sum_int(const rd_kw_type *rd_kw); -double rd_kw_element_sum_float(const rd_kw_type *rd_kw); -void rd_kw_element_sum(const rd_kw_type *, void *); -void rd_kw_element_sum_indexed(const rd_kw_type *rd_kw, - const std::vector &index_list, void *_sum); -void rd_kw_max_min(const rd_kw_type *, void *, void *); -void *rd_kw_get_void_ptr(const rd_kw_type *rd_kw); - -void rd_kw_memcpy_data(rd_kw_type *target, const rd_kw_type *src); - -void rd_kw_scalar_set_float_or_double(rd_kw_type *rd_kw, double value); - -#define RD_KW_SCALAR_SET_TYPED_HEADER(ctype) \ - void rd_kw_scalar_set_##ctype(rd_kw_type *rd_kw, ctype value); -RD_KW_SCALAR_SET_TYPED_HEADER(int) -RD_KW_SCALAR_SET_TYPED_HEADER(float) -RD_KW_SCALAR_SET_TYPED_HEADER(double) -#undef RD_KW_SCALAR_SET_TYPED_HEADER - -rd_kw_type *rd_kw_alloc_scatter_copy(const rd_kw_type *src_kw, int target_size, - const int *mapping, void *def_value); - -void rd_kw_inplace_add_squared(rd_kw_type *target_kw, const rd_kw_type *add_kw); -void rd_kw_inplace_add(rd_kw_type *target_kw, const rd_kw_type *add_kw); -void rd_kw_inplace_sub(rd_kw_type *target_kw, const rd_kw_type *sub_kw); -void rd_kw_inplace_div(rd_kw_type *target_kw, const rd_kw_type *div_kw); -void rd_kw_inplace_mul(rd_kw_type *target_kw, const rd_kw_type *mul_kw); -void rd_kw_inplace_abs(rd_kw_type *kw); - -void rd_kw_inplace_add_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *add_kw); -void rd_kw_inplace_sub_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *sub_kw); -void rd_kw_inplace_mul_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *mul_kw); -void rd_kw_inplace_div_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *div_kw); -void rd_kw_copy_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *src_kw); - -bool rd_kw_assert_binary_numeric(const rd_kw_type *kw1, const rd_kw_type *kw2); -bool rd_kw_assert_numeric(const rd_kw_type *kw); -bool rd_kw_assert_binary(const rd_kw_type *kw1, const rd_kw_type *kw2); - -#define RD_KW_ASSERT_TYPED_BINARY_OP_HEADER(ctype) \ - bool rd_kw_assert_binary_##ctype(const rd_kw_type *kw1, \ - const rd_kw_type *kw2) -RD_KW_ASSERT_TYPED_BINARY_OP_HEADER(int); -RD_KW_ASSERT_TYPED_BINARY_OP_HEADER(float); -RD_KW_ASSERT_TYPED_BINARY_OP_HEADER(double); -#undef RD_KW_ASSERT_TYPED_BINARY_OP_HEADER - -#define RD_KW_SCALE_TYPED_HEADER(ctype) \ - void rd_kw_scale_##ctype(rd_kw_type *rd_kw, ctype scale_factor) -RD_KW_SCALE_TYPED_HEADER(int); -RD_KW_SCALE_TYPED_HEADER(float); -RD_KW_SCALE_TYPED_HEADER(double); -#undef RD_KW_SCALE_TYPED_HEADER -void rd_kw_scale_float_or_double(rd_kw_type *rd_kw, double scale_factor); - -#define RD_KW_SHIFT_TYPED_HEADER(ctype) \ - void rd_kw_shift_##ctype(rd_kw_type *rd_kw, ctype shift_factor) -RD_KW_SHIFT_TYPED_HEADER(int); -RD_KW_SHIFT_TYPED_HEADER(float); -RD_KW_SHIFT_TYPED_HEADER(double); -#undef RD_KW_SHIFT_TYPED_HEADER -void rd_kw_shift_float_or_double(rd_kw_type *rd_kw, double shift_value); - -#define RD_KW_IGET_TYPED_HEADER(type) \ - type rd_kw_iget_##type(const rd_kw_type *, int) -RD_KW_IGET_TYPED_HEADER(double); -RD_KW_IGET_TYPED_HEADER(float); -RD_KW_IGET_TYPED_HEADER(int); -#undef RD_KW_IGET_TYPED_HEADER -bool rd_kw_iget_bool(const rd_kw_type *rd_kw, int i); - -#define RD_KW_ISET_TYPED_HEADER(type) \ - void rd_kw_iset_##type(rd_kw_type *, int, type) -RD_KW_ISET_TYPED_HEADER(double); -RD_KW_ISET_TYPED_HEADER(float); -RD_KW_ISET_TYPED_HEADER(int); -#undef RD_KW_ISET_TYPED_HEADER -void rd_kw_iset_bool(rd_kw_type *rd_kw, int i, bool bool_value); - -#define RD_KW_GET_TYPED_PTR_HEADER(type) \ - type *rd_kw_get_##type##_ptr(const rd_kw_type *) -RD_KW_GET_TYPED_PTR_HEADER(double); -RD_KW_GET_TYPED_PTR_HEADER(float); -RD_KW_GET_TYPED_PTR_HEADER(int); -RD_KW_GET_TYPED_PTR_HEADER(bool); -#undef RD_KW_GET_TYPED_PTR_HEADER - -#define RD_KW_SET_INDEXED_HEADER(ctype) \ - void rd_kw_set_indexed_##ctype( \ - rd_kw_type *rd_kw, const std::vector &index_list, ctype value) -RD_KW_SET_INDEXED_HEADER(double); -RD_KW_SET_INDEXED_HEADER(float); -RD_KW_SET_INDEXED_HEADER(int); -#undef RD_KW_SET_INDEXED_HEADER - -#define RD_KW_SHIFT_INDEXED_HEADER(ctype) \ - void rd_kw_shift_indexed_##ctype( \ - rd_kw_type *rd_kw, const std::vector &index_list, ctype shift) -RD_KW_SHIFT_INDEXED_HEADER(int); -RD_KW_SHIFT_INDEXED_HEADER(float); -RD_KW_SHIFT_INDEXED_HEADER(double); -#undef RD_KW_SHIFT_INDEXED_HEADER - -#define RD_KW_SCALE_INDEXED_HEADER(ctype) \ - void rd_kw_scale_indexed_##ctype( \ - rd_kw_type *rd_kw, const std::vector &index_list, ctype scale) -RD_KW_SCALE_INDEXED_HEADER(int); -RD_KW_SCALE_INDEXED_HEADER(float); -RD_KW_SCALE_INDEXED_HEADER(double); -#undef RD_KW_SCALE_INDEXED_HEADER - -#define RD_KW_MAX_MIN_HEADER(ctype) \ - void rd_kw_max_min_##ctype(const rd_kw_type *rd_kw, ctype *_max, \ - ctype *_min) -RD_KW_MAX_MIN_HEADER(int); -RD_KW_MAX_MIN_HEADER(float); -RD_KW_MAX_MIN_HEADER(double); -#undef RD_KW_MAX_MIN_HEADER - -void rd_kw_fix_uninitialized(rd_kw_type *rd_kw, int nx, int ny, int nz, - const int *actnum); - -rd_type_enum rd_kw_get_type(const rd_kw_type *); - -using rd_kw_ptr = std::unique_ptr; -inline rd_kw_ptr make_rd_kw(const char *header, int size, - rd_data_type data_type) { - return {rd_kw_alloc(header, size, data_type), rd_kw_free}; -} - -inline rd_kw_ptr make_rd_kw() { return {rd_kw_alloc_empty(), rd_kw_free}; } - -inline rd_kw_ptr make_rd_kw(const char *header, int size, - rd_data_type data_type, const void *data) { - return {rd_kw_alloc_new(header, size, data_type, data), rd_kw_free}; -} - -inline std::string rd_kw_iget_stripped_string(const rd_kw_type *kw, int index) { - const char *raw = static_cast(rd_kw_iget_ptr(kw, index)); - const size_t width = rd_type_get_sizeof_iotype(rd_kw_get_data_type(kw)); - size_t len = 0; - while (len < width && raw[len] != '\0') - len++; - return rd::strip_spaces(std::string(raw, len)); -} diff --git a/lib/include/resdata/rd_region.hpp b/lib/include/resdata/rd_region.hpp index 1e3dfadaf..a939e9d8f 100644 --- a/lib/include/resdata/rd_region.hpp +++ b/lib/include/resdata/rd_region.hpp @@ -46,23 +46,21 @@ bool rd_region_contains_global(const rd_region_type *rd_region, bool rd_region_contains_active(const rd_region_type *rd_region, int active_index); -void rd_region_select_true(rd_region_type *region, const rd_kw_type *rd_kw); +void rd_region_select_true(rd_region_type *region, const rd::KW *rd_kw); void rd_region_invert_selection(rd_region_type *region); void rd_region_select_all(rd_region_type *region); void rd_region_deselect_all(rd_region_type *region); -void rd_region_select_false(rd_region_type *region, const rd_kw_type *rd_kw); +void rd_region_select_false(rd_region_type *region, const rd::KW *rd_kw); -void rd_region_select_in_interval(rd_region_type *region, - const rd_kw_type *rd_kw, float min_value, - float max_value); -void rd_region_deselect_in_interval(rd_region_type *region, - const rd_kw_type *rd_kw, float min_value, - float max_value); +void rd_region_select_in_interval(rd_region_type *region, const rd::KW *rd_kw, + float min_value, float max_value); +void rd_region_deselect_in_interval(rd_region_type *region, const rd::KW *rd_kw, + float min_value, float max_value); -void rd_region_select_equal(rd_region_type *region, const rd_kw_type *rd_kw, +void rd_region_select_equal(rd_region_type *region, const rd::KW *rd_kw, int value); -void rd_region_deselect_equal(rd_region_type *region, const rd_kw_type *rd_kw, +void rd_region_deselect_equal(rd_region_type *region, const rd::KW *rd_kw, int value); void rd_region_select_inactive_cells(rd_region_type *region); @@ -107,23 +105,23 @@ void rd_region_intersection(rd_region_type *region, void rd_region_union(rd_region_type *region, const rd_region_type *new_region); void rd_region_subtract(rd_region_type *region, const rd_region_type *new_region); -void rd_region_select_smaller(rd_region_type *rd_region, - const rd_kw_type *rd_kw, float limit); -void rd_region_deselect_smaller(rd_region_type *rd_region, - const rd_kw_type *rd_kw, float limit); -void rd_region_select_larger(rd_region_type *rd_region, const rd_kw_type *rd_kw, +void rd_region_select_smaller(rd_region_type *rd_region, const rd::KW *rd_kw, + float limit); +void rd_region_deselect_smaller(rd_region_type *rd_region, const rd::KW *rd_kw, + float limit); +void rd_region_select_larger(rd_region_type *rd_region, const rd::KW *rd_kw, float limit); -void rd_region_deselect_larger(rd_region_type *rd_region, - const rd_kw_type *rd_kw, float limit); - -void rd_region_cmp_select_less(rd_region_type *rd_region, const rd_kw_type *kw1, - const rd_kw_type *kw2); -void rd_region_cmp_deselect_less(rd_region_type *rd_region, - const rd_kw_type *kw1, const rd_kw_type *kw2); -void rd_region_cmp_select_more(rd_region_type *rd_region, const rd_kw_type *kw1, - const rd_kw_type *kw2); -void rd_region_cmp_deselect_more(rd_region_type *rd_region, - const rd_kw_type *kw1, const rd_kw_type *kw2); +void rd_region_deselect_larger(rd_region_type *rd_region, const rd::KW *rd_kw, + float limit); + +void rd_region_cmp_select_less(rd_region_type *rd_region, const rd::KW *kw1, + const rd::KW *kw2); +void rd_region_cmp_deselect_less(rd_region_type *rd_region, const rd::KW *kw1, + const rd::KW *kw2); +void rd_region_cmp_select_more(rd_region_type *rd_region, const rd::KW *kw1, + const rd::KW *kw2); +void rd_region_cmp_deselect_more(rd_region_type *rd_region, const rd::KW *kw1, + const rd::KW *kw2); void rd_region_select_above_plane(rd_region_type *region, const double n[3], const double p[3]); @@ -147,51 +145,79 @@ void rd_region_select_from_layer(rd_region_type *region, const layer_type *layer, int k, int layer_value); -void rd_region_set_kw_int(rd_region_type *rd_region, rd_kw_type *rd_kw, - int value, bool force_active); -void rd_region_set_kw_float(rd_region_type *rd_region, rd_kw_type *rd_kw, - float value, bool force_active); -void rd_region_set_kw_double(rd_region_type *rd_region, rd_kw_type *rd_kw, - double value, bool force_active); -void rd_region_kw_copy(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *src_kw, bool force_active); - -void rd_region_kw_iadd(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *delta_kw, bool force_active); -void rd_region_kw_idiv(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *div_kw, bool force_active); -void rd_region_kw_imul(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *mul_kw, bool force_active); -void rd_region_kw_isub(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *delta_kw, bool force_active); +void rd_region_kw_copy(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *src_kw, bool force_active); + +void rd_region_kw_iadd(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *delta_kw, bool force_active); +void rd_region_kw_idiv(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *div_kw, bool force_active); +void rd_region_kw_imul(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *mul_kw, bool force_active); +void rd_region_kw_isub(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *delta_kw, bool force_active); bool rd_region_equal(const rd_region_type *region1, const rd_region_type *region2); -void rd_region_scale_kw_float(rd_region_type *rd_region, rd_kw_type *rd_kw, - float value, bool force_active); -void rd_region_scale_kw_double(rd_region_type *rd_region, rd_kw_type *rd_kw, - double value, bool force_active); -void rd_region_scale_kw_int(rd_region_type *rd_region, rd_kw_type *rd_kw, - int value, bool force_active); -void rd_region_shift_kw_int(rd_region_type *rd_region, rd_kw_type *rd_kw, - int value, bool force_active); -void rd_region_shift_kw_double(rd_region_type *rd_region, rd_kw_type *rd_kw, - double value, bool force_active); -void rd_region_shift_kw_float(rd_region_type *rd_region, rd_kw_type *rd_kw, - float value, bool force_active); - const std::vector &rd_region_get_kw_index_list(rd_region_type *rd_region, - const rd_kw_type *rd_kw, + const rd::KW *rd_kw, bool force_active); void rd_region_set_name(rd_region_type *region, const std::optional &name); std::optional rd_region_get_name(const rd_region_type *region); -double rd_region_sum_kw_double(rd_region_type *rd_region, - const rd_kw_type *rd_kw, bool force_active); -int rd_region_sum_kw_int(rd_region_type *rd_region, const rd_kw_type *rd_kw, - bool force_active); -float rd_region_sum_kw_float(rd_region_type *rd_region, const rd_kw_type *rd_kw, - bool force_active); +template +T rd_region_sum_kw(rd_region_type *rd_region, const rd::KW *rd_kw, + bool force_active) { + const std::vector &index_set = + rd_region_get_kw_index_list(rd_region, rd_kw, force_active); + auto data = rd_kw->get_vector(); + T sum{}; + for (const auto i : index_set) + sum += data[i]; + return sum; +} + +inline int rd_region_sum_kw_bool(rd_region_type *rd_region, const rd::KW *rd_kw, + bool force_active) { + const std::vector &index_set = + rd_region_get_kw_index_list(rd_region, rd_kw, force_active); + auto data = rd_kw->get_vector(); + int sum = 0; + for (const auto i : index_set) + if (data[i] != 0) + sum += 1; + return sum; +} + +template +void rd_region_scale_kw(rd_region_type *rd_region, rd::KW *rd_kw, T value, + bool force_active) { + const std::vector &index_set = + rd_region_get_kw_index_list(rd_region, rd_kw, force_active); + auto &data = rd_kw->get_vector(); + for (const auto i : index_set) + data[i] *= value; +} + +template +void rd_region_shift_kw(rd_region_type *rd_region, rd::KW *rd_kw, T value, + bool force_active) { + const std::vector &index_set = + rd_region_get_kw_index_list(rd_region, rd_kw, force_active); + auto &data = rd_kw->get_vector(); + for (const auto i : index_set) + data[i] += value; +} + +template +void rd_region_set_kw(rd_region_type *rd_region, rd::KW *rd_kw, T value, + bool force_active) { + const std::vector &index_set = + rd_region_get_kw_index_list(rd_region, rd_kw, force_active); + auto &data = rd_kw->get_vector(); + for (const auto i : index_set) + data[i] = value; +} diff --git a/lib/include/resdata/rd_rsthead.hpp b/lib/include/resdata/rd_rsthead.hpp index 209ce8b61..7b930d05f 100644 --- a/lib/include/resdata/rd_rsthead.hpp +++ b/lib/include/resdata/rd_rsthead.hpp @@ -1,5 +1,7 @@ #pragma once #include +#include +#include #include @@ -73,15 +75,15 @@ struct RSTHead { nisegz(nisegz), nsegmx(nsegmx), nswlmx(nswlmx), nlbrmx(nlbrmx), nilbrz(nilbrz), nrsegz(nrsegz), dualp(dualp), sim_days(sim_days) {}; - inline RSTHead(int report_step, const rd_kw_type *intehead_kw, - const rd_kw_type *doubhead_kw, const rd_kw_type *logihead_kw) + inline RSTHead(int report_step, const rd::KW *intehead_kw, + const rd::KW *doubhead_kw, const rd::KW *logihead_kw) : report_step(report_step), - sim_days(rd_kw_iget_double(doubhead_kw, DOUBHEAD_DAYS_INDEX)) { + sim_days(doubhead_kw->at(DOUBHEAD_DAYS_INDEX)) { - int nihead = rd_kw_get_size(intehead_kw); - const int *data = (const int *)rd_kw_get_void_ptr(intehead_kw); + const std::vector &data = intehead_kw->get_vector(); + int nihead = static_cast(data.size()); - auto get = [data, nihead](int index) { + auto get = [&data, nihead](int index) { return index < nihead ? data[index] : 0; }; @@ -117,22 +119,22 @@ struct RSTHead { this->sim_time = rd_make_date(this->day, this->month, this->year); if (logihead_kw) - this->dualp = rd_kw_iget_bool(logihead_kw, LOGIHEAD_DUALP_INDEX); + this->dualp = logihead_kw->at(LOGIHEAD_DUALP_INDEX); else this->dualp = false; } 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; + const rd::KW *intehead_kw = rst_view->get_kw(INTEHEAD_KW, 0); + const rd::KW *doubhead_kw = rst_view->get_kw(DOUBHEAD_KW, 0); + const rd::KW *logihead_kw = NULL; if (rst_view->has_kw(LOGIHEAD_KW)) logihead_kw = rst_view->get_kw(LOGIHEAD_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); + const rd::KW *seqnum_kw = rst_view->get_kw(SEQNUM_KW, 0); + report_step = seqnum_kw->at(0); } return {report_step, intehead_kw, doubhead_kw, logihead_kw}; diff --git a/lib/include/resdata/rd_sum_tstep.hpp b/lib/include/resdata/rd_sum_tstep.hpp index 048fc825e..bf11e3f9c 100644 --- a/lib/include/resdata/rd_sum_tstep.hpp +++ b/lib/include/resdata/rd_sum_tstep.hpp @@ -15,7 +15,7 @@ typedef struct rd_sum_tstep_struct rd_sum_tstep_type; void rd_sum_tstep_free(rd_sum_tstep_type *ministep); rd_sum_tstep_type *rd_sum_tstep_alloc_from_file(int report_step, int ministep_nr, - const rd_kw_type *params_kw, + const rd::KW *params_kw, const char *src_file, const rd_smspec_type *smspec); diff --git a/lib/include/resdata/rd_type.hpp b/lib/include/resdata/rd_type.hpp index a6b8d5fb5..0d2f7f12b 100644 --- a/lib/include/resdata/rd_type.hpp +++ b/lib/include/resdata/rd_type.hpp @@ -108,6 +108,24 @@ template <> struct iotype { static constexpr rd_type_enum tag = RD_INT_TYPE; }; +template struct datatype { + static_assert(always_false, + "Type cannot be read element-wise from a keyword data " + "section; expected float, double or int"); +}; + +template <> struct datatype { + static constexpr rd_data_type tag = RD_FLOAT; +}; + +template <> struct datatype { + static constexpr rd_data_type tag = RD_DOUBLE; +}; + +template <> struct datatype { + static constexpr rd_data_type tag = RD_INT; +}; + /** Asserts that the keyword named @kw holds data of type @expected. The keyword types of the restart and summary formats are fixed by the diff --git a/lib/include/resdata/rd_util.hpp b/lib/include/resdata/rd_util.hpp index b04f9ca33..fa1e8ede6 100644 --- a/lib/include/resdata/rd_util.hpp +++ b/lib/include/resdata/rd_util.hpp @@ -168,6 +168,16 @@ inline std::string strip_spaces(std::string_view s) { return std::string(s.substr(first, last - first + 1)); } +/** Fits @s to exactly @width characters: pads with trailing spaces if + shorter, truncates if longer. */ +inline std::string pad_spaces(std::string_view s, size_t width) { + if (s.size() >= width) + return std::string(s.substr(0, width)); + std::string result(s); + result.append(width - s.size(), ' '); + return result; +} + /** Compares two strings in "natural" order: maximal runs of digits are compared by numeric value, so that "S9" sorts before "S10", while all other characters are compared bytewise. diff --git a/lib/include/resdata/well/well_conn.hpp b/lib/include/resdata/well/well_conn.hpp index f16ef5b5d..f9f5b46e4 100644 --- a/lib/include/resdata/well/well_conn.hpp +++ b/lib/include/resdata/well/well_conn.hpp @@ -61,12 +61,11 @@ class WellConnection { } static std::shared_ptr - from_keywords(const rd_kw_type *icon_kw, const rd_kw_type *scon_kw, - const rd_kw_type *xcon_kw, const RSTHead &header, int well_nr, + from_keywords(const rd::KW *icon_kw, const rd::KW *scon_kw, + const rd::KW *xcon_kw, const RSTHead &header, int well_nr, int conn_nr); static std::shared_ptr - read_wellhead(const rd_kw_type *iwel_kw, const RSTHead &header, - int well_nr); + read_wellhead(const rd::KW *iwel_kw, const RSTHead &header, int well_nr); [[nodiscard]] bool is_MSW() const { return segment_id != WELL_CONN_NORMAL_WELL_SEGMENT_ID; } diff --git a/lib/include/resdata/well/well_segment.hpp b/lib/include/resdata/well/well_segment.hpp index 9d7f606d8..0e37f3b09 100644 --- a/lib/include/resdata/well/well_segment.hpp +++ b/lib/include/resdata/well/well_segment.hpp @@ -34,7 +34,7 @@ class WellSegment { outlet_segment_id(outlet_segment_id), depth(depth), length(length), total_length(total_length), diameter(diameter) {}; static std::shared_ptr - from_kw(const rd_kw_type *iseg_kw, well_rseg_loader_type *rseg_loader, + from_kw(const rd::KW *iseg_kw, well_rseg_loader_type *rseg_loader, const RSTHead &header, int well_nr, int segment_index, int segment_id); [[nodiscard]] bool is_active() const { @@ -79,5 +79,5 @@ class WellSegment { } }; -bool well_segment_well_is_MSW(int well_nr, const rd_kw_type *iwel_kw, +bool well_segment_well_is_MSW(int well_nr, const rd::KW *iwel_kw, const RSTHead &rst_head); diff --git a/lib/include/resdata/well/well_segment_collection.hpp b/lib/include/resdata/well/well_segment_collection.hpp index 29c820f42..98f62cdee 100644 --- a/lib/include/resdata/well/well_segment_collection.hpp +++ b/lib/include/resdata/well/well_segment_collection.hpp @@ -34,7 +34,7 @@ void well_segment_collection_add_branches( int well_segment_collection_load_from_kw( well_segment_collection_type *segment_collection, int well_nr, - const rd_kw_type *iwel_kw, const rd_kw_type *iseg_kw, + const rd::KW *iwel_kw, const rd::KW *iseg_kw, well_rseg_loader_type *rseg_loader, const RSTHead &rst_head, bool load_segment_information, bool *is_MSW_well); void well_segment_collection_add_connections( diff --git a/lib/include/resdata/well/well_state.hpp b/lib/include/resdata/well/well_state.hpp index cdbe36011..ec04589e5 100644 --- a/lib/include/resdata/well/well_state.hpp +++ b/lib/include/resdata/well/well_state.hpp @@ -123,10 +123,10 @@ class WellState { std::map> name_wellhead; // A WellConnection for the wellhead - indexed by lgr_name. - void add_wellhead(const RSTHead &header, const rd_kw_type *iwel_kw, - int well_nr, const std::string &grid_name, int grid_nr); + void add_wellhead(const RSTHead &header, const rd::KW *iwel_kw, int well_nr, + const std::string &grid_name, int grid_nr); bool add_rates(rd::FileView *rst_view, int well_nr); - int get_lgr_well_nr(rd::FileView *file_view); + std::optional 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); diff --git a/lib/resdata/FortIO.cpp b/lib/resdata/FortIO.cpp index 5ac6988b4..4d9d0bf1f 100644 --- a/lib/resdata/FortIO.cpp +++ b/lib/resdata/FortIO.cpp @@ -1,5 +1,8 @@ #include -#include +#include +#include +#include +#include #include #include #include @@ -7,6 +10,7 @@ #include #include +#include #include #include #include @@ -17,59 +21,47 @@ #include -#define READ_MODE_TXT "r" -#define READ_MODE_BINARY "rb" -#define WRITE_MODE_TXT "w" -#define WRITE_MODE_BINARY "wb" -#define READ_WRITE_MODE_TXT "r+" -#define READ_WRITE_MODE_BINARY "r+b" -#define APPEND_MODE_TXT "a" -#define APPEND_MODE_BINARY "ab" - /* Observe that the stream open functions accept a failure, and call the fopen() function directly. */ -static const char *fortio_fopen_read_mode(bool fmt_file) { - if (fmt_file) - return READ_MODE_TXT; - else - return READ_MODE_BINARY; -} - -static const char *fortio_fopen_write_mode(bool fmt_file) { - if (fmt_file) - return WRITE_MODE_TXT; - else - return WRITE_MODE_BINARY; -} +static std::ios_base::openmode fortio_open_mode(std::ios_base::openmode mode, + bool fmt_file, + const std::string &filename) { + std::ios_base::openmode result; + if (mode == (std::ios_base::in | std::ios_base::out)) { + result = std::ios_base::in | std::ios_base::out; + } else if (mode == std::ios_base::in) { + if (util_file_exists(filename.c_str())) + result = std::ios_base::in; + else + throw std::ios_base::failure("File " + filename + + " does not exist"); + } else if (mode == std::ios_base::app) { + result = std::ios_base::out | std::ios_base::app; + } else { + result = std::ios_base::out | std::ios_base::trunc; + } -static const char *fortio_fopen_readwrite_mode(bool fmt_file) { - if (fmt_file) - return READ_WRITE_MODE_TXT; - else - return READ_WRITE_MODE_BINARY; -} + if (!fmt_file) + result |= std::ios_base::binary; -static const char *fortio_fopen_append_mode(bool fmt_file) { - if (fmt_file) - return APPEND_MODE_TXT; - else - return APPEND_MODE_BINARY; + return result; } /** Helper function for fortio_is_fortran_stream__(). */ -static bool __read_int(FILE *stream, int *value, bool endian_flip) { - /* This fread() can fail - can not use util_fread() here. */ - if (fread(value, sizeof *value, 1, stream) == 1) { +static bool __read_int(std::istream &stream, int *value, bool endian_flip) { + if (stream.read(reinterpret_cast(value), sizeof *value)) { if (endian_flip) util_endian_flip_vector(value, sizeof *value, 1); return true; - } else + } else { + stream.clear(); return false; + } } /** @@ -77,10 +69,10 @@ static bool __read_int(FILE *stream, int *value, bool endian_flip) { particular stream is formatted according to fortran io, for a fixed endianness. */ -static bool fortio_is_fortran_stream__(FILE *stream, bool endian_flip) { +static bool fortio_is_fortran_stream__(std::istream &stream, bool endian_flip) { const bool strict_checking = true; /* True: requires that *ALL* records in the file are fortran formatted */ - offset_type init_pos = util_ftell(stream); + offset_type init_pos = stream.tellg(); bool is_fortran_stream = false; int header, tail; bool cont; @@ -89,7 +81,9 @@ static bool fortio_is_fortran_stream__(FILE *stream, bool endian_flip) { cont = false; if (__read_int(stream, &header, endian_flip)) { if (header >= 0) { - if (util_fseek(stream, (offset_type)header, SEEK_CUR) == 0) { + stream.seekg(static_cast(header), + std::ios_base::cur); + if (stream.good()) { if (__read_int(stream, &tail, endian_flip)) { cont = true; // Read a header and a tail so it might be a fortran file. @@ -113,7 +107,8 @@ static bool fortio_is_fortran_stream__(FILE *stream, bool endian_flip) { } } } while (cont); - util_fseek(stream, init_pos, SEEK_SET); + stream.clear(); + stream.seekg(init_pos, std::ios_base::beg); return is_fortran_stream; } @@ -124,26 +119,14 @@ FortIO::FortIO(const std::string &filename, std::ios_base::openmode mode, open(filename, mode, fmt_file, endian_flip_header); } -FortIO::FortIO(const std::string &filename, bool fmt_file, bool writable, - FILE *stream, bool endian_flip_header) { - m_filename = filename; - m_endian_flip_header = endian_flip_header; - m_fmt_file = fmt_file; - m_stream_owner = false; - m_writable = writable; - m_read_size = 0; - m_stream = stream; -} - FortIO::~FortIO() { close(); } FortIO::FortIO(FortIO &&other) noexcept - : m_stream(std::exchange(other.m_stream, nullptr)), + : m_stream(std::move(other.m_stream)), m_filename(std::move(other.m_filename)), m_endian_flip_header(std::exchange(other.m_endian_flip_header, false)), m_fmt_file(std::exchange(other.m_fmt_file, false)), - m_fopen_mode(std::exchange(other.m_fopen_mode, nullptr)), - m_stream_owner(std::exchange(other.m_stream_owner, false)), + m_open_mode(std::exchange(other.m_open_mode, std::ios_base::openmode{})), m_writable(std::exchange(other.m_writable, false)), m_read_size(std::exchange(other.m_read_size, 0)) { other.m_filename = ""; @@ -155,12 +138,11 @@ FortIO &FortIO::operator=(FortIO &&other) noexcept { close(); - m_stream = std::exchange(other.m_stream, nullptr); + m_stream = std::move(other.m_stream); m_filename = std::move(other.m_filename); m_endian_flip_header = std::exchange(other.m_endian_flip_header, false); m_fmt_file = std::exchange(other.m_fmt_file, false); - m_fopen_mode = std::exchange(other.m_fopen_mode, nullptr); - m_stream_owner = std::exchange(other.m_stream_owner, false); + m_open_mode = std::exchange(other.m_open_mode, std::ios_base::openmode{}); m_writable = std::exchange(other.m_writable, false); m_read_size = std::exchange(other.m_read_size, 0); @@ -171,42 +153,30 @@ FortIO &FortIO::operator=(FortIO &&other) noexcept { void FortIO::open(const std::string &filename, std::ios_base::openmode mode, bool fmt_file, bool endian_flip_header) { - const char *cmode; - if (mode == (std::ios_base::in | std::ios_base::out)) { - cmode = fortio_fopen_readwrite_mode(fmt_file); - } else if (mode == std::ios_base::in) { - if (util_file_exists(filename.c_str())) { - cmode = fortio_fopen_read_mode(fmt_file); - } else - throw std::ios_base::failure("File " + filename + - " does not exist"); - } else if (mode == std::ios_base::app) { - cmode = fortio_fopen_append_mode(fmt_file); - } else { - cmode = fortio_fopen_write_mode(fmt_file); - } + std::ios_base::openmode open_mode = + fortio_open_mode(mode, fmt_file, filename); - FILE *stream = fopen(filename.c_str(), cmode); - if (!stream) + std::fstream stream(filename, open_mode); + if (!stream.is_open()) throw std::ios_base::failure("Failed to open FortIO file " + filename); + m_filename = filename; m_endian_flip_header = endian_flip_header; m_fmt_file = fmt_file; - m_stream_owner = true; m_writable = (mode & std::ios_base::out) || (mode & std::ios_base::app); m_read_size = 0; - m_stream = stream; - m_fopen_mode = cmode; - m_read_size = util_fd_size(fileno(m_stream)); + m_stream = std::move(stream); + m_open_mode = open_mode; + m_read_size = + static_cast(std::filesystem::file_size(filename)); } void FortIO::close() { - if (m_stream && m_stream_owner) - fclose(m_stream); - m_stream = nullptr; + if (m_stream.is_open()) + m_stream.close(); + m_stream = std::fstream(); m_filename = ""; - m_fopen_mode = nullptr; - m_stream_owner = false; + m_open_mode = std::ios_base::openmode{}; m_writable = false; m_read_size = 0; } @@ -228,51 +198,35 @@ void FortIO::close() { zeroes. In that case it is difficult to determine, and we continue. */ bool FortIO::looks_like_fortran_file(const char *filename, bool endian_flip) { - std::unique_ptr stream{fopen(filename, "rb"), - [](FILE *f) { fclose(f); }}; - if (!stream) + std::ifstream stream(filename, std::ios_base::binary); + if (!stream.is_open()) throw std::system_error(errno, std::generic_category(), "looks_like_fortran_file: failed to open file"); - bool is_fortran_stream = - fortio_is_fortran_stream__(stream.get(), endian_flip); + bool is_fortran_stream = fortio_is_fortran_stream__(stream, endian_flip); return is_fortran_stream; } bool FortIO::fclose_stream() { - if (m_stream_owner) { - if (m_stream) { - int fclose_return = fclose(m_stream); - m_stream = nullptr; - if (fclose_return == 0) - return true; - else - return false; - } else - return false; // Already closed. + if (m_stream.is_open()) { + m_stream.close(); + return !m_stream.fail(); } else - return false; + return false; // Already closed. } bool FortIO::fopen_stream() { - if (m_stream == nullptr) { - m_stream = fopen(m_filename.c_str(), m_fopen_mode); - if (m_stream) - return true; - else - return false; + if (!m_stream.is_open()) { + m_stream.clear(); + m_stream.open(m_filename, m_open_mode); + return m_stream.is_open(); } else return false; } -bool FortIO::stream_is_open() const { - if (m_stream) - return true; - else - return false; -} +bool FortIO::stream_is_open() const { return m_stream.is_open(); } bool FortIO::assert_stream_open() { - if (m_stream) + if (m_stream.is_open()) return true; else { fopen_stream(); @@ -287,20 +241,21 @@ bool FortIO::assert_stream_open() { it will return -1. */ int FortIO::init_read() { - int elm_read; int record_size; - - elm_read = fread(&record_size, sizeof(record_size), 1, m_stream); - if (elm_read == 1) { + if (m_stream.read(reinterpret_cast(&record_size), + sizeof record_size)) { if (m_endian_flip_header) util_endian_flip_vector(&record_size, sizeof record_size, 1); return record_size; - } else + } else { + m_stream.clear(); return -1; + } } -bool FortIO::data_fskip(int element_size, int element_count, int block_count) { +bool FortIO::data_fskip(size_t element_size, size_t element_count, + size_t block_count) { offset_type headers = static_cast(block_count) * 4; offset_type trailers = static_cast(block_count) * 4; offset_type bytes_to_skip = @@ -312,7 +267,7 @@ bool FortIO::data_fskip(int element_size, int element_count, int block_count) { void FortIO::data_fseek(offset_type data_offset, size_t data_element, size_t element_size, int element_count, - int block_size) { + size_t block_size) { if (element_count < 0 || data_element >= static_cast(element_count)) throw std::invalid_argument( fmt::format("Element index is out of range: 0 <= {} < {}", @@ -330,28 +285,30 @@ void FortIO::data_fseek(offset_type data_offset, size_t data_element, } int FortIO::fclean() { - long current_pos = ::ftell(m_stream); - if (current_pos == -1) + offset_type current_pos = m_stream.tellg(); + if (current_pos == static_cast(-1)) return -1; - int flush_status = ::fflush(m_stream); - if (flush_status != 0) - return flush_status; + m_stream.flush(); + if (!m_stream) + return -1; - return ::fseek(m_stream, current_pos, SEEK_SET); + m_stream.clear(); + m_stream.seekg(current_pos, std::ios_base::beg); + m_stream.seekp(current_pos, std::ios_base::beg); + return m_stream.good() ? 0 : -1; } bool FortIO::complete_read(int record_size) { int trailer; - size_t read_count = fread(&trailer, sizeof trailer, 1, m_stream); - - if (read_count == 1) { + if (m_stream.read(reinterpret_cast(&trailer), sizeof trailer)) { if (m_endian_flip_header) util_endian_flip_vector(&trailer, sizeof trailer, 1); if (record_size == trailer) return true; - } + } else + m_stream.clear(); return false; } @@ -374,10 +331,14 @@ bool FortIO::fread_buffer(char *buffer, int buffer_size) { return false; if (end - itr < static_cast(record_size)) return false; - size_t items_read = 0; - if (record_size > 0) - items_read = fread(itr, 1, record_size, m_stream); - if (items_read != static_cast(record_size) || + std::streamsize items_read = 0; + if (record_size > 0) { + m_stream.read(itr, record_size); + items_read = m_stream.gcount(); + if (items_read != record_size) + m_stream.clear(); + } + if (items_read != static_cast(record_size) || !complete_read(record_size)) return false; itr += record_size; @@ -398,7 +359,8 @@ void FortIO::init_write(int record_size) { if (m_endian_flip_header) util_endian_flip_vector(&file_header, sizeof file_header, 1); - util_fwrite_int(file_header, m_stream); + m_stream.write(reinterpret_cast(&file_header), + sizeof file_header); } void FortIO::complete_write(int record_size) { @@ -406,23 +368,42 @@ void FortIO::complete_write(int record_size) { if (m_endian_flip_header) util_endian_flip_vector(&file_header, sizeof file_header, 1); - util_fwrite_int(file_header, m_stream); + m_stream.write(reinterpret_cast(&file_header), + sizeof file_header); } void FortIO::fwrite_record(const char *buffer, int record_size) { init_write(record_size); - util_fwrite(buffer, 1, record_size, m_stream, __func__); + m_stream.write(buffer, record_size); + if (!m_stream) + throw std::runtime_error(fmt::format( + "{}: failed to write {} bytes to disk", __func__, record_size)); complete_write(record_size); } -offset_type FortIO::ftell() const { return util_ftell(m_stream); } +offset_type FortIO::ftell() const { return m_stream.tellg(); } bool FortIO::fseek_(offset_type offset, int whence) { - int fseek_return = util_fseek(m_stream, offset, whence); - if (fseek_return == 0) - return true; - else + m_stream.clear(); + switch (whence) { + case SEEK_SET: + m_stream.seekg(offset, std::ios_base::beg); + m_stream.seekp(offset, std::ios_base::beg); + break; + case SEEK_END: + m_stream.seekg(offset, std::ios_base::end); + m_stream.seekp(offset, std::ios_base::end); + break; + case SEEK_CUR: { + offset_type target = ftell() + offset; + m_stream.seekg(target, std::ios_base::beg); + m_stream.seekp(target, std::ios_base::beg); + break; + } + default: return false; + } + return m_stream.good(); } /** @@ -463,9 +444,28 @@ bool FortIO::fseek(offset_type offset, int whence) { } } -bool FortIO::ftruncate(offset_type size) { - fseek(size, SEEK_SET); - return util_ftruncate(m_stream, size); +bool FortIO::ftruncate(std::uintmax_t size) { + if (size > + static_cast(std::numeric_limits::max())) + throw std::invalid_argument( + "Size to ftruncate exceeded std::streamoff size"); + std::streamoff offset = static_cast(size); + + if (!m_writable) + return false; + + // Resize the file on disk directly; no need to close/reopen the stream + // since resize_file() operates on the path, not the open file handle. + m_stream.flush(); + + std::error_code ec; + std::filesystem::resize_file(m_filename, size, ec); + if (ec) + return false; + + m_stream.clear(); + + return fseek(offset, SEEK_SET); } /** @@ -490,10 +490,15 @@ void FortIO::fwrite_error() { std::filesystem::remove(m_filename); } -void FortIO::fflush() const { ::fflush(m_stream); } -FILE *FortIO::get_FILE() const { return m_stream; } +void FortIO::fflush() const { m_stream.flush(); } +std::istream &FortIO::get_istream() { return m_stream; } +std::ostream &FortIO::get_ostream() { return m_stream; } bool FortIO::fmt_file() const { return m_fmt_file; } -void FortIO::rewind() const { util_rewind(m_stream); } +void FortIO::rewind() const { + m_stream.clear(); + m_stream.seekg(0, std::ios_base::beg); + m_stream.seekp(0, std::ios_base::beg); +} const char *FortIO::filename_ref() const { return m_filename.c_str(); } } // namespace ERT diff --git a/lib/resdata/cwrap_pybind.cpp b/lib/resdata/cwrap_pybind.cpp index c91a6638c..8c30f8aa4 100644 --- a/lib/resdata/cwrap_pybind.cpp +++ b/lib/resdata/cwrap_pybind.cpp @@ -43,21 +43,21 @@ py::object ResdataKW() { return cls; } -template <> rd_kw_type *from_cwrap(py::handle obj) { +template <> rd::KW *from_cwrap(py::handle obj) { if (!py::isinstance(obj, ResdataKW())) throw py::type_error("Expected ResdataKW, got " + static_cast(py::repr(obj))); - return cast_cwrap(obj); + return cast_cwrap(obj); } -template <> rd_kw_type *from_cwrap(std::optional obj) { +template <> rd::KW *from_cwrap(std::optional obj) { if (!obj) return nullptr; if (!py::isinstance(*obj, ResdataKW())) throw py::type_error("Expected ResdataKW, got " + static_cast(py::repr(*obj))); - return cast_cwrap(*obj); + return cast_cwrap(*obj); } py::object Grid() { diff --git a/lib/resdata/fault_block_layer.cpp b/lib/resdata/fault_block_layer.cpp index 98ca3efe2..1ba93230a 100644 --- a/lib/resdata/fault_block_layer.cpp +++ b/lib/resdata/fault_block_layer.cpp @@ -118,12 +118,12 @@ void fault_block_layer_scan_layer(fault_block_layer_type *fault_layer, */ bool fault_block_layer_scan_kw(fault_block_layer_type *layer, - const rd_kw_type *fault_block_kw) { + const rd::KW *fault_block_kw) { bool assign_zero = true; - if (rd_kw_get_size(fault_block_kw) != rd_grid_get_global_size(layer->grid)) + if (rd::kw_get_size(fault_block_kw) != rd_grid_get_global_size(layer->grid)) return false; - else if (!rd_type_is_int(rd_kw_get_data_type(fault_block_kw))) + else if (!rd_type_is_int(fault_block_kw->data_type())) return false; else { int max_block_id = 0; @@ -132,8 +132,9 @@ bool fault_block_layer_scan_kw(fault_block_layer_type *layer, for (int j = 0; j < rd_grid_get_ny(layer->grid); j++) { for (int i = 0; i < rd_grid_get_nx(layer->grid); i++) { - int g = rd_grid_get_global_index3(layer->grid, i, j, layer->k); - int block_id = rd_kw_iget_int(fault_block_kw, g); + size_t g = + rd_grid_get_global_index3(layer->grid, i, j, layer->k); + int block_id = fault_block_kw->at(g); if (block_id > 0) { layer_iset_cell_value(work_layer.get(), i, j, block_id); @@ -157,16 +158,17 @@ bool fault_block_layer_scan_kw(fault_block_layer_type *layer, */ bool fault_block_layer_load_kw(fault_block_layer_type *layer, - const rd_kw_type *fault_block_kw) { - if (rd_kw_get_size(fault_block_kw) != rd_grid_get_global_size(layer->grid)) + const rd::KW *fault_block_kw) { + if (rd::kw_get_size(fault_block_kw) != rd_grid_get_global_size(layer->grid)) return false; - else if (!rd_type_is_int(rd_kw_get_data_type(fault_block_kw))) + else if (!rd_type_is_int(fault_block_kw->data_type())) return false; else { for (int j = 0; j < rd_grid_get_ny(layer->grid); j++) { for (int i = 0; i < rd_grid_get_nx(layer->grid); i++) { - int g = rd_grid_get_global_index3(layer->grid, i, j, layer->k); - int block_id = rd_kw_iget_int(fault_block_kw, g); + size_t g = + rd_grid_get_global_index3(layer->grid, i, j, layer->k); + int block_id = fault_block_kw->at(g); if (block_id > 0) { fault_block_layer_add_block(layer, block_id); { @@ -266,16 +268,17 @@ void fault_block_layer_insert_block_content(fault_block_layer_type *layer, } bool fault_block_layer_export(const fault_block_layer_type *layer, - rd_kw_type *faultblock_kw) { - if (rd_type_is_int(rd_kw_get_data_type(faultblock_kw)) && - (rd_kw_get_size(faultblock_kw) == + rd::KW *faultblock_kw) { + if (rd_type_is_int(faultblock_kw->data_type()) && + (rd::kw_get_size(faultblock_kw) == rd_grid_get_global_size(layer->grid))) { for (int j = 0; j < rd_grid_get_ny(layer->grid); j++) { for (int i = 0; i < rd_grid_get_nx(layer->grid); i++) { - int g = rd_grid_get_global_index3(layer->grid, i, j, layer->k); + size_t g = + rd_grid_get_global_index3(layer->grid, i, j, layer->k); int cell_value = layer_iget_cell_value(layer->layer.get(), i, j); - rd_kw_iset_int(faultblock_kw, g, cell_value); + faultblock_kw->at(g) = cell_value; } } return true; diff --git a/lib/resdata/fault_block_layer_pybind.cpp b/lib/resdata/fault_block_layer_pybind.cpp index d357054cb..52646026f 100644 --- a/lib/resdata/fault_block_layer_pybind.cpp +++ b/lib/resdata/fault_block_layer_pybind.cpp @@ -79,12 +79,12 @@ PYBIND11_MODULE(_fault_block_layer, m) { m.def("_scan_keyword", [](py::handle self, py::handle fault_block_kw) { return fault_block_layer_scan_kw( from_cwrap(self), - from_cwrap(fault_block_kw)); + from_cwrap(fault_block_kw)); }); m.def("_load_keyword", [](py::handle self, py::handle fault_block_kw) { return fault_block_layer_load_kw( from_cwrap(self), - from_cwrap(fault_block_kw)); + from_cwrap(fault_block_kw)); }); m.def("_getK", [](py::handle self) { return fault_block_layer_get_k( @@ -104,8 +104,7 @@ PYBIND11_MODULE(_fault_block_layer, m) { }); m.def("_export_kw", [](py::handle self, py::handle kw) { return fault_block_layer_export( - from_cwrap(self), - from_cwrap(kw)); + from_cwrap(self), from_cwrap(kw)); }); m.def("_get_layer", [](py::handle self) { return Layer().attr("createCReference")( diff --git a/lib/resdata/fortio_pybind.cpp b/lib/resdata/fortio_pybind.cpp index cf875d807..2b778bffc 100644 --- a/lib/resdata/fortio_pybind.cpp +++ b/lib/resdata/fortio_pybind.cpp @@ -126,7 +126,7 @@ PYBIND11_MODULE(fortio, m) { cls.def("get_position", &ERT::FortIO::ftell); cls.def( "truncate", - [](ERT::FortIO &self, std::optional size) { + [](ERT::FortIO &self, std::optional size) { if (!size) size = self.ftell(); if (!self.ftruncate(*size)) { diff --git a/lib/resdata/rd_file.cpp b/lib/resdata/rd_file.cpp index f399a8b0b..9704f073f 100644 --- a/lib/resdata/rd_file.cpp +++ b/lib/resdata/rd_file.cpp @@ -124,31 +124,21 @@ namespace fs = std::filesystem; the file, possible garbage at the end will be ignored. */ void rd::File::scan() { context->fortio.fseek(0, SEEK_SET); - { - rd_kw_ptr work_kw = make_rd_kw("WORK-KW", 0, RD_INT, nullptr); - - while (true) { - if (context->fortio.read_at_eof()) - break; - - { - offset_type current_offset = context->fortio.ftell(); - rd_read_status_enum read_status = - rd_kw_fread_header(work_kw.get(), context->fortio); - if (read_status == RD_KW_READ_FAIL) - break; - - if (read_status == RD_KW_READ_OK) { - auto file_kw = - std::make_shared(work_kw.get(), current_offset); - - if (file_kw->skip_data(context->fortio)) { - global_view->add_kw(file_kw); - } else { - break; - } - } - } + while (true) { + if (context->fortio.read_at_eof()) + break; + + offset_type current_offset = context->fortio.ftell(); + auto work_kw = rd::KW::fread_header(context->fortio); + if (!work_kw) + break; + + auto file_kw = std::make_shared(work_kw.get(), current_offset); + + if (file_kw->skip_data(context->fortio)) { + global_view->add_kw(file_kw); + } else { + break; } } global_view->make_index(); @@ -202,7 +192,7 @@ std::unique_ptr rd::File::open(const std::string &filename, 3. The rd_file must have been opened with one of the _writable() open functions. */ -bool rd::File::save_kw(const rd_kw_type *rd_kw) { +bool rd::File::save_kw(const rd::KW *rd_kw) { FileKW *file_kw = context->inv_map.at(rd_kw); if (context->fortio.assert_stream_open()) { diff --git a/lib/resdata/rd_file_kw.cpp b/lib/resdata/rd_file_kw.cpp index fc5ef866c..791f712b8 100644 --- a/lib/resdata/rd_file_kw.cpp +++ b/lib/resdata/rd_file_kw.cpp @@ -20,17 +20,17 @@ void FileKW::assert_kw() const { if (!kw) throw std::runtime_error("keyword could not be loaded from file " - "(rd_kw_fread_alloc returned NULL)"); + "(rd::KW::fread returned NULL)"); - if (!rd_type_is_equal(this->data_type, rd_kw_get_data_type(kw.get()))) + if (!rd_type_is_equal(this->data_type, kw->data_type())) throw std::runtime_error(std::string(__func__) + ": type mismatch between header and file."); - if (kw_size != rd_kw_get_size(kw.get())) + if (kw_size != rd::kw_get_size(kw.get())) throw std::runtime_error(std::string(__func__) + ": size mismatch between header and file."); - if (header != rd_kw_get_header(kw.get())) + if (header != kw->header()) throw std::runtime_error(std::string(__func__) + ": name mismatch between header and file."); } @@ -44,11 +44,11 @@ void FileKW::load_kw(ERT::FortIO &fortio) { fortio.fseek(file_offset, SEEK_SET); // Note load_kw is only called when kw is nullptr - kw.reset(rd_kw_fread_alloc(fortio)); + kw = rd::KW::fread(fortio); assert_kw(); } -rd_kw_type *FileKW::get_kw(ERT::FortIO &fortio) { +rd::KW *FileKW::get_kw(ERT::FortIO &fortio) { if (!kw) load_kw(fortio); @@ -56,15 +56,15 @@ rd_kw_type *FileKW::get_kw(ERT::FortIO &fortio) { } bool FileKW::skip_data(ERT::FortIO &fortio) const { - return rd_kw_fskip_data__(data_type, kw_size, fortio); + return rd::KW::fskip_data(data_type, kw_size, fortio); } void FileKW::inplace_write(ERT::FortIO &fortio) const { assert_kw(); fortio.fseek(file_offset, SEEK_SET); - rd_kw_fskip_header(fortio); + rd::KW::fskip_header(fortio); fortio.fclean(); - rd_kw_fwrite_data(kw.get(), fortio); + kw->fwrite_data(fortio); } void FileKW::write_header(std::ostream &stream) const { diff --git a/lib/resdata/rd_file_pybind.cpp b/lib/resdata/rd_file_pybind.cpp index 2ae60c7f0..340a9b0bf 100644 --- a/lib/resdata/rd_file_pybind.cpp +++ b/lib/resdata/rd_file_pybind.cpp @@ -29,7 +29,7 @@ namespace py = pybind11; namespace { -py::object create_kw_reference(rd_kw_type *kw, py::object parent) { +py::object create_kw_reference(rd::KW *kw, py::object parent) { if (!kw) return py::none(); return ResdataKW().attr("createCReference")(to_capsule(kw), parent); @@ -210,7 +210,7 @@ PYBIND11_MODULE(rd_file, m) { "save_kw", [](rd::File &self, py::handle kw) { if (self.is_writable()) { - self.save_kw(from_cwrap(kw)); + self.save_kw(from_cwrap(kw)); } else { PyErr_SetString( PyExc_OSError, @@ -610,7 +610,7 @@ PYBIND11_MODULE(rd_file, m) { size_t num_steps = self.num_named_kw("SEQNUM"); py::list steps; for (size_t i = 0; i < num_steps; i++) - steps.append(rd_kw_iget_int(self.get_kw("SEQNUM", i), 0)); + steps.append((self.get_kw("SEQNUM", i))->at(0)); return steps; }, "Will return a list of all report steps.\n" @@ -634,9 +634,9 @@ PYBIND11_MODULE(rd_file, m) { } if (view->has_kw("INTEHEAD")) { auto intehead = view->get_kw("INTEHEAD", 0); - int year = rd_kw_iget_int(intehead, 66); - int month = rd_kw_iget_int(intehead, 65); - int day = rd_kw_iget_int(intehead, 64); + int year = intehead->at(66); + int month = intehead->at(65); + int day = intehead->at(64); py::object datetime = py::module_::import("datetime").attr("datetime"); py::list dates; diff --git a/lib/resdata/rd_file_view.cpp b/lib/resdata/rd_file_view.cpp index bddcf0ccb..2dd48835b 100644 --- a/lib/resdata/rd_file_view.cpp +++ b/lib/resdata/rd_file_view.cpp @@ -60,8 +60,8 @@ bool FileView::drop_flags(FileMode flag) { return flag_set; } -rd_kw_type *FileView::get_kw(const std::shared_ptr &file_kw) { - rd_kw_type *rd_kw = file_kw->get_kw_ptr(); +rd::KW *FileView::get_kw(const std::shared_ptr &file_kw) { + rd::KW *rd_kw = file_kw->get_kw_ptr(); if (!rd_kw) { if (context->fortio.assert_stream_open()) { rd_kw = file_kw->get_kw(context->fortio); @@ -103,8 +103,8 @@ FileView::validate_index_fload_kw(const std::string &kw, int 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); + rd::KW *rd_kw = get_kw(index); + rd_kw->fwrite(target); } } @@ -250,10 +250,10 @@ static time_t rsthead_date(int day, int month, int year) { return rd_make_date(day, month, year); } -static time_t rd_rsthead_date(const rd_kw_type *intehead_kw) { - return rsthead_date(rd_kw_iget_int(intehead_kw, INTEHEAD_DAY_INDEX), - rd_kw_iget_int(intehead_kw, INTEHEAD_MONTH_INDEX), - rd_kw_iget_int(intehead_kw, INTEHEAD_YEAR_INDEX)); +static time_t rd_rsthead_date(const rd::KW *intehead_kw) { + return rsthead_date(intehead_kw->at(INTEHEAD_DAY_INDEX), + intehead_kw->at(INTEHEAD_MONTH_INDEX), + intehead_kw->at(INTEHEAD_YEAR_INDEX)); } time_t FileView::restart_sim_date(size_t seqnum_index) { @@ -261,7 +261,7 @@ time_t FileView::restart_sim_date(size_t seqnum_index) { blockview(SEQNUM_KW, SEQNUM_KW, seqnum_index); if (seqnum_map) { - rd_kw_type *intehead_kw = seqnum_map->get_kw(INTEHEAD_KW, 0); + rd::KW *intehead_kw = seqnum_map->get_kw(INTEHEAD_KW, 0); return rd_rsthead_date(intehead_kw); } @@ -274,8 +274,8 @@ double FileView::restart_sim_days(size_t seqnum_index) { blockview(SEQNUM_KW, SEQNUM_KW, seqnum_index); if (seqnum_map) { - rd_kw_type *doubhead_kw = seqnum_map->get_kw(DOUBHEAD_KW, 0); - return rd_kw_iget_double(doubhead_kw, DOUBHEAD_DAYS_INDEX); + rd::KW *doubhead_kw = seqnum_map->get_kw(DOUBHEAD_KW, 0); + return doubhead_kw->at(DOUBHEAD_DAYS_INDEX); } throw std::out_of_range( @@ -317,7 +317,7 @@ std::optional FileView::find_sim_time(time_t sim_time) { 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]); + const rd::KW *intehead_kw = get_kw(intehead_index_list[index]); if (rd_rsthead_date(intehead_kw) == sim_time) return index; } @@ -335,8 +335,10 @@ FileView::restart_view_from_seqnum_index(size_t index) { } std::shared_ptr FileView::restart_view_from_report_step(int report_step) { - auto block = find_block(SEQNUM_KW, [&](const rd_kw_type *seqnum_kw) { - return rd_kw_data_equal(seqnum_kw, &report_step); + auto block = find_block(SEQNUM_KW, [&](const rd::KW *seqnum_kw) { + return seqnum_kw->size() > 0 && + rd_type_is_int(seqnum_kw->data_type()) && + seqnum_kw->at(0) == report_step; }); if (!block.has_value()) throw std::invalid_argument( @@ -346,7 +348,7 @@ FileView::restart_view_from_report_step(int report_step) { std::shared_ptr FileView::restart_view_from_sim_time(time_t sim_time) { - auto block = find_block(INTEHEAD_KW, [&](const rd_kw_type *intehead_kw) { + auto block = find_block(INTEHEAD_KW, [&](const rd::KW *intehead_kw) { return rd_rsthead_date(intehead_kw) == sim_time; }); if (!block.has_value()) @@ -357,9 +359,9 @@ FileView::restart_view_from_sim_time(time_t sim_time) { std::shared_ptr FileView::restart_view_from_sim_days(double sim_days) { - auto block = find_block(DOUBHEAD_KW, [&](const rd_kw_type *doubhead_kw) { + auto block = find_block(DOUBHEAD_KW, [&](const rd::KW *doubhead_kw) { return util_double_approx_equal( - sim_days, rd_kw_iget_double(doubhead_kw, DOUBHEAD_DAYS_INDEX)); + sim_days, doubhead_kw->at(DOUBHEAD_DAYS_INDEX)); }); if (!block.has_value()) throw std::invalid_argument( diff --git a/lib/resdata/rd_file_view_pybind.cpp b/lib/resdata/rd_file_view_pybind.cpp index 93d335c87..241e409d7 100644 --- a/lib/resdata/rd_file_view_pybind.cpp +++ b/lib/resdata/rd_file_view_pybind.cpp @@ -29,7 +29,7 @@ namespace py = pybind11; namespace { -py::object create_kw_reference(rd_kw_type *kw, py::object parent) { +py::object create_kw_reference(rd::KW *kw, py::object parent) { if (!kw) return py::none(); return ResdataKW().attr("createCReference")(to_capsule(kw), parent); diff --git a/lib/resdata/rd_grav.cpp b/lib/resdata/rd_grav.cpp index af36096ab..b51bfcc1b 100644 --- a/lib/resdata/rd_grav.cpp +++ b/lib/resdata/rd_grav.cpp @@ -193,8 +193,8 @@ static double rd_grav_phase_eval(rd_grav_phase_type *base_phase, keyword is not sufficiently large or the value at INTEHEAD_IPROG_INDEX is invalid. */ static rd_version_enum get_simulator_version(const rd::File *file) { - rd_kw_type *intehead_kw = file->get_kw(INTEHEAD_KW, 0); - int int_value = rd_kw_iget_int(intehead_kw, INTEHEAD_IPROG_INDEX); + rd::KW *intehead_kw = file->get_kw(INTEHEAD_KW, 0); + int int_value = intehead_kw->at(INTEHEAD_IPROG_INDEX); switch (int_value) { case INTEHEAD_ECLIPSE100_VALUE: @@ -224,14 +224,14 @@ rd_grav_phase_alloc(rd_grav_type *rd_grav, rd_grav_survey_type *survey, auto grav_phase = std::make_unique( grid_cache, rd_grav->aquifer_cell, phase); - const int size = grid_cache->size(); + const size_t size = static_cast(grid_cache->size()); if (calc_type == GRAV_CALC_FIP) { - rd_kw_type *pvtnum_kw = init_file->get_kw(PVTNUM_KW, 0); + rd::KW *pvtnum_kw = init_file->get_kw(PVTNUM_KW, 0); const std::vector std_density = rd_grav->std_density[std::string(rd_get_phase_name(phase))]; - rd_kw_type *fip_kw; + rd::KW *fip_kw; if (phase == Phase::OIL) fip_kw = restart_file->get_kw(FIPOIL_KW, 0); @@ -240,9 +240,9 @@ rd_grav_phase_alloc(rd_grav_type *rd_grav, rd_grav_survey_type *survey, else 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); - int pvtnum = rd_kw_iget_int(pvtnum_kw, iactive); + for (size_t iactive = 0; iactive < size; iactive++) { + double fip = fip_kw->as_double(iactive); + int pvtnum = pvtnum_kw->at(iactive); if (pvtnum < 0 || std_density.size() <= static_cast(pvtnum)) return {nullptr}; grav_phase->fluid_mass[iactive] = fip * std_density[pvtnum]; @@ -250,10 +250,10 @@ rd_grav_phase_alloc(rd_grav_type *rd_grav, rd_grav_survey_type *survey, } else { rd_version_enum rd_version = get_simulator_version(init_file); 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); + const rd::KW *den_kw = restart_file->get_kw(den_kw_name, 0); if (calc_type == GRAV_CALC_RFIP) { - rd_kw_type *rfip_kw; + rd::KW *rfip_kw; if (phase == Phase::OIL) rfip_kw = restart_file->get_kw(RFIPOIL_KW, 0); else if (phase == Phase::GAS) @@ -261,46 +261,37 @@ rd_grav_phase_alloc(rd_grav_type *rd_grav, rd_grav_survey_type *survey, else rfip_kw = restart_file->get_kw(RFIPWAT_KW, 0); - { - int iactive; - for (iactive = 0; iactive < size; iactive++) { - double rho = rd_kw_iget_as_double(den_kw, iactive); - double rfip = rd_kw_iget_as_double(rfip_kw, iactive); - grav_phase->fluid_mass[iactive] = rho * rfip; - } + for (size_t iactive = 0; iactive < size; iactive++) { + double rho = den_kw->as_double(iactive); + double rfip = rfip_kw->as_double(iactive); + grav_phase->fluid_mass[iactive] = rho * rfip; } } else { /* (calc_type == GRAV_CALC_RPORV) || (calc_type == GRAV_CALC_PORMOD) */ - rd_kw_type *sat_kw; - bool private_sat_kw = false; + rd::KW *sat_kw; + std::unique_ptr sat_kw_guard{nullptr}; 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 = 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 */ + const rd::KW *swat_kw = restart_file->get_kw("SWAT", 0); + sat_kw_guard.reset(new rd::KW(*swat_kw)); + sat_kw = sat_kw_guard.get(); + sat_kw->scalar_set(1.0); + *sat_kw -= *swat_kw; if (restart_file->has_kw("SGAS")) { - const rd_kw_type *sgas_kw = restart_file->get_kw("SGAS", 0); - rd_kw_inplace_sub(sat_kw, sgas_kw); /* sat -= SGAS */ + const rd::KW *sgas_kw = restart_file->get_kw("SGAS", 0); + *sat_kw -= *sgas_kw; } - private_sat_kw = true; } - { - int iactive; - for (iactive = 0; iactive < size; iactive++) { - double rho = rd_kw_iget_as_double(den_kw, iactive); - double sat = rd_kw_iget_as_double(sat_kw, iactive); - grav_phase->fluid_mass[iactive] = - rho * sat * survey->porv[iactive]; - } + for (size_t iactive = 0; iactive < size; iactive++) { + double rho = den_kw->as_double(iactive); + double sat = sat_kw->as_double(iactive); + grav_phase->fluid_mass[iactive] = + rho * sat * survey->porv[iactive]; } - - if (private_sat_kw) - rd_kw_free(sat_kw); } } @@ -323,8 +314,8 @@ rd_grav_survey_add_phase(rd_grav_survey_type *survey, Phase phase, 6: Gas + water 7: Gas + Water + Oil */ static int get_phases(const rd::File *init_file) { - rd_kw_type *intehead_kw = init_file->get_kw(INTEHEAD_KW, 0); - int phases = rd_kw_iget_int(intehead_kw, INTEHEAD_PHASE_INDEX); + rd::KW *intehead_kw = init_file->get_kw(INTEHEAD_KW, 0); + int phases = intehead_kw->at(INTEHEAD_PHASE_INDEX); return phases; } @@ -368,7 +359,7 @@ static void rd_grav_survey_assert_RPORV(const rd_grav_survey_type *survey, const rd::File *init_file) { const rd::rd_grid_cache &grid_cache = *(survey->grid_cache); int active_size = grid_cache.size(); - const rd_kw_type *init_porv_kw = init_file->get_kw(PORV_KW, 0); + const rd::KW *init_porv_kw = init_file->get_kw(PORV_KW, 0); int check_points = std::min(100, active_size); int check_nr = 0; const std::vector &global_index = grid_cache.global_index(); @@ -376,8 +367,7 @@ static void rd_grav_survey_assert_RPORV(const rd_grav_survey_type *survey, while (check_nr < check_points) { int active_index = rand() % active_size; - double init_porv = rd_kw_iget_as_double( - init_porv_kw, + double init_porv = init_porv_kw->as_double( global_index[active_index]); /* NB - this uses global indexing. */ if (init_porv > 0) { double rporv = survey->porv[active_index]; @@ -452,9 +442,9 @@ rd_grav_survey_alloc_RPORV(rd_grav_type *rd_grav, rd::FileView *restart_file, ": restart file did not contain " + RPORV_KW + " keyword"); - rd_kw_type *rporv_kw = restart_file->get_kw(RPORV_KW, 0); - const int active_size = rd_grav->grid_cache->size(); - const int rporv_size = rd_kw_get_size(rporv_kw); + rd::KW *rporv_kw = restart_file->get_kw(RPORV_KW, 0); + const size_t active_size = static_cast(rd_grav->grid_cache->size()); + const size_t rporv_size = rporv_kw->size(); if (rporv_size != active_size) throw std::invalid_argument( fmt::format("{} keyword has {} elements, but the grid has {} " @@ -463,8 +453,8 @@ rd_grav_survey_alloc_RPORV(rd_grav_type *rd_grav, rd::FileView *restart_file, auto survey = std::make_unique( rd_grav->grid_cache, rd_grav->aquifer_cell, name, GRAV_CALC_RPORV); - for (int iactive = 0; iactive < active_size; iactive++) - survey->porv[iactive] = rd_kw_iget_as_double(rporv_kw, iactive); + for (size_t iactive = 0; iactive < active_size; iactive++) + survey->porv[iactive] = rporv_kw->as_double(iactive); { const rd::File *init_file = rd_grav->init_file; @@ -483,18 +473,16 @@ rd_grav_survey_alloc_PORMOD(rd_grav_type *rd_grav, rd::FileView *restart_file, auto survey = std::make_unique( rd_grav->grid_cache, rd_grav->aquifer_cell, name, GRAV_CALC_PORMOD); - rd_kw_type *init_porv_kw = + rd::KW *init_porv_kw = rd_grav->init_file->get_kw(PORV_KW, 0); /* Global indexing */ - rd_kw_type *pormod_kw = + rd::KW *pormod_kw = restart_file->get_kw(PORMOD_KW, 0); /* Active indexing */ - const int size = grid_cache.size(); + const size_t size = grid_cache.size(); const auto &global_index = grid_cache.global_index(); - int active_index; - - for (active_index = 0; active_index < size; active_index++) + for (size_t active_index = 0; active_index < size; active_index++) survey->porv[active_index] = - static_cast(rd_kw_iget_float(pormod_kw, active_index)) * - rd_kw_iget_float(init_porv_kw, global_index[active_index]); + static_cast(pormod_kw->at(active_index)) * + init_porv_kw->at(global_index[active_index]); if (!rd_grav_survey_add_phases(rd_grav, survey.get(), restart_file, GRAV_CALC_PORMOD)) diff --git a/lib/resdata/rd_grav_common.cpp b/lib/resdata/rd_grav_common.cpp index 76b4cd5d3..34e223e4c 100644 --- a/lib/resdata/rd_grav_common.cpp +++ b/lib/resdata/rd_grav_common.cpp @@ -25,8 +25,8 @@ bool *rd_grav_common_alloc_aquifer_cell(const rd::rd_grid_cache &grid_cache, aquifer_cell[active_index] = false; if (init_file->has_kw(AQUIFER_KW)) { - rd_kw_type *aquifer_kw = init_file->get_kw(AQUIFER_KW, 0); - const int *aquifer_data = rd_kw_get_int_ptr(aquifer_kw); + rd::KW *aquifer_kw = init_file->get_kw(AQUIFER_KW, 0); + const std::vector &aquifer_data = aquifer_kw->get_vector(); for (int active_index = 0; active_index < grid_cache.size(); active_index++) { diff --git a/lib/resdata/rd_grid.cpp b/lib/resdata/rd_grid.cpp index 862987172..0ddd842be 100644 --- a/lib/resdata/rd_grid.cpp +++ b/lib/resdata/rd_grid.cpp @@ -3,10 +3,13 @@ #include #include #include +#include #include +#include #include #include +#include #include #include #include @@ -213,7 +216,7 @@ namespace fs = std::filesystem; printf("lgr:%s has %d x %d x %d elements \n", rd_grid_get_name(lgr_grid) , nx , ny , nz); // ok - now we want to extract the solution vector (pressure) corresponding to this lgr: - rd_kw_type *pressure_kw = restart_data->get_kw("PRESSURE", rd_grid_get_lgr_nr(lgr_grid)); + rd::KW *pressure_kw = restart_data->get_kw("PRESSURE", rd_grid_get_lgr_nr(lgr_grid)); /// /|\ /// | /// | @@ -223,7 +226,7 @@ namespace fs = std::filesystem; { int center_index = rd_grid_get_global_index3(lgr_grid, nx/2, ny/2, nz/2); // ask the lgr_grid to get the index at the center of the lgr grid. - printf("the pressure in the middle of %s is %g \n", rd_grid_get_name(lgr_grid) , rd_kw_iget_as_double(pressure_kw , center_index)); + printf("the pressure in the middle of %s is %g \n", rd_grid_get_name(lgr_grid) , pressure_kw ->as_double(center_index)); } } @@ -313,14 +316,13 @@ namespace fs = std::filesystem; int matrix_size = rd_grid_get_nactive(rd_grid); int fracture_size = rd_grid_get_nactive_fracture(rd_grid); - rd_kw_type *swat = rst_file.get_kw("SWAT", 0); + rd::KW *swat = rst_file.get_kw("SWAT", 0); - snprintf(fracture_kw, 9, "F-%6s", rd_kw_get_header(swat)); - snprintf(matrix_kw, 9, "M-%6s", rd_kw_get_header(swat)); + snprintf(fracture_kw, 9, "F-%6s", swat->header().c_str()); + snprintf(matrix_kw, 9, "M-%6s", swat->header().c_str()); - rd_kw_type *M = rd_kw_alloc_sub_copy(swat, matrix_kw, 0, matrix_size); - rd_kw_type *F = - rd_kw_alloc_sub_copy(swat, fracture_kw, matrix_size, fracture_size); + rd::KW *M = new rd::KW{*swat, matrix_kw, 0, matrix_size}; + rd::KW *F = new rd::KW{*swat, fracture_kw, matrix_size, fracture_size}; } About nnc @@ -669,7 +671,7 @@ struct rd_cell_struct { } }; -static UnitSystem rd_grid_check_unit_system(const rd_kw_type *gridunit_kw); +static UnitSystem rd_grid_check_unit_system(const rd::KW *gridunit_kw); #define RD_GRID_ID 991010 struct rd_grid_struct { @@ -729,12 +731,12 @@ struct rd_grid_struct { double unit_y[2]; double origo[2]; std::optional> mapaxes; - rd_kw_ptr coord_kw{nullptr, - &rd_kw_free}; /* Retained for writing the grid to file. - In principal it should be possible to - recalculate this from the cell coordinates, - but in cases with skewed cells this has proved - numerically challenging. */ + std::unique_ptr coord_kw{ + nullptr}; /* Retained for writing the grid to file. + In principal it should be possible to + recalculate this from the cell coordinates, + but in cases with skewed cells this has proved + numerically challenging. */ UnitSystem unit_system; int eclipse_version; @@ -800,32 +802,32 @@ static void rd_cell_dump_ascii(rd_cell_type &cell, int i, int j, int k, static void rd_cell_fwrite_GRID(const rd_grid_type *grid, const rd_cell_type &cell, bool fracture_cell, int coords_size, int i, int j, int k, - int global_index, const rd_kw_ptr &coords_kw, - const rd_kw_ptr &corners_kw, + int global_index, + const std::unique_ptr &coords_kw, + const std::unique_ptr &corners_kw, ERT::FortIO &fortio) { - rd_kw_iset_int(coords_kw.get(), 0, i + 1); - rd_kw_iset_int(coords_kw.get(), 1, j + 1); - rd_kw_iset_int(coords_kw.get(), 2, k + 1); - rd_kw_iset_int(coords_kw.get(), 3, global_index + 1); + coords_kw->at(0) = i + 1; + coords_kw->at(1) = j + 1; + coords_kw->at(2) = k + 1; + coords_kw->at(3) = global_index + 1; - rd_kw_iset_int(coords_kw.get(), 4, 0); + coords_kw->at(4) = 0; if (fracture_cell) { if (cell.active & CELL_ACTIVE_FRACTURE) - rd_kw_iset_int(coords_kw.get(), 4, 1); + coords_kw->at(4) = 1; } else { if (cell.active & CELL_ACTIVE_MATRIX) - rd_kw_iset_int(coords_kw.get(), 4, 1); + coords_kw->at(4) = 1; } if (coords_size == 7) { - rd_kw_iset_int(coords_kw.get(), 5, cell.host_cell + 1); - rd_kw_iset_int(coords_kw.get(), 6, cell.coarse_group + 1); + coords_kw->at(5) = cell.host_cell + 1; + coords_kw->at(6) = cell.coarse_group + 1; } - rd_kw_fwrite(coords_kw.get(), fortio); + coords_kw->fwrite(fortio); { - float *corners = - static_cast(rd_kw_get_void_ptr(corners_kw.get())); + std::vector &corners = corners_kw->get_vector(); point_type point; for (int c = 0; c < 8; c++) { @@ -839,7 +841,7 @@ static void rd_cell_fwrite_GRID(const rd_grid_type *grid, corners[3 * c + 2] = point.z; } } - rd_kw_fwrite(corners_kw.get(), fortio); + corners_kw->fwrite(fortio); } static double max2(double x1, double x2) { return (x1 > x2) ? x1 : x2; } @@ -1859,11 +1861,11 @@ static void rd_grid_install_lgr_GRID(rd_grid_type *host_grid, */ static void rd_grid_set_lgr_name_EGRID(rd_grid_type *lgr_grid, const rd::File *rd_file, int grid_nr) { - rd_kw_type *lgrname_kw = rd_file->get_kw(LGR_KW, grid_nr - 1); - lgr_grid->name = rd_kw_iget_stripped_string(lgrname_kw, 0); + rd::KW *lgrname_kw = rd_file->get_kw(LGR_KW, grid_nr - 1); + lgr_grid->name = rd::strip_spaces(lgrname_kw->at(0)); if (rd_file->has_kw(LGR_PARENT_KW)) { - rd_kw_type *parent_kw = rd_file->get_kw(LGR_PARENT_KW, grid_nr - 1); - std::string parent = rd_kw_iget_stripped_string(parent_kw, 0); + rd::KW *parent_kw = rd_file->get_kw(LGR_PARENT_KW, grid_nr - 1); + std::string parent = rd::strip_spaces(parent_kw->at(0)); if (!parent.empty()) lgr_grid->parent_name = parent; @@ -1880,16 +1882,16 @@ static void rd_grid_set_lgr_name_EGRID(rd_grid_type *lgr_grid, */ static void rd_grid_set_lgr_name_GRID(rd_grid_type *lgr_grid, const rd::File *rd_file, int grid_nr) { - rd_kw_type *lgr_kw = rd_file->get_kw(LGR_KW, grid_nr - 1); - lgr_grid->name = rd_kw_iget_stripped_string(lgr_kw, 0); + rd::KW *lgr_kw = rd_file->get_kw(LGR_KW, grid_nr - 1); + lgr_grid->name = rd::strip_spaces(lgr_kw->at(0)); { /* the lgr keyword can have one or two elements; in the case of two elements the second element will be the name of the parent grid - in the case of only one element the current lgr is assumed to descend from the main grid */ - if (rd_kw_get_size(lgr_kw) == 2) { - std::string parent = rd_kw_iget_stripped_string(lgr_kw, 1); + if (lgr_kw->size() == 2) { + std::string parent = rd::strip_spaces(lgr_kw->at(1)); if (!parent.empty() && parent != GLOBAL_STRING) lgr_grid->parent_name = parent; @@ -2063,38 +2065,38 @@ rd_grid_type *rd_grid_alloc_copy(const rd_grid_type *src_grid) { return copy_grid.release(); } -static const float * -rd_grid_get_mapaxes_from_kw__(const rd_kw_type *mapaxes_kw) { - const float *mapaxes_data = rd_kw_get_float_ptr(mapaxes_kw); +static const float *rd_grid_get_mapaxes_from_kw__(const rd::KW *mapaxes_kw) { + const std::vector &mapaxes = mapaxes_kw->get_vector(); - float x1 = mapaxes_data[2]; - float y1 = mapaxes_data[3]; - float x2 = mapaxes_data[4]; - float y2 = mapaxes_data[5]; + float x1 = mapaxes[2]; + float y1 = mapaxes[3]; + float x2 = mapaxes[4]; + float y2 = mapaxes[5]; float norm_denominator = x1 * y2 - x2 * y1; if (norm_denominator == 0.0) { - mapaxes_data = NULL; + return NULL; } - return mapaxes_data; + return mapaxes.data(); } -static rd_grid_ptr rd_grid_alloc_GRDECL_kw__( - rd_grid_type *global_grid, int dualp_flag, bool apply_mapaxes, - const rd_kw_type *gridhead_kw, const rd_kw_type *zcorn_kw, - const rd_kw_type *coord_kw, const rd_kw_type *gridunit_kw, /* Can be NULL */ - const rd_kw_type *mapaxes_kw, /* Can be NULL */ - const rd_kw_type *corsnum_kw, /* Can be NULL */ - const int *actnum) { /* Can be NULL */ +static rd_grid_ptr +rd_grid_alloc_GRDECL_kw__(rd_grid_type *global_grid, int dualp_flag, + bool apply_mapaxes, const rd::KW *gridhead_kw, + const rd::KW *zcorn_kw, const rd::KW *coord_kw, + const rd::KW *gridunit_kw, /* Can be NULL */ + const rd::KW *mapaxes_kw, /* Can be NULL */ + const rd::KW *corsnum_kw, /* Can be NULL */ + const int *actnum) { /* Can be NULL */ int gtype, nx, ny, nz, lgr_nr; UnitSystem unit_system = UnitSystem::METRIC; - gtype = rd_kw_iget_int(gridhead_kw, GRIDHEAD_TYPE_INDEX); - nx = rd_kw_iget_int(gridhead_kw, GRIDHEAD_NX_INDEX); - ny = rd_kw_iget_int(gridhead_kw, GRIDHEAD_NY_INDEX); - nz = rd_kw_iget_int(gridhead_kw, GRIDHEAD_NZ_INDEX); - lgr_nr = rd_kw_iget_int(gridhead_kw, GRIDHEAD_LGR_INDEX); + gtype = gridhead_kw->at(GRIDHEAD_TYPE_INDEX); + nx = gridhead_kw->at(GRIDHEAD_NX_INDEX); + ny = gridhead_kw->at(GRIDHEAD_NY_INDEX); + nz = gridhead_kw->at(GRIDHEAD_NZ_INDEX); + lgr_nr = gridhead_kw->at(GRIDHEAD_LGR_INDEX); if (nx <= 0 || ny <= 0 || nz <= 0) throw std::invalid_argument(fmt::format( @@ -2110,30 +2112,35 @@ static rd_grid_ptr rd_grid_alloc_GRDECL_kw__( const int64_t expected_coord_size = int64_t{6} * (nx64 + 1) * (ny64 + 1); const int64_t expected_zcorn_size = int64_t{8} * nx64 * ny64 * nz64; - if (expected_coord_size > std::numeric_limits::max() || - expected_zcorn_size > std::numeric_limits::max()) + if (expected_coord_size < 0 || + static_cast(expected_coord_size) > + std::numeric_limits::max() || + expected_zcorn_size < 0 || + static_cast(expected_zcorn_size) > + std::numeric_limits::max()) throw std::invalid_argument(fmt::format( - "Grid dimensions too large: nx={}, ny={}, nz={}", nx, ny, nz)); + "Grid dimensions negative or too large: nx={}, ny={}, nz={}", nx, + ny, nz)); - const int coord_size = static_cast(expected_coord_size); - const int zcorn_size = static_cast(expected_zcorn_size); + const size_t coord_size = static_cast(expected_coord_size); + const size_t zcorn_size = static_cast(expected_zcorn_size); - if (rd_kw_get_size(coord_kw) != coord_size) + if (coord_kw->size() != coord_size) throw std::invalid_argument( fmt::format("Invalid size of COORD keyword = {}, expected 6 * " "(nx + 1) * (ny + 1) = {}", - rd_kw_get_size(coord_kw), coord_size)); + coord_kw->size(), coord_size)); - if (rd_kw_get_size(zcorn_kw) != zcorn_size) + if (zcorn_kw->size() != zcorn_size) throw std::invalid_argument( fmt::format("Invalid size of ZCORN keyword = {}, expected 8 * " "nx * ny * nz = {}", - rd_kw_get_size(zcorn_kw), zcorn_size)); + zcorn_kw->size(), zcorn_size)); /* The code used to have this test: - if (grid_nr != rd_kw_iget_int( gridhead_kw , GRIDHEAD_LGR_INDEX)) + if (grid_nr != gridhead_kw->at(GRIDHEAD_LGR_INDEX)) util_abort("%s: internal error in grid loader - lgr index mismatch\n",__func__); But then suddenly a EGRID file where this did not apply appeared :-( @@ -2147,30 +2154,32 @@ static rd_grid_ptr rd_grid_alloc_GRDECL_kw__( const float *mapaxes = nullptr; if (mapaxes_kw) { - if (rd_kw_get_size(mapaxes_kw) != 6) + if (mapaxes_kw->size() != 6) throw std::invalid_argument( fmt::format("Invalid size of MAPAXES keyword = {}, expected 6", - rd_kw_get_size(mapaxes_kw))); + mapaxes_kw->size())); mapaxes = rd_grid_get_mapaxes_from_kw__(mapaxes_kw); } const int *corsnum = nullptr; if (corsnum_kw) { const int64_t expected_corsnum_size = nx64 * ny64 * nz64; - if (expected_corsnum_size > std::numeric_limits::max() || - rd_kw_get_size(corsnum_kw) != expected_corsnum_size) + if (expected_corsnum_size < 0 || + static_cast(expected_corsnum_size) > + std::numeric_limits::max() || + corsnum_kw->size() != static_cast(expected_corsnum_size)) throw std::invalid_argument( fmt::format("Invalid size of CORSNUM keyword = {}, expected " "nx * ny * nz = {}", - rd_kw_get_size(corsnum_kw), expected_corsnum_size)); - corsnum = rd_kw_get_int_ptr(corsnum_kw); + corsnum_kw->size(), expected_corsnum_size)); + corsnum = corsnum_kw->get_vector().data(); } if (gridunit_kw) unit_system = rd_grid_check_unit_system(gridunit_kw); - float *zcorn = rd_kw_get_float_ptr(zcorn_kw); - float *coord = rd_kw_get_float_ptr(coord_kw); + const float *zcorn = zcorn_kw->get_vector().data(); + const float *coord = coord_kw->get_vector().data(); auto rd_grid = rd_grid_ptr(rd_grid_alloc_empty(global_grid, unit_system, dualp_flag, nx, ny, nz, lgr_nr, true), @@ -2181,8 +2190,8 @@ static rd_grid_ptr rd_grid_alloc_GRDECL_kw__( if (corsnum != NULL) rd_grid->coarsening_active = true; - rd_grid->coord_kw.reset( - rd_kw_alloc_new("COORD", coord_size, RD_FLOAT, coord)); + rd_grid->coord_kw = std::make_unique( + *coord_kw, std::string("COORD"), 0, coord_size); int j; #pragma omp parallel for for (j = 0; j < ny; j++) @@ -2196,18 +2205,16 @@ static rd_grid_ptr rd_grid_alloc_GRDECL_kw__( return rd_grid; } -static rd_kw_type *rd_grid_alloc_gridhead_kw(int nx, int ny, int nz, - int grid_nr) { - auto gridhead_kw = make_rd_kw(GRIDHEAD_KW, GRIDHEAD_SIZE, RD_INT); - rd_kw_scalar_set_int(gridhead_kw.get(), 0); - rd_kw_iset_int(gridhead_kw.get(), GRIDHEAD_TYPE_INDEX, - GRIDHEAD_GRIDTYPE_CORNERPOINT); - rd_kw_iset_int(gridhead_kw.get(), GRIDHEAD_NX_INDEX, nx); - rd_kw_iset_int(gridhead_kw.get(), GRIDHEAD_NY_INDEX, ny); - rd_kw_iset_int(gridhead_kw.get(), GRIDHEAD_NZ_INDEX, nz); - rd_kw_iset_int(gridhead_kw.get(), GRIDHEAD_NUMRES_INDEX, 1); - rd_kw_iset_int(gridhead_kw.get(), GRIDHEAD_LGR_INDEX, grid_nr); - return gridhead_kw.release(); +static std::unique_ptr rd_grid_alloc_gridhead_kw(int nx, int ny, int nz, + int grid_nr) { + std::vector gridhead_data(GRIDHEAD_SIZE, 0); + gridhead_data[GRIDHEAD_TYPE_INDEX] = GRIDHEAD_GRIDTYPE_CORNERPOINT; + gridhead_data[GRIDHEAD_NX_INDEX] = nx; + gridhead_data[GRIDHEAD_NY_INDEX] = ny; + gridhead_data[GRIDHEAD_NZ_INDEX] = nz; + gridhead_data[GRIDHEAD_NUMRES_INDEX] = 1; + gridhead_data[GRIDHEAD_LGR_INDEX] = grid_nr; + return std::make_unique(GRIDHEAD_KW, std::move(gridhead_data)); } /** @@ -2217,10 +2224,10 @@ static rd_kw_type *rd_grid_alloc_gridhead_kw(int nx, int ny, int nz, hierarchies. */ rd_grid_type * -rd_grid_alloc_GRDECL_kw(int nx, int ny, int nz, const rd_kw_type *zcorn_kw, - const rd_kw_type *coord_kw, - const rd_kw_type *actnum_kw, /* Can be NULL */ - const rd_kw_type *mapaxes_kw) { /* Can be NULL */ +rd_grid_alloc_GRDECL_kw(int nx, int ny, int nz, const rd::KW *zcorn_kw, + const rd::KW *coord_kw, + const rd::KW *actnum_kw, /* Can be NULL */ + const rd::KW *mapaxes_kw) { /* Can be NULL */ if (nx < 0 || ny < 0 || nz < 0) throw std::invalid_argument( @@ -2231,24 +2238,26 @@ rd_grid_alloc_GRDECL_kw(int nx, int ny, int nz, const rd_kw_type *zcorn_kw, if (actnum_kw) { const int64_t expected_actnum_size = int64_t{nx} * ny * nz; - if (expected_actnum_size > std::numeric_limits::max()) + if (expected_actnum_size < 0 || + static_cast(expected_actnum_size) > + std::numeric_limits::max()) throw std::invalid_argument(fmt::format( - "Grid dimensions too large: nx={}, ny={}, nz={}", nx, ny, nz)); + "Grid dimensions negative or too large: nx={}, ny={}, nz={}", + nx, ny, nz)); - const int actnum_size = static_cast(expected_actnum_size); + const size_t actnum_size = static_cast(expected_actnum_size); - if (rd_kw_get_size(actnum_kw) != actnum_size) + if (actnum_kw->size() != actnum_size) throw std::invalid_argument( fmt::format("Invalid size of ACTNUM keyword = {}, expected nz " "* nx * ny = {}", - rd_kw_get_size(actnum_kw), actnum_size)); - actnum_data = rd_kw_get_int_ptr(actnum_kw); + actnum_kw->size(), actnum_size)); + actnum_data = actnum_kw->get_vector().data(); } bool apply_mapaxes = true; - auto gridhead_kw = - rd_kw_ptr(rd_grid_alloc_gridhead_kw(nx, ny, nz, 0), &rd_kw_free); - rd_kw_type *gridunit_kw = NULL; + auto gridhead_kw = rd_grid_alloc_gridhead_kw(nx, ny, nz, 0); + rd::KW *gridunit_kw = NULL; return rd_grid_alloc_GRDECL_kw__( NULL, FILEHEAD_SINGLE_POROSITY, apply_mapaxes, gridhead_kw.get(), zcorn_kw, coord_kw, gridunit_kw, mapaxes_kw, NULL, actnum_data) @@ -2290,7 +2299,7 @@ static void rd_grid_init_cell_nnc_info(rd_grid_type *rd_grid, ERT::FortIO init_file("CASE.INIT", std::ios_base::out, ... rd_grid_type * grid ... - rd_kw_type * trannnc_kw = rd_kw_alloc( "TRANNNC" , num_nnc , RD_FLOAT_TYPE ); + rd::KW trannnc_kw{"TRANNNC" , num_nnc , RD_FLOAT_TYPE}; for (int i = 0; i < num_nnc; i++) { int g1 = ... @@ -2298,11 +2307,11 @@ static void rd_grid_init_cell_nnc_info(rd_grid_type *rd_grid, float T = .. rd_grid_add_self_nnc( grid , g1 , g2 , i ); - rd_kw_iset( trannnc_kw , i , T ); + trannnc_kw.at( i ) = T; } ... rd_grid_fwrite_EGRID( grid , ... ); - rd_kw_fwrite( trannnc_kw , init_file ); + trannnc_kw.fwrite(init_file ); */ void rd_grid_add_self_nnc(rd_grid_type *grid, int cell_index1, int cell_index2, @@ -2327,12 +2336,12 @@ void rd_grid_add_self_nnc(rd_grid_type *grid, int cell_index1, int cell_index2, NNA1 -> NNA2 For links between different LGRs */ static void rd_grid_init_nnc_cells(rd_grid_type *grid1, rd_grid_type *grid2, - const rd_kw_type *keyword1, - const rd_kw_type *keyword2) { + const rd::KW *keyword1, + const rd::KW *keyword2) { - int *grid1_nnc_cells = rd_kw_get_int_ptr(keyword1); - int *grid2_nnc_cells = rd_kw_get_int_ptr(keyword2); - int nnc_count = rd_kw_get_size(keyword2); + const int *grid1_nnc_cells = keyword1->get_vector().data(); + const int *grid2_nnc_cells = keyword2->get_vector().data(); + int nnc_count = rd::kw_get_size(keyword2); for (int nnc_index = 0; nnc_index < nnc_count; nnc_index++) { int grid1_cell_index = grid1_nnc_cells[nnc_index] - 1; @@ -2384,12 +2393,12 @@ static void rd_grid_init_nnc(rd_grid_type *main_grid, rd::File *rd_file) { auto lgr_view = rd_file->blockview(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); + rd::KW *nnchead_kw = lgr_view->get_kw(NNCHEAD_KW, 0); + int lgr_nr = nnchead_kw->at(NNCHEAD_LGR_INDEX); 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); + const rd::KW *nnc1 = lgr_view->get_kw(NNC1_KW, 0); + const rd::KW *nnc2 = lgr_view->get_kw(NNC2_KW, 0); { rd_grid_type *grid = @@ -2401,8 +2410,8 @@ static void rd_grid_init_nnc(rd_grid_type *main_grid, rd::File *rd_file) { } 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); + const rd::KW *nncl = lgr_view->get_kw(NNCL_KW, 0); + const rd::KW *nncg = lgr_view->get_kw(NNCG_KW, 0); { rd_grid_type *grid = (lgr_nr > 0) @@ -2424,17 +2433,17 @@ static void rd_grid_init_nnc_amalgamated(rd_grid_type *main_grid, size_t num_nncheada_kw = rd_file->num_named_kw(NNCHEADA_KW); for (size_t i = 0; i < num_nncheada_kw; i++) { - rd_kw_type *nncheada_kw = rd_file->get_kw(NNCHEADA_KW, i); - int lgr_nr1 = rd_kw_iget_int(nncheada_kw, NNCHEADA_ILOC1_INDEX); - int lgr_nr2 = rd_kw_iget_int(nncheada_kw, NNCHEADA_ILOC2_INDEX); + rd::KW *nncheada_kw = rd_file->get_kw(NNCHEADA_KW, i); + int lgr_nr1 = nncheada_kw->at(NNCHEADA_ILOC1_INDEX); + int lgr_nr2 = nncheada_kw->at(NNCHEADA_ILOC2_INDEX); rd_grid_type *lgr_grid1 = rd_grid_get_lgr_from_lgr_nr(main_grid, lgr_nr1); rd_grid_type *lgr_grid2 = rd_grid_get_lgr_from_lgr_nr(main_grid, lgr_nr2); - rd_kw_type *nna1_kw = rd_file->get_kw(NNA1_KW, i); - rd_kw_type *nna2_kw = rd_file->get_kw(NNA2_KW, i); + rd::KW *nna1_kw = rd_file->get_kw(NNA1_KW, i); + rd::KW *nna2_kw = rd_file->get_kw(NNA2_KW, i); rd_grid_init_nnc_cells(lgr_grid1, lgr_grid2, nna1_kw, nna2_kw); } @@ -2457,19 +2466,19 @@ static rd_grid_ptr rd_grid_alloc_EGRID__(rd_grid_type *main_grid, const rd::File *rd_file, size_t grid_nr, bool apply_mapaxes, const int *ext_actnum) { - rd_kw_type *gridhead_kw = rd_file->get_kw(GRIDHEAD_KW, grid_nr); - rd_kw_type *zcorn_kw = rd_file->get_kw(ZCORN_KW, grid_nr); - rd_kw_type *coord_kw = rd_file->get_kw(COORD_KW, grid_nr); - rd_kw_type *corsnum_kw = NULL; - rd_kw_type *actnum_kw = NULL; - rd_kw_type *gridunit_kw = NULL; - rd_kw_type *mapaxes_kw = NULL; + rd::KW *gridhead_kw = rd_file->get_kw(GRIDHEAD_KW, grid_nr); + rd::KW *zcorn_kw = rd_file->get_kw(ZCORN_KW, grid_nr); + rd::KW *coord_kw = rd_file->get_kw(COORD_KW, grid_nr); + rd::KW *corsnum_kw = NULL; + rd::KW *actnum_kw = NULL; + rd::KW *gridunit_kw = NULL; + rd::KW *mapaxes_kw = NULL; int dualp_flag; int eclipse_version; if (grid_nr == 0) { - rd_kw_type *filehead_kw = rd_file->get_kw(FILEHEAD_KW, grid_nr); - dualp_flag = rd_kw_iget_int(filehead_kw, FILEHEAD_DUALP_INDEX); - eclipse_version = rd_kw_iget_int(filehead_kw, FILEHEAD_YEAR_INDEX); + rd::KW *filehead_kw = rd_file->get_kw(FILEHEAD_KW, grid_nr); + dualp_flag = filehead_kw->at(FILEHEAD_DUALP_INDEX); + eclipse_version = filehead_kw->at(FILEHEAD_YEAR_INDEX); } else { dualp_flag = main_grid->dualp_flag; eclipse_version = main_grid->eclipse_version; @@ -2485,7 +2494,7 @@ static rd_grid_ptr rd_grid_alloc_EGRID__(rd_grid_type *main_grid, else { if (rd_file->num_named_kw(ACTNUM_KW) > grid_nr) { actnum_kw = rd_file->get_kw(ACTNUM_KW, grid_nr); - actnum_data = rd_kw_get_int_ptr(actnum_kw); + actnum_data = actnum_kw->get_vector().data(); } } @@ -2537,7 +2546,7 @@ static rd_grid_ptr rd_grid_alloc_EGRID_all_grids(const char *grid_file, rd_grid_add_lgr(main_grid.get(), std::move(lgr_grid)); { rd_grid_type *host_grid; - rd_kw_type *hostnum_kw = + rd::KW *hostnum_kw = rd_file->get_kw(HOSTNUM_KW, grid_nr - 1); if (!lgr->parent_name) host_grid = main_grid.get(); @@ -2545,8 +2554,8 @@ static rd_grid_ptr rd_grid_alloc_EGRID_all_grids(const char *grid_file, host_grid = rd_grid_get_lgr(main_grid.get(), lgr->parent_name->c_str()); - rd_grid_install_lgr_EGRID(host_grid, lgr, - rd_kw_get_int_ptr(hostnum_kw)); + rd_grid_install_lgr_EGRID( + host_grid, lgr, hostnum_kw->get_vector().data()); } } main_grid->name = grid_file; @@ -2564,10 +2573,12 @@ static rd_grid_ptr rd_grid_alloc_EGRID(const char *grid_file, return rd_grid_alloc_EGRID_all_grids(grid_file, apply_mapaxes, NULL); } -static rd_grid_ptr rd_grid_alloc_GRID_data__( - rd_grid_type *global_grid, size_t num_coords, UnitSystem unit_system, - int dualp_flag, bool apply_mapaxes, int nx, int ny, int nz, int grid_nr, - int coords_size, int **coords, float **corners, const float *mapaxes) { +static rd_grid_ptr +rd_grid_alloc_GRID_data__(rd_grid_type *global_grid, size_t num_coords, + UnitSystem unit_system, int dualp_flag, + bool apply_mapaxes, int nx, int ny, int nz, + int grid_nr, int coords_size, const int **coords, + const float **corners, const float *mapaxes) { if (dualp_flag != FILEHEAD_SINGLE_POROSITY) nz = nz / 2; @@ -2591,10 +2602,10 @@ static rd_grid_ptr rd_grid_alloc_GRID_data__( } static int rd_grid_dual_porosity_GRID_check(rd::File *rd_file) { - rd_kw_type *dimens_kw = rd_file->get_kw(DIMENS_KW, 0); - int nx = rd_kw_iget_int(dimens_kw, DIMENS_NX_INDEX); - int ny = rd_kw_iget_int(dimens_kw, DIMENS_NY_INDEX); - int nz = rd_kw_iget_int(dimens_kw, DIMENS_NZ_INDEX); + rd::KW *dimens_kw = rd_file->get_kw(DIMENS_KW, 0); + int nx = dimens_kw->at(DIMENS_NX_INDEX); + int ny = dimens_kw->at(DIMENS_NY_INDEX); + int nz = dimens_kw->at(DIMENS_NZ_INDEX); if (nx < 0 || ny < 0 || nz < 0) throw std::invalid_argument( @@ -2609,8 +2620,8 @@ static int rd_grid_dual_porosity_GRID_check(rd::File *rd_file) { size_t matrix_index = 0; size_t fracture_index; - rd_kw_type *matrix_kw; - rd_kw_type *fracture_kw; + rd::KW *matrix_kw; + rd::KW *fracture_kw; size_t num_cells = static_cast(nx) * ny * nz; if (num_corners > num_cells) @@ -2622,7 +2633,7 @@ static int rd_grid_dual_porosity_GRID_check(rd::File *rd_file) { matrix_kw = rd_file->get_kw(CORNERS_KW, matrix_index); fracture_kw = rd_file->get_kw(CORNERS_KW, fracture_index); - if (!rd_kw_equal(matrix_kw, fracture_kw)) { + if (!(*matrix_kw == *fracture_kw)) { dualp_flag = FILEHEAD_SINGLE_POROSITY; break; } @@ -2647,10 +2658,10 @@ static rd_grid_ptr rd_grid_alloc_GRID__(rd_grid_type *global_grid, // 1: Fetching header data from the DIMENS keyword. { - rd_kw_type *dimens_kw = rd_file->get_kw(DIMENS_KW, grid_nr); - nx = rd_kw_iget_int(dimens_kw, DIMENS_NX_INDEX); - ny = rd_kw_iget_int(dimens_kw, DIMENS_NY_INDEX); - nz = rd_kw_iget_int(dimens_kw, DIMENS_NZ_INDEX); + rd::KW *dimens_kw = rd_file->get_kw(DIMENS_KW, grid_nr); + nx = dimens_kw->at(DIMENS_NX_INDEX); + ny = dimens_kw->at(DIMENS_NY_INDEX); + nz = dimens_kw->at(DIMENS_NZ_INDEX); if (nx < 0 || ny < 0 || nz < 0) throw std::invalid_argument(fmt::format( "Dimensions of grid were negative: nx={}, ny={}, nz={}", nx, ny, @@ -2661,7 +2672,7 @@ static rd_grid_ptr rd_grid_alloc_GRID__(rd_grid_type *global_grid, // keyword is optional, and is only applicable to the global grid. { if ((grid_nr == 0) && (rd_file->has_kw(MAPAXES_KW))) { - const rd_kw_type *mapaxes_kw = rd_file->get_kw(MAPAXES_KW, 0); + const rd::KW *mapaxes_kw = rd_file->get_kw(MAPAXES_KW, 0); mapaxes_data = rd_grid_get_mapaxes_from_kw__(mapaxes_kw); } } @@ -2718,18 +2729,18 @@ static rd_grid_ptr rd_grid_alloc_GRID__(rd_grid_type *global_grid, // CORNERS keywords. int coords_size = -1; - std::vector coords(num_coords); - std::vector corners(num_coords); + std::vector coords(num_coords); + std::vector corners(num_coords); for (size_t index = 0; index < num_coords; index++) { - const rd_kw_type *coords_kw = + const rd::KW *coords_kw = rd_file->get_kw(COORDS_KW, index + cell_offset); - const rd_kw_type *corners_kw = + const rd::KW *corners_kw = rd_file->get_kw(CORNERS_KW, index + cell_offset); - coords[index] = rd_kw_get_int_ptr(coords_kw); - corners[index] = rd_kw_get_float_ptr(corners_kw); - coords_size = rd_kw_get_size(coords_kw); + coords[index] = coords_kw->get_vector().data(); + corners[index] = corners_kw->get_vector().data(); + coords_size = rd::kw_get_size(coords_kw); } // Create the grid: auto grid = rd_grid_alloc_GRID_data__( @@ -4259,9 +4270,9 @@ double rd_grid_get_cell_volume1A(const rd_grid_type *rd_grid, */ static int rd_grid_get_property_index__(const rd_grid_type *rd_grid, - const rd_kw_type *rd_kw, int i, int j, + const rd::KW *rd_kw, int i, int j, int k) { - int kw_size = rd_kw_get_size(rd_kw); + int kw_size = rd::kw_get_size(rd_kw); int lookup_index = -1; if (kw_size == rd_grid->nx * rd_grid->ny * rd_grid->nz) @@ -4279,15 +4290,15 @@ static int rd_grid_get_property_index__(const rd_grid_type *rd_grid, return lookup_index; } -double rd_grid_get_property(const rd_grid_type *rd_grid, - const rd_kw_type *rd_kw, int i, int j, int k) { - rd_data_type data_type = rd_kw_get_data_type(rd_kw); +double rd_grid_get_property(const rd_grid_type *rd_grid, const rd::KW *rd_kw, + int i, int j, int k) { + rd_data_type data_type = rd_kw->data_type(); if (rd_type_is_numeric(data_type)) { int lookup_index = rd_grid_get_property_index__(rd_grid, rd_kw, i, j, k); if (lookup_index >= 0) - return rd_kw_iget_as_double(rd_kw, lookup_index); + return rd_kw->as_double(lookup_index); else return -1; /* Tried to lookup an inactive cell. */ @@ -4310,11 +4321,11 @@ double rd_grid_get_property(const rd_grid_type *rd_grid, types, otherwise it raises std::invalid_argument. */ std::vector rd_grid_get_column_property(const rd_grid_type *rd_grid, - const rd_kw_type *rd_kw, int i, + const rd::KW *rd_kw, int i, int j) { - rd_data_type data_type = rd_kw_get_data_type(rd_kw); + rd_data_type data_type = rd_kw->data_type(); if (rd_type_is_numeric(data_type)) { - int kw_size = rd_kw_get_size(rd_kw); + int kw_size = rd::kw_get_size(rd_kw); bool use_global_index = false; if (kw_size == rd_grid->nx * rd_grid->ny * rd_grid->nz) @@ -4325,17 +4336,17 @@ std::vector rd_grid_get_column_property(const rd_grid_type *rd_grid, throw std::invalid_argument(fmt::format( "incommensurable sizes: nx*ny*nz = {} nactive = {} " "kw_size = {}", - rd_grid->size, rd_grid->total_active, rd_kw_get_size(rd_kw))); + rd_grid->size, rd_grid->total_active, rd::kw_get_size(rd_kw))); std::vector column(rd_grid->nz, std::nan("")); for (int k = 0; k < rd_grid->nz; k++) { if (use_global_index) { int global_index = rd_grid_get_global_index3(rd_grid, i, j, k); - column[k] = rd_kw_iget_as_double(rd_kw, global_index); + column[k] = rd_kw->as_double(global_index); } else { int active_index = rd_grid_get_active_index3(rd_grid, i, j, k); if (active_index >= 0) - column[k] = rd_kw_iget_as_double(rd_kw, active_index); + column[k] = rd_kw->as_double(active_index); } } return column; @@ -4418,51 +4429,44 @@ void rd_grid_init_mapaxes_data_double(const rd_grid_type *grid, mapaxes[i] = grid->mapaxes.value()[i]; } -std::optional rd_grid_alloc_mapaxes_kw(const rd_grid_type *grid) { +std::optional> +rd_grid_alloc_mapaxes_kw(const rd_grid_type *grid) { if (grid->mapaxes) - return make_rd_kw(MAPAXES_KW, 6, RD_FLOAT, grid->mapaxes->data()); + return std::make_unique( + MAPAXES_KW, + std::vector(grid->mapaxes->begin(), grid->mapaxes->end())); else return std::nullopt; } -static rd_kw_type *rd_grid_alloc_mapunits_kw(UnitSystem output_unit) { - auto mapunits_kw = make_rd_kw(MAPUNITS_KW, 1, RD_CHAR); - - if (output_unit == UnitSystem::FIELD) - rd_kw_iset_string8(mapunits_kw.get(), 0, "FEET"); - - if (output_unit == UnitSystem::METRIC) - rd_kw_iset_string8(mapunits_kw.get(), 0, "METRES"); - - if (output_unit == UnitSystem::LAB) - rd_kw_iset_string8(mapunits_kw.get(), 0, "CM"); +static const std::unordered_map length_units = { + {UnitSystem::FIELD, "FEET"}, + {UnitSystem::METRIC, "METRES"}, + {UnitSystem::LAB, "CM"}, +}; - return mapunits_kw.release(); +static std::unique_ptr +rd_grid_alloc_mapunits_kw(UnitSystem output_unit) { + return std::make_unique( + MAPUNITS_KW, + std::initializer_list{length_units.at(output_unit)}); } -static rd_kw_type *rd_grid_alloc_gridunits_kw(UnitSystem output_unit) { - auto gridunits_kw = make_rd_kw(GRIDUNIT_KW, 2, RD_CHAR); - - if (output_unit == UnitSystem::FIELD) - rd_kw_iset_string8(gridunits_kw.get(), 0, "FEET"); - - if (output_unit == UnitSystem::METRIC) - rd_kw_iset_string8(gridunits_kw.get(), 0, "METRES"); - - if (output_unit == UnitSystem::LAB) - rd_kw_iset_string8(gridunits_kw.get(), 0, "CM"); - - rd_kw_iset_string8(gridunits_kw.get(), 1, ""); - return gridunits_kw.release(); +static std::unique_ptr +rd_grid_alloc_gridunits_kw(UnitSystem output_unit) { + return std::make_unique( + GRIDUNIT_KW, + std::initializer_list{length_units.at(output_unit), ""}); } -static UnitSystem rd_grid_check_unit_system(const rd_kw_type *gridunit_kw) { - const char *length_unit = rd_kw_iget_char_ptr(gridunit_kw, 0); +static UnitSystem rd_grid_check_unit_system(const rd::KW *gridunit_kw) { + const std::string length_unit = + rd::strip_spaces(gridunit_kw->at(0)); - if (strncmp(length_unit, "FEET", 4) == 0) + if (length_unit == "FEET") return UnitSystem::FIELD; - if (strncmp(length_unit, "CM", 2) == 0) + if (length_unit == "CM") return UnitSystem::LAB; return UnitSystem::METRIC; @@ -4493,19 +4497,21 @@ float rd_grid_output_scaling(const rd_grid_type *grid, UnitSystem output_unit) { static void rd_grid_fwrite_mapaxes(const rd_grid_type *grid, ERT::FortIO &fortio) { if (auto mapaxes_kw = rd_grid_alloc_mapaxes_kw(grid)) - rd_kw_fwrite(mapaxes_kw->get(), fortio); + (*mapaxes_kw)->fwrite(fortio); } static void rd_grid_fwrite_mapunits(ERT::FortIO &fortio, UnitSystem output_unit) { - rd_kw_ptr mapunits_kw(rd_grid_alloc_mapunits_kw(output_unit), rd_kw_free); - rd_kw_fwrite(mapunits_kw.get(), fortio); + std::unique_ptr mapunits_kw = + rd_grid_alloc_mapunits_kw(output_unit); + mapunits_kw->fwrite(fortio); } static void rd_grid_fwrite_gridunits(ERT::FortIO &fortio, UnitSystem output_unit) { - rd_kw_ptr gridunits_kw(rd_grid_alloc_gridunits_kw(output_unit), rd_kw_free); - rd_kw_fwrite(gridunits_kw.get(), fortio); + std::unique_ptr gridunits_kw = + rd_grid_alloc_gridunits_kw(output_unit); + gridunits_kw->fwrite(fortio); } static void rd_grid_fwrite_main_GRID_headers(const rd_grid_type *rd_grid, @@ -4521,34 +4527,23 @@ static void rd_grid_fwrite_main_GRID_headers(const rd_grid_type *rd_grid, static void rd_grid_fwrite_GRID__(const rd_grid_type *grid, int coords_size, ERT::FortIO &fortio, UnitSystem output_unit) { if (grid->parent_grid != NULL) { - auto lgr_kw = make_rd_kw(LGR_KW, 1, RD_CHAR); - rd_kw_iset_string8(lgr_kw.get(), 0, grid->name.c_str()); - rd_kw_fwrite(lgr_kw.get(), fortio); + rd::KW{LGR_KW, {grid->name}}.fwrite(fortio); } - { - auto dimens_kw = make_rd_kw(DIMENS_KW, 3, RD_INT); - rd_kw_iset_int(dimens_kw.get(), 0, grid->nx); - rd_kw_iset_int(dimens_kw.get(), 1, grid->ny); - if (grid->dualp_flag == FILEHEAD_SINGLE_POROSITY) - rd_kw_iset_int(dimens_kw.get(), 2, grid->nz); - else - rd_kw_iset_int(dimens_kw.get(), 2, 2 * grid->nz); - - rd_kw_fwrite(dimens_kw.get(), fortio); - } + rd::KW{DIMENS_KW, + std::vector{grid->nx, grid->ny, + grid->dualp_flag == FILEHEAD_SINGLE_POROSITY + ? grid->nz + : 2 * grid->nz}} + .fwrite(fortio); if (grid->parent_grid == NULL) rd_grid_fwrite_main_GRID_headers(grid, fortio, output_unit); - { - auto radial_kw = make_rd_kw(RADIAL_KW, 1, RD_CHAR); - rd_kw_iset_string8(radial_kw.get(), 0, "FALSE"); - rd_kw_fwrite(radial_kw.get(), fortio); - } + rd::KW{RADIAL_KW, {"FALSE"}}.fwrite(fortio); - auto coords_kw = make_rd_kw(COORDS_KW, coords_size, RD_INT); - auto corners_kw = make_rd_kw(CORNERS_KW, 24, RD_FLOAT); + auto coords_kw = std::make_unique(COORDS_KW, coords_size, RD_INT); + auto corners_kw = std::make_unique(CORNERS_KW, 24, RD_FLOAT); for (int k = 0; k < grid->nz; k++) { for (int j = 0; j < grid->ny; j++) { for (int i = 0; i < grid->nx; i++) { @@ -4628,22 +4623,16 @@ static void rd_grid_fwrite_main_EGRID_header(const rd_grid_type *grid, int RELEASE_YEAR = 2007; int COMPAT_VERSION = 0; { - auto filehead_kw = make_rd_kw(FILEHEAD_KW, 100, RD_INT); - rd_kw_scalar_set_int(filehead_kw.get(), 0); - - rd_kw_iset_int(filehead_kw.get(), FILEHEAD_VERSION_INDEX, - EGRID_VERSION); - rd_kw_iset_int(filehead_kw.get(), FILEHEAD_YEAR_INDEX, RELEASE_YEAR); - rd_kw_iset_int(filehead_kw.get(), FILEHEAD_COMPAT_INDEX, - COMPAT_VERSION); - rd_kw_iset_int(filehead_kw.get(), FILEHEAD_TYPE_INDEX, - FILEHEAD_GRIDTYPE_CORNERPOINT); - rd_kw_iset_int(filehead_kw.get(), FILEHEAD_DUALP_INDEX, - grid->dualp_flag); - rd_kw_iset_int(filehead_kw.get(), FILEHEAD_ORGFORMAT_INDEX, - FILEHEAD_ORGTYPE_CORNERPOINT); - - rd_kw_fwrite(filehead_kw.get(), fortio); + std::vector filehead_data(100, 0); + filehead_data[FILEHEAD_VERSION_INDEX] = EGRID_VERSION; + filehead_data[FILEHEAD_YEAR_INDEX] = RELEASE_YEAR; + filehead_data[FILEHEAD_COMPAT_INDEX] = COMPAT_VERSION; + filehead_data[FILEHEAD_TYPE_INDEX] = FILEHEAD_GRIDTYPE_CORNERPOINT; + filehead_data[FILEHEAD_DUALP_INDEX] = grid->dualp_flag; + filehead_data[FILEHEAD_ORGFORMAT_INDEX] = FILEHEAD_ORGTYPE_CORNERPOINT; + + rd::KW filehead_kw{FILEHEAD_KW, std::move(filehead_data)}; + filehead_kw.fwrite(fortio); } rd_grid_fwrite_mapunits(fortio, output_unit); @@ -4655,9 +4644,9 @@ static void rd_grid_fwrite_main_EGRID_header(const rd_grid_type *grid, static void rd_grid_fwrite_gridhead_kw(int nx, int ny, int nz, int grid_nr, ERT::FortIO &fortio) { - rd_kw_ptr gridhead_kw(rd_grid_alloc_gridhead_kw(nx, ny, nz, grid_nr), - rd_kw_free); - rd_kw_fwrite(gridhead_kw.get(), fortio); + std::unique_ptr gridhead_kw = + rd_grid_alloc_gridhead_kw(nx, ny, nz, grid_nr); + gridhead_kw->fwrite(fortio); } /** @@ -4810,10 +4799,10 @@ void rd_grid_init_coord_data_double(const rd_grid_type *grid, double *coord) { static void rd_grid_assert_coord_kw(rd_grid_type *grid) { if (!grid->coord_kw) { - grid->coord_kw.reset( - rd_kw_alloc(COORD_KW, rd_grid_get_coord_size(grid), RD_FLOAT)); - rd_grid_init_coord_data(grid, static_cast(rd_kw_get_void_ptr( - grid->coord_kw.get()))); + grid->coord_kw = std::make_unique( + COORD_KW, rd_grid_get_coord_size(grid), RD_FLOAT); + rd_grid_init_coord_data(grid, + grid->coord_kw->get_vector().data()); } } @@ -4871,21 +4860,20 @@ void rd_grid_init_zcorn_data_double(const rd_grid_type *grid, double *zcorn) { rd_grid_init_zcorn_data__(grid, NULL, zcorn); } -rd_kw_ptr rd_grid_alloc_zcorn_kw(const rd_grid_type *grid) { - auto zcorn_kw = - make_rd_kw(ZCORN_KW, rd_grid_get_zcorn_size(grid), RD_FLOAT); - rd_grid_init_zcorn_data( - grid, static_cast(rd_kw_get_void_ptr(zcorn_kw.get()))); +std::unique_ptr rd_grid_alloc_zcorn_kw(const rd_grid_type *grid) { + auto zcorn_kw = std::make_unique( + ZCORN_KW, rd_grid_get_zcorn_size(grid), RD_FLOAT); + rd_grid_init_zcorn_data(grid, zcorn_kw->get_vector().data()); return zcorn_kw; } -rd_kw_ptr rd_grid_alloc_coord_kw(const rd_grid_type *grid) { +std::unique_ptr rd_grid_alloc_coord_kw(const rd_grid_type *grid) { if (grid->coord_kw) - return {rd_kw_alloc_copy(grid->coord_kw.get()), &rd_kw_free}; + return std::make_unique(*grid->coord_kw.get()); - auto coord_kw = - make_rd_kw(COORD_KW, RD_GRID_COORD_SIZE(grid->nx, grid->ny), RD_FLOAT); - rd_grid_init_coord_data(grid, rd_kw_get_float_ptr(coord_kw.get())); + auto coord_kw = std::make_unique( + COORD_KW, RD_GRID_COORD_SIZE(grid->nx, grid->ny), RD_FLOAT); + rd_grid_init_coord_data(grid, coord_kw->get_vector().data()); return coord_kw; } @@ -4932,52 +4920,66 @@ void rd_grid_init_actnum_data(const rd_grid_type *grid, int *actnum) { } } -rd_kw_ptr rd_grid_alloc_actnum_kw(const rd_grid_type *grid) { +std::unique_ptr rd_grid_alloc_actnum_kw(const rd_grid_type *grid) { if (grid->size > std::numeric_limits::max()) throw std::out_of_range( "Size of grid overflowed max size of ACTNUM keyword"); - auto actnum_kw = - make_rd_kw(ACTNUM_KW, static_cast(grid->size), RD_INT); - rd_grid_init_actnum_data( - grid, static_cast(rd_kw_get_void_ptr(actnum_kw.get()))); + auto actnum_kw = std::make_unique(ACTNUM_KW, grid->size, RD_INT); + rd_grid_init_actnum_data(grid, actnum_kw->get_vector().data()); return actnum_kw; } -void rd_grid_compressed_kw_copy(const rd_grid_type *grid, rd_kw_type *target_kw, - const rd_kw_type *src_kw) { - if ((rd_kw_get_size(target_kw) == rd_grid_get_nactive(grid)) && - (rd_kw_get_size(src_kw) == rd_grid_get_global_size(grid))) { - int active_index = 0; - for (int i = 0; i < rd_grid_get_global_size(grid); i++) { - if (rd_grid_cell_active1(grid, i)) { - rd_kw_iset(target_kw, active_index, rd_kw_iget_ptr(src_kw, i)); - active_index++; - } - } +void rd_grid_compressed_kw_copy(const rd_grid_type *grid, rd::KW *target_kw, + const rd::KW *src_kw) { + if ((rd::kw_get_size(target_kw) == rd_grid_get_nactive(grid)) && + (rd::kw_get_size(src_kw) == rd_grid_get_global_size(grid))) { + std::visit( + [&](auto &&target_alt) { + using T = + typename std::decay_t::value_type; + auto &target_vec = target_kw->get_vector(); + const auto &src_vec = src_kw->get_vector(); + int active_index = 0; + for (int i = 0; i < rd_grid_get_global_size(grid); i++) { + if (rd_grid_cell_active1(grid, i)) { + target_vec[active_index] = src_vec[i]; + active_index++; + } + } + }, + target_kw->data().value()); } else throw std::invalid_argument(fmt::format( "rd_grid_compressed_kw_copy: size mismatch target:{} src:{} " "expected {},{}", - rd_kw_get_size(target_kw), rd_kw_get_size(src_kw), + rd::kw_get_size(target_kw), rd::kw_get_size(src_kw), rd_grid_get_nactive(grid), rd_grid_get_global_size(grid))); } -void rd_grid_global_kw_copy(const rd_grid_type *grid, rd_kw_type *target_kw, - const rd_kw_type *src_kw) { - if ((rd_kw_get_size(src_kw) == rd_grid_get_nactive(grid)) && - (rd_kw_get_size(target_kw) == rd_grid_get_global_size(grid))) { - int active_index = 0; - for (int i = 0; i < rd_grid_get_global_size(grid); i++) { - if (rd_grid_cell_active1(grid, i)) { - rd_kw_iset(target_kw, i, rd_kw_iget_ptr(src_kw, active_index)); - active_index++; - } - } +void rd_grid_global_kw_copy(const rd_grid_type *grid, rd::KW *target_kw, + const rd::KW *src_kw) { + if ((rd::kw_get_size(src_kw) == rd_grid_get_nactive(grid)) && + (rd::kw_get_size(target_kw) == rd_grid_get_global_size(grid))) { + std::visit( + [&](auto &&target_alt) { + using T = + typename std::decay_t::value_type; + auto &target_vec = target_kw->get_vector(); + const auto &src_vec = src_kw->get_vector(); + int active_index = 0; + for (int i = 0; i < rd_grid_get_global_size(grid); i++) { + if (rd_grid_cell_active1(grid, i)) { + target_vec[i] = src_vec[active_index]; + active_index++; + } + } + }, + target_kw->data().value()); } else throw std::invalid_argument(fmt::format( "rd_grid_global_kw_copy: size mismatch target:{} src:{} " "expected {},{}", - rd_kw_get_size(target_kw), rd_kw_get_size(src_kw), + rd::kw_get_size(target_kw), rd::kw_get_size(src_kw), rd_grid_get_global_size(grid), rd_grid_get_nactive(grid))); } @@ -4988,14 +4990,13 @@ static void rd_grid_init_hostnum_data(const rd_grid_type *grid, int *hostnum) { } } -static rd_kw_ptr rd_grid_alloc_hostnum_kw(const rd_grid_type *grid) { +static std::unique_ptr +rd_grid_alloc_hostnum_kw(const rd_grid_type *grid) { if (grid->size > std::numeric_limits::max()) throw std::out_of_range( "Size of grid overflowed max size of HOSTNUM keyword"); - auto hostnum_kw = - make_rd_kw(HOSTNUM_KW, static_cast(grid->size), RD_INT); - rd_grid_init_hostnum_data( - grid, static_cast(rd_kw_get_void_ptr(hostnum_kw.get()))); + auto hostnum_kw = std::make_unique(HOSTNUM_KW, grid->size, RD_INT); + rd_grid_init_hostnum_data(grid, hostnum_kw->get_vector().data()); return hostnum_kw; } @@ -5006,15 +5007,14 @@ static void rd_grid_init_corsnum_data(const rd_grid_type *grid, int *corsnum) { } } -static rd_kw_type *rd_grid_alloc_corsnum_kw(const rd_grid_type *grid) { +static std::unique_ptr +rd_grid_alloc_corsnum_kw(const rd_grid_type *grid) { if (grid->size > std::numeric_limits::max()) throw std::out_of_range( "Size of grid overflowed max size of CORSNUM keyword"); - auto corsnum_kw = - make_rd_kw(CORSNUM_KW, static_cast(grid->size), RD_INT); - rd_grid_init_corsnum_data( - grid, static_cast(rd_kw_get_void_ptr(corsnum_kw.get()))); - return corsnum_kw.release(); + auto corsnum_kw = std::make_unique(CORSNUM_KW, grid->size, RD_INT); + rd_grid_init_corsnum_data(grid, corsnum_kw->get_vector().data()); + return corsnum_kw; } void rd_grid_reset_actnum(rd_grid_type *grid, const int *actnum) { @@ -5063,27 +5063,16 @@ static void rd_grid_fwrite_self_nnc(const rd_grid_type *grid, "rd_grid_fwrite_self_nnc: NNC count exceeds INT_MAX"); int num_nnc = static_cast(g1.size()); - // ensure that g1.data() != nullptr - if (g1.empty()) { - g1.resize(1, default_index); - g2.resize(1, default_index); - } - - auto nnc1_kw = - rd_kw_ptr(rd_kw_alloc_new_shared(NNC1_KW, num_nnc, RD_INT, g1.data()), - &rd_kw_free); - auto nnc2_kw = - rd_kw_ptr(rd_kw_alloc_new_shared(NNC2_KW, num_nnc, RD_INT, g2.data()), - &rd_kw_free); - auto nnchead_kw = make_rd_kw(NNCHEAD_KW, NNCHEAD_SIZE, RD_INT); - - rd_kw_scalar_set_int(nnchead_kw.get(), 0); - rd_kw_iset_int(nnchead_kw.get(), NNCHEAD_NUMNNC_INDEX, num_nnc); - rd_kw_iset_int(nnchead_kw.get(), NNCHEAD_LGR_INDEX, grid->lgr_nr); + rd::KW nnc1_kw{NNC1_KW, std::move(g1)}; + rd::KW nnc2_kw{NNC2_KW, std::move(g2)}; + std::vector nnchead_data(NNCHEAD_SIZE, 0); + nnchead_data[NNCHEAD_NUMNNC_INDEX] = num_nnc; + nnchead_data[NNCHEAD_LGR_INDEX] = grid->lgr_nr; - rd_kw_fwrite(nnchead_kw.get(), fortio); - rd_kw_fwrite(nnc1_kw.get(), fortio); - rd_kw_fwrite(nnc2_kw.get(), fortio); + rd::KW nnchead_kw{NNCHEAD_KW, std::move(nnchead_data)}; + nnchead_kw.fwrite(fortio); + nnc1_kw.fwrite(fortio); + nnc2_kw.fwrite(fortio); } static void rd_grid_fwrite_EGRID__(rd_grid_type *grid, ERT::FortIO &fortio, @@ -5096,21 +5085,16 @@ static void rd_grid_fwrite_EGRID__(rd_grid_type *grid, ERT::FortIO &fortio, if (!is_lgr) { rd_grid_fwrite_main_EGRID_header(grid, fortio, output_unit); } else { - { - auto lgr_kw = make_rd_kw(LGR_KW, 1, RD_CHAR); - rd_kw_iset_string8(lgr_kw.get(), 0, grid->name.c_str()); - rd_kw_fwrite(lgr_kw.get(), fortio); - } + rd::KW{LGR_KW, {grid->name}}.fwrite(fortio); { - auto lgr_parent_kw = make_rd_kw(LGR_PARENT_KW, 1, RD_CHAR); + rd::KW lgr_parent_kw{LGR_PARENT_KW, 1, RD_CHAR}; if (grid->parent_name.has_value()) - rd_kw_iset_string8(lgr_parent_kw.get(), 0, - grid->parent_name->c_str()); + lgr_parent_kw.set_padded(0, *grid->parent_name); else - rd_kw_iset_string8(lgr_parent_kw.get(), 0, ""); + lgr_parent_kw.set_padded(0, ""); - rd_kw_fwrite(lgr_parent_kw.get(), fortio); + lgr_parent_kw.fwrite(fortio); } } @@ -5120,41 +5104,39 @@ static void rd_grid_fwrite_EGRID__(rd_grid_type *grid, ERT::FortIO &fortio, { rd_grid_assert_coord_kw(grid); { - auto coord_kw = - rd_kw_ptr(rd_kw_alloc_copy(grid->coord_kw.get()), &rd_kw_free); + rd::KW coord_kw{*grid->coord_kw.get()}; auto zcorn_kw = rd_grid_alloc_zcorn_kw(grid); if (output_unit != grid->unit_system) { double scale_factor = rd_grid_output_scaling(grid, output_unit); - rd_kw_scale_float(coord_kw.get(), scale_factor); - rd_kw_scale_float(zcorn_kw.get(), scale_factor); + coord_kw.scale(static_cast(scale_factor)); + zcorn_kw->scale(static_cast(scale_factor)); } - rd_kw_fwrite(coord_kw.get(), fortio); - rd_kw_fwrite(zcorn_kw.get(), fortio); + coord_kw.fwrite(fortio); + zcorn_kw->fwrite(fortio); } { auto actnum_kw = rd_grid_alloc_actnum_kw(grid); - rd_kw_fwrite(actnum_kw.get(), fortio); + actnum_kw->fwrite(fortio); } if (is_lgr) { auto hostnum_kw = rd_grid_alloc_hostnum_kw(grid); - rd_kw_fwrite(hostnum_kw.get(), fortio); + hostnum_kw->fwrite(fortio); } if (grid->coarsening_active) { - auto corsnum_kw = - rd_kw_ptr(rd_grid_alloc_corsnum_kw(grid), &rd_kw_free); - rd_kw_fwrite(corsnum_kw.get(), fortio); + auto corsnum_kw = rd_grid_alloc_corsnum_kw(grid); + corsnum_kw->fwrite(fortio); } { - auto endgrid_kw = make_rd_kw(ENDGRID_KW, 0, RD_INT); - rd_kw_fwrite(endgrid_kw.get(), fortio); + rd::KW endgrid_kw{ENDGRID_KW, 0, RD_INT}; + endgrid_kw.fwrite(fortio); } } if (is_lgr) { - auto endlgr_kw = make_rd_kw(ENDLGR_KW, 0, RD_INT); - rd_kw_fwrite(endlgr_kw.get(), fortio); + rd::KW endlgr_kw{ENDLGR_KW, 0, RD_INT}; + endlgr_kw.fwrite(fortio); } rd_grid_fwrite_self_nnc(grid, fortio); } @@ -5198,12 +5180,12 @@ bool rd_grid_dual_grid(const rd_grid_type *rd_grid) { return true; } -static rd_kw_ptr rd_grid_alloc_volume_kw_active(const rd_grid_type *grid) { - auto volume_kw = - make_rd_kw("VOLUME", rd_grid_get_active_size(grid), RD_DOUBLE); +static std::unique_ptr +rd_grid_alloc_volume_kw_active(const rd_grid_type *grid) { + auto volume_kw = std::make_unique( + "VOLUME", rd_grid_get_active_size(grid), RD_DOUBLE); { - double *volume_data = - static_cast(rd_kw_get_ptr(volume_kw.get())); + std::vector &volume_data = volume_kw->get_vector(); int active_index; for (active_index = 0; active_index < rd_grid_get_active_size(grid); active_index++) { @@ -5214,12 +5196,12 @@ static rd_kw_ptr rd_grid_alloc_volume_kw_active(const rd_grid_type *grid) { return volume_kw; } -static rd_kw_ptr rd_grid_alloc_volume_kw_global(const rd_grid_type *grid) { - auto volume_kw = - make_rd_kw("VOLUME", rd_grid_get_global_size(grid), RD_DOUBLE); +static std::unique_ptr +rd_grid_alloc_volume_kw_global(const rd_grid_type *grid) { + auto volume_kw = std::make_unique( + "VOLUME", rd_grid_get_global_size(grid), RD_DOUBLE); { - double *volume_data = - static_cast(rd_kw_get_ptr(volume_kw.get())); + std::vector &volume_data = volume_kw->get_vector(); int global_index; for (global_index = 0; global_index < rd_grid_get_global_size(grid); global_index++) { @@ -5230,7 +5212,8 @@ static rd_kw_ptr rd_grid_alloc_volume_kw_global(const rd_grid_type *grid) { return volume_kw; } -rd_kw_ptr rd_grid_alloc_volume_kw(const rd_grid_type *grid, bool active_size) { +std::unique_ptr rd_grid_alloc_volume_kw(const rd_grid_type *grid, + bool active_size) { if (active_size) return rd_grid_alloc_volume_kw_active(grid); else diff --git a/lib/resdata/rd_grid_pybind.cpp b/lib/resdata/rd_grid_pybind.cpp index e51b6fe39..c98dd9ed9 100644 --- a/lib/resdata/rd_grid_pybind.cpp +++ b/lib/resdata/rd_grid_pybind.cpp @@ -38,9 +38,9 @@ PYBIND11_MODULE(_grid, m) { std::optional actnum, std::optional mapaxes) { return to_capsule(rd_grid_alloc_GRDECL_kw( - nx, ny, nz, from_cwrap(zcorn), - from_cwrap(coord), from_cwrap(actnum), - from_cwrap(mapaxes))); + nx, ny, nz, from_cwrap(zcorn), + from_cwrap(coord), from_cwrap(actnum), + from_cwrap(mapaxes))); }, py::return_value_policy::reference); m.def( @@ -196,7 +196,7 @@ PYBIND11_MODULE(_grid, m) { m.def("_grid_value", [](py::handle self, py::handle kw, int i, int j, int k) { return rd_grid_get_property(from_cwrap(self), - from_cwrap(kw), i, j, k); + from_cwrap(kw), i, j, k); }); m.def("_get_cell_volume", [](py::handle self, int index) { return rd_grid_get_cell_volume1(from_cwrap(self), index); @@ -216,7 +216,7 @@ PYBIND11_MODULE(_grid, m) { }); m.def("_load_column", [](py::handle self, py::handle kw, int i, int j) { return rd_grid_get_column_property(from_cwrap(self), - from_cwrap(kw), i, j); + from_cwrap(kw), i, j); }); m.def("_get_top", [](py::handle self, int i, int j) { return rd_grid_get_top2(from_cwrap(self), i, j); @@ -283,11 +283,9 @@ PYBIND11_MODULE(_grid, m) { [](py::handle self) { auto rd_grid = from_cwrap(self); int size = rd_grid_get_global_size(rd_grid); - rd_kw_ptr actnum(rd_kw_alloc("ACTNUM", size, RD_INT), rd_kw_free); - if (!actnum) - throw std::runtime_error( - fmt::format("Could not allocate ACTNUM of size {}", size)); - rd_grid_init_actnum_data(rd_grid, rd_kw_get_int_ptr(actnum.get())); + std::unique_ptr actnum = + std::make_unique("ACTNUM", size, RD_INT); + rd_grid_init_actnum_data(rd_grid, actnum->get_vector().data()); return to_capsule(actnum.release()); }, @@ -295,14 +293,14 @@ PYBIND11_MODULE(_grid, m) { m.def("_compressed_kw_copy", [](py::handle self, py::handle kw_copy, py::handle kw) { rd_grid_compressed_kw_copy(from_cwrap(self), - from_cwrap(kw_copy), - from_cwrap(kw)); + from_cwrap(kw_copy), + from_cwrap(kw)); }); m.def("_global_kw_copy", [](py::handle self, py::handle kw_copy, py::handle kw) { rd_grid_global_kw_copy(from_cwrap(self), - from_cwrap(kw_copy), - from_cwrap(kw)); + from_cwrap(kw_copy), + from_cwrap(kw)); }); m.def( "_create_volume_keyword", @@ -367,7 +365,7 @@ PYBIND11_MODULE(_grid, m) { }); m.def("_export_data_as_int", [](py::array_t idx, py::handle kw, int32_t fill_value) { - auto rd_kw = from_cwrap(kw); + auto rd_kw = from_cwrap(kw); auto idx_buffer = idx.request(); int32_t *idx_ptr = static_cast(idx_buffer.ptr); @@ -376,7 +374,7 @@ PYBIND11_MODULE(_grid, m) { int32_t *data_ptr = static_cast(data_buffer.ptr); std::fill(data_ptr, data_ptr + data_buffer.size, fill_value); - int *input = rd_kw_get_int_ptr(rd_kw); + int *input = rd_kw->get_vector().data(); for (py::ssize_t i = 0; i < idx_buffer.size; i++) { int32_t di = idx_ptr[i]; if (di >= 0) @@ -386,7 +384,7 @@ PYBIND11_MODULE(_grid, m) { }); m.def("_export_data_as_double", [](py::array_t idx, py::handle kw, double fill_value) { - auto rd_kw = from_cwrap(kw); + auto rd_kw = from_cwrap(kw); auto idx_buffer = idx.request(); int32_t *idx_ptr = static_cast(idx_buffer.ptr); @@ -398,7 +396,7 @@ PYBIND11_MODULE(_grid, m) { for (py::ssize_t i = 0; i < idx_buffer.size; i++) { int32_t di = idx_ptr[i]; if (di >= 0) - data_ptr[i] = rd_kw_iget_as_double(rd_kw, di); + data_ptr[i] = rd_kw->as_double(di); } return data; }); diff --git a/lib/resdata/rd_kw.cpp b/lib/resdata/rd_kw.cpp index fef3eefa7..e6841cfa9 100644 --- a/lib/resdata/rd_kw.cpp +++ b/lib/resdata/rd_kw.cpp @@ -4,8 +4,16 @@ #include #include +#include +#include +#include +#include +#include #include #include +#include +#include +#include #include #include @@ -17,21 +25,26 @@ #include #include #include +#include + +double rd::KW::as_double(size_t index) const { + if (rd_type_is_float(m_data_type)) { + return static_cast(this->at(index)); + } else if (rd_type_is_double(m_data_type)) { + return this->at(index); + } else if (rd_type_is_int(m_data_type)) { + return static_cast(this->at(index)); + } else + throw std::invalid_argument("cannot be converted to double"); +} -#define RD_KW_TYPE_ID 6111098 - -struct rd_kw_struct { - UTIL_TYPE_ID_DECLARATION; - int size; - rd_data_type data_type; - char * - header8; /* Header which is right padded with ' ' to become exactly 8 characters long. Should only be used internally.*/ - char *header; /* Header which is trimmed to no-space. */ - char *data; /* The actual data vector. */ - bool shared_data; /* Whether this keyword has shared data or not. */ -}; - -UTIL_IS_INSTANCE_FUNCTION(rd_kw, RD_KW_TYPE_ID) +/* + Character data in restart format files comes as an array of fixed-length + string. Each of these strings is 8 characters long. The type name, + i.e. 'REAL', 'INTE', ... , come as 4 character strings. +*/ +#define RD_KW_HEADER_DATA_SIZE RD_STRING8_LENGTH + RD_TYPE_LENGTH + 4 +#define RD_KW_HEADER_FORTIO_SIZE RD_KW_HEADER_DATA_SIZE + 8 /* For some peculiar reason the keyword data is written in blocks, all numeric data is in blocks of 1000 elements, and character data is @@ -61,32 +74,7 @@ UTIL_IS_INSTANCE_FUNCTION(rd_kw, RD_KW_TYPE_ID) #define COLUMNS_BOOL 25 /* Format string used when writing a formatted header. */ -#define WRITE_HEADER_FMT " '%-8s' %11d '%-4s'\n" - -/* Format string used when reading and writing formatted - files. Observe the following about these format strings: - - 1. The format string for reading double contains two '%' - identifiers, that is because doubles are read by parsing a - prefix and power separately. - - 2. For both double and float the write format contains two '%' - characters - that is because the values are split in a prefix - and a power prior to writing - see the function - __fprintf_scientific(). - - 3. The logical type involves converting back and forth between 'T' - and 'F' and internal logical representation. The format strings - are therefore for reading/writing a character. - -*/ - -#define READ_FMT_CHAR "%8c" -#define READ_FMT_FLOAT "%gE" -#define READ_FMT_INT "%d" -#define READ_FMT_MESS "%8c" -#define READ_FMT_BOOL " %c" -#define READ_FMT_DOUBLE "%lgD%d" +#define WRITE_HEADER_FMT " '{:<8}' {:11d} '{:<4}'\n" /* The boolean type is not a native type which can be uniquely identified between Fortran, C, formatted and unformatted @@ -101,55 +89,20 @@ UTIL_IS_INSTANCE_FUNCTION(rd_kw, RD_KW_TYPE_ID) RD_BOOL_FALSE_INT respectively. Internally in an rd_kw instance boolean values are represented as - integers (NOT bool), with the representation given by RD_BOOL_TRUE_INT - and RD_BOOL_FALSE_INT. This implies that read/write of unformatted - data can go transparently without between ECLIPSE and the rd_kw - implementation, but exported set()/get() functions with bool must - intercept the bool values and convert to the appropriate integer - value. -*/ + char (NOT bool). */ // For formatted files: #define BOOL_TRUE_CHAR 'T' #define BOOL_FALSE_CHAR 'F' -rd_type_enum rd_kw_get_type(const rd_kw_type *); -void rd_kw_set_data_type(rd_kw_type *rd_kw, rd_data_type data_type); - -static std::string read_fmt_string(const rd_data_type rd_type) { - return fmt::format("%{}c", rd_type_get_sizeof_iotype(rd_type)); -} - -static std::string read_fmt(const rd_data_type data_type) { - switch (rd_type_get_type(data_type)) { - case (RD_CHAR_TYPE): - return READ_FMT_CHAR; - case (RD_INT_TYPE): - return READ_FMT_INT; - case (RD_FLOAT_TYPE): - return READ_FMT_FLOAT; - case (RD_DOUBLE_TYPE): - return READ_FMT_DOUBLE; - case (RD_BOOL_TYPE): - return READ_FMT_BOOL; - case (RD_MESS_TYPE): - return READ_FMT_MESS; - case (RD_STRING_TYPE): - return read_fmt_string(data_type); - default: - throw std::invalid_argument( - fmt::format("invalid rd_type: {}", rd_type_name(data_type))); - } -} - -static int get_blocksize(rd_data_type data_type) { +static size_t get_blocksize(rd_data_type data_type) { if (rd_type_is_alpha(data_type)) return BLOCKSIZE_CHAR; return BLOCKSIZE_NUMERIC; } -static int get_columns(const rd_data_type data_type) { +static size_t get_columns(const rd_data_type data_type) { switch (rd_type_get_type(data_type)) { case (RD_CHAR_TYPE): return COLUMNS_CHAR; @@ -171,320 +124,130 @@ static int get_columns(const rd_data_type data_type) { } } -static void rd_kw_assert_index(const rd_kw_type *rd_kw, int index, - const char *caller) { - if (index < 0 || index >= rd_kw->size) - throw std::invalid_argument( - fmt::format("Invalid index lookup. kw:{} input_index:{} size:{}", - rd_kw->header, index, rd_kw->size)); -} - -static char *rd_kw_alloc_output_buffer(const rd_kw_type *rd_kw) { - size_t sizeof_iotype = rd_type_get_sizeof_iotype(rd_kw->data_type); - size_t buffer_size = rd_kw->size * sizeof_iotype; - char *buffer = (char *)util_malloc(buffer_size); - - if (rd_type_is_bool(rd_kw->data_type)) { - int *int_data = (int *)buffer; - bool *bool_data = (bool *)rd_kw->data; - - for (int i = 0; i < rd_kw->size; i++) - if (bool_data[i]) - int_data[i] = RD_BOOL_TRUE_INT; - else - int_data[i] = RD_BOOL_FALSE_INT; - - util_endian_flip_vector(buffer, sizeof_iotype, - static_cast(rd_kw->size)); - return buffer; - } - - if (rd_type_is_char(rd_kw->data_type) || - rd_type_is_string(rd_kw->data_type)) { - size_t sizeof_ctype = rd_type_get_sizeof_ctype(rd_kw->data_type); - for (int i = 0; i < rd_kw->size; i++) { - size_t buffer_offset = i * sizeof_iotype; - size_t data_offset = i * sizeof_ctype; - size_t string_length = strlen(&rd_kw->data[data_offset]); - - for (size_t i = 0; i < string_length; i++) - buffer[buffer_offset + i] = rd_kw->data[data_offset + i]; - - // Pad with spaces - for (size_t i = string_length; i < sizeof_iotype; i++) - buffer[buffer_offset + i] = ' '; - } +static std::unique_ptr +alloc_output_buffer(const rd::KW *rd_kw) { + size_t sizeof_iotype = rd_kw->iotype_size(); + size_t buffer_size = rd_kw->size() * sizeof_iotype; + auto buffer = rd::checked_calloc(buffer_size); + const auto &m_data = rd_kw->data(); + if (!m_data.has_value()) + /* RD_MESS_TYPE keywords carry no element-wise data. */ return buffer; - } - - if (rd_type_is_mess(rd_kw->data_type)) - return buffer; - - if (rd_kw->data && buffer_size > 0) { - memcpy(buffer, rd_kw->data, buffer_size); - util_endian_flip_vector(buffer, sizeof_iotype, - static_cast(rd_kw->size)); - } - - return buffer; -} - -static char *rd_kw_alloc_input_buffer(const rd_kw_type *rd_kw) { - if (rd_kw->size < 0) - throw std::invalid_argument( - fmt::format("rd_kw->size was negative: {}", rd_kw->size)); - - size_t sizeof_iotype = rd_type_get_sizeof_iotype(rd_kw->data_type); - size_t count = static_cast(rd_kw->size); - if (sizeof_iotype != 0 && - count > std::numeric_limits::max() / sizeof_iotype) - throw std::invalid_argument( - fmt::format("buffer size overflow: {} * {}", count, sizeof_iotype)); - size_t buffer_size = count * sizeof_iotype; - char *buffer = (char *)util_malloc(buffer_size); + std::visit( + [&](const auto &vec) { + using VecT = std::decay_t; + if constexpr (std::is_same_v>) { + /* RD_BOOL_TYPE, stored as vector with 0/1 values. */ + for (size_t i = 0; i < vec.size(); i++) { + int value = vec[i] ? RD_BOOL_TRUE_INT : RD_BOOL_FALSE_INT; + std::memcpy(&buffer[i * sizeof_iotype], &value, + sizeof(value)); + } + util_endian_flip_vector(buffer.get(), sizeof_iotype, + vec.size()); + } else if constexpr (std::is_same_v>) { + for (size_t i = 0; i < vec.size(); i++) { + size_t buffer_offset = i * sizeof_iotype; + size_t string_length = + std::min(vec[i].size(), sizeof_iotype); + + std::memcpy(&buffer[buffer_offset], vec[i].data(), + string_length); + + // Pad with spaces + for (size_t j = string_length; j < sizeof_iotype; j++) + buffer[buffer_offset + j] = ' '; + } + } else { + /* RD_INT_TYPE / RD_FLOAT_TYPE / RD_DOUBLE_TYPE: element + layout matches the on-disk iotype directly. */ + if (!vec.empty()) + std::memcpy(buffer.get(), vec.data(), buffer_size); + util_endian_flip_vector(buffer.get(), sizeof_iotype, + vec.size()); + } + }, + m_data.value()); return buffer; } -static void rd_kw_load_from_input_buffer(rd_kw_type *rd_kw, char *buffer) { - size_t sizeof_iotype = rd_type_get_sizeof_iotype(rd_kw->data_type); - size_t sizeof_ctype = rd_type_get_sizeof_ctype(rd_kw->data_type); - size_t buffer_size = rd_kw->size * sizeof_iotype; - if (RD_ENDIAN_FLIP) { - if (rd_type_is_numeric(rd_kw->data_type) || - rd_type_is_bool(rd_kw->data_type)) - util_endian_flip_vector(buffer, sizeof_iotype, - static_cast(rd_kw->size)); - } - - /* - Special case bool: Return Eclipse integer representation of bool to native bool. - */ - if (rd_type_is_bool(rd_kw->data_type)) { - int *int_data = (int *)buffer; - bool *bool_data = (bool *)rd_kw->data; - - for (int i = 0; i < rd_kw->size; i++) { - if (int_data[i] == RD_BOOL_TRUE_INT) - bool_data[i] = true; - else - bool_data[i] = false; - } - return; - } - - /* - Special case: insert '\0' termination at end of strings loaded from file; - when writing out again strlen() will be called on data - i.e. it is - paramount to add this '\0'. - */ - if (rd_type_is_char(rd_kw->data_type) || - rd_type_is_string(rd_kw->data_type)) { - const char null_char = '\0'; - for (int i = 0; i < rd_kw->size; i++) { - size_t buffer_offset = i * sizeof_iotype; - size_t data_offset = i * sizeof_ctype; - memcpy(&rd_kw->data[data_offset], &buffer[buffer_offset], - sizeof_iotype); - rd_kw->data[data_offset + sizeof_iotype] = null_char; - } - return; - } - - if (rd_type_is_mess(rd_kw->data_type)) - return; - - /* - Plain int, double, float data - that can be copied straight over to the ->data field. - */ - memcpy(rd_kw->data, buffer, buffer_size); -} - -static const char *rd_kw_get_header8(const rd_kw_type *rd_kw) { - return rd_kw->header8; -} - -/* - Return the header without the trailing spaces -*/ -const char *rd_kw_get_header(const rd_kw_type *rd_kw) { return rd_kw->header; } - -void rd_kw_get_memcpy_data(const rd_kw_type *rd_kw, void *target) { - if (rd_kw->size < 0) - throw std::invalid_argument( - fmt::format("rd_kw size was negative: {}", rd_kw->size)); - memcpy(target, rd_kw->data, - static_cast(rd_kw->size) * - rd_type_get_sizeof_ctype(rd_kw->data_type)); -} - -void rd_kw_set_memcpy_data(rd_kw_type *rd_kw, const void *src) { - if (rd_kw->size < 0) - throw std::invalid_argument( - fmt::format("rd_kw size was negative: {}", rd_kw->size)); - if (src != NULL) - memcpy(rd_kw->data, src, - static_cast(rd_kw->size) * - rd_type_get_sizeof_ctype(rd_kw->data_type)); -} - -static bool rd_kw_string_eq(const char *s1, const char *s2) { - const char space_char = ' '; - const char *long_kw = (strlen(s1) >= strlen(s2)) ? s1 : s2; - const char *short_kw = (strlen(s1) < strlen(s2)) ? s1 : s2; - const int len1 = strlen(long_kw); - const int len2 = strlen(short_kw); - int index; - bool eq = true; - if (len1 > RD_STRING8_LENGTH) - throw std::invalid_argument( - fmt::format("eclipse keyword:{} is too long", long_kw)); - - for (index = 0; index < len2; index++) - eq = eq & (long_kw[index] == short_kw[index]); - - if (eq) { - for (index = len2; index < len1; index++) - eq = eq & (long_kw[index] == space_char); - } - - return eq; -} - -bool rd_kw_size_and_type_equal(const rd_kw_type *rd_kw1, - const rd_kw_type *rd_kw2) { - return (rd_kw1->size == rd_kw2->size && - rd_type_is_equal(rd_kw1->data_type, rd_kw2->data_type)); -} - -static bool rd_kw_header_eq(const rd_kw_type *rd_kw1, - const rd_kw_type *rd_kw2) { - bool equal = true; - - if (strcmp(rd_kw1->header8, rd_kw2->header8) != 0) - equal = false; - else - equal = rd_kw_size_and_type_equal(rd_kw1, rd_kw2); - - return equal; -} - -static bool rd_kw_data_equal__(const rd_kw_type *rd_kw, const void *data, - int cmp_elements) { - if (cmp_elements < 0) - throw std::invalid_argument( - fmt::format("cmp_elements was negative: {}", cmp_elements)); - int cmp = memcmp(rd_kw->data, data, - static_cast(cmp_elements) * - rd_type_get_sizeof_ctype(rd_kw->data_type)); - if (cmp == 0) - return true; - else - return false; -} - -/** - Observe that the comparison is done with memcmp() - - i.e. "reasonably good" numerical agreement is *not* enough. -*/ - -bool rd_kw_data_equal(const rd_kw_type *rd_kw, const void *data) { - return rd_kw_data_equal__(rd_kw, data, rd_kw->size); +bool rd::KW::size_and_type_equal(const rd::KW *rd_kw2) const { + return (this->size() == rd_kw2->size() && + rd_type_is_equal(this->data_type(), rd_kw2->data_type())); } -bool rd_kw_content_equal(const rd_kw_type *rd_kw1, const rd_kw_type *rd_kw2) { - if (rd_kw_size_and_type_equal(rd_kw1, rd_kw2)) - return rd_kw_data_equal__(rd_kw1, rd_kw2->data, rd_kw1->size); - else - return false; +static bool rd_kw_header_eq(const rd::KW *rd_kw1, const rd::KW *rd_kw2) { + return (fmt::format("{:8.8}", rd_kw1->header()) == + fmt::format("{:8.8}", rd_kw2->header())) && + rd_kw1->size_and_type_equal(rd_kw2); } /** This function compares two rd_kw instances, and returns true if they are equal. */ -bool rd_kw_equal(const rd_kw_type *rd_kw1, const rd_kw_type *rd_kw2) { - bool equal = rd_kw_header_eq(rd_kw1, rd_kw2); +bool rd::KW::operator==(const rd::KW &other) const { + bool equal = rd_kw_header_eq(this, &other); if (equal) - equal = rd_kw_data_equal(rd_kw1, rd_kw2->data); + equal = this->data() == other.data(); return equal; } -#define RD_KW_NUMERIC_CMP(ctype) \ - static bool rd_kw_numeric_equal_##ctype(const rd_kw_type *rd_kw1, \ - const rd_kw_type *rd_kw2, \ - ctype abs_diff, ctype rel_diff) { \ - int index; \ - bool equal = true; \ - { \ - const ctype *data1 = (const ctype *)rd_kw1->data; \ - const ctype *data2 = (const ctype *)rd_kw2->data; \ - for (index = 0; index < rd_kw1->size; index++) { \ - equal = util_##ctype##_approx_equal__( \ - data1[index], data2[index], rel_diff, abs_diff); \ - if (!equal) \ - break; \ - } \ - } \ - return equal; \ - } - -RD_KW_NUMERIC_CMP(float) -RD_KW_NUMERIC_CMP(double) -#undef RD_KW_NUMERIC_CMP - -/** - This function compares the data of two rd_kw instances, and - returns true if the relative numerical difference is less than - @rel_diff. Does not consider consider the kw header. -*/ - -bool rd_kw_numeric_equal(const rd_kw_type *rd_kw1, const rd_kw_type *rd_kw2, - double abs_diff, double rel_diff) { - if (!rd_kw_size_and_type_equal(rd_kw1, rd_kw2)) - return false; - - if (rd_type_is_float(rd_kw1->data_type)) - return rd_kw_numeric_equal_float(rd_kw1, rd_kw2, abs_diff, rel_diff); - else if (rd_type_is_double(rd_kw1->data_type)) - return rd_kw_numeric_equal_double(rd_kw1, rd_kw2, abs_diff, rel_diff); - else - return rd_kw_data_equal(rd_kw1, rd_kw2->data); +template bool approx_equal(T a, T b, T rel_diff, T abs_diff); +template <> +bool approx_equal(float a, float b, float rel_diff, float abs_diff) { + return util_float_approx_equal__(a, b, rel_diff, abs_diff); } - -static void rd_kw_set_shared_ref(rd_kw_type *rd_kw, void *data_ptr) { - if (!rd_kw->shared_data) { - if (rd_kw->data != NULL) - throw std::invalid_argument( - "can not change to shared for keyword with allocated storage"); - } - rd_kw->shared_data = true; - rd_kw->data = (char *)data_ptr; +template <> +bool approx_equal(double a, double b, double rel_diff, + double abs_diff) { + return util_double_approx_equal__(a, b, rel_diff, abs_diff); } -static void rd_kw_initialize(rd_kw_type *rd_kw, const char *header, int size, - rd_data_type data_type) { - rd_kw_set_data_type(rd_kw, data_type); - rd_kw_set_header_name(rd_kw, header); - rd_kw->size = size; -} +bool rd::KW::approx_equal(const rd::KW &other, double abs_diff, + double rel_diff) const { + if (!size_and_type_equal(&other)) + return false; -static size_t rd_kw_fortio_data_size(const rd_kw_type *rd_kw) { - if (rd_kw->size < 0) - throw std::invalid_argument( - fmt::format("rd_kw->size was negative: {}", rd_kw->size)); + if (!this->data().has_value() || !other.data().has_value()) + return this->m_data == other.m_data; + + return std::visit( + [&](const auto &vec1) { + using VecT = std::decay_t; + const auto &vec2 = std::get(other.m_data.value()); + + if constexpr (std::is_same_v> || + std::is_same_v>) { + using T = typename VecT::value_type; + if (vec1.size() != vec2.size()) + return false; + for (size_t index = 0; index < vec1.size(); index++) { + if (!::approx_equal(vec1[index], vec2[index], + static_cast(rel_diff), + static_cast(abs_diff))) + return false; + } + return true; + } else { + return vec1 == vec2; + } + }, + this->data().value()); +} - const int blocksize = get_blocksize(rd_kw->data_type); - const int num_blocks = - rd_kw->size / blocksize + (rd_kw->size % blocksize == 0 ? 0 : 1); +static size_t rd_kw_fortio_data_size(const rd::KW *rd_kw) { + const size_t blocksize = get_blocksize(rd_kw->data_type()); + const size_t num_blocks = + rd_kw->size() / blocksize + (rd_kw->size() % blocksize == 0 ? 0 : 1); - return static_cast(num_blocks) * - (4 + 4) + // Fortran fluff for each block - static_cast(rd_kw->size) * - rd_type_get_sizeof_iotype(rd_kw->data_type); // Actual data + return num_blocks * (4 + 4) + // Fortran fluff for each block + rd_kw->size() * rd_kw->iotype_size(); // Actual data } /** @@ -493,122 +256,12 @@ static size_t rd_kw_fortio_data_size(const rd_kw_type *rd_kw) { the fortran header and trailer combo. */ -size_t rd_kw_fortio_size(const rd_kw_type *rd_kw) { +size_t rd::KW::fortio_size() const { size_t size = RD_KW_HEADER_FORTIO_SIZE; - size += rd_kw_fortio_data_size(rd_kw); + size += rd_kw_fortio_data_size(this); return size; } -/** - This is where the storage buffer of the rd_kw is allocated. -*/ -static void rd_kw_alloc_data(rd_kw_type *rd_kw) { - if (rd_kw->shared_data) - throw std::invalid_argument( - "trying to allocate data for rd_kw object which has been declared " - "with shared storage"); - - { - - if (rd_kw->size < 0) - throw std::invalid_argument( - fmt::format("rd_kw size was negative: {}", rd_kw->size)); - size_t byte_size = static_cast(rd_kw->size) * - rd_type_get_sizeof_ctype(rd_kw->data_type); - rd_kw->data = (char *)util_realloc(rd_kw->data, byte_size); - if (rd_kw->data) { - memset(rd_kw->data, 0, byte_size); - } - } -} - -/** - The data is copied from the input argument to the rd_kw; data can be NULL. -*/ -rd_kw_type *rd_kw_alloc_new(const char *header, int size, - rd_data_type data_type, const void *data) { - rd_kw_ptr rd_kw = make_rd_kw(); - rd_kw_initialize(rd_kw.get(), header, size, data_type); - if (data != NULL) { - rd_kw_alloc_data(rd_kw.get()); - rd_kw_set_memcpy_data(rd_kw.get(), data); - } - return rd_kw.release(); -} - -rd_kw_type *rd_kw_alloc(const char *header, int size, rd_data_type data_type) { - rd_kw_ptr rd_kw = make_rd_kw(); - rd_kw_initialize(rd_kw.get(), header, size, data_type); - rd_kw_alloc_data(rd_kw.get()); - return rd_kw.release(); -} - -rd_kw_type *rd_kw_alloc_new_shared(const char *header, int size, - rd_data_type data_type, void *data) { - rd_kw_ptr rd_kw = make_rd_kw(); - rd_kw_initialize(rd_kw.get(), header, size, data_type); - rd_kw_set_shared_ref(rd_kw.get(), data); - return rd_kw.release(); -} - -rd_kw_type *rd_kw_alloc_empty() { - rd_kw_type *rd_kw; - - rd_kw = (rd_kw_type *)util_malloc(sizeof *rd_kw); - rd_kw->header = NULL; - rd_kw->header8 = NULL; - rd_kw->data = NULL; - rd_kw->shared_data = false; - rd_kw->size = 0; - - UTIL_TYPE_ID_INIT(rd_kw, RD_KW_TYPE_ID); - - return rd_kw; -} - -static void rd_kw_free_data(rd_kw_type *rd_kw) { - if (!rd_kw->shared_data) - free(rd_kw->data); - - rd_kw->data = NULL; -} - -void rd_kw_free(rd_kw_type *rd_kw) { - free(rd_kw->header); - free(rd_kw->header8); - rd_kw_free_data(rd_kw); - free(rd_kw); -} - -void rd_kw_memcpy_data(rd_kw_type *target, const rd_kw_type *src) { - if (!rd_kw_size_and_type_equal(target, src)) - throw std::invalid_argument("type/size mismatch"); - - if (target->size < 0) - throw std::invalid_argument( - fmt::format("target size was negative: {}", target->size)); - if (target->size == 0) - return; - memcpy(target->data, src->data, - static_cast(target->size) * - rd_type_get_sizeof_ctype(target->data_type)); -} - -void rd_kw_memcpy(rd_kw_type *target, const rd_kw_type *src) { - target->size = src->size; - rd_kw_set_data_type(target, src->data_type); - - rd_kw_set_header_name(target, src->header); - rd_kw_alloc_data(target); - rd_kw_memcpy_data(target, src); -} - -rd_kw_type *rd_kw_alloc_copy(const rd_kw_type *src) { - rd_kw_ptr new_ = make_rd_kw(); - rd_kw_memcpy(new_.get(), src); - return new_.release(); -} - /** This function will allocate a new copy of @src, where only the elements corresponding to the slice [index1:index2) is included. @@ -623,75 +276,48 @@ rd_kw_type *rd_kw_alloc_copy(const rd_kw_type *src) { <= 0. */ -rd_kw_type *rd_kw_alloc_slice_copy(const rd_kw_type *src, int index1, - int index2, int stride) { - if (index1 < 0) - index1 = 0; - if (index2 > src->size) - index2 = src->size; - if (index1 >= src->size) +rd::KW::KW(const rd::KW &other, size_t index1, size_t index2, size_t stride) + : m_size(0), m_data_type(other.data_type()) { + if (index2 > other.size()) + index2 = other.size(); + if (index1 >= other.size()) throw std::invalid_argument( - fmt::format("index1={} > size:{}", index1, src->size)); - if (stride <= 0) + fmt::format("index1={} > size:{}", index1, other.size())); + if (stride == 0) throw std::invalid_argument( - fmt::format("stride:{} completely broken ...", stride)); + fmt::format("stride:{} must be positive", stride)); - rd_kw_ptr new_kw(nullptr, rd_kw_free); - int src_index = index1; + size_t src_index = index1; /* 1: Determine size of the sliced copy. */ - int new_size = 0; + size_t new_size = 0; while (src_index < index2) { new_size++; src_index += stride; } if (new_size > 0) { - new_kw.reset(rd_kw_alloc_empty()); - rd_kw_initialize(new_kw.get(), src->header, new_size, src->data_type); - rd_kw_alloc_data(new_kw.get()); - - /* 2: Copy over the elements. */ - src_index = index1; - { - int target_index = 0; - const char *src_ptr = src->data; - char *new_ptr = new_kw->data; - int sizeof_ctype = rd_type_get_sizeof_ctype(new_kw->data_type); - - while (src_index < index2) { - memcpy(&new_ptr[target_index * sizeof_ctype], - &src_ptr[src_index * sizeof_ctype], sizeof_ctype); - src_index += stride; - target_index += 1; - } - } + this->m_header = other.header(); + this->m_size = new_size; + + if (other.m_data.has_value()) + this->m_data = std::visit( + [index1, index2, stride](const auto &vec) -> rd::kw_data { + using VecT = std::decay_t; + VecT result; + for (size_t src_index = index1; src_index < index2; + src_index += stride) + result.push_back(vec[src_index]); + return result; + }, + other.m_data.value()); } - return new_kw.release(); } -void rd_kw_resize(rd_kw_type *rd_kw, int new_size) { - if (rd_kw->shared_data) - throw std::invalid_argument( - "trying to allocate data for rd_kw object which has been declared " - "with shared storage"); - - if (new_size != rd_kw->size) { - if (rd_kw->size < 0) - throw std::invalid_argument( - fmt::format("rd_kw size was negative: {}", rd_kw->size)); - if (new_size < 0) - throw std::invalid_argument( - fmt::format("new_size was negative: {}", new_size)); - size_t old_byte_size = static_cast(rd_kw->size) * - rd_type_get_sizeof_ctype(rd_kw->data_type); - size_t new_byte_size = static_cast(new_size) * - rd_type_get_sizeof_ctype(rd_kw->data_type); - - rd_kw->data = (char *)util_realloc(rd_kw->data, new_byte_size); - if (new_byte_size > old_byte_size) { - size_t offset = old_byte_size; - memset(&rd_kw->data[offset], 0, new_byte_size - old_byte_size); - } - rd_kw->size = new_size; +void rd::KW::resize(size_t new_size) { + if (new_size != m_size) { + m_size = new_size; + if (m_data.has_value()) + std::visit([new_size](auto &vec) { vec.resize(new_size); }, + m_data.value()); } } @@ -703,463 +329,289 @@ void rd_kw_resize(rd_kw_type *rd_kw, int new_size) { used. */ -rd_kw_type *rd_kw_alloc_sub_copy(const rd_kw_type *src, const char *new_kw, - int offset, int count) { - if (new_kw == NULL) - new_kw = src->header; - - if (count < 0) - count = src->size - offset; - - if ((offset < 0) || (offset >= src->size)) +rd::KW::KW(const rd::KW &other, const std::optional &new_kw, + size_t offset, size_t count) + : m_size(count), m_data_type(other.data_type()) { + if (offset >= other.size()) throw std::invalid_argument( - fmt::format("invalid offset - limits: [{},{})", 0, src->size)); - if ((count + offset) > src->size) + fmt::format("invalid offset - limits: [{},{})", 0, other.size())); + if ((count + offset) > other.size()) throw std::invalid_argument( fmt::format("invalid count value: {}", count)); - { - void *src_data = rd_kw_iget_ptr(src, offset); - return rd_kw_alloc_new(new_kw, count, src->data_type, src_data); - } -} + if (new_kw.has_value()) + m_header = strip_header(*new_kw); + else + m_header = other.header(); -static void *rd_kw_iget_ptr_static(const rd_kw_type *rd_kw, int i) { - rd_kw_assert_index(rd_kw, i, __func__); - return &rd_kw->data[i * rd_type_get_sizeof_ctype(rd_kw->data_type)]; + if (other.m_data.has_value()) + this->m_data = std::visit( + [offset, count](const auto &vec) -> rd::kw_data { + using VecT = std::decay_t; + return VecT(vec.begin() + offset, vec.begin() + offset + count); + }, + other.m_data.value()); } -static void rd_kw_iget_static(const rd_kw_type *rd_kw, int i, void *iptr) { - memcpy(iptr, rd_kw_iget_ptr_static(rd_kw, i), - rd_type_get_sizeof_ctype(rd_kw->data_type)); +void rd::KW::zero_init_data() { + switch (rd_type_get_type(data_type())) { + case RD_INT_TYPE: + m_data = std::vector(size(), 0); + break; + case RD_FLOAT_TYPE: + m_data = std::vector(size(), 0.0f); + break; + case RD_DOUBLE_TYPE: + m_data = std::vector(size(), 0.0); + break; + case RD_BOOL_TYPE: + m_data = std::vector(size(), 0); + break; + case RD_CHAR_TYPE: + case RD_STRING_TYPE: + m_data = std::vector(size()); + break; + default: + /* RD_MESS_TYPE carries no element-wise data and is not + representable by rd::kw_data. */ + m_data = std::nullopt; + break; + } } -static void rd_kw_iset_static(rd_kw_type *rd_kw, int i, const void *iptr) { - size_t sizeof_ctype = rd_type_get_sizeof_ctype(rd_kw->data_type); - rd_kw_assert_index(rd_kw, i, __func__); - memcpy(&rd_kw->data[i * sizeof_ctype], iptr, sizeof_ctype); +static bool skip_space_until_quote(std::istream &stream) { + const char sep = '\''; + const char space = ' '; + const char newline = '\n'; + const char tab = '\t'; + bool OK = true; + int c; + bool cont = true; + while (cont) { + c = stream.get(); + if (c == EOF) { + cont = false; + OK = false; + } else { + char cc = static_cast(c); + if (cc == space || cc == newline || cc == tab) + cont = true; + else if (cc == sep) + cont = false; + } + } + return OK; } -void rd_kw_iget(const rd_kw_type *rd_kw, int i, void *iptr) { - rd_kw_iget_static(rd_kw, i, iptr); -} +/** Reads a string separated by ' but assumed to be of size len */ +static bool read_sized_quoted_string(char *s, size_t len, + std::istream &stream) { + bool OK = skip_space_until_quote(stream); + if (OK) { + stream.read(s, len); + s[len] = '\0'; + char last_sep; + stream.get(last_sep); -/** - Will return a double value for underlying data types of double, - float and int. -*/ -double rd_kw_iget_as_double(const rd_kw_type *rd_kw, int index) { - if (rd_type_is_float(rd_kw->data_type)) - return rd_kw_iget_float( - rd_kw, - index); /* Here the compiler will silently insert a float -> double conversion. */ - else if (rd_type_is_double(rd_kw->data_type)) - return rd_kw_iget_double(rd_kw, index); - else if (rd_type_is_int(rd_kw->data_type)) - return rd_kw_iget_int(rd_kw, index); /* */ - else { - throw std::invalid_argument( - "can not be converted to double - no data for you!"); - return -1; + if (last_sep != '\'') + throw std::runtime_error( + "reading 'xxxxxxxx' formatted string failed"); } + return OK; } -#define RD_KW_IGET_TYPED(ctype, RD_TYPE) \ - ctype rd_kw_iget_##ctype(const rd_kw_type *rd_kw, int i) { \ - ctype value; \ - if (rd_kw_get_type(rd_kw) != RD_TYPE) \ - throw std::invalid_argument(fmt::format( \ - "Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); \ - rd_kw_iget_static(rd_kw, i, &value); \ - return value; \ - } +/* This rather painful parsing is because formatted eclipse double + format : 0.ddddD+01 - difficult to parse the 'D'; */ +static double parse_double(std::istream &stream) { + double arg; + stream >> arg; + char exponent_char = '\0'; + stream.get(exponent_char); + int power = 0; + if (stream && exponent_char == 'D') + stream >> power; + else + stream.setstate(std::ios_base::failbit); + + if (!stream) + throw std::runtime_error("read failed"); + return arg * pow(10, power); +} + +/* Reads one formatted numeric value with stream::operator>>, throwing with a + * helpful message (including how far we got) on failure. */ +template +static void read_formatted_value(std::istream &stream, T &value, size_t index, + const rd::KW *rd_kw, ERT::FortIO &fortio) { + stream >> value; + if (stream.fail()) + throw std::runtime_error( + fmt::format("after reading {} values reading of keyword:{:8.8} " + "from:{} failed", + index, rd_kw->header(), fortio.filename_ref())); +} + +static char read_formatted_bool(std::istream &stream) { + stream >> std::ws; + char bool_char = '\0'; + stream.get(bool_char); + if (stream.fail()) + throw std::runtime_error("read failed - premature file end?"); + if (bool_char == BOOL_TRUE_CHAR) + return 1; + if (bool_char == BOOL_FALSE_CHAR) + return 0; + throw std::runtime_error( + fmt::format("Logical value: [{}] not recogniced", bool_char)); +} -RD_KW_IGET_TYPED(double, RD_DOUBLE_TYPE); -RD_KW_IGET_TYPED(float, RD_FLOAT_TYPE); -RD_KW_IGET_TYPED(int, RD_INT_TYPE); -RD_KW_IGET_TYPED(bool, RD_BOOL_TYPE); -#undef RD_KW_IGET_TYPED +static std::optional read_formatted_data(rd::KW *rd_kw, + ERT::FortIO &fortio) { + const rd_type_enum type = rd_kw->get_type(); + const size_t size = rd_kw->size(); + std::istream &stream = fortio.get_istream(); + std::optional data; -const char *rd_kw_iget_char_ptr(const rd_kw_type *rd_kw, int i) { - if (rd_kw_get_type(rd_kw) != RD_CHAR_TYPE) - throw std::invalid_argument( - fmt::format("Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); - return (const char *)rd_kw_iget_ptr(rd_kw, i); + switch (type) { + case RD_INT_TYPE: { + std::vector values(size); + for (size_t i = 0; i < size; i++) + read_formatted_value(stream, values[i], i, rd_kw, fortio); + data = std::move(values); + } break; + case RD_FLOAT_TYPE: { + std::vector values(size); + for (size_t i = 0; i < size; i++) + read_formatted_value(stream, values[i], i, rd_kw, fortio); + data = std::move(values); + } break; + case RD_DOUBLE_TYPE: { + std::vector values(size); + for (size_t i = 0; i < size; i++) + values[i] = parse_double(stream); + data = std::move(values); + } break; + case RD_BOOL_TYPE: { + std::vector values(size); + for (size_t i = 0; i < size; i++) + values[i] = read_formatted_bool(stream); + data = std::move(values); + } break; + case RD_CHAR_TYPE: + case RD_STRING_TYPE: { + const size_t width = + type == RD_CHAR_TYPE ? RD_STRING8_LENGTH : rd_kw->iotype_size(); + std::vector buf(width + 1); + std::vector values; + values.reserve(size); + for (size_t i = 0; i < size; i++) { + read_sized_quoted_string(buf.data(), width, stream); + values.emplace_back(buf.data()); + } + data = std::move(values); + } break; + case RD_MESS_TYPE: { + char buf[RD_STRING8_LENGTH + 1]; + for (size_t i = 0; i < size; i++) + read_sized_quoted_string(buf, RD_STRING8_LENGTH, stream); + /* leave data as nullopt. */ + } break; + default: + throw std::runtime_error(fmt::format( + "Internal error: internal eclipse_type: {} not recognized", type)); + } + + /* Skip the trailing newline */ + fortio.fseek(1, SEEK_CUR); + return data; } -const char *rd_kw_iget_string_ptr(const rd_kw_type *rd_kw, int i) { - if (rd_kw_get_type(rd_kw) != RD_STRING_TYPE) +static bool read_unformatted_data(rd::KW *rd_kw, ERT::FortIO &fortio, + std::optional &out) { + const rd_type_enum type = rd_kw->get_type(); + const size_t size = rd_kw->size(); + const size_t sizeof_iotype = rd_kw->iotype_size(); + if (sizeof_iotype != 0 && + size > std::numeric_limits::max() / sizeof_iotype) throw std::invalid_argument( - fmt::format("Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); - return (const char *)rd_kw_iget_ptr(rd_kw, i); -} + fmt::format("buffer size overflow: {} * {}", size, sizeof_iotype)); -/** - This will set the elemnts of the rd_kw data storage in index to - the value of s8; if s8 is shorter than 8 characters the result will - be padded, if s8 is longer than 8 characters the characters from 9 - and out will be ignored. -*/ -void rd_kw_iset_string8(rd_kw_type *rd_kw, int index, const char *s8) { - char *rd_string = (char *)rd_kw_iget_ptr(rd_kw, index); - if (strlen(s8) >= RD_STRING8_LENGTH) { - /* The whole string goes in - possibly loosing content at the end. */ - int i; - for (i = 0; i < RD_STRING8_LENGTH; i++) - rd_string[i] = s8[i]; - } else { - /* The string is padded with trailing spaces. */ - int string_length = strlen(s8); - int i; + const size_t record_size = size * sizeof_iotype; + if (record_size > std::numeric_limits::max()) + throw std::invalid_argument( + "record size exceeded signed 32 bit integer"); - for (i = 0; i < string_length; i++) - rd_string[i] = s8[i]; + std::vector buffer(record_size); + bool read_ok = + fortio.fread_buffer(buffer.data(), static_cast(record_size)); + if (!read_ok) + return false; - for (i = string_length; i < RD_STRING8_LENGTH; i++) - rd_string[i] = ' '; + if (RD_ENDIAN_FLIP) { + if (rd_type_is_numeric(rd_kw->data_type()) || + rd_type_is_bool(rd_kw->data_type())) + util_endian_flip_vector(buffer.data(), sizeof_iotype, size); } - rd_string[RD_STRING8_LENGTH] = '\0'; -} - -/** - This function will set the string @index in the rd_kw string array - to @s. IFF @s is longer than 8 characters, the first part will go - in element @index, and then we will continue writing into the next - elements. If the resulting index goes beyond the length of the - keyword - WhamBang! - - You should know what you are doing when sending in a string of - length greater than 8 - maybe the overwriting of consecutive - elements is not what you want? -*/ -void rd_kw_iset_char_ptr(rd_kw_type *rd_kw, int index, const char *s) { - int strings = strlen(s) / RD_STRING8_LENGTH; - if ((strlen(s) % RD_STRING8_LENGTH) != 0) - strings++; - { - int sub_index; - for (sub_index = 0; sub_index < strings; sub_index++) - rd_kw_iset_string8(rd_kw, index + sub_index, - &s[sub_index * RD_STRING8_LENGTH]); + switch (type) { + case RD_INT_TYPE: { + std::vector result(size); + if (record_size > 0) + std::memcpy(result.data(), buffer.data(), record_size); + out = std::move(result); + } break; + case RD_FLOAT_TYPE: { + std::vector result(size); + if (record_size > 0) + std::memcpy(result.data(), buffer.data(), record_size); + out = std::move(result); + } break; + case RD_DOUBLE_TYPE: { + std::vector result(size); + if (record_size > 0) + std::memcpy(result.data(), buffer.data(), record_size); + out = std::move(result); + } break; + case RD_BOOL_TYPE: { + std::vector result(size); + const int *int_data = reinterpret_cast(buffer.data()); + for (size_t i = 0; i < size; i++) + result[i] = (int_data[i] == RD_BOOL_TRUE_INT) ? 1 : 0; + out = std::move(result); + } break; + case RD_CHAR_TYPE: + case RD_STRING_TYPE: { + std::vector result; + result.reserve(size); + for (size_t i = 0; i < size; i++) + result.emplace_back(&buffer[i * sizeof_iotype], sizeof_iotype); + out = std::move(result); + } break; + default: + /* RD_MESS_TYPE: leave out unset (nullopt). */ + out = std::nullopt; + break; } + return true; } -/** - This function will verify that the given string is of approperiate - length (0 <= lenght <= data_type.element_size). If so, the elements - of @s will be written to the @rd_kw string array starting at - @index. If the input string is shorter than the type length the - string will be padded with trailing spaces. - */ -void rd_kw_iset_string_ptr(rd_kw_type *rd_kw, int index, const char *s) { - if (!rd_type_is_alpha(rd_kw_get_data_type(rd_kw))) { - throw std::invalid_argument( - fmt::format("Expected alphabetic data type (CHAR, CXXX or MESS), " - "was {}", - rd_type_name(rd_kw_get_data_type(rd_kw)))); +bool rd::KW::fread_data(rd::KW *rd_kw, ERT::FortIO &fortio) { + if (rd_kw->size() == 0) { + /* The keyword has zero size - and reading data is trivially OK. */ + rd_kw->zero_init_data(); + return true; } - size_t input_len = strlen(s); - size_t type_len = rd_type_get_sizeof_iotype(rd_kw->data_type); - - if (input_len > type_len) - throw std::invalid_argument(fmt::format( - "String of length {} cannot hold input string of length {}", - type_len, input_len)); - - { - char *rd_string = (char *)rd_kw_iget_ptr(rd_kw, index); - size_t i; - - for (i = 0; i < input_len; ++i) - rd_string[i] = s[i]; - - for (i = input_len; i < type_len; ++i) - rd_string[i] = ' '; - - rd_string[type_len] = '\0'; - } -} - -/** - This function will compare the string at position @index with the - input @other string. The comparison will be done in a - 'space-tolerant', i.e. trailing spaces are ignored in the - comparison. If the strings are considered equal true is returned. -*/ - -bool rd_kw_icmp_string(const rd_kw_type *rd_kw, int index, - const char *other_string) { - const char *kw_string = (const char *)rd_kw_iget_char_ptr(rd_kw, index); - if (strlen(other_string)) { - const char *match = strstr(kw_string, other_string); - if (match == kw_string) - return true; - } - - return false; -} - -#define RD_KW_ISET_TYPED(ctype, RD_TYPE) \ - void rd_kw_iset_##ctype(rd_kw_type *rd_kw, int i, ctype value) { \ - if (rd_kw_get_type(rd_kw) != RD_TYPE) \ - throw std::invalid_argument(fmt::format( \ - "Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); \ - rd_kw_iset_static(rd_kw, i, &value); \ - } - -RD_KW_ISET_TYPED(double, RD_DOUBLE_TYPE); -RD_KW_ISET_TYPED(float, RD_FLOAT_TYPE); -RD_KW_ISET_TYPED(int, RD_INT_TYPE); -RD_KW_ISET_TYPED(bool, RD_BOOL_TYPE); -#undef RD_KW_ISET_TYPED - -#define RD_KW_SET_INDEXED(ctype, RD_TYPE) \ - void rd_kw_set_indexed_##ctype( \ - rd_kw_type *rd_kw, const std::vector &index_list, ctype value) { \ - if (rd_kw_get_type(rd_kw) != RD_TYPE) \ - throw std::invalid_argument(fmt::format( \ - "Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); \ - { \ - ctype *data = (ctype *)rd_kw->data; \ - for (const auto i : index_list) \ - data[i] = value; \ - } \ - } - -RD_KW_SET_INDEXED(double, RD_DOUBLE_TYPE); -RD_KW_SET_INDEXED(float, RD_FLOAT_TYPE); -RD_KW_SET_INDEXED(int, RD_INT_TYPE); -#undef RD_KW_SET_INDEXED - -#define RD_KW_SHIFT_INDEXED(ctype, RD_TYPE) \ - void rd_kw_shift_indexed_##ctype( \ - rd_kw_type *rd_kw, const std::vector &index_list, ctype shift) { \ - if (rd_kw_get_type(rd_kw) != RD_TYPE) \ - throw std::invalid_argument(fmt::format( \ - "Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); \ - { \ - ctype *data = (ctype *)rd_kw->data; \ - for (const auto i : index_list) \ - data[i] += shift; \ - } \ - } - -RD_KW_SHIFT_INDEXED(double, RD_DOUBLE_TYPE); -RD_KW_SHIFT_INDEXED(float, RD_FLOAT_TYPE); -RD_KW_SHIFT_INDEXED(int, RD_INT_TYPE); -#undef RD_KW_SHIFT_INDEXED - -#define RD_KW_SCALE_INDEXED(ctype, RD_TYPE) \ - void rd_kw_scale_indexed_##ctype( \ - rd_kw_type *rd_kw, const std::vector &index_list, ctype scale) { \ - if (rd_kw_get_type(rd_kw) != RD_TYPE) \ - throw std::invalid_argument(fmt::format( \ - "Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); \ - { \ - ctype *data = (ctype *)rd_kw->data; \ - for (const auto i : index_list) \ - data[i] *= scale; \ - } \ - } - -RD_KW_SCALE_INDEXED(double, RD_DOUBLE_TYPE); -RD_KW_SCALE_INDEXED(float, RD_FLOAT_TYPE); -RD_KW_SCALE_INDEXED(int, RD_INT_TYPE); -#undef RD_KW_SCALE_INDEXED - -#define RD_KW_GET_TYPED_PTR(ctype, RD_TYPE) \ - ctype *rd_kw_get_##ctype##_ptr(const rd_kw_type *rd_kw) { \ - if (rd_kw_get_type(rd_kw) != RD_TYPE) \ - throw std::invalid_argument(fmt::format( \ - "Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); \ - return (ctype *)rd_kw->data; \ - } - -RD_KW_GET_TYPED_PTR(double, RD_DOUBLE_TYPE); -RD_KW_GET_TYPED_PTR(float, RD_FLOAT_TYPE); -RD_KW_GET_TYPED_PTR(int, RD_INT_TYPE); -RD_KW_GET_TYPED_PTR(bool, RD_BOOL_TYPE); -#undef RD_KW_GET_TYPED_PTR - -void *rd_kw_get_void_ptr(const rd_kw_type *rd_kw) { return rd_kw->data; } - -void *rd_kw_iget_ptr(const rd_kw_type *rd_kw, int i) { - return rd_kw_iget_ptr_static(rd_kw, i); -} - -void rd_kw_iset(rd_kw_type *rd_kw, int i, const void *iptr) { - rd_kw_iset_static(rd_kw, i, iptr); -} - -static bool rd_kw_qskip(FILE *stream) { - const char sep = '\''; - const char space = ' '; - const char newline = '\n'; - const char tab = '\t'; - bool OK = true; - char c; - bool cont = true; - while (cont) { - c = fgetc(stream); - if (c == EOF) { - cont = false; - OK = false; - } else { - if (c == space || c == newline || c == tab) - cont = true; - else if (c == sep) - cont = false; - } - } - return OK; -} - -static bool rd_kw_fscanf_qstring(char *s, const char *fmt, int len, - FILE *stream) { - const char null_char = '\0'; - char last_sep; - bool OK; - OK = rd_kw_qskip(stream); - if (OK) { - int read_count = 0; - read_count += fscanf(stream, fmt, s); - s[len] = null_char; - read_count += fscanf(stream, "%c", &last_sep); - - if (read_count != 2) - throw std::runtime_error( - "reading 'xxxxxxxx' formatted string failed"); - } - return OK; -} - -/* - This rather painful parsing is because formatted eclipse double - format : 0.ddddD+01 - difficult to parse the 'D'; -*/ -/** Should be: NESTED */ - -static double __fscanf_RD_double(FILE *stream, const char *fmt) { - int read_count, power; - double value, arg; - read_count = fscanf(stream, fmt, &arg, &power); - if (read_count == 2) - value = arg * pow(10, power); - else { - throw std::runtime_error("read failed"); - value = -1; - } - return value; -} - -static bool rd_kw_fread_data(rd_kw_type *rd_kw, ERT::FortIO &fortio) { - bool fmt_file = fortio.fmt_file(); - if (rd_kw->size > 0) { - const int blocksize = get_blocksize(rd_kw->data_type); - if (fmt_file) { - const int blocks = rd_kw->size / blocksize + - (rd_kw->size % blocksize == 0 ? 0 : 1); - const std::string read_format = read_fmt(rd_kw->data_type); - FILE *stream = fortio.get_FILE(); - int offset = 0; - int index = 0; - int ib, ir; - for (ib = 0; ib < blocks; ib++) { - int read_elm = std::min((ib + 1) * blocksize, rd_kw->size) - - ib * blocksize; - for (ir = 0; ir < read_elm; ir++) { - switch (rd_kw_get_type(rd_kw)) { - case (RD_CHAR_TYPE): - rd_kw_fscanf_qstring(&rd_kw->data[offset], - read_format.c_str(), 8, stream); - break; - case (RD_STRING_TYPE): - rd_kw_fscanf_qstring(&rd_kw->data[offset], - read_format.c_str(), - rd_type_get_sizeof_iotype( - rd_kw_get_data_type(rd_kw)), - stream); - break; - case (RD_INT_TYPE): { - int iread = fscanf(stream, read_format.c_str(), - (int *)&rd_kw->data[offset]); - if (iread != 1) - throw std::runtime_error(fmt::format( - "after reading {} values reading of keyword:{} " - "from:{} failed", - offset / - rd_type_get_sizeof_ctype(rd_kw->data_type), - rd_kw->header8, fortio.filename_ref())); - } break; - case (RD_FLOAT_TYPE): { - int iread = fscanf(stream, read_format.c_str(), - (float *)&rd_kw->data[offset]); - if (iread != 1) { - throw std::runtime_error(fmt::format( - "after reading {} values reading of keyword:{} " - "from:{} failed", - offset / - rd_type_get_sizeof_ctype(rd_kw->data_type), - rd_kw->header8, fortio.filename_ref())); - } - } break; - case (RD_DOUBLE_TYPE): { - double value = - __fscanf_RD_double(stream, read_format.c_str()); - rd_kw_iset(rd_kw, index, &value); - } break; - case (RD_BOOL_TYPE): { - char bool_char; - if (fscanf(stream, read_format.c_str(), &bool_char) == - 1) { - if (bool_char == BOOL_TRUE_CHAR) - rd_kw_iset_bool(rd_kw, index, true); - else if (bool_char == BOOL_FALSE_CHAR) - rd_kw_iset_bool(rd_kw, index, false); - else - throw std::runtime_error(fmt::format( - "Logical value: [{}] not recogniced", - bool_char)); - } else - throw std::runtime_error( - "read failed - premature file end?"); - } break; - case (RD_MESS_TYPE): - rd_kw_fscanf_qstring(&rd_kw->data[offset], - read_format.c_str(), 8, stream); - break; - default: - throw std::runtime_error( - fmt::format("Internal error: internal " - "eclipse_type: {} not recognized", - rd_kw_get_type(rd_kw))); - } - offset += rd_type_get_sizeof_ctype(rd_kw->data_type); - index++; - } - } - - /* Skip the trailing newline */ - fortio.fseek(1, SEEK_CUR); - return true; - } else { - char *buffer = rd_kw_alloc_input_buffer(rd_kw); - const int sizeof_iotype = - rd_type_get_sizeof_iotype(rd_kw->data_type); - bool read_ok = - fortio.fread_buffer(buffer, rd_kw->size * sizeof_iotype); - - if (read_ok) - rd_kw_load_from_input_buffer(rd_kw, buffer); - - free(buffer); - return read_ok; - } - } else - /* The keyword has zero size - and reading data is trivially OK. */ + if (fortio.fmt_file()) { + rd_kw->m_data = read_formatted_data(rd_kw, fortio); return true; + } else { + std::optional out; + bool read_ok = read_unformatted_data(rd_kw, fortio, out); + if (read_ok) + rd_kw->m_data = std::move(out); + return read_ok; + } } /** @@ -1168,32 +620,58 @@ static bool rd_kw_fread_data(rd_kw_type *rd_kw, ERT::FortIO &fortio) { offset of the start of the keyword (i.e. its header) in the file, as stored by rd_file_kw. */ -void rd_kw_fread_indexed_data(ERT::FortIO &fortio, offset_type kw_offset, - rd_data_type data_type, int element_count, - const std::vector &index_map, - char *io_buffer) { +void rd::KW::fread_indexed_data(ERT::FortIO &fortio, offset_type kw_offset, + rd_data_type data_type, int element_count, + const std::vector &index_map, + char *io_buffer) { size_t sizeof_iotype = rd_type_get_sizeof_iotype(data_type); // For unformatted (binary) files the individual elements have a fixed // on-disk size, so we can seek directly to each requested element. For // formatted (ASCII) files the elements have a variable text width and // direct seeking is not possible; in that case we read the whole - // keyword and extract the requested elements afterwards. + // keyword via fread() and extract the requested elements from m_data + // afterwards. if (fortio.fmt_file()) { fortio.fseek(kw_offset, SEEK_SET); - rd_kw_ptr rd_kw(rd_kw_fread_alloc(fortio), rd_kw_free); + std::unique_ptr rd_kw = rd::KW::fread(fortio); if (rd_kw == NULL) throw std::runtime_error(fmt::format( "failed to load keyword at offset:{}", (long)kw_offset)); - for (size_t index = 0; index < index_map.size(); index++) { - int element_index = index_map[index]; - memcpy(&io_buffer[index * sizeof_iotype], - rd_kw_iget_ptr(rd_kw.get(), element_index), sizeof_iotype); - } + if (!rd_kw->m_data.has_value()) + throw std::runtime_error(fmt::format( + "failed to load keyword data at offset:{}", (long)kw_offset)); + + std::visit( + [&](const auto &vec) { + using VecT = std::decay_t; + for (size_t index = 0; index < index_map.size(); index++) { + int element_index = index_map[index]; + char *dst = &io_buffer[index * sizeof_iotype]; + if constexpr (std::is_same_v>) { + /* RD_BOOL_TYPE, stored as vector with 0/1 + values; on-disk representation is a full int. */ + int int_value = vec[element_index] ? RD_BOOL_TRUE_INT + : RD_BOOL_FALSE_INT; + std::memcpy(dst, &int_value, sizeof_iotype); + } else if constexpr (std::is_same_v< + VecT, std::vector>) { + const std::string &s = vec[element_index]; + size_t string_length = + std::min(s.size(), sizeof_iotype); + std::memcpy(dst, s.data(), string_length); + for (size_t j = string_length; j < sizeof_iotype; j++) + dst[j] = ' '; + } else { + std::memcpy(dst, &vec[element_index], sizeof_iotype); + } + } + }, + rd_kw->m_data.value()); } else { - const int block_size = get_blocksize(data_type); - FILE *stream = fortio.get_FILE(); + const size_t block_size = get_blocksize(data_type); + std::istream &stream = fortio.get_istream(); offset_type data_offset = kw_offset + RD_KW_HEADER_FORTIO_SIZE; for (size_t index = 0; index < index_map.size(); index++) { @@ -1206,8 +684,10 @@ void rd_kw_fread_indexed_data(ERT::FortIO &fortio, offset_type kw_offset, fortio.data_fseek(data_offset, element_index, sizeof_iotype, element_count, block_size); - util_fread(&io_buffer[index * sizeof_iotype], sizeof_iotype, 1, - stream, __func__); + if (!stream.read(&io_buffer[index * sizeof_iotype], sizeof_iotype)) + throw std::runtime_error( + fmt::format("{}: only read {}/{} bytes from disk", __func__, + stream.gcount(), sizeof_iotype)); } if (RD_ENDIAN_FLIP) @@ -1218,16 +698,7 @@ void rd_kw_fread_indexed_data(ERT::FortIO &fortio, offset_type kw_offset, /** Allocates storage and reads data. */ -bool rd_kw_fread_realloc_data(rd_kw_type *rd_kw, ERT::FortIO &fortio) { - rd_kw_alloc_data(rd_kw); - return rd_kw_fread_data(rd_kw, fortio); -} - -/** - Static method without a class instance. -*/ - -bool rd_kw_fskip_data__(rd_data_type data_type, const int element_count, +bool rd::KW::fskip_data(rd_data_type data_type, const int element_count, ERT::FortIO &fortio) { if (element_count <= 0) return true; @@ -1235,27 +706,22 @@ bool rd_kw_fskip_data__(rd_data_type data_type, const int element_count, bool fmt_file = fortio.fmt_file(); if (fmt_file) { /* Formatted skipping actually involves reading the data - nice ??? */ - rd_kw_ptr tmp_kw = make_rd_kw(); - rd_kw_initialize(tmp_kw.get(), "WORK", element_count, data_type); - rd_kw_alloc_data(tmp_kw.get()); - rd_kw_fread_data(tmp_kw.get(), fortio); + rd::KW tmp_kw{"WORK", element_count, data_type}; + fread_data(&tmp_kw, fortio); } else { - const int blocksize = get_blocksize(data_type); - const int block_count = - element_count / blocksize + (element_count % blocksize != 0); - int element_size = rd_type_get_sizeof_iotype(data_type); + size_t num_elements = static_cast(element_count); + const size_t blocksize = get_blocksize(data_type); + const size_t block_count = + num_elements / blocksize + (num_elements % blocksize != 0); + size_t element_size = rd_type_get_sizeof_iotype(data_type); - if (!fortio.data_fskip(element_size, element_count, block_count)) + if (!fortio.data_fskip(element_size, num_elements, block_count)) return false; } return true; } -bool rd_kw_fskip_data(rd_kw_type *rd_kw, ERT::FortIO &fortio) { - return rd_kw_fskip_data__(rd_kw_get_data_type(rd_kw), rd_kw->size, fortio); -} - /** This function will skip the header part of an rd_kw instance. The function will read the file content at the current position, it is @@ -1264,49 +730,45 @@ bool rd_kw_fskip_data(rd_kw_type *rd_kw, ERT::FortIO &fortio) { will be complete crash and burn. */ -void rd_kw_fskip_header(ERT::FortIO &fortio) { +void rd::KW::fskip_header(ERT::FortIO &fortio) { bool fmt_file = fortio.fmt_file(); if (fmt_file) { - rd_kw_ptr rd_kw = make_rd_kw(); - rd_kw_fread_header(rd_kw.get(), fortio); + rd::KW::fread_header(fortio); } else fortio.fskip_record(); } -rd_read_status_enum rd_kw_fread_header(rd_kw_type *rd_kw, ERT::FortIO &fortio) { +std::unique_ptr rd::KW::fread_header(ERT::FortIO &fortio) { const char null_char = '\0'; - FILE *stream = fortio.get_FILE(); + std::istream &stream = fortio.get_istream(); bool fmt_file = fortio.fmt_file(); char header[RD_STRING8_LENGTH + 1]; char rd_type_str[RD_TYPE_LENGTH + 1]; - int record_size; int size; if (fmt_file) { - if (!rd_kw_fscanf_qstring(header, "%8c", 8, stream)) - return RD_KW_READ_FAIL; + if (!read_sized_quoted_string(header, 8, stream)) + return {nullptr}; - int read_count = fscanf(stream, "%d", &size); - if (read_count != 1) - return RD_KW_READ_FAIL; + stream >> size; + if (stream.fail()) + return {nullptr}; - if (!rd_kw_fscanf_qstring(rd_type_str, "%4c", 4, stream)) - return RD_KW_READ_FAIL; + if (!read_sized_quoted_string(rd_type_str, 4, stream)) + return {nullptr}; - fgetc(stream); /* Reading the trailing newline ... */ + stream.get(); /* Reading the trailing newline ... */ } else { header[RD_STRING8_LENGTH] = null_char; rd_type_str[RD_TYPE_LENGTH] = null_char; - record_size = fortio.init_read(); + int record_size = fortio.init_read(); if (record_size <= 0) - return RD_KW_READ_FAIL; + return {nullptr}; char buffer[RD_KW_HEADER_DATA_SIZE]; - size_t read_bytes = fread(buffer, 1, RD_KW_HEADER_DATA_SIZE, stream); - - if (read_bytes != RD_KW_HEADER_DATA_SIZE) - return RD_KW_READ_FAIL; + if (!stream.read(buffer, RD_KW_HEADER_DATA_SIZE)) + return {nullptr}; memcpy(header, &buffer[0], RD_STRING8_LENGTH); void *ptr = &buffer[RD_STRING8_LENGTH]; @@ -1316,1131 +778,418 @@ rd_read_status_enum rd_kw_fread_header(rd_kw_type *rd_kw, ERT::FortIO &fortio) { RD_TYPE_LENGTH); if (!fortio.complete_read(record_size)) - return RD_KW_READ_FAIL; + return {nullptr}; if (RD_ENDIAN_FLIP) util_endian_flip_vector(&size, sizeof size, 1); } rd_data_type data_type = rd_type_create_from_name(rd_type_str); - rd_kw_initialize(rd_kw, header, size, data_type); - - return RD_KW_READ_OK; -} - -/** - Will seek through the open fortio file and search for a keyword with - header 'kw'. It will always start the search from the present - position in the file, but if rewind is true it will rewind the - fortio file if not finding 'kw' between current offset and EOF. - - If the kw is found the fortio pointer is positioned at the - beginning of the keyword, and the function returns true. If the the - 'kw' is NOT found the file will be repositioned to the initial - position, and the function will return false; unless abort_on_error - == true in which case the function will abort if the 'kw' is not - found. -*/ - -bool rd_kw_fseek_kw(const char *kw, bool rewind, bool abort_on_error, - ERT::FortIO &fortio) { - rd_kw_ptr tmp_kw = make_rd_kw(); - long int init_pos = fortio.ftell(); - bool cont, kw_found; - - cont = true; - kw_found = false; - while (cont) { - long current_pos = fortio.ftell(); - if (rd_kw_fread_header(tmp_kw.get(), fortio) == RD_KW_READ_OK) { - if (rd_kw_string_eq(rd_kw_get_header8(tmp_kw.get()), kw)) { - fortio.fseek(current_pos, SEEK_SET); - kw_found = true; - cont = false; - } else - rd_kw_fskip_data(tmp_kw.get(), fortio); - } else { - if (rewind) { - fortio.rewind(); - rewind = false; - } else - cont = false; - } - } - if (!kw_found) { - if (abort_on_error) - throw std::runtime_error( - fmt::format("failed to locate keyword:{} in file:{}", kw, - fortio.filename_ref())); - - fortio.fseek(init_pos, SEEK_SET); - } - return kw_found; -} - -void rd_kw_set_data_ptr(rd_kw_type *rd_kw, void *data) { - if (!rd_kw->shared_data) - free(rd_kw->data); - rd_kw->data = (char *)data; -} - -void rd_kw_set_header_name(rd_kw_type *rd_kw, const char *header) { - rd_kw->header8 = (char *)realloc(rd_kw->header8, RD_STRING8_LENGTH + 1); - if (strlen(header) <= 8) { - sprintf(rd_kw->header8, "%-8s", header); - - /* Internalizing a header without the trailing spaces as well. */ - free(rd_kw->header); - rd_kw->header = util_alloc_strip_copy(rd_kw->header8); - } else { - free(rd_kw->header); - rd_kw->header = (char *)util_alloc_copy(header, strlen(header) + 1); - } + return std::make_unique(header, size, data_type); } -void rd_kw_set_data_type(rd_kw_type *rd_kw, rd_data_type data_type) { - memcpy(&rd_kw->data_type, &data_type, sizeof data_type); -} - -bool rd_kw_fread_realloc(rd_kw_type *rd_kw, ERT::FortIO &fortio) { - if (rd_kw_fread_header(rd_kw, fortio) == RD_KW_READ_OK) - return rd_kw_fread_realloc_data(rd_kw, fortio); - else - return false; -} - -rd_kw_type *rd_kw_fread_alloc(ERT::FortIO &fortio) { - rd_kw_ptr rd_kw = make_rd_kw(); - if (!rd_kw_fread_realloc(rd_kw.get(), fortio)) { - return nullptr; - } - return rd_kw.release(); -} +std::unique_ptr rd::KW::fread(ERT::FortIO &fortio) { + if (auto rd_kw = rd::KW::fread_header(fortio)) { + if (!fread_data(rd_kw.get(), fortio)) + return {nullptr}; -void rd_kw_fskip(ERT::FortIO &fortio) { - rd_kw_type *tmp_kw; - tmp_kw = rd_kw_fread_alloc(fortio); - rd_kw_free(tmp_kw); + return rd_kw; + } else + return {nullptr}; } -static void rd_kw_fwrite_data_unformatted(const rd_kw_type *rd_kw, +static void rd_kw_fwrite_data_unformatted(const rd::KW *rd_kw, ERT::FortIO &fortio) { - char *iobuffer = rd_kw_alloc_output_buffer(rd_kw); - int sizeof_iotype = rd_type_get_sizeof_iotype(rd_kw->data_type); + auto iobuffer = alloc_output_buffer(rd_kw); + size_t sizeof_iotype = rd_kw->iotype_size(); { - const int blocksize = get_blocksize(rd_kw->data_type); - const int num_blocks = - rd_kw->size / blocksize + (rd_kw->size % blocksize == 0 ? 0 : 1); - int block_nr; - - for (block_nr = 0; block_nr < num_blocks; block_nr++) { - int this_blocksize = - std::min((block_nr + 1) * blocksize, rd_kw->size) - - block_nr * blocksize; - int record_size = + const size_t blocksize = get_blocksize(rd_kw->data_type()); + const size_t num_blocks = rd_kw->size() / blocksize + + (rd_kw->size() % blocksize == 0 ? 0 : 1); + for (size_t block_nr = 0; block_nr < num_blocks; block_nr++) { + size_t blocksize_rem = + std::min((block_nr + 1) * blocksize, rd_kw->size()); + size_t blocksize_prev = block_nr * blocksize; + size_t this_blocksize = blocksize_prev > blocksize_rem + ? 0 + : blocksize_rem - blocksize_prev; + size_t record_size = this_blocksize * sizeof_iotype; /* The total size in bytes of the record written by the fortio layer. */ + if (record_size > std::numeric_limits::max()) + throw std::invalid_argument(fmt::format( + "Size of record exceeded 32-bit signed integer")); fortio.fwrite_record( - &iobuffer[block_nr * blocksize * sizeof_iotype], record_size); + &iobuffer[block_nr * blocksize * sizeof_iotype], + static_cast(record_size)); } } - free(iobuffer); } -static void rd_kw_fwrite_data_formatted(rd_kw_type *rd_kw, +static void rd_kw_fwrite_data_formatted(const rd::KW *rd_kw, ERT::FortIO &fortio) { + const auto &m_data = rd_kw->data(); + if (!m_data.has_value()) + /* RD_MESS_TYPE keywords carry no element-wise data. */ + return; - { - - FILE *stream = fortio.get_FILE(); - const int blocksize = get_blocksize(rd_kw->data_type); - const int columns = get_columns(rd_kw->data_type); - const int string_width = rd_type_get_sizeof_iotype(rd_kw->data_type); - const int num_blocks = - rd_kw->size / blocksize + (rd_kw->size % blocksize == 0 ? 0 : 1); - int block_nr; - - for (block_nr = 0; block_nr < num_blocks; block_nr++) { - int this_blocksize = - std::min((block_nr + 1) * blocksize, rd_kw->size) - - block_nr * blocksize; - int num_lines = this_blocksize / columns + - (this_blocksize % columns == 0 ? 0 : 1); - int line_nr; - for (line_nr = 0; line_nr < num_lines; line_nr++) { - int num_columns = - std::min((line_nr + 1) * columns, this_blocksize) - - columns * line_nr; - int col_nr; - for (col_nr = 0; col_nr < num_columns; col_nr++) { - int data_index = - block_nr * blocksize + line_nr * columns + col_nr; - void *data_ptr = rd_kw_iget_ptr_static(rd_kw, data_index); - std::string element; - switch (rd_kw_get_type(rd_kw)) { - case (RD_CHAR_TYPE): - element = rd::format_kw_element((char *)data_ptr); - break; - case (RD_STRING_TYPE): - element = rd::format_kw_element((char *)data_ptr, - string_width); - break; - case (RD_INT_TYPE): - element = rd::format_kw_element(((int *)data_ptr)[0]); - break; - case (RD_BOOL_TYPE): - element = rd::format_kw_element( - ((unsigned char *)data_ptr)[0] != 0); - break; - case (RD_FLOAT_TYPE): - element = rd::format_kw_element(((float *)data_ptr)[0]); - break; - case (RD_DOUBLE_TYPE): - element = - rd::format_kw_element(((double *)data_ptr)[0]); - break; - case (RD_MESS_TYPE): - throw std::runtime_error( - "Internal inconsistency : message type keywords " - "should not have data"); - break; + std::ostream &stream = fortio.get_ostream(); + const size_t blocksize = get_blocksize(rd_kw->data_type()); + const size_t columns = get_columns(rd_kw->data_type()); + const size_t string_width = rd_kw->iotype_size(); + const rd_type_enum type = rd_kw->get_type(); + const size_t num_blocks = + rd_kw->size() / blocksize + (rd_kw->size() % blocksize == 0 ? 0 : 1); + std::visit( + [&](const auto &vec) { + using VecT = std::decay_t; + for (size_t block_nr = 0; block_nr < num_blocks; block_nr++) { + size_t block_next = + std::min((block_nr + 1) * blocksize, rd_kw->size()); + size_t block_prev = block_nr * blocksize; + size_t this_blocksize = + block_prev > block_next ? 0 : block_next - block_prev; + size_t num_lines = this_blocksize / columns + + (this_blocksize % columns == 0 ? 0 : 1); + for (size_t line_nr = 0; line_nr < num_lines; line_nr++) { + size_t num_columns = + std::min((line_nr + 1) * columns, this_blocksize) - + columns * line_nr; + for (size_t col_nr = 0; col_nr < num_columns; col_nr++) { + size_t data_index = + block_nr * blocksize + line_nr * columns + col_nr; + if (data_index >= vec.size()) + throw std::logic_error( + "Loop exhausted size in " + "rd_kw_fwrite_data_formatted"); + std::string element; + if constexpr (std::is_same_v< + VecT, std::vector>) { + if (type == RD_CHAR_TYPE) + element = rd::format_kw_element( + vec[data_index].c_str()); + else + element = rd::format_kw_element( + vec[data_index].c_str(), string_width); + } else if constexpr (std::is_same_v< + VecT, std::vector>) { + element = + rd::format_kw_element(vec[data_index] != 0); + } else { + element = rd::format_kw_element(vec[data_index]); + } + stream << element; } - fputs(element.c_str(), stream); + stream << "\n"; } - fprintf(stream, "\n"); } - } - } + }, + m_data.value()); } -void rd_kw_fwrite_data(const rd_kw_type *_rd_kw, ERT::FortIO &fortio) { - rd_kw_type *rd_kw = (rd_kw_type *)_rd_kw; +void rd::KW::fwrite_data(ERT::FortIO &fortio) const { bool fmt_file = fortio.fmt_file(); if (fmt_file) - rd_kw_fwrite_data_formatted(rd_kw, fortio); + rd_kw_fwrite_data_formatted(this, fortio); else - rd_kw_fwrite_data_unformatted(rd_kw, fortio); + rd_kw_fwrite_data_unformatted(this, fortio); } -void rd_kw_fwrite_header(const rd_kw_type *rd_kw, ERT::FortIO &fortio) { - FILE *stream = fortio.get_FILE(); +void rd_kw_fwrite_header(const rd::KW *rd_kw, ERT::FortIO &fortio) { + std::ostream &stream = fortio.get_ostream(); bool fmt_file = fortio.fmt_file(); - std::string type_name = rd_type_name(rd_kw->data_type); + std::string type_name = rd_type_name(rd_kw->data_type()); + + if (rd_kw->size() > std::numeric_limits::max()) + throw std::invalid_argument( + fmt::format("Size of rd_kw exceeds format: {}", rd_kw->size())); + + std::string header8 = fmt::format("{:8.8}", rd_kw->header()); if (fmt_file) - fprintf(stream, WRITE_HEADER_FMT, rd_kw->header8, rd_kw->size, - type_name.c_str()); + stream << fmt::format(WRITE_HEADER_FMT, header8, + static_cast(rd_kw->size()), type_name); else { - int size = rd_kw->size; + int size = static_cast(rd_kw->size()); if (RD_ENDIAN_FLIP) util_endian_flip_vector(&size, sizeof size, 1); fortio.init_write(RD_KW_HEADER_DATA_SIZE); - fwrite(rd_kw->header8, sizeof(char), RD_STRING8_LENGTH, stream); - fwrite(&size, sizeof(int), 1, stream); - fwrite(type_name.c_str(), sizeof(char), RD_TYPE_LENGTH, stream); + stream.write(header8.c_str(), RD_STRING8_LENGTH); + stream.write(reinterpret_cast(&size), sizeof(int)); + stream.write(type_name.c_str(), RD_TYPE_LENGTH); fortio.complete_write(RD_KW_HEADER_DATA_SIZE); } } -bool rd_kw_fwrite(const rd_kw_type *rd_kw, ERT::FortIO &fortio) { - if (strlen(rd_kw_get_header(rd_kw)) > RD_STRING8_LENGTH) { +bool rd::KW::fwrite(ERT::FortIO &fortio) const { + if (this->header().size() > RD_STRING8_LENGTH) { fortio.fwrite_error(); return false; } - rd_kw_fwrite_header(rd_kw, fortio); - rd_kw_fwrite_data(rd_kw, fortio); + rd_kw_fwrite_header(this, fortio); + this->fwrite_data(fortio); return true; } -static void *rd_kw_get_data_ref(const rd_kw_type *rd_kw) { return rd_kw->data; } - -void *rd_kw_get_ptr(const rd_kw_type *rd_kw) { - return rd_kw_get_data_ref(rd_kw); -} - -int rd_kw_get_size(const rd_kw_type *rd_kw) { return rd_kw->size; } - -rd_type_enum rd_kw_get_type(const rd_kw_type *rd_kw) { - return rd_type_get_type(rd_kw->data_type); -} - -rd_data_type rd_kw_get_data_type(const rd_kw_type *rd_kw) { - return rd_kw->data_type; -} - -/* - Untyped - low level alternative. -*/ -static void rd_kw_scalar_set__(rd_kw_type *rd_kw, const void *value) { - int sizeof_ctype = rd_type_get_sizeof_ctype(rd_kw->data_type); - int i; - for (i = 0; i < rd_kw->size; i++) - memcpy(&rd_kw->data[i * sizeof_ctype], value, sizeof_ctype); -} - -/** - Will create a new keyword of the same type as src_kw, and size - @target_size. The integer array mapping is a list sizeof(src_kw) - elements, where each element is the new index, i.e. - - new_kw[ mapping[i] ] = src_kw[i] - - For all inactive elements in new kw are set as follows: - - 0 - For float / int / double - False - For logical - "" - For char -*/ - -rd_kw_type *rd_kw_alloc_scatter_copy(const rd_kw_type *src_kw, int target_size, - const int *mapping, void *def_value) { - int default_int = 0; - double default_double = 0; - float default_float = 0; - bool default_bool = false; - const char *default_char = ""; - rd_kw_ptr new_kw = - make_rd_kw(src_kw->header, target_size, src_kw->data_type); - - if (def_value != NULL) - rd_kw_scalar_set__(new_kw.get(), def_value); - else { - /** Initialize with defaults .*/ - switch (rd_kw_get_type(src_kw)) { - case (RD_INT_TYPE): - rd_kw_scalar_set__(new_kw.get(), &default_int); - break; - case (RD_FLOAT_TYPE): - rd_kw_scalar_set__(new_kw.get(), &default_float); - break; - case (RD_DOUBLE_TYPE): - rd_kw_scalar_set__(new_kw.get(), &default_double); - break; - case (RD_BOOL_TYPE): - rd_kw_scalar_set__(new_kw.get(), &default_bool); - break; - case (RD_CHAR_TYPE): - rd_kw_scalar_set__(new_kw.get(), default_char); - break; - default: - throw std::invalid_argument( - fmt::format("unsupported type:{}", rd_kw_get_type(src_kw))); - } - } - - { - int sizeof_ctype = rd_type_get_sizeof_ctype(src_kw->data_type); - int i; - for (i = 0; i < src_kw->size; i++) { - int target_index = mapping[i]; - memcpy(&new_kw->data[target_index * sizeof_ctype], - &src_kw->data[i * sizeof_ctype], sizeof_ctype); - } - } - - return new_kw.release(); +int rd::kw_get_size(const rd::KW *rd_kw) { + if (rd_kw->size() > std::numeric_limits::max()) + throw std::invalid_argument( + fmt::format("Size of rd_kw exceeded int max: {}", rd_kw->size())); + return static_cast(rd_kw->size()); } -rd_kw_type *rd_kw_alloc_global_copy(const rd_kw_type *src, - const rd_kw_type *actnum) { - if (rd_kw_get_type(actnum) != RD_INT_TYPE) +std::unique_ptr rd::KW::global_copy(const rd::KW *src, + const rd::KW *actnum) { + if (actnum->get_type() != RD_INT_TYPE) return NULL; - const int global_size = rd_kw_get_size(actnum); - rd_kw_ptr global_copy = - make_rd_kw(rd_kw_get_header(src), global_size, src->data_type); - const int *mapping = rd_kw_get_int_ptr(actnum); - const int src_size = rd_kw_get_size(src); - int src_index = 0; - for (int global_index = 0; global_index < global_size; global_index++) { - if (mapping[global_index]) { - /* We ran through and beyond the size of the src keyword. */ - if (src_index >= src_size) { - global_copy = NULL; - break; + const size_t global_size = actnum->size(); + auto global_copy = + std::make_unique(src->header(), global_size, src->data_type()); + auto mapping = actnum->get_vector(); + const size_t src_size = src->size(); + size_t src_index = 0; + bool overflow = false; + std::visit( + [&](auto &&target_alt) { + using T = typename std::decay_t::value_type; + auto &target_vec = global_copy->get_vector(); + const auto &src_vec = src->get_vector(); + for (size_t global_index = 0; global_index < global_size; + global_index++) { + if (mapping[global_index]) { + /* We ran through and beyond the size of the src keyword. */ + if (src_index >= src_size) { + overflow = true; + break; + } + target_vec[global_index] = src_vec[src_index]; + src_index++; + } } - const void *value_ptr = rd_kw_iget_ptr(src, src_index); - rd_kw_iset_static(global_copy.get(), global_index, value_ptr); - src_index++; - } - } + }, + global_copy->data().value()); + + if (overflow) + global_copy.reset(nullptr); /* Not all the src data was distributed. */ if (src_index < src_size) { global_copy.reset(nullptr); } - return global_copy.release(); -} - -void rd_kw_summarize(const rd_kw_type *rd_kw) { - std::string type_name = rd_type_name(rd_kw->data_type); - printf("%8s %10d:%4s \n", rd_kw_get_header8(rd_kw), rd_kw_get_size(rd_kw), - type_name.c_str()); -} - -#define RD_KW_SCALAR_SET_TYPED(ctype, RD_TYPE) \ - void rd_kw_scalar_set_##ctype(rd_kw_type *rd_kw, ctype value) { \ - if (rd_kw_get_type(rd_kw) == RD_TYPE) { \ - ctype *data = (ctype *)rd_kw_get_data_ref(rd_kw); \ - int i; \ - for (i = 0; i < rd_kw->size; i++) \ - data[i] = value; \ - } else \ - throw std::invalid_argument("wrong type"); \ - } - -RD_KW_SCALAR_SET_TYPED(int, RD_INT_TYPE) -RD_KW_SCALAR_SET_TYPED(float, RD_FLOAT_TYPE) -RD_KW_SCALAR_SET_TYPED(double, RD_DOUBLE_TYPE) -RD_KW_SCALAR_SET_TYPED(bool, RD_BOOL_TYPE) -#undef RD_KW_SCALAR_SET_TYPED - -void rd_kw_scalar_set_float_or_double(rd_kw_type *rd_kw, double value) { - rd_type_enum rd_type = rd_kw_get_type(rd_kw); - if (rd_type == RD_FLOAT_TYPE) - rd_kw_scalar_set_float(rd_kw, (float)value); - else if (rd_type == RD_DOUBLE_TYPE) - rd_kw_scalar_set_double(rd_kw, value); - else - throw std::invalid_argument("wrong type"); + return global_copy; } -#define RD_KW_SCALE_TYPED(ctype, RD_TYPE) \ - void rd_kw_scale_##ctype(rd_kw_type *rd_kw, ctype scale_factor) { \ - if (rd_kw_get_type(rd_kw) != RD_TYPE) \ - throw std::invalid_argument(fmt::format( \ - "Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); \ - { \ - ctype *data = (ctype *)rd_kw_get_data_ref(rd_kw); \ - int size = rd_kw_get_size(rd_kw); \ - int i; \ - for (i = 0; i < size; i++) \ - data[i] *= scale_factor; \ - } \ - } - -RD_KW_SCALE_TYPED(int, RD_INT_TYPE) -RD_KW_SCALE_TYPED(float, RD_FLOAT_TYPE) -RD_KW_SCALE_TYPED(double, RD_DOUBLE_TYPE) -#undef RD_KW_SCALE_TYPED - -void rd_kw_scale_float_or_double(rd_kw_type *rd_kw, double scale_factor) { - rd_type_enum rd_type = rd_kw_get_type(rd_kw); - if (rd_type == RD_FLOAT_TYPE) - rd_kw_scale_float(rd_kw, (float)scale_factor); - else if (rd_type == RD_DOUBLE_TYPE) - rd_kw_scale_double(rd_kw, scale_factor); - else - throw std::invalid_argument("wrong type"); -} - -#define RD_KW_SHIFT_TYPED(ctype, RD_TYPE) \ - void rd_kw_shift_##ctype(rd_kw_type *rd_kw, ctype shift_value) { \ - if (rd_kw_get_type(rd_kw) != RD_TYPE) \ - throw std::invalid_argument(fmt::format( \ - "Keyword: {} is wrong type", rd_kw_get_header8(rd_kw))); \ - { \ - ctype *data = (ctype *)rd_kw_get_data_ref(rd_kw); \ - int size = rd_kw_get_size(rd_kw); \ - int i; \ - for (i = 0; i < size; i++) \ - data[i] += shift_value; \ - } \ - } - -RD_KW_SHIFT_TYPED(int, RD_INT_TYPE) -RD_KW_SHIFT_TYPED(float, RD_FLOAT_TYPE) -RD_KW_SHIFT_TYPED(double, RD_DOUBLE_TYPE) -#undef RD_KW_SHIFT_TYPED - -void rd_kw_shift_float_or_double(rd_kw_type *rd_kw, double shift_value) { - rd_type_enum rd_type = rd_kw_get_type(rd_kw); - if (rd_type == RD_FLOAT_TYPE) - rd_kw_shift_float(rd_kw, (float)shift_value); - else if (rd_type == RD_DOUBLE_TYPE) - rd_kw_shift_double(rd_kw, shift_value); - else - throw std::invalid_argument("wrong type"); -} - -bool rd_kw_size_and_numeric_type_equal(const rd_kw_type *kw1, - const rd_kw_type *kw2) { - return rd_kw_size_and_type_equal(kw1, kw2) && - rd_type_is_numeric(kw1->data_type); -} - -#define RD_KW_ASSERT_TYPED_BINARY_OP(ctype, RD_TYPE) \ - bool rd_kw_assert_binary_##ctype(const rd_kw_type *kw1, \ - const rd_kw_type *kw2) { \ - if (!rd_kw_size_and_numeric_type_equal(kw1, kw2)) \ - return false; \ - if (rd_kw_get_type(kw1) != RD_TYPE) \ - return false; /* Type mismatch */ \ - return true; \ - } - -RD_KW_ASSERT_TYPED_BINARY_OP(int, RD_INT_TYPE) -RD_KW_ASSERT_TYPED_BINARY_OP(float, RD_FLOAT_TYPE) -RD_KW_ASSERT_TYPED_BINARY_OP(double, RD_DOUBLE_TYPE) -#undef RD_KW_ASSERT_TYPED_BINARY_OP - -void rd_kw_copy_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *src_kw) { - if (!rd_kw_size_and_type_equal(target_kw, src_kw)) - throw std::invalid_argument("type/size mismatch"); - char *target_data = (char *)rd_kw_get_data_ref(target_kw); - const char *src_data = (const char *)rd_kw_get_data_ref(src_kw); - int sizeof_ctype = rd_type_get_sizeof_ctype(target_kw->data_type); - for (const auto index : index_set) - memcpy(&target_data[index * sizeof_ctype], - &src_data[index * sizeof_ctype], sizeof_ctype); -} - -#define RD_KW_TYPED_INPLACE_ADD_INDEXED(ctype) \ - static void rd_kw_inplace_add_indexed_##ctype( \ - rd_kw_type *target_kw, const std::vector &index_set, \ - const rd_kw_type *add_kw) { \ - if (!rd_kw_assert_binary_##ctype(target_kw, add_kw)) \ - throw std::invalid_argument("type/size mismatch"); \ - ctype *target_data = (ctype *)rd_kw_get_data_ref(target_kw); \ - const ctype *add_data = (const ctype *)rd_kw_get_data_ref(add_kw); \ - for (const auto index : index_set) \ - target_data[index] += add_data[index]; \ - } - -RD_KW_TYPED_INPLACE_ADD_INDEXED(int) -RD_KW_TYPED_INPLACE_ADD_INDEXED(double) -RD_KW_TYPED_INPLACE_ADD_INDEXED(float) -#undef RD_KW_TYPED_INPLACE_ADD - -void rd_kw_inplace_add_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *add_kw) { - rd_type_enum type = rd_kw_get_type(target_kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_add_indexed_float(target_kw, index_set, add_kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_add_indexed_double(target_kw, index_set, add_kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_add_indexed_int(target_kw, index_set, add_kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace add not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(target_kw)))); - } +bool rd::KW::size_and_numeric_type_equal(const rd::KW *kw2) const { + return this->size_and_type_equal(kw2) && + rd_type_is_numeric(this->data_type()); } -#define RD_KW_TYPED_INPLACE_ADD(ctype) \ - static void rd_kw_inplace_add_##ctype(rd_kw_type *target_kw, \ - const rd_kw_type *add_kw) { \ - if (!rd_kw_assert_binary_##ctype(target_kw, add_kw)) \ - throw std::invalid_argument("type/size mismatch"); \ - { \ - ctype *target_data = (ctype *)rd_kw_get_data_ref(target_kw); \ - const ctype *add_data = (const ctype *)rd_kw_get_data_ref(add_kw); \ - int i; \ - for (i = 0; i < target_kw->size; i++) \ - target_data[i] += add_data[i]; \ - } \ - } -RD_KW_TYPED_INPLACE_ADD(int) -RD_KW_TYPED_INPLACE_ADD(double) -RD_KW_TYPED_INPLACE_ADD(float) - -#undef RD_KW_TYPED_INPLACE_ADD - -void rd_kw_inplace_add(rd_kw_type *target_kw, const rd_kw_type *add_kw) { - rd_type_enum type = rd_kw_get_type(target_kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_add_float(target_kw, add_kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_add_double(target_kw, add_kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_add_int(target_kw, add_kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace add not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(target_kw)))); - } -} - -#define RD_KW_TYPED_INPLACE_ADD_SQUARED(ctype) \ - static void rd_kw_inplace_add_squared_##ctype(rd_kw_type *target_kw, \ - const rd_kw_type *add_kw) { \ - if (!rd_kw_assert_binary_##ctype(target_kw, add_kw)) \ - throw std::invalid_argument("type/size mismatch"); \ - { \ - ctype *target_data = (ctype *)rd_kw_get_data_ref(target_kw); \ - const ctype *add_data = (const ctype *)rd_kw_get_data_ref(add_kw); \ - int i; \ - for (i = 0; i < target_kw->size; i++) \ - target_data[i] += add_data[i] * add_data[i]; \ - } \ - } -RD_KW_TYPED_INPLACE_ADD_SQUARED(int) -RD_KW_TYPED_INPLACE_ADD_SQUARED(double) -RD_KW_TYPED_INPLACE_ADD_SQUARED(float) - -#undef RD_KW_TYPED_INPLACE_ADD - -void rd_kw_inplace_add_squared(rd_kw_type *target_kw, - const rd_kw_type *add_kw) { - rd_type_enum type = rd_kw_get_type(target_kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_add_squared_float(target_kw, add_kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_add_squared_double(target_kw, add_kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_add_squared_int(target_kw, add_kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace add not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(target_kw)))); - } +void rd::KW::operator-=(const rd::KW &sub_kw) { + std::visit( + [&](auto &&target_alt) { + using T = typename std::decay_t::value_type; + if constexpr (std::is_same_v || std::is_same_v || + std::is_same_v) { + if (!this->size_and_numeric_type_equal(&sub_kw)) + throw std::invalid_argument("type/size mismatch"); + auto &target_data = this->get_vector(); + const auto &sub_data = sub_kw.get_vector(); + for (size_t i = 0; i < target_data.size(); i++) + target_data[i] -= sub_data[i]; + } else + throw std::invalid_argument( + fmt::format("inplace sub not implemented for type:{}", + rd_type_name(this->data_type()))); + }, + this->data().value()); } -#define RD_KW_TYPED_INPLACE_SUB(ctype) \ - void rd_kw_inplace_sub_##ctype(rd_kw_type *target_kw, \ - const rd_kw_type *sub_kw) { \ - if (!rd_kw_assert_binary_##ctype(target_kw, sub_kw)) \ - throw std::invalid_argument("type/size mismatch"); \ - { \ - ctype *target_data = (ctype *)rd_kw_get_data_ref(target_kw); \ - const ctype *sub_data = (const ctype *)rd_kw_get_data_ref(sub_kw); \ - int i; \ - for (i = 0; i < target_kw->size; i++) \ - target_data[i] -= sub_data[i]; \ - } \ - } -RD_KW_TYPED_INPLACE_SUB(int) -RD_KW_TYPED_INPLACE_SUB(double) -RD_KW_TYPED_INPLACE_SUB(float) -#undef RD_KW_TYPED_INPLACE_SUB - -void rd_kw_inplace_sub(rd_kw_type *target_kw, const rd_kw_type *sub_kw) { - rd_type_enum type = rd_kw_get_type(target_kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_sub_float(target_kw, sub_kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_sub_double(target_kw, sub_kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_sub_int(target_kw, sub_kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace sub not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(target_kw)))); - } +static bool elm_equal_numeric(const rd::KW *rd_kw1, const rd::KW *rd_kw2, + size_t offset, double abs_epsilon, + double rel_epsilon) { + double v1 = rd_kw1->as_double(offset); + double v2 = rd_kw2->as_double(offset); + return util_double_approx_equal__(v1, v2, rel_epsilon, abs_epsilon); } -#define RD_KW_TYPED_INPLACE_SUB_INDEXED(ctype) \ - static void rd_kw_inplace_sub_indexed_##ctype( \ - rd_kw_type *target_kw, const std::vector &index_set, \ - const rd_kw_type *sub_kw) { \ - if (!rd_kw_assert_binary_##ctype(target_kw, sub_kw)) \ - throw std::invalid_argument("type/size mismatch"); \ - ctype *target_data = (ctype *)rd_kw_get_data_ref(target_kw); \ - const ctype *sub_data = (const ctype *)rd_kw_get_data_ref(sub_kw); \ - for (const auto index : index_set) \ - target_data[index] -= sub_data[index]; \ - } - -RD_KW_TYPED_INPLACE_SUB_INDEXED(int) -RD_KW_TYPED_INPLACE_SUB_INDEXED(double) -RD_KW_TYPED_INPLACE_SUB_INDEXED(float) -#undef RD_KW_TYPED_INPLACE_SUB +static bool elm_equal(const rd::KW *rd_kw1, const rd::KW *rd_kw2, + size_t offset) { + const auto &data1 = rd_kw1->data(); + const auto &data2 = rd_kw2->data(); + if (!data1.has_value() || !data2.has_value()) + return false; -void rd_kw_inplace_sub_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *sub_kw) { - rd_type_enum type = rd_kw_get_type(target_kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_sub_indexed_float(target_kw, index_set, sub_kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_sub_indexed_double(target_kw, index_set, sub_kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_sub_indexed_int(target_kw, index_set, sub_kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace sub not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(target_kw)))); - } + return std::visit( + [offset, &data2](const auto &vec1) { + using VecT = std::decay_t; + const auto &vec2 = std::get(*data2); + return vec1[offset] == vec2[offset]; + }, + *data1); } -#define RD_KW_TYPED_INPLACE_ABS(ctype, abs_func) \ - void rd_kw_inplace_abs_##ctype(rd_kw_type *kw) { \ - ctype *data = (ctype *)rd_kw_get_data_ref(kw); \ - int i; \ - for (i = 0; i < kw->size; i++) \ - data[i] = abs_func(data[i]); \ - } - -RD_KW_TYPED_INPLACE_ABS(int, abs) -RD_KW_TYPED_INPLACE_ABS(double, fabs) -RD_KW_TYPED_INPLACE_ABS(float, fabsf) -#undef RD_KW_TYPED_INPLACE_ABS +size_t rd::KW::first_different(const rd::KW *rd_kw2, size_t offset, + double abs_epsilon, double rel_epsilon) const { + if (!size_and_type_equal(rd_kw2)) + throw std::invalid_argument("sorry invalid comparison"); -void rd_kw_inplace_abs(rd_kw_type *kw) { - rd_type_enum type = rd_kw_get_type(kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_abs_float(kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_abs_double(kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_abs_int(kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace abs not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(kw)))); + if (offset >= this->size()) + throw std::invalid_argument(fmt::format( + "offset value in first_difference exceeded size: {}", offset)); + + bool numeric_compare = false; + + if (((abs_epsilon > 0) || (rel_epsilon > 0)) && + ((get_type() == RD_FLOAT_TYPE) || (get_type() == RD_DOUBLE_TYPE))) + numeric_compare = true; + for (size_t index = offset; index < this->size(); index++) { + bool equal = (numeric_compare) + ? elm_equal_numeric(this, rd_kw2, index, abs_epsilon, + rel_epsilon) + : elm_equal(this, rd_kw2, index); + if (!equal) + return index; } + return this->size(); } -static int sqrti(int x) { return round(sqrt(x)); } +/* + This is an extremely special-case function written for the region + creation code. Given a completed rd_kw regions keyword, the purpose + of this function is to "detect and correct" uninitialized cells with + value 0. This function is purely heuristic: + + 1. It only considers cells which are active in the grid, i.e. where + actnum[] != 0. + + 2. It will scan the four neighbours in the xy plane, if all + neighbours agree on region value this value will be applied; + otherwise the value will not be changed. Neighbouring cells with + value zero are not considered when comparing. +*/ +void rd::KW::fix_uninitialized(int nx, int ny, int nz, const int *actnum) { + int i, j, k; + std::vector &data = get_vector(); -#define RD_KW_TYPED_INPLACE_SQRT(ctype, sqrt_func) \ - void rd_kw_inplace_sqrt_##ctype(rd_kw_type *kw) { \ - ctype *data = (ctype *)rd_kw_get_data_ref(kw); \ - int i; \ - for (i = 0; i < kw->size; i++) \ - data[i] = sqrt_func(data[i]); \ - } + auto undetermined1 = std::make_unique>(); + auto undetermined2 = std::make_unique>(); -RD_KW_TYPED_INPLACE_SQRT(double, sqrt) -RD_KW_TYPED_INPLACE_SQRT(float, sqrtf) -RD_KW_TYPED_INPLACE_SQRT(int, sqrti) -#undef RD_KW_TYPED_INPLACE_SQRT + for (k = 0; k < nz; k++) { + undetermined1->clear(); + for (j = 0; j < ny; j++) { + for (i = 0; i < nx; i++) { + int g0 = i + j * nx + k * nx * ny; -void rd_kw_inplace_sqrt(rd_kw_type *kw) { - rd_type_enum type = rd_kw_get_type(kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_sqrt_float(kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_sqrt_double(kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_sqrt_int(kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace sqrt not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(kw)))); - } -} + if (data[g0] == 0 && actnum[g0]) + undetermined1->push_back(g0); + } + } -#define RD_KW_TYPED_INPLACE_MUL(ctype) \ - void rd_kw_inplace_mul_##ctype(rd_kw_type *target_kw, \ - const rd_kw_type *mul_kw) { \ - if (!rd_kw_assert_binary_##ctype(target_kw, mul_kw)) \ - throw std::invalid_argument("type/size mismatch"); \ - { \ - ctype *target_data = (ctype *)rd_kw_get_data_ref(target_kw); \ - const ctype *mul_data = (const ctype *)rd_kw_get_data_ref(mul_kw); \ - int i; \ - for (i = 0; i < target_kw->size; i++) \ - target_data[i] *= mul_data[i]; \ - } \ - } -RD_KW_TYPED_INPLACE_MUL(int) -RD_KW_TYPED_INPLACE_MUL(double) -RD_KW_TYPED_INPLACE_MUL(float) -#undef RD_KW_TYPED_INPLACE_MUL + while (true) { + bool finished = true; -void rd_kw_inplace_mul(rd_kw_type *target_kw, const rd_kw_type *mul_kw) { - rd_type_enum type = rd_kw_get_type(target_kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_mul_float(target_kw, mul_kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_mul_double(target_kw, mul_kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_mul_int(target_kw, mul_kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace mul not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(target_kw)))); - } -} + undetermined2->clear(); + for (auto g0 : *undetermined1) { + int j = (g0 - k * nx * ny) / nx; + int i = g0 - k * nx * ny - j * nx; -#define RD_KW_TYPED_INPLACE_MUL_INDEXED(ctype) \ - static void rd_kw_inplace_mul_indexed_##ctype( \ - rd_kw_type *target_kw, const std::vector &index_set, \ - const rd_kw_type *mul_kw) { \ - if (!rd_kw_assert_binary_##ctype(target_kw, mul_kw)) \ - throw std::invalid_argument("type/size mismatch"); \ - ctype *target_data = (ctype *)rd_kw_get_data_ref(target_kw); \ - const ctype *mul_data = (const ctype *)rd_kw_get_data_ref(mul_kw); \ - for (const auto index : index_set) \ - target_data[index] *= mul_data[index]; \ - } - -RD_KW_TYPED_INPLACE_MUL_INDEXED(int) -RD_KW_TYPED_INPLACE_MUL_INDEXED(double) -RD_KW_TYPED_INPLACE_MUL_INDEXED(float) -#undef RD_KW_TYPED_INPLACE_MUL + if (data[g0] == 0 && actnum[g0]) { + int n1 = 0; + int n2 = 0; + int n3 = 0; + int n4 = 0; -void rd_kw_inplace_mul_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *mul_kw) { - rd_type_enum type = rd_kw_get_type(target_kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_mul_indexed_float(target_kw, index_set, mul_kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_mul_indexed_double(target_kw, index_set, mul_kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_mul_indexed_int(target_kw, index_set, mul_kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace mul not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(target_kw)))); - } -} - -#define RD_KW_TYPED_INPLACE_DIV(ctype) \ - void rd_kw_inplace_div_##ctype(rd_kw_type *target_kw, \ - const rd_kw_type *div_kw) { \ - if (!rd_kw_assert_binary_##ctype(target_kw, div_kw)) \ - throw std::invalid_argument("type/size mismatch"); \ - { \ - ctype *target_data = (ctype *)rd_kw_get_data_ref(target_kw); \ - const ctype *div_data = (const ctype *)rd_kw_get_data_ref(div_kw); \ - int i; \ - for (i = 0; i < target_kw->size; i++) \ - target_data[i] /= div_data[i]; \ - } \ - } -RD_KW_TYPED_INPLACE_DIV(int) -RD_KW_TYPED_INPLACE_DIV(double) -RD_KW_TYPED_INPLACE_DIV(float) -#undef RD_KW_TYPED_INPLACE_DIV - -void rd_kw_inplace_div(rd_kw_type *target_kw, const rd_kw_type *div_kw) { - rd_type_enum type = rd_kw_get_type(target_kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_div_float(target_kw, div_kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_div_double(target_kw, div_kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_div_int(target_kw, div_kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace div not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(target_kw)))); - } -} + if (i > 0) { + int g1 = g0 - 1; + if (actnum[g1]) + n1 = data[g1]; + } -#define RD_KW_TYPED_INPLACE_DIV_INDEXED(ctype) \ - static void rd_kw_inplace_div_indexed_##ctype( \ - rd_kw_type *target_kw, const std::vector &index_set, \ - const rd_kw_type *div_kw) { \ - if (!rd_kw_assert_binary_##ctype(target_kw, div_kw)) \ - throw std::invalid_argument("type/size mismatch"); \ - ctype *target_data = (ctype *)rd_kw_get_data_ref(target_kw); \ - const ctype *div_data = (const ctype *)rd_kw_get_data_ref(div_kw); \ - for (const auto index : index_set) \ - target_data[index] /= div_data[index]; \ - } + if (i < (nx - 1)) { + int g2 = g0 + 1; + if (actnum[g2]) + n2 = data[g2]; + } -RD_KW_TYPED_INPLACE_DIV_INDEXED(int) -RD_KW_TYPED_INPLACE_DIV_INDEXED(double) -RD_KW_TYPED_INPLACE_DIV_INDEXED(float) -#undef RD_KW_TYPED_INPLACE_DIV + if (j > 0) { + int g3 = g0 - nx; + if (actnum[g3]) + n3 = data[g3]; + } -void rd_kw_inplace_div_indexed(rd_kw_type *target_kw, - const std::vector &index_set, - const rd_kw_type *div_kw) { - rd_type_enum type = rd_kw_get_type(target_kw); - switch (type) { - case (RD_FLOAT_TYPE): - rd_kw_inplace_div_indexed_float(target_kw, index_set, div_kw); - break; - case (RD_DOUBLE_TYPE): - rd_kw_inplace_div_indexed_double(target_kw, index_set, div_kw); - break; - case (RD_INT_TYPE): - rd_kw_inplace_div_indexed_int(target_kw, index_set, div_kw); - break; - default: - throw std::invalid_argument( - fmt::format("inplace div not implemented for type:{}", - rd_type_name(rd_kw_get_data_type(target_kw)))); - } -} + if (j < (ny - 1)) { + int g4 = g0 + nx; + if (actnum[g4]) + n4 = data[g4]; + } -bool rd_kw_inplace_safe_div(rd_kw_type *target_kw, const rd_kw_type *divisor) { - if (rd_kw_get_type(target_kw) != RD_FLOAT_TYPE) - return false; + { + int new_value = 0; - if (rd_kw_get_type(divisor) != RD_INT_TYPE) - return false; + if (n1) + new_value = n1; - float *target_data = (float *)rd_kw_get_data_ref(target_kw); - const int *div_data = (const int *)rd_kw_get_data_ref(divisor); - for (int i = 0; i < target_kw->size; i++) { - if (div_data[i] != 0) - target_data[i] /= div_data[i]; - } + if (n2) { + if (new_value == 0) + new_value = n2; + else if (new_value != n2) + new_value = -1; + } - return true; -} + if (n3) { + if (new_value == 0) + new_value = n3; + else if (new_value != n3) + new_value = -1; + } -#define KW_MAX_MIN(type) \ - { \ - type *data = (type *)rd_kw_get_data_ref(rd_kw); \ - type max = data[0]; \ - type min = data[0]; \ - int i; \ - for (i = 1; i < rd_kw_get_size(rd_kw); i++) \ - util_update_##type##_max_min(data[i], &max, &min); \ - memcpy(_max, &max, rd_type_get_sizeof_ctype(rd_kw->data_type)); \ - memcpy(_min, &min, rd_type_get_sizeof_ctype(rd_kw->data_type)); \ - } + if (n4) { + if (new_value == 0) + new_value = n4; + else if (new_value != n4) + new_value = -1; + } -void rd_kw_max_min(const rd_kw_type *rd_kw, void *_max, void *_min) { - switch (rd_kw_get_type(rd_kw)) { - case (RD_FLOAT_TYPE): - KW_MAX_MIN(float); - break; - case (RD_DOUBLE_TYPE): - KW_MAX_MIN(double); - break; - case (RD_INT_TYPE): - KW_MAX_MIN(int); - break; - default: - throw std::invalid_argument("invalid type for element sum"); + if (new_value > 0) { + data[g0] = new_value; + finished = false; + } + } + if ((n1 + n2 + n3 + n4) == 0) + undetermined2->push_back(g0); + } + } + undetermined1.swap(undetermined2); + if (finished || undetermined1->empty()) + break; + } } } -#define RD_KW_MAX_MIN(ctype) \ - void rd_kw_max_min_##ctype(const rd_kw_type *rd_kw, ctype *_max, \ - ctype *_min) { \ - if (rd_kw->size < 1) \ - throw std::invalid_argument( \ - "size of zero length array is undefined"); \ - KW_MAX_MIN(ctype); \ - } - -#define RD_KW_MAX(ctype) \ - ctype rd_kw_##ctype##_max(const rd_kw_type *rd_kw) { \ - ctype max, min; \ - rd_kw_max_min_##ctype(rd_kw, &max, &min); \ - return max; \ - } - -#define RD_KW_MIN(ctype) \ - ctype rd_kw_##ctype##_min(const rd_kw_type *rd_kw) { \ - ctype max, min; \ - rd_kw_max_min_##ctype(rd_kw, &max, &min); \ - return min; \ - } +std::unique_ptr rd::KW::make_actnum(const rd::KW *porv_kw, + float porv_limit) { + if (!rd_type_is_float(porv_kw->data_type())) + return NULL; -RD_KW_MAX_MIN(int) -RD_KW_MAX_MIN(float) -RD_KW_MAX_MIN(double) - -RD_KW_MAX(int) -RD_KW_MAX(float) -RD_KW_MAX(double) - -RD_KW_MIN(int) -RD_KW_MIN(float) -RD_KW_MIN(double) - -#undef RD_KW_MAX -#undef RD_KW_MIN -#undef KW_MAX_MIN -#undef RD_KW_MAX_MIN - -#define KW_SUM_INDEXED(type) \ - { \ - const type *data = (const type *)rd_kw_get_data_ref(rd_kw); \ - type sum = 0; \ - for (auto const i : index_list) \ - sum += data[i]; \ - memcpy(_sum, &sum, rd_type_get_sizeof_ctype(rd_kw->data_type)); \ - } + if (porv_kw->header() != PORV_KW) + return NULL; -void rd_kw_element_sum_indexed(const rd_kw_type *rd_kw, - const std::vector &index_list, void *_sum) { - switch (rd_kw_get_type(rd_kw)) { - case (RD_FLOAT_TYPE): - KW_SUM_INDEXED(float); - break; - case (RD_DOUBLE_TYPE): - KW_SUM_INDEXED(double); - break; - case (RD_INT_TYPE): - KW_SUM_INDEXED(int); - break; - case (RD_BOOL_TYPE): { - const bool *data = (const bool *)rd_kw_get_data_ref(rd_kw); - int sum = 0; - for (const auto i : index_list) - sum += (data[i]); + const size_t size = porv_kw->size(); + std::vector actnum_values(size, 0); + const std::vector &porv_values = porv_kw->get_vector(); - memcpy(_sum, &sum, sizeof sum); - } break; - default: - throw std::invalid_argument("invalid type for element sum"); - } -} -#undef KW_SUM - -#define KW_SUM(type) \ - { \ - const type *data = (const type *)rd_kw_get_data_ref(rd_kw); \ - type sum = 0; \ - for (int i = 0; i < rd_kw_get_size(rd_kw); i++) \ - sum += data[i]; \ - memcpy(_sum, &sum, rd_type_get_sizeof_ctype(rd_kw->data_type)); \ + for (size_t i = 0; i < size; i++) { + if (porv_values[i] > porv_limit) + actnum_values[i] = 1; + else + actnum_values[i] = 0; } -void rd_kw_element_sum(const rd_kw_type *rd_kw, void *_sum) { - switch (rd_kw_get_type(rd_kw)) { - case (RD_FLOAT_TYPE): - KW_SUM(float); - break; - case (RD_DOUBLE_TYPE): - KW_SUM(double); - break; - case (RD_INT_TYPE): - KW_SUM(int); - break; - default: - throw std::invalid_argument("invalid type for element sum"); - } + return std::make_unique(ACTNUM_KW, actnum_values); } -#undef KW_SUM - -double rd_kw_element_sum_float(const rd_kw_type *rd_kw) { - float float_sum; - double double_sum; - void *sum_ptr = NULL; - - if (rd_type_is_double(rd_kw->data_type)) - sum_ptr = &double_sum; - else if (rd_type_is_float(rd_kw->data_type)) - sum_ptr = &float_sum; - else - throw std::invalid_argument("invalid type:"); - - rd_kw_element_sum(rd_kw, sum_ptr); - - if (rd_type_is_double(rd_kw->data_type)) - return double_sum; - else if (rd_type_is_float(rd_kw->data_type)) - return float_sum; - else - return 0; -} - -int rd_kw_element_sum_int(const rd_kw_type *rd_kw) { - int int_sum; - rd_kw_element_sum(rd_kw, &int_sum); - - return int_sum; -} - -static bool rd_kw_elm_equal_numeric__(const rd_kw_type *rd_kw1, - const rd_kw_type *rd_kw2, int offset, - double abs_epsilon, double rel_epsilon) { - double v1 = rd_kw_iget_as_double(rd_kw1, offset); - double v2 = rd_kw_iget_as_double(rd_kw2, offset); - return util_double_approx_equal__(v1, v2, rel_epsilon, abs_epsilon); -} - -static bool rd_kw_elm_equal__(const rd_kw_type *rd_kw1, - const rd_kw_type *rd_kw2, int offset) { - if (offset < 0) - throw std::invalid_argument( - fmt::format("offset was negative: {}", offset)); - size_t data_offset = static_cast(offset) * - rd_type_get_sizeof_ctype(rd_kw1->data_type); - int cmp = memcmp(&rd_kw1->data[data_offset], &rd_kw2->data[data_offset], - rd_type_get_sizeof_ctype(rd_kw1->data_type)); - if (cmp == 0) - return true; - else - return false; -} - -int rd_kw_first_different(const rd_kw_type *rd_kw1, const rd_kw_type *rd_kw2, - int offset, double abs_epsilon, double rel_epsilon) { - if (!rd_kw_size_and_type_equal(rd_kw1, rd_kw2)) - throw std::invalid_argument("sorry invalid comparison"); - - if (offset >= rd_kw_get_size(rd_kw1)) - throw std::invalid_argument("sorry - invalid offset value"); - - { - bool numeric_compare = false; - - if (((abs_epsilon > 0) || (rel_epsilon > 0)) && - ((rd_kw_get_type(rd_kw1) == RD_FLOAT_TYPE) || - (rd_kw_get_type(rd_kw1) == RD_DOUBLE_TYPE))) - numeric_compare = true; - { - int index = offset; - - while (true) { - bool equal = - (numeric_compare) - ? rd_kw_elm_equal_numeric__(rd_kw1, rd_kw2, index, - abs_epsilon, rel_epsilon) - : rd_kw_elm_equal__(rd_kw1, rd_kw2, index); - if (!equal) - break; - - index++; - if (index == rd_kw_get_size(rd_kw1)) - break; - } - - return index; - } - } -} - -#include "rd_kw_functions.cpp" diff --git a/lib/resdata/rd_kw_functions.cpp b/lib/resdata/rd_kw_functions.cpp deleted file mode 100644 index 1efe9306f..000000000 --- a/lib/resdata/rd_kw_functions.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - This file is included from the rd_kw.c file during compilation. It - contains functions which are not really related to the rd_kw as a - datastructure, but rather use an rd_kw instance in a function. -*/ - -/* - This is an extremely special-case function written for the region - creation code. Given a completed rd_kw regions keyword, the purpose - of this function is to "detect and correct" uninitialized cells with - value 0. This function is purely heuristic: - - 1. It only considers cells which are active in the grid, i.e. where - actnum[] != 0. - - 2. It will scan the four neighbours in the xy plane, if all - neighbours agree on region value this value will be applied; - otherwise the value will not be changed. Neighbouring cells with - value zero are not considered when comparing. -*/ - -void rd_kw_fix_uninitialized(rd_kw_type *rd_kw, int nx, int ny, int nz, - const int *actnum) { - int i, j, k; - int *data = (int *)rd_kw_get_ptr(rd_kw); - - auto undetermined1 = std::make_unique>(); - auto undetermined2 = std::make_unique>(); - - for (k = 0; k < nz; k++) { - undetermined1->clear(); - for (j = 0; j < ny; j++) { - for (i = 0; i < nx; i++) { - int g0 = i + j * nx + k * nx * ny; - - if (data[g0] == 0 && actnum[g0]) - undetermined1->push_back(g0); - } - } - - while (true) { - bool finished = true; - - undetermined2->clear(); - for (auto g0 : *undetermined1) { - int j = (g0 - k * nx * ny) / nx; - int i = g0 - k * nx * ny - j * nx; - - if (data[g0] == 0 && actnum[g0]) { - int n1 = 0; - int n2 = 0; - int n3 = 0; - int n4 = 0; - - if (i > 0) { - int g1 = g0 - 1; - if (actnum[g1]) - n1 = data[g1]; - } - - if (i < (nx - 1)) { - int g2 = g0 + 1; - if (actnum[g2]) - n2 = data[g2]; - } - - if (j > 0) { - int g3 = g0 - nx; - if (actnum[g3]) - n3 = data[g3]; - } - - if (j < (ny - 1)) { - int g4 = g0 + nx; - if (actnum[g4]) - n4 = data[g4]; - } - - { - int new_value = 0; - - if (n1) - new_value = n1; - - if (n2) { - if (new_value == 0) - new_value = n2; - else if (new_value != n2) - new_value = -1; - } - - if (n3) { - if (new_value == 0) - new_value = n3; - else if (new_value != n3) - new_value = -1; - } - - if (n4) { - if (new_value == 0) - new_value = n4; - else if (new_value != n4) - new_value = -1; - } - - if (new_value > 0) { - data[g0] = new_value; - finished = false; - } - } - if ((n1 + n2 + n3 + n4) == 0) - undetermined2->push_back(g0); - } - } - undetermined1.swap(undetermined2); - if (finished || undetermined1->empty()) - break; - } - } -} - -rd_kw_type *rd_kw_alloc_actnum(const rd_kw_type *porv_kw, float porv_limit) { - if (!rd_type_is_float(porv_kw->data_type)) - return NULL; - - if (!util_string_equal(PORV_KW, rd_kw_get_header(porv_kw))) - return NULL; - - const int size = rd_kw_get_size(porv_kw); - auto actnum_kw = make_rd_kw(ACTNUM_KW, size, RD_INT); - const float *porv_values = rd_kw_get_float_ptr(porv_kw); - int *actnum_values = rd_kw_get_int_ptr(actnum_kw.get()); - - for (int i = 0; i < size; i++) { - if (porv_values[i] > porv_limit) - actnum_values[i] = 1; - else - actnum_values[i] = 0; - } - - return actnum_kw.release(); -} diff --git a/lib/resdata/rd_kw_pybind.cpp b/lib/resdata/rd_kw_pybind.cpp index 25253dc70..0ddfad4ba 100644 --- a/lib/resdata/rd_kw_pybind.cpp +++ b/lib/resdata/rd_kw_pybind.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -16,6 +17,8 @@ #include #include +#include +#include namespace py = pybind11; @@ -24,27 +27,26 @@ namespace { class KwIterator { public: explicit KwIterator(py::object self) - : m_self(std::move(self)), m_kw(from_cwrap(m_self)), - m_index(0), m_size(rd_kw_get_size(m_kw)), - m_type(rd_kw_get_type(m_kw)) {} + : m_self(std::move(self)), m_kw(from_cwrap(m_self)), m_index(0), + m_size(m_kw->size()), m_type(m_kw->get_type()) {} py::object next() { if (m_index >= m_size) throw py::stop_iteration(); - int i = m_index++; + size_t i = m_index++; switch (m_type) { case RD_INT_TYPE: - return py::cast(rd_kw_iget_int(m_kw, i)); + return py::cast(m_kw->at(i)); case RD_FLOAT_TYPE: - return py::cast(rd_kw_iget_float(m_kw, i)); + return py::cast(m_kw->at(i)); case RD_DOUBLE_TYPE: - return py::cast(rd_kw_iget_double(m_kw, i)); + return py::cast(m_kw->at(i)); case RD_BOOL_TYPE: - return py::cast(rd_kw_iget_bool(m_kw, i)); + return py::cast(m_kw->at(i)); case RD_CHAR_TYPE: - return py::cast(rd_kw_iget_char_ptr(m_kw, i)); + return py::cast(m_kw->at(i)); case RD_STRING_TYPE: - return py::cast(rd_kw_iget_string_ptr(m_kw, i)); + return py::cast(m_kw->at(i)); default: throw std::invalid_argument( "ResdataKW iteration not supported for this type"); @@ -53,72 +55,72 @@ class KwIterator { private: // Keeps the owning ResdataKW Python object (and therefore its - // underlying rd_kw_type allocation) alive for as long as the + // underlying rd::KW allocation) alive for as long as the // iterator itself is alive. py::object m_self; - rd_kw_type *m_kw; - int m_index; - int m_size; + rd::KW *m_kw; + size_t m_index; + size_t m_size; rd_type_enum m_type; }; static py::list format_grdecl_tokens(py::object self) { - rd_kw_type *kw = from_cwrap(self); - int size = rd_kw_get_size(kw); - rd_type_enum type = rd_kw_get_type(kw); - int string_width = - static_cast(rd_type_get_sizeof_iotype(rd_kw_get_data_type(kw))); + rd::KW *kw = from_cwrap(self); + size_t size = kw->size(); + rd_type_enum type = kw->get_type(); + size_t string_width = kw->iotype_size(); py::list tokens(size); switch (type) { case RD_INT_TYPE: { char buf[32]; - for (int i = 0; i < size; i++) { - size_t len = rd::format_kw_element_buf(buf, sizeof(buf), - rd_kw_iget_int(kw, i)); + for (size_t i = 0; i < size; i++) { + size_t len = + rd::format_kw_element_buf(buf, sizeof(buf), kw->at(i)); tokens[i] = py::str(buf, len); } break; } case RD_FLOAT_TYPE: { char buf[48]; - for (int i = 0; i < size; i++) { - size_t len = rd::format_kw_element_buf(buf, sizeof(buf), - rd_kw_iget_float(kw, i)); + for (size_t i = 0; i < size; i++) { + size_t len = + rd::format_kw_element_buf(buf, sizeof(buf), kw->at(i)); tokens[i] = py::str(buf, len); } break; } case RD_DOUBLE_TYPE: { char buf[48]; - for (int i = 0; i < size; i++) { - size_t len = rd::format_kw_element_buf(buf, sizeof(buf), - rd_kw_iget_double(kw, i)); + for (size_t i = 0; i < size; i++) { + size_t len = + rd::format_kw_element_buf(buf, sizeof(buf), kw->at(i)); tokens[i] = py::str(buf, len); } break; } case RD_BOOL_TYPE: - for (int i = 0; i < size; i++) - tokens[i] = - rd_kw_iget_bool(kw, i) ? py::str(" T") : py::str(" F"); + for (size_t i = 0; i < size; i++) + tokens[i] = kw->at(i) ? py::str(" T") : py::str(" F"); break; case RD_CHAR_TYPE: { const std::string fmt = rd::format_kw_element_fmt(8); std::vector buf(8 + 4); - for (int i = 0; i < size; i++) { - size_t len = rd::format_kw_element_buf( - buf.data(), buf.size(), rd_kw_iget_char_ptr(kw, i), fmt); + for (size_t i = 0; i < size; i++) { + const std::string value = kw->at(i); + size_t len = rd::format_kw_element_buf(buf.data(), buf.size(), + value.c_str(), fmt); tokens[i] = py::str(buf.data(), len); } break; } case RD_STRING_TYPE: { const std::string fmt = rd::format_kw_element_fmt(string_width); - std::vector buf(static_cast(string_width) + 4); - for (int i = 0; i < size; i++) { - size_t len = rd::format_kw_element_buf( - buf.data(), buf.size(), rd_kw_iget_string_ptr(kw, i), fmt); + std::vector buf(string_width + 4); + for (size_t i = 0; i < size; i++) { + const std::string value = kw->at(i); + size_t len = rd::format_kw_element_buf(buf.data(), buf.size(), + value.c_str(), fmt); tokens[i] = py::str(buf.data(), len); } break; @@ -141,216 +143,342 @@ PYBIND11_MODULE(_kw, m) { m.def( "_alloc_new", - [](std::string name, int size, py::handle data_type) { + [](std::string name, size_t size, py::handle data_type) { auto *rd_data_type = from_cwrap<::rd_data_type>(data_type); if (rd_data_type == nullptr) throw std::invalid_argument("data_type must not be None"); - return to_capsule(rd_kw_alloc(name.c_str(), size, *rd_data_type)); + return to_capsule(new rd::KW{name, size, *rd_data_type}); }, py::return_value_policy::reference); m.def( "_fread_alloc", [](ERT::FortIO &fortio) { - return to_capsule(rd_kw_fread_alloc(fortio)); + return to_capsule(rd::KW::fread(fortio).release()); }, py::return_value_policy::reference); m.def( "_sub_copy", - [](py::handle self, std::optional new_kw, int offset, - int count) { - auto *src = from_cwrap(self); - if (new_kw.has_value()) - return to_capsule( - rd_kw_alloc_sub_copy(src, new_kw->c_str(), offset, count)); + [](py::handle self, std::optional new_kw, size_t offset, + py::int_ count) { + auto *src = from_cwrap(self); + + size_t count_size; + if (count < py::int_{0}) + count_size = py::int_{src->size() - offset}; else - return to_capsule( - rd_kw_alloc_sub_copy(src, nullptr, offset, count)); + count_size = count.cast(); + + return to_capsule(new rd::KW{*src, new_kw, offset, count_size}); }, py::return_value_policy::reference); m.def( "_copyc", [](py::handle self) { - return to_capsule(rd_kw_alloc_copy(from_cwrap(self))); + return to_capsule(new rd::KW{*from_cwrap(self)}); }, py::return_value_policy::reference); m.def( "_slice_copyc", - [](py::handle self, int index1, int index2, int stride) { - return to_capsule(rd_kw_alloc_slice_copy( - from_cwrap(self), index1, index2, stride)); + [](py::handle self, py::int_ index1, py::int_ index2, size_t stride) { + if (index1 < py::int_{0}) + index1 = 0; + if (index2 < py::int_{0}) + index2 = 0; + return to_capsule(new rd::KW{*from_cwrap(self), + index1.cast(), + index2.cast(), stride}); }, py::return_value_policy::reference); m.def( "_global_copy", [](py::handle self, py::handle new_actnum) { return to_capsule( - rd_kw_alloc_global_copy(from_cwrap(self), - from_cwrap(new_actnum))); + rd::KW::global_copy(from_cwrap(self), + from_cwrap(new_actnum)) + .release()); }, py::return_value_policy::reference); - m.def("_get_size", [](py::handle self) { - return rd_kw_get_size(from_cwrap(self)); - }); + m.def("_get_size", + [](py::handle self) { return from_cwrap(self)->size(); }); m.def("_get_fortio_size", [](py::handle self) { - return rd_kw_fortio_size(from_cwrap(self)); + return from_cwrap(self)->fortio_size(); }); m.def("_get_type", [](py::handle self) { - return static_cast(rd_kw_get_type(from_cwrap(self))); + return static_cast(from_cwrap(self)->get_type()); }); - m.def("_iget_char_ptr", [](py::handle self, int index) { - return rd_kw_iget_char_ptr(from_cwrap(self), index); + m.def("_iget_char_ptr", [](py::handle self, size_t index) { + return from_cwrap(self)->at(index); }); - m.def("_iset_char_ptr", [](py::handle self, int index, std::string value) { - rd_kw_iset_char_ptr(from_cwrap(self), index, value.c_str()); - }); - m.def("_iget_string_ptr", [](py::handle self, int index) { - return rd_kw_iget_string_ptr(from_cwrap(self), index); + m.def("_iset_char_ptr", + [](py::handle self, size_t index, std::string value) { + from_cwrap(self)->set_string_array(index, value); + }); + m.def("_iget_string_ptr", [](py::handle self, size_t index) { + return from_cwrap(self)->at(index); }); m.def("_iset_string_ptr", [](py::handle self, int index, std::string value) { - rd_kw_iset_string_ptr(from_cwrap(self), index, - value.c_str()); + auto kw = from_cwrap(self); + kw->set_padded(index, value); }); - m.def("_iget_bool", [](py::handle self, int index) { - return rd_kw_iget_bool(from_cwrap(self), index); + m.def("_iget_bool", [](py::handle self, size_t index) { + return (from_cwrap(self))->at(index); }); - m.def("_iset_bool", [](py::handle self, int index, bool value) { - rd_kw_iset_bool(from_cwrap(self), index, value); + m.def("_iset_bool", [](py::handle self, size_t index, bool value) { + (from_cwrap(self))->at(index) = value; }); m.def( "_int_ptr", [](py::handle self) { return reinterpret_cast( - rd_kw_get_int_ptr(from_cwrap(self))); + from_cwrap(self)->get_vector().data()); }, py::return_value_policy::reference); m.def( "_float_ptr", [](py::handle self) { return reinterpret_cast( - rd_kw_get_float_ptr(from_cwrap(self))); + from_cwrap(self)->get_vector().data()); }, py::return_value_policy::reference); m.def( "_double_ptr", [](py::handle self) { return reinterpret_cast( - rd_kw_get_double_ptr(from_cwrap(self))); + from_cwrap(self)->get_vector().data()); }, py::return_value_policy::reference); m.def( "_bool_ptr", [](py::handle self) { return reinterpret_cast( - rd_kw_get_bool_ptr(from_cwrap(self))); + from_cwrap(self)->get_vector().data()); }, py::return_value_policy::reference); - m.def("_free", - [](py::handle self) { rd_kw_free(from_cwrap(self)); }); + m.def("_free", [](py::handle self) { delete from_cwrap(self); }); m.def("_fwrite", [](py::handle self, ERT::FortIO &fortio) { - rd_kw_fwrite(from_cwrap(self), fortio); - }); - m.def("_get_header", [](py::handle self) { - return rd_kw_get_header(from_cwrap(self)); + from_cwrap(self)->fwrite(fortio); }); + m.def("_get_header", + [](py::handle self) { return from_cwrap(self)->header(); }); m.def("_set_header", [](py::handle self, std::string name) { - rd_kw_set_header_name(from_cwrap(self), name.c_str()); + from_cwrap(self)->set_header(name); }); m.def( "_get_data_type", [](py::handle self) { - auto rd_kw = from_cwrap(self); - rd_data_type data_type = rd_kw_get_data_type(rd_kw); + auto rd_kw = from_cwrap(self); + rd_data_type data_type = rd_kw->data_type(); return to_capsule(new rd_data_type(data_type)); }, py::return_value_policy::reference); - m.def("_int_sum", [](py::handle self) { - return rd_kw_element_sum_int(from_cwrap(self)); - }); - m.def("_float_sum", [](py::handle self) { - return rd_kw_element_sum_float(from_cwrap(self)); - }); m.def("_iadd_squared", [](py::handle self, py::handle other) { - rd_kw_inplace_add_squared(from_cwrap(self), - from_cwrap(other)); + auto target_kw = from_cwrap(self); + auto add_kw = from_cwrap(other); + std::visit( + [&](auto &&target_alt) { + using T = + typename std::decay_t::value_type; + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v) { + if (!target_kw->size_and_numeric_type_equal(add_kw)) + throw std::invalid_argument("type/size mismatch"); + auto &target_data = target_kw->get_vector(); + const auto &add_data = add_kw->get_vector(); + for (size_t i = 0; i < target_data.size(); i++) + target_data[i] += add_data[i] * add_data[i]; + } else + throw std::invalid_argument( + fmt::format("inplace add not implemented for type:{}", + rd_type_name(target_kw->data_type()))); + }, + target_kw->data().value()); }); m.def("_isqrt", [](py::handle self) { - rd_kw_inplace_sqrt(from_cwrap(self)); + auto kw = from_cwrap(self); + std::visit( + [&](auto &&alt) { + using T = typename std::decay_t::value_type; + if constexpr (std::is_same_v) { + auto &data = kw->get_vector(); + for (auto &value : data) + value = static_cast(std::round(std::sqrt(value))); + } else if constexpr (std::is_same_v || + std::is_same_v) { + auto &data = kw->get_vector(); + for (auto &value : data) + value = std::sqrt(value); + } else + throw std::invalid_argument( + fmt::format("inplace sqrt not implemented for type:{}", + rd_type_name(kw->data_type()))); + }, + kw->data().value()); }); m.def("_iadd", [](py::handle self, py::handle other) { - rd_kw_inplace_add(from_cwrap(self), - from_cwrap(other)); + auto target_kw = from_cwrap(self); + auto add_kw = from_cwrap(other); + std::visit( + [&](auto &&target_alt) { + using T = + typename std::decay_t::value_type; + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v) { + if (!target_kw->size_and_numeric_type_equal(add_kw)) + throw std::invalid_argument("type/size mismatch"); + auto &target_data = target_kw->get_vector(); + const auto &add_data = add_kw->get_vector(); + for (size_t i = 0; i < target_data.size(); i++) + target_data[i] += add_data[i]; + } else + throw std::invalid_argument( + fmt::format("inplace add not implemented for type:{}", + rd_type_name(target_kw->data_type()))); + }, + target_kw->data().value()); }); m.def("_imul", [](py::handle self, py::handle other) { - rd_kw_inplace_mul(from_cwrap(self), - from_cwrap(other)); + auto target_kw = from_cwrap(self); + auto mul_kw = from_cwrap(other); + + std::visit( + [&](auto &&target_alt) { + using T = + typename std::decay_t::value_type; + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v) { + if (!target_kw->size_and_numeric_type_equal(mul_kw)) + throw std::invalid_argument("type/size mismatch"); + auto &target_data = target_kw->get_vector(); + const auto &mul_data = mul_kw->get_vector(); + for (size_t i = 0; i < target_data.size(); i++) + target_data[i] *= mul_data[i]; + } else + throw std::invalid_argument( + fmt::format("inplace mul not implemented for type:{}", + rd_type_name(target_kw->data_type()))); + }, + target_kw->data().value()); }); m.def("_idiv", [](py::handle self, py::handle other) { - rd_kw_inplace_div(from_cwrap(self), - from_cwrap(other)); + auto target_kw = from_cwrap(self); + auto div_kw = from_cwrap(other); + std::visit( + [&](auto &&target_alt) { + using T = + typename std::decay_t::value_type; + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v) { + if (!target_kw->size_and_numeric_type_equal(div_kw)) + throw std::invalid_argument("type/size mismatch"); + auto &target_data = target_kw->get_vector(); + const auto &div_data = div_kw->get_vector(); + for (size_t i = 0; i < target_data.size(); i++) + target_data[i] /= div_data[i]; + } else + throw std::invalid_argument( + fmt::format("inplace div not implemented for type:{}", + rd_type_name(target_kw->data_type()))); + }, + target_kw->data().value()); }); m.def("_isub", [](py::handle self, py::handle other) { - rd_kw_inplace_sub(from_cwrap(self), - from_cwrap(other)); + *from_cwrap(self) -= *from_cwrap(other); }); m.def("_iabs", [](py::handle self) { - rd_kw_inplace_abs(from_cwrap(self)); + auto kw = from_cwrap(self); + std::visit( + [&](auto &&alt) { + using T = typename std::decay_t::value_type; + if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v) { + auto &data = kw->get_vector(); + for (auto &value : data) + value = std::abs(value); + } else + throw std::invalid_argument( + fmt::format("inplace abs not implemented for type:{}", + rd_type_name(kw->data_type()))); + }, + kw->data().value()); }); m.def("_equal", [](py::handle self, py::handle other) { - return rd_kw_equal(from_cwrap(self), - from_cwrap(other)); + return *from_cwrap(self) == *from_cwrap(other); }); m.def("_equal_numeric", [](py::handle self, py::handle other, double abs_epsilon, double rel_epsilon) { - return rd_kw_numeric_equal(from_cwrap(self), - from_cwrap(other), abs_epsilon, - rel_epsilon); + return from_cwrap(self)->approx_equal( + *from_cwrap(other), abs_epsilon, rel_epsilon); }); m.def("_assert_binary", [](py::handle self, py::handle other) { - return rd_kw_size_and_numeric_type_equal(from_cwrap(self), - from_cwrap(other)); + return from_cwrap(self)->size_and_numeric_type_equal( + from_cwrap(other)); }); m.def("_scale_int", [](py::handle self, int factor) { - rd_kw_scale_int(from_cwrap(self), factor); + from_cwrap(self)->scale(factor); }); m.def("_scale_float", [](py::handle self, double factor) { - rd_kw_scale_float_or_double(from_cwrap(self), factor); + rd::KW *rd_kw = from_cwrap(self); + rd_type_enum rd_type = rd_kw->get_type(); + if (rd_type == RD_FLOAT_TYPE) + rd_kw->scale(factor); + else if (rd_type == RD_DOUBLE_TYPE) + rd_kw->scale(factor); + else + throw std::invalid_argument("wrong type"); }); m.def("_shift_int", [](py::handle self, int delta) { - rd_kw_shift_int(from_cwrap(self), delta); + from_cwrap(self)->shift(delta); }); m.def("_shift_float", [](py::handle self, double delta) { - rd_kw_shift_float_or_double(from_cwrap(self), delta); + auto rd_kw = from_cwrap(self); + rd_type_enum rd_type = rd_kw->get_type(); + if (rd_type == RD_FLOAT_TYPE) + rd_kw->shift(static_cast(delta)); + else if (rd_type == RD_DOUBLE_TYPE) + rd_kw->shift(delta); + else + throw std::invalid_argument("wrong type"); }); m.def("_copy_data", [](py::handle self, py::handle src) { - rd_kw_memcpy_data(from_cwrap(self), - from_cwrap(src)); + from_cwrap(self)->copy_data_from(*from_cwrap(src)); }); m.def("_set_int", [](py::handle self, int value) { - rd_kw_scalar_set_int(from_cwrap(self), value); + from_cwrap(self)->scalar_set(value); }); m.def("_set_float", [](py::handle self, double value) { - rd_kw_scalar_set_float_or_double(from_cwrap(self), value); + auto rd_kw = from_cwrap(self); + rd_type_enum rd_type = rd_kw->get_type(); + if (rd_type == RD_FLOAT_TYPE) + rd_kw->scalar_set((float)value); + else if (rd_type == RD_DOUBLE_TYPE) + rd_kw->scalar_set(value); + else + throw std::invalid_argument("wrong type"); }); m.def("_max_min_int", [](py::handle self) { - int max = 0; - int min = 0; - rd_kw_max_min_int(from_cwrap(self), &max, &min); - return std::make_tuple(max, min); + auto &data = from_cwrap(self)->get_vector(); + auto [min_it, max_it] = std::minmax_element(data.begin(), data.end()); + + return std::make_tuple(*max_it, *min_it); }); m.def("_max_min_float", [](py::handle self) { - float max = 0; - float min = 0; - rd_kw_max_min_float(from_cwrap(self), &max, &min); - return std::make_tuple(max, min); + auto &data = from_cwrap(self)->get_vector(); + auto [min_it, max_it] = std::minmax_element(data.begin(), data.end()); + + return std::make_tuple(*max_it, *min_it); }); m.def("_max_min_double", [](py::handle self) { - double max = 0; - double min = 0; - rd_kw_max_min_double(from_cwrap(self), &max, &min); - return std::make_tuple(max, min); + auto &data = from_cwrap(self)->get_vector(); + auto [min_it, max_it] = std::minmax_element(data.begin(), data.end()); + return std::make_tuple(*max_it, *min_it); }); m.def( "_fix_uninitialized", @@ -366,28 +494,43 @@ PYBIND11_MODULE(_kw, m) { "actnum has {} elements, but nx*ny*nz={} were expected", actnum.size(), required_size)); - rd_kw_fix_uninitialized(from_cwrap(self), nx, ny, nz, - actnum.data()); + from_cwrap(self)->fix_uninitialized(nx, ny, nz, + actnum.data()); }); m.def( "_create_actnum", [](py::handle self, float porv_limit) { return to_capsule( - rd_kw_alloc_actnum(from_cwrap(self), porv_limit)); + rd::KW::make_actnum(from_cwrap(self), porv_limit) + .release()); }, py::return_value_policy::reference); - m.def("_first_different", [](py::handle self, py::handle other, int offset, - double abs_epsilon, double rel_epsilon) { - return rd_kw_first_different(from_cwrap(self), - from_cwrap(other), offset, - abs_epsilon, rel_epsilon); - }); - m.def("_resize", [](py::handle self, int new_size) { - rd_kw_resize(from_cwrap(self), new_size); + m.def("_first_different", + [](py::handle self, py::handle other, size_t offset, + double abs_epsilon, double rel_epsilon) { + return from_cwrap(self)->first_different( + from_cwrap(other), offset, abs_epsilon, rel_epsilon); + }); + m.def("_resize", [](py::handle self, size_t new_size) { + from_cwrap(self)->resize(new_size); }); m.def("_safe_div", [](py::handle self, py::handle divisor) { - return rd_kw_inplace_safe_div(from_cwrap(self), - from_cwrap(divisor)); + auto target_kw = from_cwrap(self); + auto divisor_kw = from_cwrap(divisor); + if (target_kw->get_type() != RD_FLOAT_TYPE) + return false; + + if (divisor_kw->get_type() != RD_INT_TYPE) + return false; + + auto &target_data = target_kw->get_vector(); + const auto &div_data = divisor_kw->get_vector(); + for (size_t i = 0; i < target_kw->size(); i++) { + if (div_data[i] != 0) + target_data[i] /= static_cast(div_data[i]); + } + + return true; }); } } // namespace diff --git a/lib/resdata/rd_region.cpp b/lib/resdata/rd_region.cpp index 81283180f..e4218f9ad 100644 --- a/lib/resdata/rd_region.cpp +++ b/lib/resdata/rd_region.cpp @@ -53,8 +53,8 @@ -------- rd_grid_type * rd_grid; - rd_kw_type * soil; - rd_kw_type * regions; + rd::KW * soil; + rd::KW * regions; rd_region_type * rd_region; // Load grid, soil and regions somehow. @@ -171,8 +171,8 @@ const std::vector &rd_region_get_global_list(rd_region_type *region) { } static void rd_region_assert_kw(const rd_region_type *region, - const rd_kw_type *rd_kw, bool *global_kw) { - int kw_size = rd_kw_get_size(rd_kw); + const rd::KW *rd_kw, bool *global_kw) { + int kw_size = rd::kw_get_size(rd_kw); if (!(kw_size == region->grid_vol || kw_size == region->grid_active)) throw std::invalid_argument( "size mismatch between rd_kw instance and region->grid"); @@ -189,14 +189,14 @@ void rd_region_reset(rd_region_type *rd_region) { } static void rd_region_select_equal__(rd_region_type *region, - const rd_kw_type *rd_kw, int value, + const rd::KW *rd_kw, int value, bool select) { bool global_kw; rd_region_assert_kw(region, rd_kw, &global_kw); - if (!rd_type_is_int(rd_kw_get_data_type(rd_kw))) + if (!rd_type_is_int(rd_kw->data_type())) throw std::invalid_argument( "select by equality is only supported for integer keywords"); - const int *kw_data = rd_kw_get_int_ptr(rd_kw); + const int *kw_data = rd_kw->get_vector().data(); if (global_kw) { for (int global_index = 0; global_index < region->grid_vol; global_index++) { @@ -216,34 +216,35 @@ static void rd_region_select_equal__(rd_region_type *region, rd_region_invalidate_index_list(region); } -void rd_region_select_equal(rd_region_type *region, const rd_kw_type *rd_kw, +void rd_region_select_equal(rd_region_type *region, const rd::KW *rd_kw, int value) { rd_region_select_equal__(region, rd_kw, value, true); } -void rd_region_deselect_equal(rd_region_type *region, const rd_kw_type *rd_kw, +void rd_region_deselect_equal(rd_region_type *region, const rd::KW *rd_kw, int value) { rd_region_select_equal__(region, rd_kw, value, false); } static void rd_region_select_bool_equal__(rd_region_type *region, - const rd_kw_type *rd_kw, bool value, + const rd::KW *rd_kw, bool value, bool select) { bool global_kw; rd_region_assert_kw(region, rd_kw, &global_kw); - if (!rd_type_is_bool(rd_kw_get_data_type(rd_kw))) + if (!rd_type_is_bool(rd_kw->data_type())) throw std::invalid_argument( "select by equality is only supported for boolean keywords"); if (global_kw) { - for (int global_index = 0; global_index < region->grid_vol; + for (size_t global_index = 0; + global_index < static_cast(region->grid_vol); global_index++) { - if (rd_kw_iget_bool(rd_kw, global_index) == value) + if (rd_kw->at(global_index) == value) region->active_mask[global_index] = select; } } else { for (int active_index = 0; active_index < region->grid_active; active_index++) { - if (rd_kw_iget_bool(rd_kw, active_index) == value) { + if (rd_kw->at(active_index) == value) { int global_index = rd_grid_get_global_index1A( region->parent_grid, active_index); region->active_mask[global_index] = select; @@ -253,25 +254,24 @@ static void rd_region_select_bool_equal__(rd_region_type *region, rd_region_invalidate_index_list(region); } -void rd_region_select_true(rd_region_type *region, const rd_kw_type *rd_kw) { +void rd_region_select_true(rd_region_type *region, const rd::KW *rd_kw) { rd_region_select_bool_equal__(region, rd_kw, true, true); } -void rd_region_select_false(rd_region_type *region, const rd_kw_type *rd_kw) { +void rd_region_select_false(rd_region_type *region, const rd::KW *rd_kw) { rd_region_select_bool_equal__(region, rd_kw, false, true); } static void rd_region_select_in_interval__(rd_region_type *region, - const rd_kw_type *rd_kw, - float min_value, float max_value, - bool select) { + const rd::KW *rd_kw, float min_value, + float max_value, bool select) { bool global_kw; rd_region_assert_kw(region, rd_kw, &global_kw); - if (!rd_type_is_float(rd_kw_get_data_type(rd_kw))) + if (!rd_type_is_float(rd_kw->data_type())) throw std::invalid_argument( "select by in_interval is only supported for float keywords"); { - const float *kw_data = rd_kw_get_float_ptr(rd_kw); + const float *kw_data = rd_kw->get_vector().data(); if (global_kw) { for (int global_index = 0; global_index < region->grid_vol; global_index++) { @@ -294,15 +294,13 @@ static void rd_region_select_in_interval__(rd_region_type *region, rd_region_invalidate_index_list(region); } -void rd_region_select_in_interval(rd_region_type *region, - const rd_kw_type *rd_kw, float min_value, - float max_value) { +void rd_region_select_in_interval(rd_region_type *region, const rd::KW *rd_kw, + float min_value, float max_value) { rd_region_select_in_interval__(region, rd_kw, min_value, max_value, true); } -void rd_region_deselect_in_interval(rd_region_type *region, - const rd_kw_type *rd_kw, float min_value, - float max_value) { +void rd_region_deselect_in_interval(rd_region_type *region, const rd::KW *rd_kw, + float min_value, float max_value) { rd_region_select_in_interval__(region, rd_kw, min_value, max_value, false); } @@ -316,17 +314,17 @@ void rd_region_deselect_in_interval(rd_region_type *region, NBNBNBNB: Select >= on float values and select > on integer!!!!!! */ static void rd_region_select_with_limit__(rd_region_type *region, - const rd_kw_type *rd_kw, float limit, + const rd::KW *rd_kw, float limit, bool select_less, bool select) { bool global_kw; - rd_data_type data_type = rd_kw_get_data_type(rd_kw); + rd_data_type data_type = rd_kw->data_type(); rd_region_assert_kw(region, rd_kw, &global_kw); if (!rd_type_is_numeric(data_type)) throw std::invalid_argument( "select by smaller/larger is only supported for numeric keywords"); if (rd_type_is_float(data_type)) { - const float *kw_data = rd_kw_get_float_ptr(rd_kw); + const float *kw_data = rd_kw->get_vector().data(); float float_limit = limit; if (global_kw) { for (int global_index = 0; global_index < region->grid_vol; @@ -358,7 +356,7 @@ static void rd_region_select_with_limit__(rd_region_type *region, } } } else if (rd_type_is_int(data_type)) { - const int *kw_data = rd_kw_get_int_ptr(rd_kw); + const int *kw_data = rd_kw->get_vector().data(); int int_limit = (int)limit; if (global_kw) { for (int global_index = 0; global_index < region->grid_vol; @@ -390,7 +388,7 @@ static void rd_region_select_with_limit__(rd_region_type *region, } } } else if (rd_type_is_double(data_type)) { - const double *kw_data = rd_kw_get_double_ptr(rd_kw); + const double *kw_data = rd_kw->get_vector().data(); double double_limit = (double)limit; if (global_kw) { for (int global_index = 0; global_index < region->grid_vol; @@ -425,23 +423,23 @@ static void rd_region_select_with_limit__(rd_region_type *region, rd_region_invalidate_index_list(region); } -void rd_region_select_smaller(rd_region_type *rd_region, - const rd_kw_type *rd_kw, float limit) { +void rd_region_select_smaller(rd_region_type *rd_region, const rd::KW *rd_kw, + float limit) { rd_region_select_with_limit__(rd_region, rd_kw, limit, true, true); } -void rd_region_deselect_smaller(rd_region_type *rd_region, - const rd_kw_type *rd_kw, float limit) { +void rd_region_deselect_smaller(rd_region_type *rd_region, const rd::KW *rd_kw, + float limit) { rd_region_select_with_limit__(rd_region, rd_kw, limit, true, false); } -void rd_region_select_larger(rd_region_type *rd_region, const rd_kw_type *rd_kw, +void rd_region_select_larger(rd_region_type *rd_region, const rd::KW *rd_kw, float limit) { rd_region_select_with_limit__(rd_region, rd_kw, limit, false, true); } -void rd_region_deselect_larger(rd_region_type *rd_region, - const rd_kw_type *rd_kw, float limit) { +void rd_region_deselect_larger(rd_region_type *rd_region, const rd::KW *rd_kw, + float limit) { rd_region_select_with_limit__(rd_region, rd_kw, limit, false, false); } @@ -449,18 +447,18 @@ void rd_region_deselect_larger(rd_region_type *rd_region, Selection based on comparing two keywords. */ -static void rd_region_cmp_select__(rd_region_type *region, - const rd_kw_type *kw1, const rd_kw_type *kw2, - bool select_less, bool select) { +static void rd_region_cmp_select__(rd_region_type *region, const rd::KW *kw1, + const rd::KW *kw2, bool select_less, + bool select) { bool global_kw; rd_region_assert_kw(region, kw1, &global_kw); - if (!rd_type_is_float(rd_kw_get_data_type(kw1))) + if (!rd_type_is_float(kw1->data_type())) throw std::invalid_argument( "select by cmp() is only supported for float keywords"); - if (rd_kw_size_and_type_equal(kw1, kw2)) { + if (kw1->size_and_type_equal(kw2)) { - const float *kw1_data = rd_kw_get_float_ptr(kw1); - const float *kw2_data = rd_kw_get_float_ptr(kw2); + const float *kw1_data = kw1->get_vector().data(); + const float *kw2_data = kw2->get_vector().data(); if (global_kw) { for (int global_index = 0; global_index < region->grid_vol; @@ -496,23 +494,23 @@ static void rd_region_cmp_select__(rd_region_type *region, rd_region_invalidate_index_list(region); } -void rd_region_cmp_select_less(rd_region_type *rd_region, const rd_kw_type *kw1, - const rd_kw_type *kw2) { +void rd_region_cmp_select_less(rd_region_type *rd_region, const rd::KW *kw1, + const rd::KW *kw2) { rd_region_cmp_select__(rd_region, kw1, kw2, true, true); } -void rd_region_cmp_deselect_less(rd_region_type *rd_region, - const rd_kw_type *kw1, const rd_kw_type *kw2) { +void rd_region_cmp_deselect_less(rd_region_type *rd_region, const rd::KW *kw1, + const rd::KW *kw2) { rd_region_cmp_select__(rd_region, kw1, kw2, true, false); } -void rd_region_cmp_select_more(rd_region_type *rd_region, const rd_kw_type *kw1, - const rd_kw_type *kw2) { +void rd_region_cmp_select_more(rd_region_type *rd_region, const rd::KW *kw1, + const rd::KW *kw2) { rd_region_cmp_select__(rd_region, kw1, kw2, false, true); } -void rd_region_cmp_deselect_more(rd_region_type *rd_region, - const rd_kw_type *kw1, const rd_kw_type *kw2) { +void rd_region_cmp_deselect_more(rd_region_type *rd_region, const rd::KW *kw1, + const rd::KW *kw2) { rd_region_cmp_select__(rd_region, kw1, kw2, false, false); } @@ -1050,9 +1048,9 @@ void rd_region_subtract(rd_region_type *region, } const std::vector &rd_region_get_kw_index_list(rd_region_type *rd_region, - const rd_kw_type *rd_kw, + const rd::KW *rd_kw, bool force_active) { - int kw_size = rd_kw_get_size(rd_kw); + int kw_size = rd::kw_get_size(rd_kw); int grid_active = rd_grid_get_active_size(rd_region->parent_grid); int grid_global = rd_grid_get_global_size(rd_region->parent_grid); @@ -1069,102 +1067,109 @@ const std::vector &rd_region_get_kw_index_list(rd_region_type *rd_region, grid_active, grid_global, kw_size)); } -void rd_region_set_kw_int(rd_region_type *rd_region, rd_kw_type *rd_kw, - int value, bool force_active) { +void rd_region_kw_iadd(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *delta_kw, bool force_active) { const std::vector &index_set = rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_set_indexed_int(rd_kw, index_set, value); -} - -void rd_region_set_kw_float(rd_region_type *rd_region, rd_kw_type *rd_kw, - float value, bool force_active) { + if (!rd_kw->size_and_numeric_type_equal(delta_kw)) + throw std::invalid_argument("type/size mismatch"); + std::visit( + [&](auto &&target_alt) { + using T = typename std::decay_t::value_type; + if constexpr (std::is_arithmetic_v) { + auto &target_data = rd_kw->get_vector(); + const auto &delta_data = delta_kw->get_vector(); + for (const auto i : index_set) + target_data[i] += delta_data[i]; + } else + throw std::invalid_argument( + fmt::format("inplace add not implemented for type:{}", + rd_type_name(rd_kw->data_type()))); + }, + rd_kw->data().value()); +} + +void rd_region_kw_idiv(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *div_kw, bool force_active) { const std::vector &index_set = rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_set_indexed_float(rd_kw, index_set, value); -} - -void rd_region_set_kw_double(rd_region_type *rd_region, rd_kw_type *rd_kw, - double value, bool force_active) { + if (!rd_kw->size_and_numeric_type_equal(div_kw)) + throw std::invalid_argument("type/size mismatch"); + std::visit( + [&](auto &&target_alt) { + using T = typename std::decay_t::value_type; + if constexpr (std::is_arithmetic_v) { + auto &target_data = rd_kw->get_vector(); + const auto &div_data = div_kw->get_vector(); + for (const auto i : index_set) + target_data[i] /= div_data[i]; + } else + throw std::invalid_argument( + fmt::format("inplace div not implemented for type:{}", + rd_type_name(rd_kw->data_type()))); + }, + rd_kw->data().value()); +} + +void rd_region_kw_imul(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *mul_kw, bool force_active) { const std::vector &index_set = rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_set_indexed_double(rd_kw, index_set, value); -} - -void rd_region_shift_kw_int(rd_region_type *rd_region, rd_kw_type *rd_kw, - int value, bool force_active) { - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_shift_indexed_int(rd_kw, index_set, value); -} - -void rd_region_shift_kw_float(rd_region_type *rd_region, rd_kw_type *rd_kw, - float value, bool force_active) { - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_shift_indexed_float(rd_kw, index_set, value); -} - -void rd_region_shift_kw_double(rd_region_type *rd_region, rd_kw_type *rd_kw, - double value, bool force_active) { + if (!rd_kw->size_and_numeric_type_equal(mul_kw)) + throw std::invalid_argument("type/size mismatch"); + std::visit( + [&](auto &&target_alt) { + using T = typename std::decay_t::value_type; + if constexpr (std::is_arithmetic_v) { + auto &target_data = rd_kw->get_vector(); + const auto &mul_data = mul_kw->get_vector(); + for (const auto i : index_set) + target_data[i] *= mul_data[i]; + } else + throw std::invalid_argument( + fmt::format("inplace mul not implemented for type:{}", + rd_type_name(rd_kw->data_type()))); + }, + rd_kw->data().value()); +} + +void rd_region_kw_isub(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *delta_kw, bool force_active) { const std::vector &index_set = rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_shift_indexed_double(rd_kw, index_set, value); -} - -void rd_region_scale_kw_int(rd_region_type *rd_region, rd_kw_type *rd_kw, - int value, bool force_active) { - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_scale_indexed_int(rd_kw, index_set, value); -} - -void rd_region_scale_kw_float(rd_region_type *rd_region, rd_kw_type *rd_kw, - float value, bool force_active) { - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_scale_indexed_float(rd_kw, index_set, value); -} - -void rd_region_scale_kw_double(rd_region_type *rd_region, rd_kw_type *rd_kw, - double value, bool force_active) { - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_scale_indexed_double(rd_kw, index_set, value); -} - -void rd_region_kw_iadd(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *delta_kw, bool force_active) { - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_inplace_add_indexed(rd_kw, index_set, delta_kw); -} - -void rd_region_kw_idiv(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *div_kw, bool force_active) { - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_inplace_div_indexed(rd_kw, index_set, div_kw); -} - -void rd_region_kw_imul(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *mul_kw, bool force_active) { - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_inplace_mul_indexed(rd_kw, index_set, mul_kw); -} - -void rd_region_kw_isub(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *delta_kw, bool force_active) { - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_inplace_sub_indexed(rd_kw, index_set, delta_kw); -} - -void rd_region_kw_copy(rd_region_type *rd_region, rd_kw_type *rd_kw, - const rd_kw_type *src_kw, bool force_active) { + if (!rd_kw->size_and_numeric_type_equal(delta_kw)) + throw std::invalid_argument("type/size mismatch"); + std::visit( + [&](auto &&target_alt) { + using T = typename std::decay_t::value_type; + if constexpr (std::is_arithmetic_v) { + auto &target_data = rd_kw->get_vector(); + const auto &delta_data = delta_kw->get_vector(); + for (const auto i : index_set) + target_data[i] -= delta_data[i]; + } else + throw std::invalid_argument( + fmt::format("inplace sub not implemented for type:{}", + rd_type_name(rd_kw->data_type()))); + }, + rd_kw->data().value()); +} + +void rd_region_kw_copy(rd_region_type *rd_region, rd::KW *rd_kw, + const rd::KW *src_kw, bool force_active) { const std::vector &target_index = rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_copy_indexed(rd_kw, target_index, src_kw); + if (!rd_kw->size_and_type_equal(src_kw)) + throw std::invalid_argument("type/size mismatch"); + std::visit( + [&](auto &&target_alt) { + using T = typename std::decay_t::value_type; + auto &target_data = rd_kw->get_vector(); + const auto &src_data = src_kw->get_vector(); + for (const auto i : target_index) + target_data[i] = src_data[i]; + }, + rd_kw->data().value()); } void rd_region_set_name(rd_region_type *region, @@ -1184,30 +1189,3 @@ bool rd_region_equal(const rd_region_type *region1, } else return false; } - -int rd_region_sum_kw_int(rd_region_type *rd_region, const rd_kw_type *rd_kw, - bool force_active) { - int sum; - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_element_sum_indexed(rd_kw, index_set, &sum); - return sum; -} - -float rd_region_sum_kw_float(rd_region_type *rd_region, const rd_kw_type *rd_kw, - bool force_active) { - float sum; - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_element_sum_indexed(rd_kw, index_set, &sum); - return sum; -} - -double rd_region_sum_kw_double(rd_region_type *rd_region, - const rd_kw_type *rd_kw, bool force_active) { - double sum; - const std::vector &index_set = - rd_region_get_kw_index_list(rd_region, rd_kw, force_active); - rd_kw_element_sum_indexed(rd_kw, index_set, &sum); - return sum; -} diff --git a/lib/resdata/rd_region_pybind.cpp b/lib/resdata/rd_region_pybind.cpp index 7451694a6..5d1091439 100644 --- a/lib/resdata/rd_region_pybind.cpp +++ b/lib/resdata/rd_region_pybind.cpp @@ -50,74 +50,68 @@ PYBIND11_MODULE(_rd_region, m) { m.def("_set_kw_int", [](py::handle self, py::handle kw, int value, bool force_active) { - rd_region_set_kw_int(from_cwrap(self), - from_cwrap(kw), value, force_active); + rd_region_set_kw(from_cwrap(self), + from_cwrap(kw), value, force_active); }); m.def("_set_kw_float", [](py::handle self, py::handle kw, float value, bool force_active) { - rd_region_set_kw_float(from_cwrap(self), - from_cwrap(kw), value, force_active); - }); - m.def("_set_kw_double", - [](py::handle self, py::handle kw, double value, bool force_active) { - rd_region_set_kw_double(from_cwrap(self), - from_cwrap(kw), value, - force_active); - }); + rd_region_set_kw(from_cwrap(self), + from_cwrap(kw), value, force_active); + }); + m.def("_set_kw_double", [](py::handle self, py::handle kw, double value, + bool force_active) { + rd_region_set_kw(from_cwrap(self), + from_cwrap(kw), value, force_active); + }); m.def("_shift_kw_int", [](py::handle self, py::handle kw, int value, bool force_active) { - rd_region_shift_kw_int(from_cwrap(self), - from_cwrap(kw), value, force_active); - }); - m.def("_shift_kw_float", - [](py::handle self, py::handle kw, float value, bool force_active) { - rd_region_shift_kw_float(from_cwrap(self), - from_cwrap(kw), value, - force_active); - }); - m.def("_shift_kw_double", - [](py::handle self, py::handle kw, double value, bool force_active) { - rd_region_shift_kw_double(from_cwrap(self), - from_cwrap(kw), value, - force_active); - }); + rd_region_shift_kw(from_cwrap(self), + from_cwrap(kw), value, force_active); + }); + m.def("_shift_kw_float", [](py::handle self, py::handle kw, float value, + bool force_active) { + rd_region_shift_kw(from_cwrap(self), + from_cwrap(kw), value, force_active); + }); + m.def("_shift_kw_double", [](py::handle self, py::handle kw, double value, + bool force_active) { + rd_region_shift_kw(from_cwrap(self), + from_cwrap(kw), value, force_active); + }); m.def("_scale_kw_int", [](py::handle self, py::handle kw, int value, bool force_active) { - rd_region_scale_kw_int(from_cwrap(self), - from_cwrap(kw), value, force_active); - }); - m.def("_scale_kw_float", - [](py::handle self, py::handle kw, float value, bool force_active) { - rd_region_scale_kw_float(from_cwrap(self), - from_cwrap(kw), value, - force_active); - }); - m.def("_scale_kw_double", - [](py::handle self, py::handle kw, double value, bool force_active) { - rd_region_scale_kw_double(from_cwrap(self), - from_cwrap(kw), value, - force_active); - }); + rd_region_scale_kw(from_cwrap(self), + from_cwrap(kw), value, force_active); + }); + m.def("_scale_kw_float", [](py::handle self, py::handle kw, float value, + bool force_active) { + rd_region_scale_kw(from_cwrap(self), + from_cwrap(kw), value, force_active); + }); + m.def("_scale_kw_double", [](py::handle self, py::handle kw, double value, + bool force_active) { + rd_region_scale_kw(from_cwrap(self), + from_cwrap(kw), value, force_active); + }); m.def("_sum_kw_int", [](py::handle self, py::handle kw, bool force_active) { - return rd_region_sum_kw_int(from_cwrap(self), - from_cwrap(kw), force_active); + return rd_region_sum_kw(from_cwrap(self), + from_cwrap(kw), force_active); }); m.def("_sum_kw_float", [](py::handle self, py::handle kw, bool force_active) { - return rd_region_sum_kw_float(from_cwrap(self), - from_cwrap(kw), force_active); - }); - m.def("_sum_kw_double", - [](py::handle self, py::handle kw, bool force_active) { - return rd_region_sum_kw_double(from_cwrap(self), - from_cwrap(kw), - force_active); - }); - m.def("_sum_kw_bool", [](py::handle self, py::handle kw, - bool force_active) { - return rd_region_sum_kw_int(from_cwrap(self), - from_cwrap(kw), force_active); + return rd_region_sum_kw(from_cwrap(self), + from_cwrap(kw), force_active); }); + m.def("_sum_kw_double", [](py::handle self, py::handle kw, + bool force_active) { + return rd_region_sum_kw(from_cwrap(self), + from_cwrap(kw), force_active); + }); + m.def( + "_sum_kw_bool", [](py::handle self, py::handle kw, bool force_active) { + return rd_region_sum_kw_bool(from_cwrap(self), + from_cwrap(kw), force_active); + }); m.def("_free", [](py::handle self) { rd_region_free(from_cwrap(self)); @@ -133,39 +127,39 @@ PYBIND11_MODULE(_rd_region, m) { }); m.def("_select_equal", [](py::handle self, py::handle kw, int value) { rd_region_select_equal(from_cwrap(self), - from_cwrap(kw), value); + from_cwrap(kw), value); }); m.def("_deselect_equal", [](py::handle self, py::handle kw, int value) { rd_region_deselect_equal(from_cwrap(self), - from_cwrap(kw), value); + from_cwrap(kw), value); }); m.def("_select_less", [](py::handle self, py::handle kw, float limit) { rd_region_select_smaller(from_cwrap(self), - from_cwrap(kw), limit); + from_cwrap(kw), limit); }); m.def("_deselect_less", [](py::handle self, py::handle kw, float limit) { rd_region_deselect_smaller(from_cwrap(self), - from_cwrap(kw), limit); + from_cwrap(kw), limit); }); m.def("_select_more", [](py::handle self, py::handle kw, float limit) { rd_region_select_larger(from_cwrap(self), - from_cwrap(kw), limit); + from_cwrap(kw), limit); }); m.def("_deselect_more", [](py::handle self, py::handle kw, float limit) { rd_region_deselect_larger(from_cwrap(self), - from_cwrap(kw), limit); + from_cwrap(kw), limit); }); m.def("_select_in_interval", [](py::handle self, py::handle kw, float min_value, float max_value) { rd_region_select_in_interval(from_cwrap(self), - from_cwrap(kw), - min_value, max_value); + from_cwrap(kw), min_value, + max_value); }); m.def("_deselect_in_interval", [](py::handle self, py::handle kw, float min_value, float max_value) { rd_region_deselect_in_interval(from_cwrap(self), - from_cwrap(kw), - min_value, max_value); + from_cwrap(kw), min_value, + max_value); }); m.def("_invert_selection", [](py::handle self) { rd_region_invert_selection(from_cwrap(self)); @@ -184,32 +178,32 @@ PYBIND11_MODULE(_rd_region, m) { m.def("_imul_kw", [](py::handle self, py::handle kw, py::handle other, bool force_active) { rd_region_kw_imul(from_cwrap(self), - from_cwrap(kw), - from_cwrap(other), force_active); + from_cwrap(kw), from_cwrap(other), + force_active); }); m.def("_idiv_kw", [](py::handle self, py::handle kw, py::handle other, bool force_active) { rd_region_kw_idiv(from_cwrap(self), - from_cwrap(kw), - from_cwrap(other), force_active); + from_cwrap(kw), from_cwrap(other), + force_active); }); m.def("_iadd_kw", [](py::handle self, py::handle kw, py::handle other, bool force_active) { rd_region_kw_iadd(from_cwrap(self), - from_cwrap(kw), - from_cwrap(other), force_active); + from_cwrap(kw), from_cwrap(other), + force_active); }); m.def("_isub_kw", [](py::handle self, py::handle kw, py::handle other, bool force_active) { rd_region_kw_isub(from_cwrap(self), - from_cwrap(kw), - from_cwrap(other), force_active); + from_cwrap(kw), from_cwrap(other), + force_active); }); m.def("_copy_kw", [](py::handle self, py::handle kw, py::handle src_kw, bool force_active) { rd_region_kw_copy(from_cwrap(self), - from_cwrap(kw), - from_cwrap(src_kw), force_active); + from_cwrap(kw), from_cwrap(src_kw), + force_active); }); m.def("_intersect", [](py::handle self, py::handle other) { rd_region_intersection(from_cwrap(self), @@ -226,7 +220,7 @@ PYBIND11_MODULE(_rd_region, m) { m.def("_get_kw_index_list", [](py::handle self, py::handle kw, bool force_active) { return rd_region_get_kw_index_list(from_cwrap(self), - from_cwrap(kw), + from_cwrap(kw), force_active); }); m.def("_get_active_size", [](py::handle self) { @@ -246,26 +240,26 @@ PYBIND11_MODULE(_rd_region, m) { m.def("_select_cmp_less", [](py::handle self, py::handle kw1, py::handle kw2) { rd_region_cmp_select_less(from_cwrap(self), - from_cwrap(kw1), - from_cwrap(kw2)); + from_cwrap(kw1), + from_cwrap(kw2)); }); m.def("_select_cmp_more", [](py::handle self, py::handle kw1, py::handle kw2) { rd_region_cmp_select_more(from_cwrap(self), - from_cwrap(kw1), - from_cwrap(kw2)); + from_cwrap(kw1), + from_cwrap(kw2)); }); m.def("_deselect_cmp_less", [](py::handle self, py::handle kw1, py::handle kw2) { rd_region_cmp_deselect_less(from_cwrap(self), - from_cwrap(kw1), - from_cwrap(kw2)); + from_cwrap(kw1), + from_cwrap(kw2)); }); m.def("_deselect_cmp_more", [](py::handle self, py::handle kw1, py::handle kw2) { rd_region_cmp_deselect_more(from_cwrap(self), - from_cwrap(kw1), - from_cwrap(kw2)); + from_cwrap(kw1), + from_cwrap(kw2)); }); m.def("_select_islice", [](py::handle self, int i1, int i2) { rd_region_select_i1i2(from_cwrap(self), i1, i2); @@ -411,11 +405,11 @@ PYBIND11_MODULE(_rd_region, m) { }); m.def("_select_true", [](py::handle self, py::handle kw) { rd_region_select_true(from_cwrap(self), - from_cwrap(kw)); + from_cwrap(kw)); }); m.def("_select_false", [](py::handle self, py::handle kw) { rd_region_select_false(from_cwrap(self), - from_cwrap(kw)); + from_cwrap(kw)); }); m.def("_select_from_layer", [](py::handle self, py::handle layer, int k, int value) { diff --git a/lib/resdata/rd_smspec.cpp b/lib/resdata/rd_smspec.cpp index fd7023ed0..08dc7ef72 100644 --- a/lib/resdata/rd_smspec.cpp +++ b/lib/resdata/rd_smspec.cpp @@ -313,70 +313,42 @@ static rd_data_type get_wgnames_type(const rd_smspec_type *smspec) { static void rd_smspec_fwrite_INTEHEAD(const rd_smspec_type *smspec, ERT::FortIO &fortio) { - rd_kw_ptr intehead = make_rd_kw(INTEHEAD_KW, INTEHEAD_SMSPEC_SIZE, RD_INT); - rd_kw_iset_int(intehead.get(), INTEHEAD_SMSPEC_UNIT_INDEX, - static_cast(smspec->unit_system)); + std::vector intehead_data(INTEHEAD_SMSPEC_SIZE, 0); + intehead_data[INTEHEAD_SMSPEC_UNIT_INDEX] = + static_cast(smspec->unit_system); /* The simulator type is just hardcoded to ECLIPSE100. */ - rd_kw_iset_int(intehead.get(), INTEHEAD_SMSPEC_IPROG_INDEX, - INTEHEAD_ECLIPSE100_VALUE); - rd_kw_fwrite(intehead.get(), fortio); + intehead_data[INTEHEAD_SMSPEC_IPROG_INDEX] = INTEHEAD_ECLIPSE100_VALUE; + rd::KW intehead{INTEHEAD_KW, std::move(intehead_data)}; + intehead.fwrite(fortio); } static void rd_smspec_fwrite_RESTART(const rd_smspec_type *smspec, ERT::FortIO &fortio) { - rd_kw_ptr restart_kw = - make_rd_kw(RESTART_KW, SUMMARY_RESTART_SIZE, RD_CHAR); - for (int i = 0; i < SUMMARY_RESTART_SIZE; i++) - rd_kw_iset_string8(restart_kw.get(), i, ""); - - if (smspec->restart_case.size() > 0) { - size_t restart_case_len = smspec->restart_case.size(); - - size_t offset = 0; - for (size_t i = 0; i < SUMMARY_RESTART_SIZE; i++) { - if (offset < restart_case_len) - rd_kw_iset_string8(restart_kw.get(), i, - &smspec->restart_case[offset]); - offset += RD_STRING8_LENGTH; - } - } - rd_kw_fwrite(restart_kw.get(), fortio); + rd::KW restart_kw{RESTART_KW, SUMMARY_RESTART_SIZE, RD_CHAR}; + restart_kw.set_string_array(0, smspec->restart_case); + restart_kw.fwrite(fortio); } static void rd_smspec_fwrite_DIMENS(const rd_smspec_type *smspec, ERT::FortIO &fortio) { - rd_kw_ptr dimens_kw = make_rd_kw(DIMENS_KW, DIMENS_SIZE, RD_INT); int num_nodes = rd_smspec_num_nodes(smspec); - rd_kw_iset_int(dimens_kw.get(), DIMENS_SMSPEC_SIZE_INDEX, num_nodes); - rd_kw_iset_int(dimens_kw.get(), DIMENS_SMSPEC_NX_INDEX, - smspec->grid_dims[0]); - rd_kw_iset_int(dimens_kw.get(), DIMENS_SMSPEC_NY_INDEX, - smspec->grid_dims[1]); - rd_kw_iset_int(dimens_kw.get(), DIMENS_SMSPEC_NZ_INDEX, - smspec->grid_dims[2]); - rd_kw_iset_int(dimens_kw.get(), 4, 0); // Do not know what this is for. - rd_kw_iset_int(dimens_kw.get(), DIMENS_SMSPEC_RESTART_STEP_INDEX, - smspec->restart_step); - - rd_kw_fwrite(dimens_kw.get(), fortio); + rd::KW dimens_kw{ + DIMENS_KW, + std::vector{num_nodes, smspec->grid_dims[0], smspec->grid_dims[1], + smspec->grid_dims[2], 0, smspec->restart_step}}; + + dimens_kw.fwrite(fortio); } static void rd_smspec_fwrite_STARTDAT(const rd_smspec_type *smspec, ERT::FortIO &fortio) { - auto startdat_kw = make_rd_kw(STARTDAT_KW, STARTDAT_SIZE, RD_INT); int second, minute, hour, mday, month, year; rd_set_datetime_values(smspec->sim_start_time, &second, &minute, &hour, &mday, &month, &year); - rd_kw_iset_int(startdat_kw.get(), STARTDAT_DAY_INDEX, mday); - rd_kw_iset_int(startdat_kw.get(), STARTDAT_MONTH_INDEX, month); - rd_kw_iset_int(startdat_kw.get(), STARTDAT_YEAR_INDEX, year); - rd_kw_iset_int(startdat_kw.get(), STARTDAT_HOUR_INDEX, hour); - rd_kw_iset_int(startdat_kw.get(), STARTDAT_MINUTE_INDEX, minute); - rd_kw_iset_int(startdat_kw.get(), STARTDAT_MICRO_SECOND_INDEX, - second * 1000000); - - rd_kw_fwrite(startdat_kw.get(), fortio); + rd::KW startdat_kw{STARTDAT_KW, std::vector{mday, month, year, hour, + minute, second * 1000000}}; + startdat_kw.fwrite(fortio); } static void rd_smspec_fortio_fwrite(const rd_smspec_type *smspec, @@ -386,19 +358,18 @@ static void rd_smspec_fortio_fwrite(const rd_smspec_type *smspec, rd_smspec_fwrite_DIMENS(smspec, fortio); int num_nodes = rd_smspec_num_nodes(smspec); - auto keywords_kw = make_rd_kw(KEYWORDS_KW, num_nodes, RD_CHAR); - auto units_kw = make_rd_kw(UNITS_KW, num_nodes, RD_CHAR); - rd_kw_ptr nums_kw{nullptr, &rd_kw_free}; + rd::KW keywords_kw{KEYWORDS_KW, num_nodes, RD_CHAR}; + rd::KW units_kw{UNITS_KW, num_nodes, RD_CHAR}; + std::unique_ptr nums_kw{nullptr}; // If the names_type is an RD_STRING we expect this to be an INTERSECT // summary, otherwise an ECLIPSE summary. rd_data_type names_type = get_wgnames_type(smspec); - auto wgnames_kw = - make_rd_kw(rd_type_is_char(names_type) ? WGNAMES_KW : NAMES_KW, - num_nodes, names_type); + rd::KW wgnames_kw{rd_type_is_char(names_type) ? WGNAMES_KW : NAMES_KW, + num_nodes, names_type}; if (smspec->need_nums) - nums_kw.reset(rd_kw_alloc(NUMS_KW, num_nodes, RD_INT)); + nums_kw = std::make_unique(NUMS_KW, num_nodes, RD_INT); for (int i = 0; i < rd_smspec_num_nodes(smspec); i++) { const rd::smspec_node &smspec_node = @@ -422,29 +393,31 @@ static void rd_smspec_fortio_fwrite(const rd_smspec_type *smspec, ignored when/if this smspec file is read at a later stage. */ + size_t ii = static_cast(i); + + std::string wgname{DUMMY_WELL}; if (smspec_node.get_var_type() == RD_SMSPEC_INVALID_VAR) { - rd_kw_iset_string8(keywords_kw.get(), i, "WWCT"); - rd_kw_iset_string8(units_kw.get(), i, "????????"); - rd_kw_iset_string_ptr(wgnames_kw.get(), i, DUMMY_WELL.data()); + keywords_kw.set_padded(ii, "WWCT"); + units_kw.set_padded(ii, "????????"); + wgnames_kw.set_padded(ii, wgname); } else { - rd_kw_iset_string8(keywords_kw.get(), i, smspec_node.get_keyword()); - rd_kw_iset_string8(units_kw.get(), i, smspec_node.get_unit()); + keywords_kw.set_padded(ii, smspec_node.get_keyword()); + units_kw.set_padded(ii, smspec_node.get_unit()); { - std::string wgname{DUMMY_WELL}; if (smspec_node.get_wgname()) wgname = smspec_node.get_wgname(); - rd_kw_iset_string_ptr(wgnames_kw.get(), i, wgname.c_str()); + wgnames_kw.set_padded(ii, wgname); } } if (nums_kw) - rd_kw_iset_int(nums_kw.get(), i, smspec_node.get_num()); + nums_kw->at(ii) = smspec_node.get_num(); } - rd_kw_fwrite(keywords_kw.get(), fortio); - rd_kw_fwrite(wgnames_kw.get(), fortio); + keywords_kw.fwrite(fortio); + wgnames_kw.fwrite(fortio); if (nums_kw) - rd_kw_fwrite(nums_kw.get(), fortio); - rd_kw_fwrite(units_kw.get(), fortio); + nums_kw->fwrite(fortio); + units_kw.fwrite(fortio); rd_smspec_fwrite_STARTDAT(smspec, fortio); } @@ -636,19 +609,12 @@ static void rd_smspec_load_restart(rd_smspec_type *rd_smspec, const rd::File *header) { if (!header->has_kw(RESTART_KW)) return; - const rd_kw_type *restart_kw = header->get_kw(RESTART_KW, 0); + const rd::KW *restart_kw = header->get_kw(RESTART_KW, 0); if (restart_kw == nullptr) throw std::invalid_argument( "RESTART keyword lookup failed despite keyword presence"); - int num_blocks = rd_kw_get_size(restart_kw); - num_blocks = (num_blocks < 0) ? 0 : num_blocks; - auto tmp_base = rd::checked_calloc(8 * num_blocks + 1); - for (int i = 0; i < num_blocks; i++) { - const char *part = (const char *)rd_kw_iget_ptr(restart_kw, i); - strncat(tmp_base.get(), part, 8); - } - - std::string restart_base = rd::strip_spaces(std::string(tmp_base.get())); + std::string restart_base = + rd::strip_spaces(restart_kw->get_string_array(0, restart_kw->size())); /* We ignore the empty ones. */ if (!restart_base.size()) @@ -843,18 +809,17 @@ static bool rd_smspec_fread_header(rd_smspec_type *rd_smspec, if (header && rd_smspec_check_header(header.get())) { const char *names_alias = get_active_keyword_alias(header.get(), WGNAMES_KW); - rd_kw_type *wells = header->get_kw(names_alias, 0); - rd_kw_type *keywords = header->get_kw(KEYWORDS_KW, 0); - rd_kw_type *startdat = header->get_kw(STARTDAT_KW, 0); - rd_kw_type *units = header->get_kw(UNITS_KW, 0); - rd_kw_type *dimens = header->get_kw(DIMENS_KW, 0); - rd_kw_type *nums = NULL; - rd_kw_type *lgrs = NULL; - rd_kw_type *numlx = NULL; - rd_kw_type *numly = NULL; - rd_kw_type *numlz = NULL; - - int params_index; + rd::KW *wells = header->get_kw(names_alias, 0); + rd::KW *keywords = header->get_kw(KEYWORDS_KW, 0); + rd::KW *startdat = header->get_kw(STARTDAT_KW, 0); + rd::KW *units = header->get_kw(UNITS_KW, 0); + rd::KW *dimens = header->get_kw(DIMENS_KW, 0); + rd::KW *nums = NULL; + rd::KW *lgrs = NULL; + rd::KW *numlx = NULL; + rd::KW *numly = NULL; + rd::KW *numlz = NULL; + rd_smspec->num_regions = 0; if (wells == NULL) @@ -873,18 +838,18 @@ static bool rd_smspec_fread_header(rd_smspec_type *rd_smspec, throw std::invalid_argument( "Could not locate DIMENS keyword in header"); - rd_smspec->params_size = rd_kw_get_size(keywords); + rd_smspec->params_size = rd::kw_get_size(keywords); if (header->has_kw(NUMS_KW)) nums = header->get_kw(NUMS_KW, 0); if (header->has_kw(INTEHEAD_KW)) { - const rd_kw_type *intehead = header->get_kw(INTEHEAD_KW, 0); + const rd::KW *intehead = header->get_kw(INTEHEAD_KW, 0); if (intehead == NULL) throw std::invalid_argument( "INTEHEAD keyword lookup failed despite keyword presence"); rd_smspec->unit_system = static_cast( - rd_kw_iget_int(intehead, INTEHEAD_SMSPEC_UNIT_INDEX)); + intehead->at(INTEHEAD_SMSPEC_UNIT_INDEX)); /* The second item in the INTEHEAD vector is an integer designating which simulator has been used for the current simulation, that is currently @@ -908,17 +873,14 @@ static bool rd_smspec_fread_header(rd_smspec_type *rd_smspec, rd_smspec->has_lgr = false; { - int *date = rd_kw_get_int_ptr(startdat); - if (date == NULL) - throw std::invalid_argument( - "STARTDAT keyword has no integer data payload"); + const std::vector &date = startdat->get_vector(); int year = date[STARTDAT_YEAR_INDEX]; int month = date[STARTDAT_MONTH_INDEX]; int day = date[STARTDAT_DAY_INDEX]; int hour = 0; int min = 0; int sec = 0; - if (rd_kw_get_size(startdat) == 6) { + if (startdat->size() == 6) { hour = date[STARTDAT_HOUR_INDEX]; min = date[STARTDAT_MINUTE_INDEX]; sec = date[STARTDAT_MICRO_SECOND_INDEX] / 1000000; @@ -928,66 +890,60 @@ static bool rd_smspec_fread_header(rd_smspec_type *rd_smspec, rd_make_datetime(sec, min, hour, day, month, year); } - rd_smspec->grid_dims[0] = - rd_kw_iget_int(dimens, DIMENS_SMSPEC_NX_INDEX); - rd_smspec->grid_dims[1] = - rd_kw_iget_int(dimens, DIMENS_SMSPEC_NY_INDEX); - rd_smspec->grid_dims[2] = - rd_kw_iget_int(dimens, DIMENS_SMSPEC_NZ_INDEX); + rd_smspec->grid_dims[0] = dimens->at(DIMENS_SMSPEC_NX_INDEX); + rd_smspec->grid_dims[1] = dimens->at(DIMENS_SMSPEC_NY_INDEX); + rd_smspec->grid_dims[2] = dimens->at(DIMENS_SMSPEC_NZ_INDEX); rd_smspec->restart_step = - rd_kw_iget_int(dimens, DIMENS_SMSPEC_RESTART_STEP_INDEX); + dimens->at(DIMENS_SMSPEC_RESTART_STEP_INDEX); rd_get_file_type(header_file.c_str(), &rd_smspec->formatted, NULL); - { - for (params_index = 0; params_index < rd_kw_get_size(wells); - params_index++) { - float default_value = PARAMS_GLOBAL_DEFAULT; - int num = SMSPEC_NUMS_INVALID; - std::string well = - rd_kw_iget_stripped_string(wells, params_index); - std::string kw = - rd_kw_iget_stripped_string(keywords, params_index); - std::string unit = - rd_kw_iget_stripped_string(units, params_index); - - rd_smspec_var_type var_type; - if (nums != NULL) - num = rd_kw_iget_int(nums, params_index); - var_type = - rd::smspec_node::valid_type(kw.c_str(), well.c_str(), num); - if (var_type == RD_SMSPEC_INVALID_VAR) { - continue; - } - - if (rd_smspec_lgr_var_type(var_type) && !rd_smspec->has_lgr) { - throw std::invalid_argument( - "SMSPEC header contains LGR variable '" + kw + - "' but required LGR metadata keywords are missing " - "(expected LGRS, NUMLX, NUMLY, NUMLZ)"); - } - - if (rd_smspec_lgr_var_type(var_type)) { - int lgr_i = rd_kw_iget_int(numlx, params_index); - int lgr_j = rd_kw_iget_int(numly, params_index); - int lgr_k = rd_kw_iget_int(numlz, params_index); - std::string lgr_name = - rd_kw_iget_stripped_string(lgrs, params_index); - - rd_smspec_insert_node( - rd_smspec, - std::make_unique( - params_index, kw.c_str(), well.c_str(), - unit.c_str(), lgr_name.c_str(), lgr_i, lgr_j, lgr_k, - default_value, rd_smspec->key_join_string.c_str())); - } else - rd_smspec_insert_node( - rd_smspec, - std::make_unique( - params_index, kw.c_str(), well.c_str(), num, - unit.c_str(), rd_smspec->grid_dims, default_value, - rd_smspec->key_join_string.c_str())); + for (size_t params_index = 0; params_index < wells->size(); + params_index++) { + float default_value = PARAMS_GLOBAL_DEFAULT; + int num = SMSPEC_NUMS_INVALID; + std::string well = + rd::strip_spaces(wells->at(params_index)); + std::string kw = + rd::strip_spaces(keywords->at(params_index)); + std::string unit = + rd::strip_spaces(units->at(params_index)); + + if (nums != NULL) + num = nums->at(params_index); + rd_smspec_var_type var_type = + rd::smspec_node::valid_type(kw.c_str(), well.c_str(), num); + if (var_type == RD_SMSPEC_INVALID_VAR) { + continue; } + + if (rd_smspec_lgr_var_type(var_type) && !rd_smspec->has_lgr) { + throw std::invalid_argument( + "SMSPEC header contains LGR variable '" + kw + + "' but required LGR metadata keywords are missing " + "(expected LGRS, NUMLX, NUMLY, NUMLZ)"); + } + + if (rd_smspec_lgr_var_type(var_type)) { + int lgr_i = numlx->at(params_index); + int lgr_j = numly->at(params_index); + int lgr_k = numlz->at(params_index); + std::string lgr_name = + rd::strip_spaces(lgrs->at(params_index)); + + rd_smspec_insert_node( + rd_smspec, std::make_unique( + static_cast(params_index), kw.c_str(), + well.c_str(), unit.c_str(), lgr_name.c_str(), + lgr_i, lgr_j, lgr_k, default_value, + rd_smspec->key_join_string.c_str())); + } else + rd_smspec_insert_node( + rd_smspec, + std::make_unique( + static_cast(params_index), kw.c_str(), + well.c_str(), num, unit.c_str(), rd_smspec->grid_dims, + default_value, rd_smspec->key_join_string.c_str())); } rd_smspec->header_file = fs::canonical(header_file).string(); diff --git a/lib/resdata/rd_subsidence.cpp b/lib/resdata/rd_subsidence.cpp index 6661a951b..dbe2d2507 100644 --- a/lib/resdata/rd_subsidence.cpp +++ b/lib/resdata/rd_subsidence.cpp @@ -74,29 +74,28 @@ rd_subsidence_survey_alloc_PRESSURE(rd_subsidence_type *rd_subsidence, std::make_unique(*rd_subsidence, name)); const rd::rd_grid_cache &grid_cache = *(rd_subsidence->grid_cache); const auto &global_index = grid_cache.global_index(); - const int size = grid_cache.size(); + const size_t size = grid_cache.size(); - rd_kw_type *init_porv_kw = + rd::KW *init_porv_kw = rd_subsidence->init_file->get_kw(PORV_KW, 0); /*Global indexing*/ - rd_kw_type *pressure_kw = + rd::KW *pressure_kw = restart_view->get_kw(PRESSURE_KW, 0); /*Active indexing*/ - rd_kw_type *rporv_kw = nullptr; + rd::KW *rporv_kw = nullptr; if (restart_view->has_kw(RPORV_KW)) { survey->dynamic_porevolume = std::vector(rd_subsidence->grid_cache->size(), 0.0); rporv_kw = restart_view->get_kw(RPORV_KW, 0); } - for (int active_index = 0; active_index < size; active_index++) { + for (size_t active_index = 0; active_index < size; active_index++) { survey->porv[active_index] = - rd_kw_iget_float(init_porv_kw, global_index[active_index]); - survey->pressure[active_index] = - rd_kw_iget_float(pressure_kw, active_index); + init_porv_kw->at(global_index[active_index]); + survey->pressure[active_index] = pressure_kw->at(active_index); if (survey->dynamic_porevolume.has_value()) (*survey->dynamic_porevolume)[active_index] = - rd_kw_iget_float(rporv_kw, active_index); + rporv_kw->at(active_index); } return survey; } diff --git a/lib/resdata/rd_sum_file_data.cpp b/lib/resdata/rd_sum_file_data.cpp index 1878f2e30..c5b63f89e 100644 --- a/lib/resdata/rd_sum_file_data.cpp +++ b/lib/resdata/rd_sum_file_data.cpp @@ -439,9 +439,8 @@ std::pair rd_sum_file_data::report_range(int report_step) const { void rd_sum_file_data::fwrite_report(int report_step, ERT::FortIO &fortio) const { { - auto seqhdr_kw = make_rd_kw(SEQHDR_KW, SEQHDR_SIZE, RD_INT); - rd_kw_iset_int(seqhdr_kw.get(), 0, 0); - rd_kw_fwrite(seqhdr_kw.get(), fortio); + rd::KW seqhdr_kw{SEQHDR_KW, std::vector(SEQHDR_SIZE, 0)}; + seqhdr_kw.fwrite(fortio); } { @@ -533,11 +532,11 @@ void rd_sum_file_data::add_rd_file(int report_step, if (num_ministep > 0) { 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); + rd::KW *ministep_kw = summary_view.get_kw(MINISTEP_KW, ikw); + rd::KW *params_kw = summary_view.get_kw(PARAMS_KW, ikw); { - int ministep_nr = rd_kw_iget_int(ministep_kw, 0); + int ministep_nr = ministep_kw->at(0); std::string filename = summary_view.filename(); rd_sum_tstep_ptr tstep(rd_sum_tstep_alloc_from_file( report_step, ministep_nr, params_kw, diff --git a/lib/resdata/rd_sum_tstep.cpp b/lib/resdata/rd_sum_tstep.cpp index f42605497..8a9d7181b 100644 --- a/lib/resdata/rd_sum_tstep.cpp +++ b/lib/resdata/rd_sum_tstep.cpp @@ -140,17 +140,17 @@ static void rd_sum_tstep_set_time_info(rd_sum_tstep_type *tstep, rd_sum_tstep_type *rd_sum_tstep_alloc_from_file(int report_step, int ministep_nr, - const rd_kw_type *params_kw, + const rd::KW *params_kw, const char *src_file, const rd_smspec_type *smspec) { - int data_size = rd_kw_get_size(params_kw); + int data_size = rd::kw_get_size(params_kw); if (data_size == rd_smspec_get_params_size(smspec)) { std::unique_ptr ministep(rd_sum_tstep_alloc(report_step, ministep_nr, smspec), &rd_sum_tstep_free); - rd_kw_get_memcpy_data(params_kw, ministep->data.data()); + ministep->data = params_kw->get_vector(); rd_sum_tstep_set_time_info(ministep.get(), smspec); return ministep.release(); } else { @@ -225,23 +225,16 @@ int rd_sum_tstep_get_ministep(const rd_sum_tstep_type *ministep) { void rd_sum_tstep_fwrite(const rd_sum_tstep_type *ministep, const int *index_map, int index_map_size, ERT::FortIO &fortio) { - { - auto ministep_kw = make_rd_kw(MINISTEP_KW, 1, RD_INT); - rd_kw_iset_int(ministep_kw.get(), 0, ministep->ministep); - rd_kw_fwrite(ministep_kw.get(), fortio); - } - - { - int compact_size = index_map_size; - auto params_kw = make_rd_kw(PARAMS_KW, compact_size, RD_FLOAT); + rd::KW ministep_kw{MINISTEP_KW, std::vector{ministep->ministep}}; + ministep_kw.fwrite(fortio); - float *data = (float *)rd_kw_get_ptr(params_kw.get()); + int compact_size = index_map_size; + std::vector data(compact_size); + for (int i = 0; i < compact_size; i++) + data[i] = ministep->data[index_map[i]]; - for (int i = 0; i < compact_size; i++) - data[i] = ministep->data[index_map[i]]; - - rd_kw_fwrite(params_kw.get(), fortio); - } + rd::KW params_kw{PARAMS_KW, data}; + params_kw.fwrite(fortio); } void rd_sum_tstep_iset(rd_sum_tstep_type *tstep, int index, float value) { diff --git a/lib/resdata/rd_unsmry_loader.cpp b/lib/resdata/rd_unsmry_loader.cpp index 3bd18bd47..01d5ae28f 100644 --- a/lib/resdata/rd_unsmry_loader.cpp +++ b/lib/resdata/rd_unsmry_loader.cpp @@ -47,12 +47,12 @@ unsmry_loader::unsmry_loader(const rd_smspec_type *smspec, int length = file_view->num_named_kw(PARAMS_KW); if (length > 0) { - const rd_kw_type *params_kw = file_view->get_kw(PARAMS_KW, 0); + const rd::KW *params_kw = file_view->get_kw(PARAMS_KW, 0); if (params_kw == nullptr) throw std::invalid_argument( "Malformed summary file: missing PARAMS keyword entry"); - const rd_data_type params_data_type = rd_kw_get_data_type(params_kw); + const rd_data_type params_data_type = params_kw->data_type(); if (!rd_type_is_float(params_data_type)) throw std::invalid_argument( "Malformed summary file: PARAMS keyword is not float"); diff --git a/lib/resdata/rsthead_pybind.cpp b/lib/resdata/rsthead_pybind.cpp index d48c3ba07..5e4c87aae 100644 --- a/lib/resdata/rsthead_pybind.cpp +++ b/lib/resdata/rsthead_pybind.cpp @@ -33,9 +33,9 @@ PYBIND11_MODULE(_rsthead, m) { 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))); + 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)) diff --git a/lib/resdata/tests/rd_coarse_test.cpp b/lib/resdata/tests/rd_coarse_test.cpp index cd06f9ad5..7bd5d6019 100644 --- a/lib/resdata/tests/rd_coarse_test.cpp +++ b/lib/resdata/tests/rd_coarse_test.cpp @@ -44,12 +44,12 @@ int main(int argc, char **argv) { } { - const rd_kw_type *swat0 = RST_file->get_kw("SWAT", 0); - const rd_kw_type *porv = INIT_file->get_kw("PORV", 0); + const rd::KW *swat0 = RST_file->get_kw("SWAT", 0); + const rd::KW *porv = INIT_file->get_kw("PORV", 0); - test_assert_int_equal(rd_kw_get_size(swat0), + test_assert_int_equal(rd::kw_get_size(swat0), rd_grid_get_active_size(GRID.get())); - test_assert_int_equal(rd_kw_get_size(porv), + test_assert_int_equal(rd::kw_get_size(porv), rd_grid_get_global_size(GRID.get())); } diff --git a/lib/resdata/tests/rd_dualp.cpp b/lib/resdata/tests/rd_dualp.cpp index a786ea6d3..25793927b 100644 --- a/lib/resdata/tests/rd_dualp.cpp +++ b/lib/resdata/tests/rd_dualp.cpp @@ -25,16 +25,16 @@ int main(int argc, char **argv) { std::unique_ptr GRID_file = rd::File::open(grid_file); { - rd_kw_type *actnum = GRID_file->get_kw("ACTNUM", 0); - rd_kw_type *swat = RST_file->get_kw("SWAT", 0); - rd_kw_type *permx = INIT_file->get_kw("PERMX", 0); + rd::KW *actnum = GRID_file->get_kw("ACTNUM", 0); + rd::KW *swat = RST_file->get_kw("SWAT", 0); + rd::KW *permx = INIT_file->get_kw("PERMX", 0); int fracture_size = rd_grid_get_nactive_fracture(rd_grid.get()); int matrix_size = rd_grid_get_nactive(rd_grid.get()); test_assert_int_equal(fracture_size + matrix_size, - rd_kw_get_size(swat)); + rd::kw_get_size(swat)); test_assert_int_equal(fracture_size + matrix_size, - rd_kw_get_size(permx)); + rd::kw_get_size(permx)); { int gi; @@ -42,7 +42,7 @@ int main(int argc, char **argv) { int fracture_index = 0; for (gi = 0; gi < rd_grid_get_global_size(rd_grid.get()); gi++) { - if (rd_kw_iget_int(actnum, gi) & CELL_ACTIVE_MATRIX) { + if (actnum->at(gi) & CELL_ACTIVE_MATRIX) { test_assert_int_equal( rd_grid_get_active_index1(rd_grid.get(), gi), matrix_index); @@ -52,7 +52,7 @@ int main(int argc, char **argv) { matrix_index++; } - if (rd_kw_iget_int(actnum, gi) & CELL_ACTIVE_FRACTURE) { + if (actnum->at(gi) & CELL_ACTIVE_FRACTURE) { test_assert_int_equal( rd_grid_get_active_fracture_index1(rd_grid.get(), gi), fracture_index); diff --git a/lib/resdata/tests/rd_fault_block_layer.cpp b/lib/resdata/tests/rd_fault_block_layer.cpp index 434782de0..934a364d6 100644 --- a/lib/resdata/tests/rd_fault_block_layer.cpp +++ b/lib/resdata/tests/rd_fault_block_layer.cpp @@ -1,7 +1,9 @@ #include -#include #include +#include +#include + #include #include @@ -11,15 +13,14 @@ #include #include -void test_create(rd_grid_type *grid, rd_kw_type *fault_block_kw) { +void test_create(rd_grid_type *grid, rd::KW *fault_block_kw) { int k = 0; int i, j; for (j = 0; j < rd_grid_get_ny(grid); j++) { for (i = 0; i < rd_grid_get_nx(grid); i++) { - - int g = rd_grid_get_global_index3(grid, i, j, k); - rd_kw_iset_int(fault_block_kw, g, 9); + size_t g = rd_grid_get_global_index3(grid, i, j, k); + fault_block_kw->at(g) = 9; } } @@ -40,12 +41,9 @@ void test_create(rd_grid_type *grid, rd_kw_type *fault_block_kw) { } void test_create_invalid(rd_grid_type *grid) { - rd_kw_type *fault_blk_kw = - rd_kw_alloc("FAULTBLK", rd_grid_get_global_size(grid) - 1, RD_INT); + rd::KW fault_blk_kw{"FAULTBLK", rd_grid_get_global_size(grid) - 1, RD_INT}; test_assert_NULL(fault_block_layer_alloc(grid, 7)); - - rd_kw_free(fault_blk_kw); } void test_trace_edge(rd_grid_type *grid) { @@ -76,12 +74,9 @@ void test_trace_edge(rd_grid_type *grid) { void test_export(rd_grid_type *grid) { fault_block_layer_type *layer = fault_block_layer_alloc(grid, 0); - rd_kw_type *rd_kw1 = - rd_kw_alloc("FAULTBLK", rd_grid_get_global_size(grid), RD_INT); - rd_kw_type *rd_kw2 = - rd_kw_alloc("FAULTBLK", rd_grid_get_global_size(grid) + 1, RD_INT); - rd_kw_type *rd_kw3 = - rd_kw_alloc("FAULTBLK", rd_grid_get_global_size(grid), RD_FLOAT); + rd::KW rd_kw1{"FAULTBLK", rd_grid_get_global_size(grid), RD_INT}; + rd::KW rd_kw2{"FAULTBLK", rd_grid_get_global_size(grid) + 1, RD_INT}; + rd::KW rd_kw3{"FAULTBLK", rd_grid_get_global_size(grid), RD_FLOAT}; auto block = fault_block_layer_add_block(layer, 10); block->add_cell(0, 0); @@ -89,39 +84,37 @@ void test_export(rd_grid_type *grid) { block->add_cell(1, 1); block->add_cell(0, 1); - test_assert_true(fault_block_layer_export(layer, rd_kw1)); - test_assert_false(fault_block_layer_export(layer, rd_kw2)); - test_assert_false(fault_block_layer_export(layer, rd_kw3)); + test_assert_true(fault_block_layer_export(layer, &rd_kw1)); + test_assert_false(fault_block_layer_export(layer, &rd_kw2)); + test_assert_false(fault_block_layer_export(layer, &rd_kw3)); { int nx = rd_grid_get_nx(grid); - test_assert_int_equal(rd_kw_iget_int(rd_kw1, 0), 10); - test_assert_int_equal(rd_kw_iget_int(rd_kw1, 1), 10); - test_assert_int_equal(rd_kw_iget_int(rd_kw1, nx), 10); - test_assert_int_equal(rd_kw_iget_int(rd_kw1, nx + 1), 10); + test_assert_int_equal(rd_kw1.at(0), 10); + test_assert_int_equal(rd_kw1.at(1), 10); + test_assert_int_equal(rd_kw1.at(nx), 10); + test_assert_int_equal(rd_kw1.at(nx + 1), 10); } - test_assert_int_equal(40, rd_kw_element_sum_int(rd_kw1)); + auto &kw_data = rd_kw1.get_vector(); + test_assert_int_equal(40, + std::accumulate(kw_data.begin(), kw_data.end(), 0)); fault_block_layer_free(layer); - rd_kw_free(rd_kw1); - rd_kw_free(rd_kw2); - rd_kw_free(rd_kw3); } void test_neighbours(rd_grid_type *grid) { const int k = 0; fault_block_layer_type *layer = fault_block_layer_alloc(grid, k); geo_polygon_collection_type *polylines = geo_polygon_collection_alloc(); - rd_kw_type *rd_kw = - rd_kw_alloc("FAULTBLK", rd_grid_get_global_size(grid), RD_INT); - - rd_kw_iset_int(rd_kw, 0, 1); - rd_kw_iset_int(rd_kw, rd_grid_get_global_index3(grid, 3, 3, k), 2); - rd_kw_iset_int(rd_kw, rd_grid_get_global_index3(grid, 4, 3, k), 3); - rd_kw_iset_int(rd_kw, rd_grid_get_global_index3(grid, 5, 3, k), 4); - rd_kw_iset_int(rd_kw, rd_grid_get_global_index3(grid, 4, 2, k), 5); - fault_block_layer_load_kw(layer, rd_kw); + std::vector rd_kw_data(rd_grid_get_global_size(grid), 0); + rd_kw_data[0] = 1; + rd_kw_data[rd_grid_get_global_index3(grid, 3, 3, k)] = 2; + rd_kw_data[rd_grid_get_global_index3(grid, 4, 3, k)] = 3; + rd_kw_data[rd_grid_get_global_index3(grid, 5, 3, k)] = 4; + rd_kw_data[rd_grid_get_global_index3(grid, 4, 2, k)] = 5; + rd::KW rd_kw{"FAULTBLK", std::move(rd_kw_data)}; + fault_block_layer_load_kw(layer, &rd_kw); { { @@ -142,20 +135,17 @@ void test_neighbours(rd_grid_type *grid) { geo_polygon_collection_free(polylines); fault_block_layer_free(layer); - rd_kw_free(rd_kw); } int main(int argc, char **argv) { rd_grid_ptr rd_grid = make_rectangular_grid(9, 9, 2, 1, 1, 1, NULL); - rd_kw_type *fault_blk_kw = - rd_kw_alloc("FAULTBLK", rd_grid_get_global_size(rd_grid.get()), RD_INT); + rd::KW fault_blk_kw{"FAULTBLK", rd_grid_get_global_size(rd_grid.get()), + RD_INT}; - test_create(rd_grid.get(), fault_blk_kw); + test_create(rd_grid.get(), &fault_blk_kw); test_create_invalid(rd_grid.get()); test_trace_edge(rd_grid.get()); test_export(rd_grid.get()); test_neighbours(rd_grid.get()); - - rd_kw_free(fault_blk_kw); exit(0); } diff --git a/lib/resdata/tests/rd_file_equinor.cpp b/lib/resdata/tests/rd_file_equinor.cpp index 8799b3330..800c858b7 100644 --- a/lib/resdata/tests/rd_file_equinor.cpp +++ b/lib/resdata/tests/rd_file_equinor.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -18,17 +19,16 @@ void test_writable(const char *src_file) { ta.copy_file(src_file); { auto rd_file = rd::File::open(fname, FileMode::WRITABLE); - rd_kw_type *swat = rd_file->get_kw("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::KW *swat = rd_file->get_kw("SWAT", 0); + rd::KW swat0{*swat}; + test_assert_true(*swat == swat0); + swat->at(0) = 1000.0; rd_file->save_kw(swat); test_assert_true(rd_file->is_writable()); auto rd_file2 = rd::File::open(fname); swat = rd_file2->get_kw("SWAT", 0); - test_assert_true( - util_double_approx_equal(rd_kw_iget_float(swat, 0), 1000)); + test_assert_true(util_double_approx_equal(swat->at(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 f355b492f..87c76fe84 100644 --- a/lib/resdata/tests/rd_grid_dx_dy_dz.cpp +++ b/lib/resdata/tests/rd_grid_dx_dy_dz.cpp @@ -33,9 +33,9 @@ void test_dxdydz(const std::string &grid_fname, const std::string &init_fname) { << std::endl; exit(-1); } - rd_kw_type *dx = init_file->get_kw("DX", 0); - rd_kw_type *dy = init_file->get_kw("DY", 0); - rd_kw_type *dz = init_file->get_kw("DZ", 0); + rd::KW *dx = init_file->get_kw("DX", 0); + rd::KW *dy = init_file->get_kw("DY", 0); + rd::KW *dz = init_file->get_kw("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); @@ -43,9 +43,9 @@ void test_dxdydz(const std::string &grid_fname, const std::string &init_fname) { double dyg = rd_grid_get_cell_dy1(grid.get(), g); double dzg = rd_grid_get_cell_dz1(grid.get(), g); - double dxi = rd_kw_iget_float(dx, a); - double dyi = rd_kw_iget_float(dy, a); - double dzi = rd_kw_iget_float(dz, a); + double dxi = dx->at(a); + double dyi = dy->at(a); + double dzi = dz->at(a); double err_x = fabs(err(dxg, dxi)); double err_y = fabs(err(dyg, dyi)); diff --git a/lib/resdata/tests/rd_grid_export.cpp b/lib/resdata/tests/rd_grid_export.cpp index b2449d4ef..7558ca860 100644 --- a/lib/resdata/tests/rd_grid_export.cpp +++ b/lib/resdata/tests/rd_grid_export.cpp @@ -10,20 +10,19 @@ #include void export_actnum(const rd_grid_type *rd_grid, rd::File *rd_file) { - rd_kw_type *actnum_kw = rd_file->get_kw("ACTNUM", 0); - int *actnum = - (int *)util_malloc(rd_kw_get_size(actnum_kw) * sizeof *actnum); + rd::KW *actnum_kw = rd_file->get_kw("ACTNUM", 0); + int *actnum = (int *)util_malloc(actnum_kw->size() * sizeof *actnum); rd_grid_init_actnum_data(rd_grid, actnum); - for (int i = 0; i < rd_kw_get_size(actnum_kw); i++) - test_assert_int_equal(actnum[i], rd_kw_iget_int(actnum_kw, i)); + for (size_t i = 0; i < actnum_kw->size(); i++) + test_assert_int_equal(actnum[i], actnum_kw->at(i)); free(actnum); } void export_coord(const rd_grid_type *grid, rd::File *rd_file) { - rd_kw_type *coord_kw = rd_file->get_kw("COORD", 0); - test_assert_int_equal(rd_kw_get_size(coord_kw), + rd::KW *coord_kw = rd_file->get_kw("COORD", 0); + test_assert_int_equal(rd::kw_get_size(coord_kw), rd_grid_get_coord_size(grid)); { float *coord_float = (float *)util_malloc(rd_grid_get_coord_size(grid) * @@ -43,8 +42,8 @@ void export_coord(const rd_grid_type *grid, rd::File *rd_file) { } void export_zcorn(const rd_grid_type *grid, rd::File *rd_file) { - rd_kw_type *zcorn_kw = rd_file->get_kw("ZCORN", 0); - test_assert_int_equal(rd_kw_get_size(zcorn_kw), + rd::KW *zcorn_kw = rd_file->get_kw("ZCORN", 0); + test_assert_int_equal(rd::kw_get_size(zcorn_kw), rd_grid_get_zcorn_size(grid)); { float *zcorn_float = (float *)util_malloc(rd_grid_get_zcorn_size(grid) * @@ -55,10 +54,10 @@ void export_zcorn(const rd_grid_type *grid, rd::File *rd_file) { rd_grid_init_zcorn_data(grid, zcorn_float); rd_grid_init_zcorn_data_double(grid, zcorn_double); - for (int i = 0; i < rd_grid_get_zcorn_size(grid); i++) { + for (size_t i = 0; + i < static_cast(rd_grid_get_zcorn_size(grid)); i++) { test_assert_double_equal(zcorn_double[i], zcorn_float[i]); - test_assert_float_equal(zcorn_float[i], - rd_kw_iget_float(zcorn_kw, i)); + test_assert_float_equal(zcorn_float[i], zcorn_kw->at(i)); } free(zcorn_float); @@ -68,15 +67,12 @@ void export_zcorn(const rd_grid_type *grid, rd::File *rd_file) { void export_mapaxes(const rd_grid_type *grid, rd::File *rd_file) { if (rd_file->has_kw("MAPAXES")) { - rd_kw_type *mapaxes_kw = rd_file->get_kw("MAPAXES", 0); + rd::KW *mapaxes_kw = rd_file->get_kw("MAPAXES", 0); double mapaxes[6]; - int i; - test_assert_true(rd_grid_use_mapaxes(grid)); rd_grid_init_mapaxes_data_double(grid, mapaxes); - for (i = 0; i < 6; i++) - test_assert_double_equal(rd_kw_iget_float(mapaxes_kw, i), - mapaxes[i]); + for (size_t i = 0; i < 6; i++) + test_assert_double_equal(mapaxes_kw->at(i), mapaxes[i]); } } diff --git a/lib/resdata/tests/rd_grid_init_fwrite.cpp b/lib/resdata/tests/rd_grid_init_fwrite.cpp index 33393f6b1..dc8dc0b79 100644 --- a/lib/resdata/tests/rd_grid_init_fwrite.cpp +++ b/lib/resdata/tests/rd_grid_init_fwrite.cpp @@ -16,16 +16,14 @@ static void rd_grid_fwrite_depth(rd_grid_type *grid, ERT::FortIO &init_file, UnitSystem output_unit) { - rd_kw_type *depth_kw = - rd_kw_alloc("DEPTH", rd_grid_get_nactive(grid), RD_FLOAT); + rd::KW depth_kw{"DEPTH", rd_grid_get_nactive(grid), RD_FLOAT}; { - float *depth_ptr = (float *)rd_kw_get_ptr(depth_kw); + std::vector &depth_ptr = depth_kw.get_vector(); for (int i = 0; i < rd_grid_get_nactive(grid); i++) depth_ptr[i] = rd_grid_get_cdepth1A(grid, i); } - rd_kw_scale_float(depth_kw, rd_grid_output_scaling(grid, output_unit)); - rd_kw_fwrite(depth_kw, init_file); - rd_kw_free(depth_kw); + depth_kw.scale(rd_grid_output_scaling(grid, output_unit)); + depth_kw.fwrite(init_file); } void test_write_depth(rd_grid_type *grid) { @@ -36,11 +34,12 @@ void test_write_depth(rd_grid_type *grid) { } { auto init_file = rd::File::open("INIT"); - rd_kw_type *depth = init_file->get_kw("DEPTH", 0); + rd::KW *depth = init_file->get_kw("DEPTH", 0); - test_assert_int_equal(rd_kw_get_size(depth), rd_grid_get_nactive(grid)); + 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), + test_assert_double_equal(depth->as_double(i), rd_grid_get_cdepth1A(grid, i)); } } @@ -48,14 +47,14 @@ void test_write_depth(rd_grid_type *grid) { static void rd_grid_fwrite_dims(const rd_grid_type *grid, ERT::FortIO &init_file, UnitSystem output_unit) { - rd_kw_type *dx = rd_kw_alloc("DX", rd_grid_get_nactive(grid), RD_FLOAT); - rd_kw_type *dy = rd_kw_alloc("DY", rd_grid_get_nactive(grid), RD_FLOAT); - rd_kw_type *dz = rd_kw_alloc("DZ", rd_grid_get_nactive(grid), RD_FLOAT); + rd::KW dx{"DX", rd_grid_get_nactive(grid), RD_FLOAT}; + rd::KW dy{"DY", rd_grid_get_nactive(grid), RD_FLOAT}; + rd::KW dz{"DZ", rd_grid_get_nactive(grid), RD_FLOAT}; { { - float *dx_ptr = (float *)rd_kw_get_ptr(dx); - float *dy_ptr = (float *)rd_kw_get_ptr(dy); - float *dz_ptr = (float *)rd_kw_get_ptr(dz); + std::vector &dx_ptr = dx.get_vector(); + std::vector &dy_ptr = dy.get_vector(); + std::vector &dz_ptr = dz.get_vector(); for (int i = 0; i < rd_grid_get_nactive(grid); i++) { dx_ptr[i] = rd_grid_get_cell_dx1A(grid, i); @@ -66,17 +65,14 @@ static void rd_grid_fwrite_dims(const rd_grid_type *grid, { float scale_factor = rd_grid_output_scaling(grid, output_unit); - rd_kw_scale_float(dx, scale_factor); - rd_kw_scale_float(dy, scale_factor); - rd_kw_scale_float(dz, scale_factor); + dx.scale(scale_factor); + dy.scale(scale_factor); + dz.scale(scale_factor); } } - rd_kw_fwrite(dx, init_file); - rd_kw_fwrite(dy, init_file); - rd_kw_fwrite(dz, init_file); - rd_kw_free(dx); - rd_kw_free(dy); - rd_kw_free(dz); + dx.fwrite(init_file); + dy.fwrite(init_file); + dz.fwrite(init_file); } void test_write_dims(const rd_grid_type *grid) { @@ -87,19 +83,19 @@ void test_write_dims(const rd_grid_type *grid) { } { auto init_file = rd::File::open("INIT"); - rd_kw_type *DX = init_file->get_kw("DX", 0); - rd_kw_type *DY = init_file->get_kw("DY", 0); - rd_kw_type *DZ = init_file->get_kw("DZ", 0); + rd::KW *DX = init_file->get_kw("DX", 0); + rd::KW *DY = init_file->get_kw("DY", 0); + rd::KW *DZ = init_file->get_kw("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)); - test_assert_int_equal(rd_kw_get_size(DZ), rd_grid_get_nactive(grid)); + 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)); + test_assert_int_equal(rd::kw_get_size(DZ), 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(DX, i), + test_assert_double_equal(DX->as_double(i), rd_grid_get_cell_dx1A(grid, i)); - test_assert_double_equal(rd_kw_iget_as_double(DY, i), + test_assert_double_equal(DY->as_double(i), rd_grid_get_cell_dy1A(grid, i)); - test_assert_double_equal(rd_kw_iget_as_double(DZ, i), + test_assert_double_equal(DZ->as_double(i), rd_grid_get_cell_dz1A(grid, i)); } } diff --git a/lib/resdata/tests/rd_grid_volume.cpp b/lib/resdata/tests/rd_grid_volume.cpp index c95b001d8..65479b2f5 100644 --- a/lib/resdata/tests/rd_grid_volume.cpp +++ b/lib/resdata/tests/rd_grid_volume.cpp @@ -21,10 +21,10 @@ int main(int argc, char **argv) { std::unique_ptr init = rd::File::open(init_file); rd_grid_ptr grid = read_grid(grid_file); - const rd_kw_type *poro_kw = init->get_kw("PORO", 0); - const rd_kw_type *porv_kw = init->get_kw("PORV", 0); - rd_kw_type *multpv = NULL; - rd_kw_type *NTG = NULL; + const rd::KW *poro_kw = init->get_kw("PORO", 0); + const rd::KW *porv_kw = init->get_kw("PORV", 0); + rd::KW *multpv = NULL; + rd::KW *NTG = NULL; bool error_found = false; double total_volume = 0; @@ -41,14 +41,14 @@ int main(int argc, char **argv) { ++iactive) { int iglobal = rd_grid_get_global_index1A(grid.get(), iactive); double grid_volume = rd_grid_get_cell_volume1(grid.get(), iglobal); - double eclipse_volume = rd_kw_iget_float(porv_kw, iglobal) / - rd_kw_iget_float(poro_kw, iactive); + double eclipse_volume = + porv_kw->at(iglobal) / poro_kw->at(iactive); if (NTG) - eclipse_volume /= rd_kw_iget_float(NTG, iactive); + eclipse_volume /= NTG->at(iactive); if (multpv) - eclipse_volume *= rd_kw_iget_float(multpv, iactive); + eclipse_volume *= multpv->at(iactive); total_volume += grid_volume; total_diff += fabs(eclipse_volume - grid_volume); diff --git a/lib/resdata/tests/rd_kw_cmp_string.cpp b/lib/resdata/tests/rd_kw_cmp_string.cpp deleted file mode 100644 index 1444fcb85..000000000 --- a/lib/resdata/tests/rd_kw_cmp_string.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -#include -#include -#include - -void test_cmp_string() { - rd_kw_type *rd_kw = rd_kw_alloc("HEADER", 1, RD_CHAR); - - rd_kw_iset_string8(rd_kw, 0, "ABCD"); - - test_assert_int_equal(0, strcmp(rd_kw_iget_char_ptr(rd_kw, 0), "ABCD ")); - test_assert_true(rd_kw_icmp_string(rd_kw, 0, "ABCD")); - test_assert_true(rd_kw_icmp_string(rd_kw, 0, "ABCD ")); - test_assert_true(rd_kw_icmp_string(rd_kw, 0, "ABCD ")); - - test_assert_false(rd_kw_icmp_string(rd_kw, 0, "Different")); - test_assert_false(rd_kw_icmp_string(rd_kw, 0, "")); - test_assert_false(rd_kw_icmp_string(rd_kw, 0, "")); - - rd_kw_free(rd_kw); -} - -int main(int argc, char **argv) { - test_cmp_string(); - - exit(0); -} diff --git a/lib/resdata/tests/rd_kw_equal.cpp b/lib/resdata/tests/rd_kw_equal.cpp deleted file mode 100644 index 750bf4131..000000000 --- a/lib/resdata/tests/rd_kw_equal.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include - -#include -#include -#include -#include - -int main(int argc, char **argv) { - rd_kw_type *rd_kw1 = rd_kw_alloc("KW", 10, RD_INT); - int data[10]; - int i; - for (i = 0; i < 10; i++) { - rd_kw_iset_int(rd_kw1, i, i); - data[i] = i; - } - - { - rd_kw_type *rd_kw2 = rd_kw_alloc_copy(rd_kw1); - - test_assert_true(rd_kw_equal(rd_kw1, rd_kw2)); - - rd_kw_iset_int(rd_kw2, 1, 77); - test_assert_false(rd_kw_equal(rd_kw1, rd_kw2)); - rd_kw_iset_int(rd_kw2, 1, 1); - test_assert_true(rd_kw_equal(rd_kw1, rd_kw2)); - - rd_kw_set_header_name(rd_kw2, "TEST"); - test_assert_false(rd_kw_equal(rd_kw1, rd_kw2)); - test_assert_true(rd_kw_content_equal(rd_kw1, rd_kw2)); - rd_kw_free(rd_kw2); - } - - { - rd_kw_type *rd_ikw = rd_kw_alloc_new_shared("KW", 10, RD_INT, data); - rd_kw_type *rd_fkw = rd_kw_alloc_new_shared("KW", 10, RD_FLOAT, data); - - test_assert_true(rd_kw_content_equal(rd_kw1, rd_ikw)); - test_assert_false(rd_kw_content_equal(rd_kw1, rd_fkw)); - - rd_kw_free(rd_ikw); - rd_kw_free(rd_fkw); - } - - test_assert_true(rd_kw_data_equal(rd_kw1, data)); - data[0] = 99; - test_assert_false(rd_kw_data_equal(rd_kw1, data)); - rd_kw_free(rd_kw1); -} diff --git a/lib/resdata/tests/rd_kw_fread.cpp b/lib/resdata/tests/rd_kw_fread.cpp index 5db514023..7439bb639 100644 --- a/lib/resdata/tests/rd_kw_fread.cpp +++ b/lib/resdata/tests/rd_kw_fread.cpp @@ -1,6 +1,8 @@ #include #include +#include +#include #include #include @@ -12,46 +14,22 @@ #include #include -void test_truncated(const char *filename, offset_type truncate_size) { - { - FILE *stream = util_fopen(filename, "r+"); - util_ftruncate(stream, truncate_size); - fclose(stream); - } - { - ERT::FortIO fortio(filename, std::ios_base::in, false, true); - rd_kw_type *kw2 = rd_kw_fread_alloc(fortio); - test_assert_NULL(kw2); - } -} - void test_fread_alloc() { rd::util::TestArea ta("fread_alloc"); { - rd_kw_type *kw1 = rd_kw_alloc("INT", 100, RD_INT); - int i; - for (i = 0; i < 100; i++) - rd_kw_iset_int(kw1, i, i); + std::vector data(100); + for (size_t i = 0; i < 100; i++) + data[i] = i; + rd::KW kw1{"INT", std::move(data)}; { ERT::FortIO fortio("INT", std::ios_base::out, false, true); - rd_kw_fwrite(kw1, fortio); + kw1.fwrite(fortio); } { ERT::FortIO fortio("INT", std::ios_base::in, false, true); - rd_kw_type *kw2 = rd_kw_fread_alloc(fortio); - test_assert_true(rd_kw_is_instance(kw2)); - test_assert_true(rd_kw_equal(kw1, kw2)); - rd_kw_free(kw2); + auto kw2 = rd::KW::fread(fortio); + test_assert_true(kw1 == *kw2.get()); } - - { - offset_type file_size = util_file_size("INT"); - test_truncated("INT", file_size - 4); - test_truncated("INT", file_size - 25); - test_truncated("INT", 5); - test_truncated("INT", 0); - } - rd_kw_free(kw1); } } @@ -60,25 +38,21 @@ void test_kw_io_charlength() { { const char *KW0 = "QWERTYUI"; const char *KW1 = "ABCDEFGHIJTTTTTTTTTTTTTTTTTTTTTTABCDEFGHIJKLMNOP"; - rd_kw_type *rd_kw_out0 = rd_kw_alloc(KW0, 5, RD_FLOAT); - rd_kw_type *rd_kw_out1 = rd_kw_alloc(KW1, 5, RD_FLOAT); - for (int i = 0; i < rd_kw_get_size(rd_kw_out1); i++) { - rd_kw_iset_float(rd_kw_out0, i, i * 1.5); - rd_kw_iset_float(rd_kw_out1, i, i * 1.5); - } + std::vector data(5); + for (size_t i = 0; i < 5; i++) + data[i] = i * 1.5f; + rd::KW rd_kw_out0{KW0, data}; + rd::KW rd_kw_out1{KW1, std::move(data)}; { ERT::FortIO f("TEST1", std::ios_base::out); - test_assert_true(rd_kw_fwrite(rd_kw_out0, f)); - test_assert_false(rd_kw_fwrite(rd_kw_out1, f)); + test_assert_true(rd_kw_out0.fwrite(f)); + test_assert_false(rd_kw_out1.fwrite(f)); } { test_assert_false(util_file_exists("TEST1")); } - - rd_kw_free(rd_kw_out0); - rd_kw_free(rd_kw_out1); } } diff --git a/lib/resdata/tests/rd_kw_init.cpp b/lib/resdata/tests/rd_kw_init.cpp index aaa7c7dac..a670c0d98 100644 --- a/lib/resdata/tests/rd_kw_init.cpp +++ b/lib/resdata/tests/rd_kw_init.cpp @@ -5,53 +5,47 @@ #include #include +#include void test_int() { int N = 1000; int i; - rd_kw_type *kw = rd_kw_alloc("KW", N, RD_INT); + rd::KW kw{"KW", N, RD_INT}; for (i = 0; i < N; i++) - test_assert_int_equal(0, rd_kw_iget_int(kw, i)); - - rd_kw_free(kw); + test_assert_int_equal(0, kw.at(i)); } void test_double() { int N = 1000; double i; - rd_kw_type *kw = rd_kw_alloc("KW", N, RD_DOUBLE); + rd::KW kw{"KW", N, RD_DOUBLE}; for (i = 0; i < N; i++) - test_assert_double_equal(0, rd_kw_iget_double(kw, i)); - - rd_kw_free(kw); + test_assert_double_equal(0, kw.at(i)); } void test_float() { int N = 1000; int i; - rd_kw_type *kw = rd_kw_alloc("KW", N, RD_FLOAT); + rd::KW kw{"KW", N, RD_FLOAT}; for (i = 0; i < N; i++) - test_assert_int_equal(0, rd_kw_iget_float(kw, i)); - - rd_kw_free(kw); + test_assert_int_equal(0, kw.at(i)); } void test_bool() { - int N = 100; + size_t N = 100; bool *data = (bool *)util_malloc(N * sizeof *data); - rd_kw_type *kw = rd_kw_alloc("BOOL", N, RD_BOOL); - for (int i = 0; i < N / 2; i++) { - rd_kw_iset_bool(kw, 2 * i, true); - rd_kw_iset_bool(kw, 2 * i + 1, false); + rd::KW kw{"BOOL", N, RD_BOOL}; + for (size_t i = 0; i < N / 2; i++) { + kw.at(2 * i) = true; + kw.at(2 * i + 1) = false; data[2 * i] = true; data[2 * i + 1] = false; } - const bool *internal_data = rd_kw_get_bool_ptr(kw); + const char *internal_data = kw.get_vector().data(); test_assert_int_equal(memcmp(internal_data, data, N * sizeof *data), 0); - rd_kw_free(kw); free(data); } diff --git a/lib/resdata/tests/rd_kw_space_pad.cpp b/lib/resdata/tests/rd_kw_space_pad.cpp index b93ac3e8e..cfd676f65 100644 --- a/lib/resdata/tests/rd_kw_space_pad.cpp +++ b/lib/resdata/tests/rd_kw_space_pad.cpp @@ -16,10 +16,9 @@ int main(int argc, char **argv) { // 1. Write a rd_kw instance with string data - uninitialized. { - rd_kw_type *rd_kw = rd_kw_alloc("SPACE", 1, RD_CHAR); + rd::KW rd_kw{"SPACE", 1, RD_CHAR}; ERT::FortIO f("file", std::ios_base::out, false, true); - rd_kw_fwrite(rd_kw, f); - rd_kw_free(rd_kw); + rd_kw.fwrite(f); } // 2. Open file with normal fopen() and verify that the data section consists of only spaces. diff --git a/lib/resdata/tests/rd_nnc_test.cpp b/lib/resdata/tests/rd_nnc_test.cpp index ceb04cdc1..28cd09f46 100644 --- a/lib/resdata/tests/rd_nnc_test.cpp +++ b/lib/resdata/tests/rd_nnc_test.cpp @@ -43,12 +43,11 @@ void test_scan(const char *grid_filename) { /* Internal nnc */ { 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; - const int g2 = rd_kw_iget_int(nnc2_kw, i) - 1; + rd::KW *nnc1_kw = nnc_view->get_kw(NNC1_KW, 0); + rd::KW *nnc2_kw = nnc_view->get_kw(NNC2_KW, 0); + for (size_t i = 0; i < nnc1_kw->size(); i++) { + const int g1 = nnc1_kw->at(i) - 1; + const int g2 = nnc2_kw->at(i) - 1; if (g2 < rd_grid_get_global_size( @@ -69,14 +68,13 @@ void test_scan(const char *grid_filename) { /* Global -> lgr */ { 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++) { - const int g = rd_kw_iget_int(nncg_kw, i) - 1; - const int l = rd_kw_iget_int(nncl_kw, i) - 1; + rd::KW *nnchead_kw = nnc_view->get_kw(NNCHEAD_KW, 0); + rd::KW *nncg_kw = nnc_view->get_kw(NNCG_KW, 0); + rd::KW *nncl_kw = nnc_view->get_kw(NNCL_KW, 0); + int lgr_nr = nnchead_kw->at(NNCHEAD_LGR_INDEX); + for (size_t i = 0; i < nncg_kw->size(); i++) { + const int g = nncg_kw->at(i) - 1; + const int l = nncl_kw->at(i) - 1; const nnc_info_type *nnc_info = rd_grid_get_cell_nnc_info1(rd_grid, g); @@ -96,17 +94,17 @@ void test_scan(const char *grid_filename) { /* Amalgamated: LGR -> LGR */ { 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); + rd::KW *nncheada_kw = nnc_view->get_kw(NNCHEADA_KW, 0); + rd::KW *nnc1_kw = nnc_view->get_kw(NNA1_KW, 0); + rd::KW *nnc2_kw = nnc_view->get_kw(NNA2_KW, 0); + int lgr_nr1 = nncheada_kw->at(NNCHEADA_ILOC1_INDEX); + int lgr_nr2 = nncheada_kw->at(NNCHEADA_ILOC2_INDEX); rd_grid_type *lgr1 = rd_grid_get_lgr_from_lgr_nr(rd_grid, lgr_nr1); - for (int i = 0; i < rd_kw_get_size(nnc1_kw); i++) { - const int g1 = rd_kw_iget_int(nnc1_kw, i) - 1; - const int g2 = rd_kw_iget_int(nnc2_kw, i) - 1; + for (size_t i = 0; i < nnc1_kw->size(); i++) { + const int g1 = nnc1_kw->at(i) - 1; + const int g2 = nnc2_kw->at(i) - 1; const nnc_info_type *nnc_info = rd_grid_get_cell_nnc_info1(lgr1, g1); diff --git a/lib/resdata/tests/rdxx_kw.cpp b/lib/resdata/tests/rdxx_kw.cpp deleted file mode 100644 index 641c8f099..000000000 --- a/lib/resdata/tests/rdxx_kw.cpp +++ /dev/null @@ -1,232 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -void test_kw_name() { - ERT::ResdataKW kw1("short", 1); - ERT::ResdataKW kw2("verylong", 1); - - test_assert_string_equal(kw1.name(), "short"); - test_assert_string_equal(kw2.name(), "verylong"); -} - -void test_kw_vector_assign() { - std::vector vec = {1, 2, 3, 4, 5}; - ERT::ResdataKW kw("XYZ", vec); - - test_assert_size_t_equal(kw.size(), vec.size()); - - for (size_t i = 0; i < kw.size(); ++i) { - test_assert_int_equal(kw.at(i), vec[i]); - test_assert_int_equal(kw[i], vec[i]); - } - - for (size_t i = 0; i < kw.size(); ++i) { - kw[i] *= 2; - test_assert_int_equal(kw[i], 2 * vec[i]); - } -} - -void test_kw_vector_string() { - std::vector vec = {"short", "sweet", "padded "}; - - std::vector too_long = {"1234567890"}; - ERT::ResdataKW kw("XYZ", vec); - - test_assert_size_t_equal(kw.size(), vec.size()); - - test_assert_string_equal(kw.at(0), "short "); - test_assert_string_equal(kw.at(1), "sweet "); - test_assert_string_equal(kw.at(2), vec.at(2)); - - test_assert_throw(ERT::ResdataKW("XY", too_long), - std::range_error); -} - -void test_kw_vector_std_string() { - std::vector vec = { - "short", - "sweet", - "padded ", - }; - std::vector too_long = {"1234567890"}; - ERT::ResdataKW kw("XYZ", vec); - - test_assert_size_t_equal(kw.size(), vec.size()); - - test_assert_string_equal(kw.at(0).c_str(), "short "); - test_assert_string_equal(kw.at(1).c_str(), "sweet "); - test_assert_string_equal(kw.at(2).c_str(), vec.at(2)); - - test_assert_throw(ERT::ResdataKW("XY", too_long), - std::range_error); -} - -void test_logical() { - //std::vector vec = {true,false,true,false}; - // ERT::ResdataKW kw("BOOL", vec); - // test_assert_int_equal(kw.size(), vec.size()); - - // for (size_t i=0; i < vec.size(); i++) - // test_assert_true( kw.at(i) == vec[i] ); -} - -void test_move_semantics_no_crash() { - std::vector vec = {1, 2, 3, 4, 5}; - ERT::ResdataKW kw1("XYZ", vec); - - ERT::ResdataKW kw2(std::move(kw1)); - test_assert_true(kw1.get() == nullptr); -} - -void test_exception_assing_ref_wrong_type() { - auto *ptr = rd_kw_alloc("XYZ", 1, RD_INT); - - try { - ERT::ResdataKW kw(ptr); - test_assert_true(false); - } catch (...) { - ERT::ResdataKW kw(ptr); - } -} - -void test_resize() { - ERT::ResdataKW kw1("short", 1); - - test_assert_int_equal(kw1.size(), 1); - kw1.resize(100); - test_assert_int_equal(kw1.size(), 100); -} - -void test_data() { - std::vector d_data = {1, 2, 3, 4}; - std::vector f_data = {10, 20, 30, 40}; - std::vector i_data = {100, 200, 300, 400}; - std::vector b_data = {true, false}; - std::vector s_data = {"S1", "S2", "S3"}; - - ERT::ResdataKW d_kw("DOUBLE", d_data); - auto d_data2 = d_kw.data(); - for (size_t i = 0; i < d_data.size(); i++) - test_assert_true(d_data[i] == d_data2[i]); - - ERT::ResdataKW f_kw("FLOATx", f_data); - auto f_data2 = f_kw.data(); - for (size_t i = 0; i < f_data.size(); i++) - test_assert_true(f_data[i] == f_data2[i]); - - ERT::ResdataKW i_kw("INT", i_data); - auto i_data2 = i_kw.data(); - for (size_t i = 0; i < i_data.size(); i++) - test_assert_true(i_data[i] == i_data2[i]); - - //ERT::ResdataKW b_kw("bbb", b_data); - //auto b_data2 = b_kw.data(); - //for (size_t i=0; i < b_data.size(); i++) - // test_assert_true(b_data[i] == b_data2[i]); - - ERT::ResdataKW s_kw("sss", s_data); - auto s_data2 = s_kw.data(); - for (size_t i = 0; i < s_data.size(); i++) - test_assert_true(s_data[i] == s_data2[i]); -} - -void test_read_write() { - std::vector d_data = {1, 2, 3, 4}; - std::vector f_data = {10, 20, 30, 40}; - std::vector i_data = {100, 200, 300, 400}; - std::vector b_data = {true, false}; - std::vector s_data = {"S1", "S2", "S3"}; - - { - rd::util::TestArea ta("kw-read-write"); - { - ERT::FortIO f("test_file", std::ios_base::out); - ERT::write_kw(f, "DOUBLE", d_data); - ERT::write_kw(f, "FLOAT", f_data); - ERT::write_kw(f, "INT", i_data); - ERT::write_kw(f, "BOOL", b_data); - ERT::write_kw(f, "STRING", s_data); - } - - { - auto f = rd::File::open(std::string("test_file")); - rd_kw_type *d_kw = f->get_kw("DOUBLE", 0); - rd_kw_type *f_kw = f->get_kw("FLOAT", 0); - rd_kw_type *i_kw = f->get_kw("INT", 0); - rd_kw_type *b_kw = f->get_kw("BOOL", 0); - rd_kw_type *s_kw = f->get_kw("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)); - - for (size_t i = 0; i < f_data.size(); i++) - test_assert_true(f_data[i] == rd_kw_iget_float(f_kw, i)); - - for (size_t i = 0; i < i_data.size(); i++) - test_assert_true(i_data[i] == rd_kw_iget_int(i_kw, i)); - - for (size_t i = 0; i < b_data.size(); i++) - test_assert_true(b_data[i] == rd_kw_iget_bool(b_kw, i)); - - for (size_t i = 0; i < s_data.size(); i++) { - std::string s8 = rd_kw_iget_char_ptr(s_kw, i); - test_assert_int_equal(s8.size(), 8); - s8.erase(s8.find_last_not_of(' ') + 1); - test_assert_true(s_data[i] == s8); - } - } - } -} - -void test_fortio_kw() { - rd::util::TestArea ta("fortio_kw"); - std::vector vec(1000); - - for (size_t i = 0; i < vec.size(); i++) - vec[i] = i; - - ERT::ResdataKW kw("XYZ", vec); - - { - ERT::FortIO fortio("new_file", std::fstream::out); - kw.fwrite(fortio); - fortio.close(); - } - - { - ERT::FortIO fortio("new_file", std::fstream::in); - ERT::ResdataKW kw2 = ERT::ResdataKW::load(fortio); - fortio.close(); - for (size_t i = 0; i < kw.size(); i++) - test_assert_int_equal(kw.at(i), kw2.at(i)); - } -} - -int main(int argc, char **argv) { - test_kw_name(); - test_kw_vector_assign(); - test_kw_vector_string(); - test_kw_vector_std_string(); - test_logical(); - test_move_semantics_no_crash(); - test_exception_assing_ref_wrong_type(); - test_resize(); - test_data(); - test_read_write(); - test_fortio_kw(); -} diff --git a/lib/resdata/tests/test_rd_file.cpp b/lib/resdata/tests/test_rd_file.cpp index 4eb86d8f2..88a429a2c 100644 --- a/lib/resdata/tests/test_rd_file.cpp +++ b/lib/resdata/tests/test_rd_file.cpp @@ -3,6 +3,9 @@ #include #include +#include +#include +#include #include #include @@ -21,24 +24,23 @@ void test_writable(size_t data_size) { rd::util::TestArea ta("file_writable"); const char *data_file_name = "test_file"; - rd_kw_type *kw = rd_kw_alloc("TEST_KW", data_size, RD_INT); + std::vector data(data_size); for (size_t i = 0; i < data_size; ++i) - rd_kw_iset_int(kw, i, ((i * 37) + 11) % data_size); + data[i] = ((i * 37) + 11) % data_size; + rd::KW kw{"TEST_KW", std::move(data)}; { ERT::FortIO fortio(data_file_name, std::ios_base::out, false, true); - rd_kw_fwrite(kw, fortio); + kw.fwrite(fortio); } for (int i = 0; i < 4; ++i) { auto rd_file = rd::File::open(data_file_name, FileMode::WRITABLE); - rd_kw_type *loaded_kw = rd_file->get_global_view()->get_kw(0); - test_assert_true(rd_kw_equal(kw, loaded_kw)); + rd::KW *loaded_kw = rd_file->get_global_view()->get_kw(0); + test_assert_true(kw == *loaded_kw); rd_file->save_kw(loaded_kw); } - - rd_kw_free(kw); } void test_truncated() { @@ -54,11 +56,10 @@ void test_truncated() { } { - offset_type file_size = util_file_size("TEST.EGRID"); - FILE *stream = util_fopen("TEST.EGRID", "r+"); - util_ftruncate(stream, file_size / 2); - fclose(stream); + auto file_size = std::filesystem::file_size("TEST.EGRID"); + std::filesystem::resize_file("TEST.EGRID", file_size / 2); } + { auto rd_file = rd::File::open("TEST.EGRID"); test_assert_true(rd_file->size() < num_kw); @@ -78,11 +79,10 @@ void test_mixed_case() { } { - offset_type file_size = util_file_size("TESTcase.EGRID"); - FILE *stream = util_fopen("TESTcase.EGRID", "r+"); - util_ftruncate(stream, file_size / 2); - fclose(stream); + auto file_size = std::filesystem::file_size("TESTcase.EGRID"); + std::filesystem::resize_file("TESTcase.EGRID", file_size / 2); } + { auto rd_file = rd::File::open("TESTcase.EGRID"); test_assert_true(rd_file->size() < num_kw); diff --git a/lib/resdata/tests/test_rd_file_index.cpp b/lib/resdata/tests/test_rd_file_index.cpp index ec1d04e93..d8beb67c3 100644 --- a/lib/resdata/tests/test_rd_file_index.cpp +++ b/lib/resdata/tests/test_rd_file_index.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -29,18 +30,18 @@ void test_create_and_load_index_file() { const std::string index_file_name = "index_file"; //creating the data file - int data_size = 10; - rd_kw_type *kw1 = rd_kw_alloc("TEST1_KW", data_size, RD_INT); - for (int i = 0; i < data_size; ++i) - rd_kw_iset_int(kw1, i, 537 + i); + std::vector kw1_data(10); + for (size_t i = 0; i < kw1_data.size(); ++i) + kw1_data[i] = 537 + i; + rd::KW kw1{"TEST1_KW", std::move(kw1_data)}; ERT::FortIO fortio(file_name, std::ios_base::out); - rd_kw_fwrite(kw1, fortio); + kw1.fwrite(fortio); - data_size = 5; - rd_kw_type *kw2 = rd_kw_alloc("TEST2_KW", data_size, RD_FLOAT); - for (int i = 0; i < data_size; ++i) - rd_kw_iset_float(kw2, i, 0.15 * i); - rd_kw_fwrite(kw2, fortio); + std::vector kw2_data(5); + for (size_t i = 0; i < kw2_data.size(); ++i) + kw2_data[i] = 0.15f * i; + rd::KW kw2{"TEST2_KW", std::move(kw2_data)}; + kw2.fwrite(fortio); fortio.fflush(); //finished creating data file @@ -70,9 +71,6 @@ void test_create_and_load_index_file() { test_assert_true(rd_file_index->has_kw("TEST1_KW")); test_assert_true(rd_file_index->has_kw("TEST2_KW")); - - rd_kw_free(kw1); - rd_kw_free(kw2); } } diff --git a/lib/resdata/tests/well_conn_CF.cpp b/lib/resdata/tests/well_conn_CF.cpp index 82910ff78..febf75e9b 100644 --- a/lib/resdata/tests/well_conn_CF.cpp +++ b/lib/resdata/tests/well_conn_CF.cpp @@ -12,8 +12,8 @@ #include #include -void well_conn_test_CF(const rd_kw_type *iwel_kw, const rd_kw_type *icon_kw, - const rd_kw_type *scon_kw, const rd_kw_type *xcon_kw, +void well_conn_test_CF(const rd::KW *iwel_kw, const rd::KW *icon_kw, + const rd::KW *scon_kw, const rd::KW *xcon_kw, const RSTHead &rst_head, int iwell, int iconn, double CF) { auto conn = WellConnection::from_keywords(icon_kw, scon_kw, xcon_kw, @@ -26,10 +26,10 @@ int main(int argc, char **argv) { auto rst_file = rd::File::open(Xfile); auto rst_head = RSTHead::read(rst_file->get_global_view().get(), rd_filename_report_nr(Xfile)); - const rd_kw_type *iwel_kw = rst_file->get_kw(IWEL_KW, 0); - const rd_kw_type *icon_kw = rst_file->get_kw(ICON_KW, 0); - const rd_kw_type *scon_kw = rst_file->get_kw(SCON_KW, 0); - const rd_kw_type *xcon_kw = 0; + const rd::KW *iwel_kw = rst_file->get_kw(IWEL_KW, 0); + const rd::KW *icon_kw = rst_file->get_kw(ICON_KW, 0); + const rd::KW *scon_kw = rst_file->get_kw(SCON_KW, 0); + const rd::KW *xcon_kw = 0; well_conn_test_CF(iwel_kw, icon_kw, scon_kw, xcon_kw, rst_head, 0, 0, 32.948); diff --git a/lib/resdata/tests/well_dualp.cpp b/lib/resdata/tests/well_dualp.cpp index 1ac001747..4126c1599 100644 --- a/lib/resdata/tests/well_dualp.cpp +++ b/lib/resdata/tests/well_dualp.cpp @@ -14,7 +14,7 @@ void test_rstfile(const char *filename, bool fracture_connection) { auto rst_file = rd::File::open(filename); - const rd_kw_type *iwel_kw = rst_file->get_kw(IWEL_KW, 0); + const rd::KW *iwel_kw = rst_file->get_kw(IWEL_KW, 0); auto header = RSTHead::read(rst_file->get_global_view().get(), rd_filename_report_nr(filename)); diff --git a/lib/resdata/tests/well_segment_load.cpp b/lib/resdata/tests/well_segment_load.cpp index 2aae17c7b..2706b745d 100644 --- a/lib/resdata/tests/well_segment_load.cpp +++ b/lib/resdata/tests/well_segment_load.cpp @@ -19,8 +19,8 @@ int main(int argc, char **argv) { auto rst_file = rd::File::open(Xfile); auto rst_view = rst_file->get_global_view(); auto rst_head = RSTHead::read(rst_view.get(), rd_filename_report_nr(Xfile)); - const rd_kw_type *iwel_kw = rst_file->get_kw(IWEL_KW, 0); - const rd_kw_type *iseg_kw = rst_file->get_kw(ISEG_KW, 0); + const rd::KW *iwel_kw = rst_file->get_kw(IWEL_KW, 0); + const rd::KW *iseg_kw = rst_file->get_kw(ISEG_KW, 0); well_rseg_loader_type *rseg_loader = well_rseg_loader_alloc(rst_view.get()); test_install_SIGNALS(); @@ -31,8 +31,7 @@ int main(int argc, char **argv) { well_segment_collection_type *segments = well_segment_collection_alloc(); int seg_well_nr = - rd_kw_iget_int(iwel_kw, - iwel_offset + IWEL_SEGMENTED_WELL_NR_INDEX) - + iwel_kw->at(iwel_offset + IWEL_SEGMENTED_WELL_NR_INDEX) - 1; // -1: Ordinary well. if (seg_well_nr >= 0) { int segment_count = 0; diff --git a/lib/resdata/well_conn.cpp b/lib/resdata/well_conn.cpp index 17c207cd6..ad0c6ae85 100644 --- a/lib/resdata/well_conn.cpp +++ b/lib/resdata/well_conn.cpp @@ -46,13 +46,12 @@ WellConnection::WellConnection(int i, int j, int k, double connection_factor, aligned with the rest of the ert libraries. */ std::shared_ptr -WellConnection::from_keywords(const rd_kw_type *icon_kw, - const rd_kw_type *scon_kw, - const rd_kw_type *xcon_kw, const RSTHead &header, +WellConnection::from_keywords(const rd::KW *icon_kw, const rd::KW *scon_kw, + const rd::KW *xcon_kw, const RSTHead &header, int well_nr, int conn_nr) { const int icon_offset = header.niconz * (header.ncwmax * well_nr + conn_nr); - int IC = rd_kw_iget_int(icon_kw, icon_offset + ICON_IC_INDEX); + int IC = icon_kw->at(icon_offset + ICON_IC_INDEX); if (IC <= 0) throw InvalidConnection("IC <= 0: Connection not in current LGR"); @@ -60,19 +59,17 @@ WellConnection::from_keywords(const rd_kw_type *icon_kw, Out in the wild we have encountered files where the integer value used to indicate direction has had an invalid value for some connections. */ - int int_direction = - rd_kw_iget_int(icon_kw, icon_offset + ICON_DIRECTION_INDEX); + int int_direction = icon_kw->at(icon_offset + ICON_DIRECTION_INDEX); if ((int_direction < 0) || (int_direction > ICON_FRACY)) throw InvalidConnection(fmt::format( "Invalid direction value:{} encountered for well", int_direction)); - int i = rd_kw_iget_int(icon_kw, icon_offset + ICON_I_INDEX) - 1; - int j = rd_kw_iget_int(icon_kw, icon_offset + ICON_J_INDEX) - 1; - int k = rd_kw_iget_int(icon_kw, icon_offset + ICON_K_INDEX) - 1; + int i = icon_kw->at(icon_offset + ICON_I_INDEX) - 1; + int j = icon_kw->at(icon_offset + ICON_J_INDEX) - 1; + int k = icon_kw->at(icon_offset + ICON_K_INDEX) - 1; double connection_factor = -1; bool matrix_connection = true; - bool is_open = - (rd_kw_iget_int(icon_kw, icon_offset + ICON_STATUS_INDEX) > 0); + bool is_open = (icon_kw->at(icon_offset + ICON_STATUS_INDEX) > 0); auto dir = WellConnDir::fracX; /* Set the K value and fracture flag. */ @@ -111,14 +108,12 @@ WellConnection::from_keywords(const rd_kw_type *icon_kw, if (scon_kw) { const int scon_offset = header.nsconz * (header.ncwmax * well_nr + conn_nr); - connection_factor = - rd_kw_iget_as_double(scon_kw, scon_offset + SCON_CF_INDEX); + connection_factor = scon_kw->as_double(scon_offset + SCON_CF_INDEX); } { - int segment_id = - rd_kw_iget_int(icon_kw, icon_offset + ICON_SEGMENT_INDEX) - - ECLIPSE_WELL_SEGMENT_OFFSET + WELL_SEGMENT_OFFSET; + int segment_id = icon_kw->at(icon_offset + ICON_SEGMENT_INDEX) - + ECLIPSE_WELL_SEGMENT_OFFSET + WELL_SEGMENT_OFFSET; auto conn = std::make_shared( i, j, k, connection_factor, dir, is_open, segment_id, matrix_connection, header.unit_system); @@ -128,13 +123,11 @@ WellConnection::from_keywords(const rd_kw_type *icon_kw, header.nxconz * (header.ncwmax * well_nr + conn_nr); conn->water_rate = - rd_kw_iget_as_double(xcon_kw, xcon_offset + XCON_WRAT_INDEX); - conn->gas_rate = - rd_kw_iget_as_double(xcon_kw, xcon_offset + XCON_GRAT_INDEX); - conn->oil_rate = - rd_kw_iget_as_double(xcon_kw, xcon_offset + XCON_ORAT_INDEX); + xcon_kw->as_double(xcon_offset + XCON_WRAT_INDEX); + conn->gas_rate = xcon_kw->as_double(xcon_offset + XCON_GRAT_INDEX); + conn->oil_rate = xcon_kw->as_double(xcon_offset + XCON_ORAT_INDEX); conn->volume_rate = - rd_kw_iget_double(xcon_kw, xcon_offset + XCON_QR_INDEX); + xcon_kw->at(xcon_offset + XCON_QR_INDEX); } /** @@ -149,16 +142,14 @@ WellConnection::from_keywords(const rd_kw_type *icon_kw, } std::shared_ptr -WellConnection::read_wellhead(const rd_kw_type *iwel_kw, const RSTHead &header, +WellConnection::read_wellhead(const rd::KW *iwel_kw, const RSTHead &header, int well_nr) { const int iwel_offset = header.niwelz * well_nr; - int conn_i = rd_kw_iget_int(iwel_kw, iwel_offset + IWEL_HEADI_INDEX) - 1; + int conn_i = iwel_kw->at(iwel_offset + IWEL_HEADI_INDEX) - 1; if (conn_i >= 0) { - int conn_j = - rd_kw_iget_int(iwel_kw, iwel_offset + IWEL_HEADJ_INDEX) - 1; - int conn_k = - rd_kw_iget_int(iwel_kw, iwel_offset + IWEL_HEADK_INDEX) - 1; + int conn_j = iwel_kw->at(iwel_offset + IWEL_HEADJ_INDEX) - 1; + int conn_k = iwel_kw->at(iwel_offset + IWEL_HEADK_INDEX) - 1; bool matrix_connection = true; bool open = true; double connection_factor = -1; diff --git a/lib/resdata/well_info.cpp b/lib/resdata/well_info.cpp index 6de75a5af..50f950aa9 100644 --- a/lib/resdata/well_info.cpp +++ b/lib/resdata/well_info.cpp @@ -80,8 +80,8 @@ void WellInfo::add_UNRST_wells(rd::File *rst_file, 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); + const rd::KW *seqnum_kw = step_view->get_kw(SEQNUM_KW, 0); + int report_nr = seqnum_kw->at(0); clear_guard clear(rst_view); add_wells(step_view.get(), report_nr, load_segment_information); diff --git a/lib/resdata/well_segment.cpp b/lib/resdata/well_segment.cpp index 0bffe5ccd..9a6ad2ddc 100644 --- a/lib/resdata/well_segment.cpp +++ b/lib/resdata/well_segment.cpp @@ -13,9 +13,9 @@ #include std::shared_ptr -WellSegment::from_kw(const rd_kw_type *iseg_kw, - well_rseg_loader_type *rseg_loader, const RSTHead &header, - int well_nr, int segment_index, int segment_id) { +WellSegment::from_kw(const rd::KW *iseg_kw, well_rseg_loader_type *rseg_loader, + const RSTHead &header, int well_nr, int segment_index, + int segment_id) { if (!rseg_loader) { throw std::invalid_argument( "fatal internal error - tried to create well_segment " @@ -26,11 +26,10 @@ WellSegment::from_kw(const rd_kw_type *iseg_kw, const int rseg_offset = header.nrsegz * (header.nsegmx * well_nr + segment_index); int outlet_segment_id = - rd_kw_iget_int(iseg_kw, iseg_offset + ISEG_OUTLET_INDEX) - + iseg_kw->at(iseg_offset + ISEG_OUTLET_INDEX) - ECLIPSE_WELL_SEGMENT_OFFSET + WELL_SEGMENT_OFFSET; // -1 - int branch_id = - rd_kw_iget_int(iseg_kw, iseg_offset + ISEG_BRANCH_INDEX) - - ECLIPSE_WELL_BRANCH_OFFSET + WELL_BRANCH_OFFSET; // -1 + int branch_id = iseg_kw->at(iseg_offset + ISEG_BRANCH_INDEX) - + ECLIPSE_WELL_BRANCH_OFFSET + WELL_BRANCH_OFFSET; // -1 const double *rseg_data = well_rseg_loader_load_values(rseg_loader, rseg_offset); @@ -67,11 +66,11 @@ bool WellSegment::add_connection(const std::string &grid_name, return false; } -bool well_segment_well_is_MSW(int well_nr, const rd_kw_type *iwel_kw, +bool well_segment_well_is_MSW(int well_nr, const rd::KW *iwel_kw, const RSTHead &rst_head) { int iwel_offset = rst_head.niwelz * well_nr; int segment_well_nr = - rd_kw_iget_int(iwel_kw, iwel_offset + IWEL_SEGMENTED_WELL_NR_INDEX) - 1; + iwel_kw->at(iwel_offset + IWEL_SEGMENTED_WELL_NR_INDEX) - 1; if (segment_well_nr == IWEL_SEGMENTED_WELL_NR_NORMAL_VALUE) return false; diff --git a/lib/resdata/well_segment_collection.cpp b/lib/resdata/well_segment_collection.cpp index cc797d75a..d7a921c48 100644 --- a/lib/resdata/well_segment_collection.cpp +++ b/lib/resdata/well_segment_collection.cpp @@ -84,13 +84,13 @@ bool well_segment_collection_has_segment( int well_segment_collection_load_from_kw( well_segment_collection_type *segment_collection, int well_nr, - const rd_kw_type *iwel_kw, const rd_kw_type *iseg_kw, + const rd::KW *iwel_kw, const rd::KW *iseg_kw, well_rseg_loader_type *rseg_loader, const RSTHead &rst_head, bool load_segments, bool *is_MSW_well) { int iwel_offset = rst_head.niwelz * well_nr; int segment_well_nr = - rd_kw_iget_int(iwel_kw, iwel_offset + IWEL_SEGMENTED_WELL_NR_INDEX) - 1; + iwel_kw->at(iwel_offset + IWEL_SEGMENTED_WELL_NR_INDEX) - 1; int segments_added = 0; if (segment_well_nr != IWEL_SEGMENTED_WELL_NR_NORMAL_VALUE) { diff --git a/lib/resdata/well_state.cpp b/lib/resdata/well_state.cpp index b449b912a..97e6c2b98 100644 --- a/lib/resdata/well_state.cpp +++ b/lib/resdata/well_state.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -38,7 +39,7 @@ WellState::WellState(std::string well_name, int global_well_nr, bool open, throw std::invalid_argument("Invalid type value for open wells."); } -void WellState::add_wellhead(const RSTHead &header, const rd_kw_type *iwel_kw, +void WellState::add_wellhead(const RSTHead &header, const rd::KW *iwel_kw, int well_nr, const std::string &grid_name, int grid_nr) { auto wellhead = WellConnection::read_wellhead(iwel_kw, header, well_nr); @@ -55,55 +56,40 @@ bool WellState::add_rates(rd::FileView *rst_view, int well_nr) { bool has_xwel_kw = rst_view->has_kw(XWEL_KW); if (has_xwel_kw) { - const rd_kw_type *xwel_kw = rst_view->get_kw(XWEL_KW, 0); + const rd::KW *xwel_kw = rst_view->get_kw(XWEL_KW, 0); auto header = RSTHead::read(rst_view, -1); int offset = header.nxwelz * well_nr; this->unit_system = header.unit_system; - this->oil_rate = - rd_kw_iget_double(xwel_kw, offset + XWEL_RES_ORAT_ITEM); - this->gas_rate = - rd_kw_iget_double(xwel_kw, offset + XWEL_RES_GRAT_ITEM); - this->water_rate = - rd_kw_iget_double(xwel_kw, offset + XWEL_RES_WRAT_ITEM); - this->volume_rate = rd_kw_iget_double(xwel_kw, offset + XWEL_RESV_ITEM); + this->oil_rate = xwel_kw->at(offset + XWEL_RES_ORAT_ITEM); + this->gas_rate = xwel_kw->at(offset + XWEL_RES_GRAT_ITEM); + this->water_rate = xwel_kw->at(offset + XWEL_RES_WRAT_ITEM); + this->volume_rate = xwel_kw->at(offset + XWEL_RESV_ITEM); } return has_xwel_kw; } /** This function assumes that the rd_file state has been restricted - to one LGR block. - - Return value -1 means that the well is not found in this LGR at - all. */ -int WellState::get_lgr_well_nr(rd::FileView *file_view) { - int well_nr = -1; + to one LGR block.*/ +std::optional WellState::get_lgr_well_nr(rd::FileView *file_view) { if (file_view->has_kw(ZWEL_KW)) { auto header = RSTHead::read(file_view, -1); - const rd_kw_type *zwel_kw = file_view->get_kw(ZWEL_KW, 0); - int num_wells = header.nwells; - well_nr = 0; - while (true) { - bool found = false; + const rd::KW *zwel_kw = file_view->get_kw(ZWEL_KW, 0); + if (header.nwells <= 0) + return std::nullopt; + if (header.nzwelz <= 0) + return std::nullopt; + size_t num_wells = static_cast(header.nwells); + size_t nzwelz = static_cast(header.nzwelz); + for (size_t well_nr = 0; well_nr < num_wells; well_nr++) { std::string lgr_well_name = - rd_kw_iget_stripped_string(zwel_kw, well_nr * header.nzwelz); - + rd::strip_spaces(zwel_kw->at(well_nr * nzwelz)); if (this->name == lgr_well_name) - found = true; - else - well_nr++; - - if (found) - break; - else if (well_nr == num_wells) { - // The well is not in this LGR at all. - well_nr = -1; - break; - } + return well_nr; } } - return well_nr; + return std::nullopt; } WellType well_state_translate_rd_type_int(int int_type) { @@ -140,28 +126,28 @@ void WellState::add_connections(rd::FileView *rst_view, int well_nr) { auto header = RSTHead::read(rst_view, -1); - const rd_kw_type *iwel_kw = rst_view->get_kw(IWEL_KW, 0); + const rd::KW *iwel_kw = rst_view->get_kw(IWEL_KW, 0); add_wellhead(header, iwel_kw, well_nr, grid_name, grid_nr); if (rst_view->has_kw(ICON_KW)) { - const rd_kw_type *icon_kw = rst_view->get_kw(ICON_KW, 0); + const rd::KW *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; + rd::KW *scon_kw = nullptr; if (rst_view->has_kw(SCON_KW)) scon_kw = rst_view->get_kw(SCON_KW, 0); - rd_kw_type *xcon_kw = nullptr; + rd::KW *xcon_kw = nullptr; if (rst_view->has_kw(XCON_KW)) { xcon_kw = rst_view->get_kw(XCON_KW, 0); } const int iwel_offset = header.niwelz * well_nr; int num_connections = - rd_kw_iget_int(iwel_kw, iwel_offset + IWEL_CONNECTIONS_INDEX); + iwel_kw->at(iwel_offset + IWEL_CONNECTIONS_INDEX); for (int iconn = 0; iconn < num_connections; iconn++) { try { @@ -197,10 +183,10 @@ void WellState::add_LGR_connections(const rd_grid_type *grid, 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.get()); - if (well_nr >= 0) + auto well_nr = get_lgr_well_nr(lgr_view.get()); + if (well_nr.has_value()) add_connections(lgr_view.get(), grid_name, lgr_index + 1, - well_nr); + static_cast(*well_nr)); } } } @@ -217,8 +203,8 @@ bool WellState::add_MSW(rd::FileView *rst_view, int well_nr, if (rst_view->has_kw(ISEG_KW)) { auto rst_head = RSTHead::read(rst_view, -1); - 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); + const rd::KW *iwel_kw = rst_view->get_kw(IWEL_KW, 0); + const rd::KW *iseg_kw = rst_view->get_kw(ISEG_KW, 0); std::unique_ptr rseg_loader(nullptr, well_rseg_loader_free); @@ -255,25 +241,25 @@ std::shared_ptr WellState::read_wells_in_restart( int global_well_nr, bool load_segment_information) { if (file_view->has_kw(IWEL_KW)) { auto global_header = RSTHead::read(file_view, -1); - 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 rd::KW *global_iwel_kw = file_view->get_kw(IWEL_KW, 0); + const rd::KW *global_zwel_kw = file_view->get_kw(ZWEL_KW, 0); const int iwel_offset = global_header.niwelz * global_well_nr; bool open = - rd_kw_iget_int(global_iwel_kw, iwel_offset + IWEL_STATUS_INDEX) > 0; + global_iwel_kw->at(iwel_offset + IWEL_STATUS_INDEX) > 0; auto type = WellType::ZERO; { int int_type = - rd_kw_iget_int(global_iwel_kw, iwel_offset + IWEL_TYPE_INDEX); + global_iwel_kw->at(iwel_offset + IWEL_TYPE_INDEX); type = well_state_translate_rd_type_int(int_type); } const int zwel_offset = global_header.nzwelz * global_well_nr; std::string name = - rd_kw_iget_stripped_string(global_zwel_kw, zwel_offset); + rd::strip_spaces(global_zwel_kw->at(zwel_offset)); auto well_state = std::make_shared(name, global_well_nr, open, type, diff --git a/lib/tests/grid_fixtures.hpp b/lib/tests/grid_fixtures.hpp index eb147dcc3..7950e8a8c 100644 --- a/lib/tests/grid_fixtures.hpp +++ b/lib/tests/grid_fixtures.hpp @@ -5,11 +5,13 @@ */ #include +#include #include #include #include #include #include +#include #include #include @@ -29,53 +31,48 @@ namespace fs = std::filesystem; */ inline void write_empty_kw(ERT::FortIO &fortio, const char *name) { - auto kw = make_rd_kw(name, 0, RD_INT); - rd_kw_fwrite(kw.get(), fortio); + rd::KW kw{name, 0, RD_INT}; + kw.fwrite(fortio); } inline void write_egrid_filehead(ERT::FortIO &fortio, int dualp_flag = FILEHEAD_SINGLE_POROSITY) { - auto filehead = make_rd_kw(FILEHEAD_KW, 100, RD_INT); - rd_kw_scalar_set_int(filehead.get(), 0); - rd_kw_iset_int(filehead.get(), FILEHEAD_VERSION_INDEX, 3); - rd_kw_iset_int(filehead.get(), FILEHEAD_YEAR_INDEX, 2007); - rd_kw_iset_int(filehead.get(), FILEHEAD_TYPE_INDEX, - FILEHEAD_GRIDTYPE_CORNERPOINT); - rd_kw_iset_int(filehead.get(), FILEHEAD_DUALP_INDEX, dualp_flag); - rd_kw_iset_int(filehead.get(), FILEHEAD_ORGFORMAT_INDEX, - FILEHEAD_ORGTYPE_CORNERPOINT); - rd_kw_fwrite(filehead.get(), fortio); + std::vector filehead_data(100, 0); + filehead_data[FILEHEAD_VERSION_INDEX] = 3; + filehead_data[FILEHEAD_YEAR_INDEX] = 2007; + filehead_data[FILEHEAD_TYPE_INDEX] = FILEHEAD_GRIDTYPE_CORNERPOINT; + filehead_data[FILEHEAD_DUALP_INDEX] = dualp_flag; + filehead_data[FILEHEAD_ORGFORMAT_INDEX] = FILEHEAD_ORGTYPE_CORNERPOINT; + rd::KW filehead{FILEHEAD_KW, std::move(filehead_data)}; + filehead.fwrite(fortio); } inline void write_egrid_gridhead(ERT::FortIO &fortio, int gnx, int gny, int gnz, int grid_nr) { - auto kw = make_rd_kw(GRIDHEAD_KW, GRIDHEAD_SIZE, RD_INT); - rd_kw_scalar_set_int(kw.get(), 0); - rd_kw_iset_int(kw.get(), GRIDHEAD_TYPE_INDEX, - GRIDHEAD_GRIDTYPE_CORNERPOINT); - rd_kw_iset_int(kw.get(), GRIDHEAD_NX_INDEX, gnx); - rd_kw_iset_int(kw.get(), GRIDHEAD_NY_INDEX, gny); - rd_kw_iset_int(kw.get(), GRIDHEAD_NZ_INDEX, gnz); - rd_kw_iset_int(kw.get(), GRIDHEAD_NUMRES_INDEX, 1); - rd_kw_iset_int(kw.get(), GRIDHEAD_LGR_INDEX, grid_nr); - rd_kw_fwrite(kw.get(), fortio); + std::vector gridhead_data(GRIDHEAD_SIZE, 0); + gridhead_data[GRIDHEAD_TYPE_INDEX] = GRIDHEAD_GRIDTYPE_CORNERPOINT; + gridhead_data[GRIDHEAD_NX_INDEX] = gnx; + gridhead_data[GRIDHEAD_NY_INDEX] = gny; + gridhead_data[GRIDHEAD_NZ_INDEX] = gnz; + gridhead_data[GRIDHEAD_NUMRES_INDEX] = 1; + gridhead_data[GRIDHEAD_LGR_INDEX] = grid_nr; + rd::KW kw{GRIDHEAD_KW, std::move(gridhead_data)}; + kw.fwrite(fortio); } inline void write_egrid_grid_body(rd_grid_type *grid, ERT::FortIO &fortio) { auto coord = rd_grid_alloc_coord_kw(grid); - rd_kw_fwrite(coord.get(), fortio); + coord->fwrite(fortio); auto zcorn = rd_grid_alloc_zcorn_kw(grid); - rd_kw_fwrite(zcorn.get(), fortio); + zcorn->fwrite(fortio); auto actnum = rd_grid_alloc_actnum_kw(grid); - rd_kw_fwrite(actnum.get(), fortio); + actnum->fwrite(fortio); } inline void write_int_kw(ERT::FortIO &fortio, const char *name, const int *values, int size) { - auto kw = make_rd_kw(name, size, RD_INT); - for (int i = 0; i < size; i++) - rd_kw_iset_int(kw.get(), i, values[i]); - rd_kw_fwrite(kw.get(), fortio); + rd::KW kw{name, std::vector(values, values + size)}; + kw.fwrite(fortio); } inline void write_int_kw(ERT::FortIO &fortio, const char *name, @@ -91,19 +88,14 @@ inline void write_int_kw(ERT::FortIO &fortio, const std::string &name, 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); - for (int i = 0; i < size; i++) - rd_kw_iset_float(kw.get(), i, values[i]); - rd_kw_fwrite(kw.get(), fortio); + rd::KW kw{name, std::vector(values, values + size)}; + kw.fwrite(fortio); } inline void write_char8_kw(ERT::FortIO &fortio, const char *name, - std::initializer_list values) { - auto kw = make_rd_kw(name, static_cast(values.size()), RD_CHAR); - int i = 0; - for (const char *v : values) - rd_kw_iset_string8(kw.get(), i++, v); - rd_kw_fwrite(kw.get(), fortio); + std::initializer_list values) { + rd::KW kw{name, values}; + kw.fwrite(fortio); } inline void write_nnc_pair_section(ERT::FortIO &fortio, int lgr_nr, @@ -112,12 +104,11 @@ inline void write_nnc_pair_section(ERT::FortIO &fortio, int lgr_nr, const std::vector &second) { if (first.empty()) return; - auto nnchead = make_rd_kw(NNCHEAD_KW, NNCHEAD_SIZE, RD_INT); - rd_kw_scalar_set_int(nnchead.get(), 0); - rd_kw_iset_int(nnchead.get(), NNCHEAD_NUMNNC_INDEX, - static_cast(first.size())); - rd_kw_iset_int(nnchead.get(), NNCHEAD_LGR_INDEX, lgr_nr); - rd_kw_fwrite(nnchead.get(), fortio); + std::vector nnchead_data(NNCHEAD_SIZE, 0); + nnchead_data[NNCHEAD_NUMNNC_INDEX] = static_cast(first.size()); + nnchead_data[NNCHEAD_LGR_INDEX] = lgr_nr; + rd::KW nnchead{NNCHEAD_KW, std::move(nnchead_data)}; + nnchead.fwrite(fortio); write_int_kw(fortio, first_kw, first); write_int_kw(fortio, second_kw, second); } @@ -126,8 +117,8 @@ inline void write_lgr_egrid_section(ERT::FortIO &fortio, const std::string &name, const std::string &parent, int grid_nr, const rd_grid_ptr &lgr, int host_global) { - write_char8_kw(fortio, LGR_KW, {name.c_str()}); - write_char8_kw(fortio, LGR_PARENT_KW, {parent.c_str()}); + write_char8_kw(fortio, LGR_KW, {name}); + write_char8_kw(fortio, LGR_PARENT_KW, {parent}); write_egrid_gridhead(fortio, rd_grid_get_nx(lgr.get()), rd_grid_get_ny(lgr.get()), rd_grid_get_nz(lgr.get()), grid_nr); @@ -178,22 +169,26 @@ inline ERT::FortIO make_fortio_writer(const fs::path &filename, fmt ? false : RD_ENDIAN_FLIP}; } -inline rd_grid_ptr build_grdecl_grid(int nx, int ny, int nz, rd_kw_type *zcorn, - rd_kw_type *coord, - rd_kw_type *actnum = nullptr) { +inline rd_grid_ptr build_grdecl_grid(int nx, int ny, int nz, rd::KW *zcorn, + rd::KW *coord, rd::KW *actnum = nullptr) { return {rd_grid_alloc_GRDECL_kw(nx, ny, nz, zcorn, coord, actnum, nullptr), &rd_grid_free}; } -inline void set_pillar(rd_kw_type *coord_kw, int pillar, float tx, float ty, - float tz, float bx, float by, float bz) { +inline void set_pillar(std::vector &coord_data, int pillar, float tx, + float ty, float tz, float bx, float by, float bz) { const int off = 6 * pillar; - rd_kw_iset_float(coord_kw, off + 0, tx); - rd_kw_iset_float(coord_kw, off + 1, ty); - rd_kw_iset_float(coord_kw, off + 2, tz); - rd_kw_iset_float(coord_kw, off + 3, bx); - rd_kw_iset_float(coord_kw, off + 4, by); - rd_kw_iset_float(coord_kw, off + 5, bz); + coord_data.at(off + 0) = tx; + coord_data.at(off + 1) = ty; + coord_data.at(off + 2) = tz; + coord_data.at(off + 3) = bx; + coord_data.at(off + 4) = by; + coord_data.at(off + 5) = bz; +} + +inline void set_pillar(rd::KW *coord_kw, int pillar, float tx, float ty, + float tz, float bx, float by, float bz) { + set_pillar(coord_kw->get_vector(), pillar, tx, ty, tz, bx, by, bz); } /* @@ -214,26 +209,26 @@ inline void set_pillar(rd_kw_type *coord_kw, int pillar, float tx, float ty, inline rd_grid_ptr generate_coordkw_grid( int num_x, int num_y, int num_z, const std::vector> &z_vector) { - auto coord_kw = - make_rd_kw(COORD_KW, RD_GRID_COORD_SIZE(num_x, num_y), RD_FLOAT); - auto zcorn_kw = - make_rd_kw(ZCORN_KW, RD_GRID_ZCORN_SIZE(num_x, num_y, num_z), RD_FLOAT); + std::vector coord_data(RD_GRID_COORD_SIZE(num_x, num_y), 0.0f); + std::vector zcorn_data(RD_GRID_ZCORN_SIZE(num_x, num_y, num_z), + 0.0f); for (int j = 0; j < num_y; j++) { for (int i = 0; i < num_x; i++) { - set_pillar(coord_kw.get(), i + j * num_x, i, j, -1, i, j, -1); + set_pillar(coord_data, i + j * num_x, i, j, -1, i, j, -1); for (int k = 0; k < num_z; k++) { for (int c = 0; c < 4; c++) { - int zi1 = rd_grid_zcorn_index__(num_x, num_y, i, j, k, c); - int zi2 = + size_t zi1 = + rd_grid_zcorn_index__(num_x, num_y, i, j, k, c); + size_t zi2 = rd_grid_zcorn_index__(num_x, num_y, i, j, k, c + 4); double z1 = k; double z2 = k + 1; - rd_kw_iset_float(zcorn_kw.get(), zi1, z1); - rd_kw_iset_float(zcorn_kw.get(), zi2, z2); + zcorn_data[zi1] = z1; + zcorn_data[zi2] = z2; } } } @@ -241,11 +236,14 @@ inline rd_grid_ptr generate_coordkw_grid( for (const auto &[i, j, k, c, z] : z_vector) { auto index = rd_grid_zcorn_index__(num_x, num_y, i, j, k, c); - rd_kw_iset_float(zcorn_kw.get(), index, z); + zcorn_data[index] = z; } - return {rd_grid_alloc_GRDECL_kw(num_x, num_y, num_z, zcorn_kw.get(), - coord_kw.get(), nullptr, nullptr), + rd::KW coord_kw{COORD_KW, std::move(coord_data)}; + rd::KW zcorn_kw{ZCORN_KW, std::move(zcorn_data)}; + + return {rd_grid_alloc_GRDECL_kw(num_x, num_y, num_z, &zcorn_kw, &coord_kw, + nullptr, nullptr), &rd_grid_free}; } @@ -355,11 +353,11 @@ inline void write_egrid_with_two_lgrs_and_amalgamated_nnc( host2_global + 1); if (!nna1.empty()) { - auto nncheada_kw = make_rd_kw(NNCHEADA_KW, NNCHEAD_SIZE, RD_INT); - rd_kw_scalar_set_int(nncheada_kw.get(), 0); - rd_kw_iset_int(nncheada_kw.get(), NNCHEADA_ILOC1_INDEX, 1); - rd_kw_iset_int(nncheada_kw.get(), NNCHEADA_ILOC2_INDEX, 2); - rd_kw_fwrite(nncheada_kw.get(), fortio); + std::vector nncheada_data(NNCHEAD_SIZE, 0); + nncheada_data[NNCHEADA_ILOC1_INDEX] = 1; + nncheada_data[NNCHEADA_ILOC2_INDEX] = 2; + rd::KW nncheada_kw{NNCHEADA_KW, std::move(nncheada_data)}; + nncheada_kw.fwrite(fortio); write_int_kw(fortio, NNA1_KW, nna1); write_int_kw(fortio, NNA2_KW, nna2); } @@ -408,9 +406,9 @@ inline void write_egrid_dual_porosity(const fs::path &filename, int nx, int ny, write_egrid_gridhead(fortio, nx, ny, nz, 0); auto coord = rd_grid_alloc_coord_kw(grid.get()); - rd_kw_fwrite(coord.get(), fortio); + coord->fwrite(fortio); auto zcorn = rd_grid_alloc_zcorn_kw(grid.get()); - rd_kw_fwrite(zcorn.get(), fortio); + zcorn->fwrite(fortio); const int size = nx * ny * nz; write_int_kw(fortio, ACTNUM_KW, actnum, size); @@ -485,10 +483,9 @@ inline void write_grid_file_with_lgrs(const fs::path &filename, int nx, int ny, for (const auto &lgr : lgrs) { if (lgr.emit_parent) - write_char8_kw(fortio, LGR_KW, - {lgr.lgr_name.c_str(), lgr.parent_name.c_str()}); + write_char8_kw(fortio, LGR_KW, {lgr.lgr_name, lgr.parent_name}); else - write_char8_kw(fortio, LGR_KW, {lgr.lgr_name.c_str()}); + write_char8_kw(fortio, LGR_KW, {lgr.lgr_name}); write_grid_dimens(fortio, lgr.nx, lgr.ny, lgr.nz); write_grid_radial_false(fortio); @@ -537,18 +534,15 @@ write_egrid_with_single_lgr_no_parent_kw(const fs::path &filename, write_egrid_grid_body(main_grid.get(), fortio); write_empty_kw(fortio, ENDGRID_KW); - auto lgr_kw = make_rd_kw(LGR_KW, 1, RD_CHAR); - rd_kw_iset_string8(lgr_kw.get(), 0, lgr_name.c_str()); - rd_kw_fwrite(lgr_kw.get(), fortio); + rd::KW{LGR_KW, {lgr_name}}.fwrite(fortio); // Deliberately NO LGR_PARENT_KW here. write_egrid_gridhead(fortio, 1, 1, 1, 1); write_egrid_grid_body(lgr_grid.get(), fortio); - auto hostnum_kw = make_rd_kw(HOSTNUM_KW, 1, RD_INT); - rd_kw_iset_int(hostnum_kw.get(), 0, 1); - rd_kw_fwrite(hostnum_kw.get(), fortio); + rd::KW hostnum_kw{HOSTNUM_KW, std::vector{1}}; + hostnum_kw.fwrite(fortio); write_empty_kw(fortio, ENDGRID_KW); write_empty_kw(fortio, ENDLGR_KW); @@ -580,10 +574,8 @@ inline void write_fegrid_minimal(const fs::path &filename) { inline rd_grid_ptr build_single_cell_grid(const double corners[8][3], int actnum_value = 1) { const int nx = 1, ny = 1, nz = 1; - auto coord_kw = make_rd_kw(COORD_KW, RD_GRID_COORD_SIZE(nx, ny), RD_FLOAT); - auto zcorn_kw = - make_rd_kw(ZCORN_KW, RD_GRID_ZCORN_SIZE(nx, ny, nz), RD_FLOAT); - auto actnum_kw = make_rd_kw(ACTNUM_KW, nx * ny * nz, RD_INT); + std::vector coord_data(RD_GRID_COORD_SIZE(nx, ny), 0.0f); + std::vector zcorn_data(RD_GRID_ZCORN_SIZE(nx, ny, nz), 0.0f); // The four pillars are at (i,j) in {0,1}x{0,1}; pillar layout is // 6*(i + j*(nx+1)). @@ -594,21 +586,22 @@ inline rd_grid_ptr build_single_cell_grid(const double corners[8][3], int pillar = i + j * (nx + 1); int top = top_corner[i + 2 * j]; int bot = bot_corner[i + 2 * j]; - set_pillar(coord_kw.get(), pillar, corners[top][0], corners[top][1], + set_pillar(coord_data, pillar, corners[top][0], corners[top][1], corners[top][2], corners[bot][0], corners[bot][1], corners[bot][2]); } } for (int c = 0; c < 8; ++c) { - int zi = rd_grid_zcorn_index__(nx, ny, 0, 0, 0, c); - rd_kw_iset_float(zcorn_kw.get(), zi, corners[c][2]); + size_t zi = rd_grid_zcorn_index__(nx, ny, 0, 0, 0, c); + zcorn_data[zi] = corners[c][2]; } - rd_kw_iset_int(actnum_kw.get(), 0, actnum_value); + rd::KW coord_kw{COORD_KW, std::move(coord_data)}; + rd::KW zcorn_kw{ZCORN_KW, std::move(zcorn_data)}; + rd::KW actnum_kw{ACTNUM_KW, std::vector(nx * ny * nz, actnum_value)}; - return build_grdecl_grid(nx, ny, nz, zcorn_kw.get(), coord_kw.get(), - actnum_kw.get()); + return build_grdecl_grid(nx, ny, nz, &zcorn_kw, &coord_kw, &actnum_kw); } inline rd_grid_ptr load_egrid_with_single_lgr( diff --git a/lib/tests/test_fault_block_layer.cpp b/lib/tests/test_fault_block_layer.cpp index fb83c234d..38748558e 100644 --- a/lib/tests/test_fault_block_layer.cpp +++ b/lib/tests/test_fault_block_layer.cpp @@ -168,15 +168,14 @@ TEST_CASE("fault_block_layer methods", "[fault_block_layer]") { * 0 0 0 0 0 * 0 0 0 0 0 */ - auto kw = make_rd_kw("FAULTBLK", nx * ny * nz, RD_INT); - rd_kw_iset_int(kw.get(), idx(0, 0), 1); - rd_kw_iset_int(kw.get(), idx(1, 0), 1); - rd_kw_iset_int(kw.get(), idx(1, 1), 2); - rd_kw_iset_int(kw.get(), - rd_grid_get_global_index3(grid.get(), 2, 1, 0), 2); + rd::KW kw{"FAULTBLK", nx * ny * nz, RD_INT}; + kw.at(idx(0, 0)) = 1; + kw.at(idx(1, 0)) = 1; + kw.at(idx(1, 1)) = 2; + kw.at(rd_grid_get_global_index3(grid.get(), 2, 1, 0)) = 2; WHEN("scan_kw is called") { - bool ok = fault_block_layer_scan_kw(layer.get(), kw.get()); + bool ok = fault_block_layer_scan_kw(layer.get(), &kw); THEN("scan_kw returns true") { REQUIRE(ok); } @@ -204,7 +203,7 @@ TEST_CASE("fault_block_layer methods", "[fault_block_layer]") { } WHEN("load_kw is called") { - bool ok = fault_block_layer_load_kw(layer.get(), kw.get()); + bool ok = fault_block_layer_load_kw(layer.get(), &kw); THEN("load_kw returns true") { REQUIRE(ok); } @@ -228,64 +227,62 @@ TEST_CASE("fault_block_layer methods", "[fault_block_layer]") { } } WHEN("Exporting to a correctly sized integer keyword") { - fault_block_layer_load_kw(layer.get(), kw.get()); - auto out_kw = make_rd_kw("OUT", nx * ny * nz, RD_INT); - bool ok = fault_block_layer_export(layer.get(), out_kw.get()); + fault_block_layer_load_kw(layer.get(), &kw); + rd::KW out_kw{"OUT", nx * ny * nz, RD_INT}; + bool ok = fault_block_layer_export(layer.get(), &out_kw); THEN("export returns true") { REQUIRE(ok); } THEN("exported cell values match the original keyword") { - REQUIRE(rd_kw_iget_int(out_kw.get(), idx(0, 0)) == 1); - REQUIRE(rd_kw_iget_int(out_kw.get(), idx(1, 0)) == 1); - REQUIRE(rd_kw_iget_int(out_kw.get(), idx(1, 1)) == 2); - REQUIRE(rd_kw_iget_int(out_kw.get(), idx(2, 1)) == 2); - REQUIRE(rd_kw_iget_int(out_kw.get(), idx(2, 0)) == 0); + REQUIRE(out_kw.at(idx(0, 0)) == 1); + REQUIRE(out_kw.at(idx(1, 0)) == 1); + REQUIRE(out_kw.at(idx(1, 1)) == 2); + REQUIRE(out_kw.at(idx(2, 1)) == 2); + REQUIRE(out_kw.at(idx(2, 0)) == 0); } } WHEN("Exporting to a keyword with wrong size") { - auto bad_kw = make_rd_kw("OUT", 1, RD_INT); + rd::KW bad_kw{"OUT", 1, RD_INT}; THEN("export returns false") { REQUIRE_FALSE( - fault_block_layer_export(layer.get(), bad_kw.get())); + fault_block_layer_export(layer.get(), &bad_kw)); } } WHEN("Exporting to a float keyword") { - auto float_kw = make_rd_kw("OUT", nx * ny * nz, RD_FLOAT); + rd::KW float_kw{"OUT", nx * ny * nz, RD_FLOAT}; THEN("export returns false") { REQUIRE_FALSE( - fault_block_layer_export(layer.get(), float_kw.get())); + fault_block_layer_export(layer.get(), &float_kw)); } } } WHEN("scan_kw is called with non-integer keyword") { - auto float_kw = make_rd_kw("FAULTBLK", nx * ny * nz, RD_FLOAT); + rd::KW float_kw{"FAULTBLK", nx * ny * nz, RD_FLOAT}; THEN("scan_kw returns false") { REQUIRE_FALSE( - fault_block_layer_scan_kw(layer.get(), float_kw.get())); + fault_block_layer_scan_kw(layer.get(), &float_kw)); } } WHEN("scan_kw is called with wrong size keyword") { - auto bad_kw = make_rd_kw("FAULTBLK", 1, RD_INT); + rd::KW bad_kw{"FAULTBLK", 1, RD_INT}; THEN("scan_kw returns false") { - REQUIRE_FALSE( - fault_block_layer_scan_kw(layer.get(), bad_kw.get())); + REQUIRE_FALSE(fault_block_layer_scan_kw(layer.get(), &bad_kw)); } } WHEN("load_kw is called with wrong size keyword") { - auto bad_kw = make_rd_kw("FAULTBLK", 1, RD_INT); + rd::KW bad_kw{"FAULTBLK", 1, RD_INT}; THEN("load_kw returns false") { - REQUIRE_FALSE( - fault_block_layer_load_kw(layer.get(), bad_kw.get())); + REQUIRE_FALSE(fault_block_layer_load_kw(layer.get(), &bad_kw)); } } WHEN("load_kw is called with non-integer keyword") { - auto float_kw = make_rd_kw("FAULTBLK", nx * ny * nz, RD_FLOAT); + rd::KW float_kw{"FAULTBLK", nx * ny * nz, RD_FLOAT}; THEN("load_kw returns false") { REQUIRE_FALSE( - fault_block_layer_load_kw(layer.get(), float_kw.get())); + fault_block_layer_load_kw(layer.get(), &float_kw)); } } AND_GIVEN("A layer with block containing two cells") { @@ -435,18 +432,16 @@ TEST_CASE("fault_block_layer methods", "[fault_block_layer]") { } } AND_GIVEN("A kw with nonzero data in k=2") { - auto kw = make_rd_kw("FAULTBLK", nx * ny * nz, RD_INT); + rd::KW kw{"FAULTBLK", nx * ny * nz, RD_INT}; // Two cells with block id=1 in the last layer only - rd_kw_iset_int(kw.get(), - rd_grid_get_global_index3(grid.get(), 0, 0, 2), 1); - rd_kw_iset_int(kw.get(), - rd_grid_get_global_index3(grid.get(), 1, 0, 2), 1); + kw.at(rd_grid_get_global_index3(grid.get(), 0, 0, 2)) = 1; + kw.at(rd_grid_get_global_index3(grid.get(), 1, 0, 2)) = 1; WHEN("scan_kw is called on layer k=2 (last layer, where data " "lives)") { auto layer_2 = make_fb_layer(grid.get(), 2); - bool ok = fault_block_layer_scan_kw(layer_2.get(), kw.get()); + bool ok = fault_block_layer_scan_kw(layer_2.get(), &kw); THEN("scan_kw returns true") { REQUIRE(ok); } @@ -458,7 +453,7 @@ TEST_CASE("fault_block_layer methods", "[fault_block_layer]") { } WHEN("scan_kw is called on layer k=0 (no data in this layer)") { - fault_block_layer_scan_kw(layer.get(), kw.get()); + fault_block_layer_scan_kw(layer.get(), &kw); // All cells in k=0 are zero; assign_zero groups them into one // single connected block. diff --git a/lib/tests/test_fortio.cpp b/lib/tests/test_fortio.cpp index 261b63c21..a61fc3350 100644 --- a/lib/tests/test_fortio.cpp +++ b/lib/tests/test_fortio.cpp @@ -195,25 +195,6 @@ TEST_CASE_METHOD(Tmpdir, "Reading data with FortIO") { REQUIRE_FALSE(fortio.fread_buffer(buffer.data(), 1)); } } - GIVEN("An externally managed FILE*") { - write_records(filename, {{"", 0}}); - std::unique_ptr stream( - fopen(filename.c_str(), "r"), fclose); - REQUIRE(stream); - WHEN("Constructing a FortIO from the FILE*") { - ERT::FortIO fortio(filename, false, false, stream.get(), false); - - THEN("fclose_stream returns false since the stream is not owned") { - REQUIRE_FALSE(fortio.fclose_stream()); - } - THEN("fopen_stream returns false since the stream is already set") { - REQUIRE_FALSE(fortio.fopen_stream()); - } - THEN("stream_is_open returns true") { - REQUIRE(fortio.stream_is_open()); - } - } - } GIVEN("A file with two records where the second is truncated mid-data") { const int record_size = 1000; std::vector buffer(record_size, 0); @@ -232,6 +213,26 @@ TEST_CASE_METHOD(Tmpdir, "Reading data with FortIO") { REQUIRE_FALSE(fortio.fread_buffer(buffer.data(), record_size)); } } + GIVEN("A file with two records truncated via a still-open read/write " + "stream") { + const int record_size = 1000; + std::vector buffer(record_size, 0); + std::ofstream(filename, std::ios_base::binary).close(); + ERT::FortIO fortio(filename, std::ios_base::in | std::ios_base::out, + false, false); + fortio.fwrite_record(buffer.data(), record_size); + fortio.fwrite_record(buffer.data(), record_size); + + THEN("Truncating leaves the same stream's read position " + "immediately consistent with the new (smaller) size") { + fortio.ftruncate(2 * record_size - 100); + REQUIRE(util_file_size(filename.c_str()) == 2 * record_size - 100); + + fortio.rewind(); + REQUIRE(fortio.fread_buffer(buffer.data(), record_size)); + REQUIRE_FALSE(fortio.fread_buffer(buffer.data(), record_size)); + } + } GIVEN("An empty file") { std::ofstream(filename).close(); diff --git a/lib/tests/test_layer.cpp b/lib/tests/test_layer.cpp index c61430e2e..40fae1df2 100644 --- a/lib/tests/test_layer.cpp +++ b/lib/tests/test_layer.cpp @@ -9,6 +9,7 @@ #include "detail/resdata/layer_cxx.hpp" #include "resdata/rd_type.hpp" +#include #include #include #include @@ -31,33 +32,33 @@ inline std::ostream &operator<<(std::ostream &os, static rd_grid_ptr generate_coordkw_grid( int num_x, int num_y, int num_z, const std::vector> &z_vector) { - auto coord_kw = - make_rd_kw(COORD_KW, RD_GRID_COORD_SIZE(num_x, num_y), RD_FLOAT); - auto zcorn_kw = - make_rd_kw(ZCORN_KW, RD_GRID_ZCORN_SIZE(num_x, num_y, num_z), RD_FLOAT); + std::vector coord_data(RD_GRID_COORD_SIZE(num_x, num_y), 0.0f); + std::vector zcorn_data(RD_GRID_ZCORN_SIZE(num_x, num_y, num_z), + 0.0f); for (int j = 0; j < num_y; j++) { for (int i = 0; i < num_x; i++) { int offset = 6 * (i + j * num_x); - rd_kw_iset_float(coord_kw.get(), offset, i); - rd_kw_iset_float(coord_kw.get(), offset + 1, j); - rd_kw_iset_float(coord_kw.get(), offset + 2, -1); + coord_data[offset] = i; + coord_data[offset + 1] = j; + coord_data[offset + 2] = -1; - rd_kw_iset_float(coord_kw.get(), offset + 3, i); - rd_kw_iset_float(coord_kw.get(), offset + 4, j); - rd_kw_iset_float(coord_kw.get(), offset + 5, -1); + coord_data[offset + 3] = i; + coord_data[offset + 4] = j; + coord_data[offset + 5] = -1; for (int k = 0; k < num_z; k++) { for (int c = 0; c < 4; c++) { - int zi1 = rd_grid_zcorn_index__(num_x, num_y, i, j, k, c); - int zi2 = + size_t zi1 = + rd_grid_zcorn_index__(num_x, num_y, i, j, k, c); + size_t zi2 = rd_grid_zcorn_index__(num_x, num_y, i, j, k, c + 4); double z1 = k; double z2 = k + 1; - rd_kw_iset_float(zcorn_kw.get(), zi1, z1); - rd_kw_iset_float(zcorn_kw.get(), zi2, z2); + zcorn_data[zi1] = z1; + zcorn_data[zi2] = z2; } } } @@ -65,11 +66,14 @@ static rd_grid_ptr generate_coordkw_grid( for (const auto &[i, j, k, c, z] : z_vector) { auto index = rd_grid_zcorn_index__(num_x, num_y, i, j, k, c); - rd_kw_iset_float(zcorn_kw.get(), index, z); + zcorn_data[index] = z; } - return {rd_grid_alloc_GRDECL_kw(num_x, num_y, num_z, zcorn_kw.get(), - coord_kw.get(), NULL, NULL), + rd::KW coord_kw{COORD_KW, std::move(coord_data)}; + rd::KW zcorn_kw{ZCORN_KW, std::move(zcorn_data)}; + + return {rd_grid_alloc_GRDECL_kw(num_x, num_y, num_z, &zcorn_kw, &coord_kw, + NULL, NULL), &rd_grid_free}; } diff --git a/lib/tests/test_rd_file_kw.cpp b/lib/tests/test_rd_file_kw.cpp index 2093e0ece..6cce0f877 100644 --- a/lib/tests/test_rd_file_kw.cpp +++ b/lib/tests/test_rd_file_kw.cpp @@ -1,17 +1,18 @@ #include -#include #include #include -#include #include +#include + +#include "ert/util/util.hpp" #include #include #include #include +#include -#include "resdata/rd_type.hpp" #include "tmpdir.hpp" SCENARIO("A FileKW is constructed from explicit header information") { @@ -33,10 +34,10 @@ SCENARIO("A FileKW is constructed from explicit header information") { SCENARIO("A FileKW is constructed from an rd_kw instance") { GIVEN("An rd_kw with a known header, size and type") { - auto kw = make_rd_kw("PORO", 5, RD_FLOAT); + rd::KW kw{"PORO", 5, RD_FLOAT}; WHEN("A FileKW is created from it with an offset") { - FileKW file_kw(kw.get(), 256); + FileKW file_kw(&kw, 256); THEN("The header information is derived from the rd_kw") { REQUIRE(file_kw.get_offset() == 256); @@ -227,18 +228,16 @@ SCENARIO_METHOD(Tmpdir, "A FileKW lazily loads its keyword from file") { GIVEN("A keyword written to a fortran formatted file") { auto filename = (dirname / "DATA").string(); - auto kw = make_rd_kw("MYKW", 4, RD_INT); - for (int i = 0; i < 4; i++) - rd_kw_iset_int(kw.get(), i, i * 10); + rd::KW kw{"MYKW", std::vector{0, 10, 20, 30}}; offset_type offset; { ERT::FortIO fortio(filename, std::ios_base::out); offset = fortio.ftell(); - rd_kw_fwrite(kw.get(), fortio); + kw.fwrite(fortio); } - FileKW file_kw(kw.get(), offset); + FileKW file_kw(&kw, offset); THEN("The keyword is not loaded until requested") { REQUIRE(file_kw.get_kw_ptr() == nullptr); @@ -246,14 +245,14 @@ SCENARIO_METHOD(Tmpdir, "A FileKW lazily loads its keyword from file") { WHEN("get_kw is called with a reading fortio handle") { ERT::FortIO fortio(filename, std::ios_base::in); - rd_kw_type *loaded = file_kw.get_kw(fortio); + rd::KW *loaded = file_kw.get_kw(fortio); THEN("The keyword is loaded and cached") { REQUIRE(loaded != nullptr); REQUIRE(file_kw.get_kw_ptr() == loaded); - REQUIRE(rd_kw_get_size(loaded) == 4); + REQUIRE(loaded->size() == 4); for (int i = 0; i < 4; i++) - REQUIRE(rd_kw_iget_int(loaded, i) == i * 10); + REQUIRE(loaded->at(i) == i * 10); } AND_WHEN("clear is called") { diff --git a/lib/tests/test_rd_grid_nnc_lgr.cpp b/lib/tests/test_rd_grid_nnc_lgr.cpp index bddcf68fb..68337ba38 100644 --- a/lib/tests/test_rd_grid_nnc_lgr.cpp +++ b/lib/tests/test_rd_grid_nnc_lgr.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -288,9 +289,9 @@ TEST_CASE_METHOD(Tmpdir, "Load EGRID with MAPAXES", "[unittest]") { REQUIRE(coord_kw != nullptr); const int nx = rd_grid_get_nx(grid.get()); const int ny = rd_grid_get_ny(grid.get()); - REQUIRE(rd_kw_get_size(coord_kw.get()) == + REQUIRE(rd::kw_get_size(coord_kw.get()) == RD_GRID_COORD_SIZE(nx, ny)); - const float *data = rd_kw_get_float_ptr(coord_kw.get()); + const float *data = coord_kw->get_vector().data(); // Fixture main grid: 3x3x3 unit cells, so pillar (i,j) has // local top (i,j,0) and bottom (i,j,3). MAPAXES would offset // x by at least the origin (10), so observing x==i, y==j @@ -316,21 +317,20 @@ TEST_CASE_METHOD(Tmpdir, "Load EGRID with MAPAXES", "[unittest]") { ERT::FortIO fortio(grid_filename.c_str(), std::ios_base::in); - rd_kw_ptr first_corners(nullptr, &rd_kw_free); + std::unique_ptr first_corners{nullptr}; while (true) { - rd_kw_type *kw = rd_kw_fread_alloc(fortio); + auto kw = rd::KW::fread(fortio); if (kw == nullptr) break; - if (std::string(rd_kw_get_header(kw)) == CORNERS_KW) { - first_corners.reset(kw); + if (kw->header() == CORNERS_KW) { + first_corners = std::move(kw); break; } - rd_kw_free(kw); } REQUIRE(first_corners != nullptr); - REQUIRE(rd_kw_get_size(first_corners.get()) == 24); - const float *corners = rd_kw_get_float_ptr(first_corners.get()); + REQUIRE(first_corners->size() == 24); + const float *corners = first_corners->get_vector().data(); // Main grid cell (0,0,0) is a unit cell; in the local frame // its corners are at the 8 combinations of {0,1} in each axis. const float expected[24] = { @@ -357,10 +357,10 @@ TEST_CASE_METHOD(Tmpdir, "Load EGRID with MAPAXES", "[unittest]") { THEN("rd_grid_alloc_mapaxes_kw returns kw with mapaxes") { auto kw = rd_grid_alloc_mapaxes_kw(grid.get()); - REQUIRE(kw != nullptr); - REQUIRE(rd_kw_get_size(kw->get()) == 6); - const float *data = rd_kw_get_float_ptr(kw->get()); - for (int i = 0; i < 6; i++) + REQUIRE(kw); + REQUIRE((*kw)->size() == 6); + const auto &data = (*kw)->get_vector(); + for (size_t i = 0; i < 6; i++) REQUIRE(data[i] == mapaxes[i]); } diff --git a/lib/tests/test_rd_grid_regular.cpp b/lib/tests/test_rd_grid_regular.cpp index d5db72364..51bddb425 100644 --- a/lib/tests/test_rd_grid_regular.cpp +++ b/lib/tests/test_rd_grid_regular.cpp @@ -47,33 +47,34 @@ TEST_CASE("Test unfractured grids", "[unittest]") { TEST_CASE("rd_grid_alloc_GRDECL_kw with explicit ACTNUM", "[unittest]") { const int nx = 2, ny = 2, nz = 2; - auto coord_kw = make_rd_kw(COORD_KW, RD_GRID_COORD_SIZE(nx, ny), RD_FLOAT); - auto zcorn_kw = - make_rd_kw(ZCORN_KW, RD_GRID_ZCORN_SIZE(nx, ny, nz), RD_FLOAT); + rd::KW coord_kw{COORD_KW, RD_GRID_COORD_SIZE(nx, ny), RD_FLOAT}; + std::vector zcorn_data(RD_GRID_ZCORN_SIZE(nx, ny, nz), 0.0f); for (int j = 0; j < ny; j++) { for (int i = 0; i < nx; i++) { - set_pillar(coord_kw.get(), (i + j * nx), i, j, -1, i, j, -1); + set_pillar(&coord_kw, (i + j * nx), i, j, -1, i, j, -1); for (int k = 0; k < nz; k++) { for (int c = 0; c < 4; c++) { - int zi1 = rd_grid_zcorn_index__(nx, ny, i, j, k, c); - int zi2 = rd_grid_zcorn_index__(nx, ny, i, j, k, c + 4); - rd_kw_iset_float(zcorn_kw.get(), zi1, k); - rd_kw_iset_float(zcorn_kw.get(), zi2, k + 1); + size_t zi1 = rd_grid_zcorn_index__(nx, ny, i, j, k, c); + size_t zi2 = rd_grid_zcorn_index__(nx, ny, i, j, k, c + 4); + zcorn_data[zi1] = k; + zcorn_data[zi2] = k + 1; } } } } + rd::KW zcorn_kw{ZCORN_KW, std::move(zcorn_data)}; + const int size = nx * ny * nz; - auto actnum_kw = make_rd_kw(ACTNUM_KW, size, RD_INT); - rd_kw_scalar_set_int(actnum_kw.get(), 1); - rd_kw_iset_int(actnum_kw.get(), 0, 0); - - auto grid = rd_grid_ptr(rd_grid_alloc_GRDECL_kw(nx, ny, nz, zcorn_kw.get(), - coord_kw.get(), - actnum_kw.get(), NULL), - &rd_grid_free); + std::vector actnum_data(size, 1); + actnum_data[0] = 0; + rd::KW actnum_kw{ACTNUM_KW, std::move(actnum_data)}; + + auto grid = + rd_grid_ptr(rd_grid_alloc_GRDECL_kw(nx, ny, nz, &zcorn_kw, &coord_kw, + &actnum_kw, NULL), + &rd_grid_free); REQUIRE(grid != nullptr); REQUIRE(rd_grid_get_active_size(grid.get()) == size - 1); } @@ -373,37 +374,33 @@ TEST_CASE("Test utility functions on a regular grid", "[unittest]") { SECTION("Keyword allocation") { auto zcorn_kw = rd_grid_alloc_zcorn_kw(grid.get()); REQUIRE(zcorn_kw != nullptr); - REQUIRE(rd_kw_get_size(zcorn_kw.get()) == - static_cast(expected_zcorn.size())); + REQUIRE(zcorn_kw->size() == expected_zcorn.size()); for (size_t i = 0; i < expected_zcorn.size(); i++) - REQUIRE(rd_kw_iget_float(zcorn_kw.get(), i) == - expected_zcorn[i]); + REQUIRE(zcorn_kw->at(i) == expected_zcorn[i]); auto actnum_kw = rd_grid_alloc_actnum_kw(grid.get()); REQUIRE(actnum_kw != nullptr); - REQUIRE(rd_kw_get_size(actnum_kw.get()) == 8); - for (int i = 0; i < 8; i++) - REQUIRE(rd_kw_iget_int(actnum_kw.get(), i) == actnum_data[i]); + REQUIRE(actnum_kw->size() == 8); + for (size_t i = 0; i < 8; i++) + REQUIRE(actnum_kw->at(i) == actnum_data[i]); auto coord_kw = rd_grid_alloc_coord_kw(grid.get()); REQUIRE(coord_kw != nullptr); - REQUIRE(rd_kw_get_size(coord_kw.get()) == - static_cast(expected_coord.size())); - for (int i = 0; i < rd_kw_get_size(coord_kw.get()); i++) - REQUIRE(rd_kw_iget_float(coord_kw.get(), i) == - expected_coord[i]); + REQUIRE(coord_kw->size() == expected_coord.size()); + for (size_t i = 0; i < coord_kw->size(); i++) + REQUIRE(coord_kw->at(i) == expected_coord[i]); auto volume_kw = rd_grid_alloc_volume_kw(grid.get(), false); REQUIRE(volume_kw != nullptr); - REQUIRE(rd_kw_get_size(volume_kw.get()) == 8); - for (int i = 0; i < rd_kw_get_size(volume_kw.get()); i++) - REQUIRE(rd_kw_iget_double(volume_kw.get(), i) == 6.0); + REQUIRE(volume_kw->size() == 8); + for (size_t i = 0; i < volume_kw->size(); i++) + REQUIRE(volume_kw->at(i) == 6.0); auto volume_kw_active = rd_grid_alloc_volume_kw(grid.get(), true); REQUIRE(volume_kw_active != nullptr); - REQUIRE(rd_kw_get_size(volume_kw_active.get()) == 7); - for (int i = 0; i < rd_kw_get_size(volume_kw_active.get()); i++) - REQUIRE(rd_kw_iget_double(volume_kw_active.get(), i) == 6.0); + REQUIRE(volume_kw_active->size() == 7); + for (size_t i = 0; i < volume_kw_active->size(); i++) + REQUIRE(volume_kw_active->at(i) == 6.0); } SECTION("ZCORN and COORD size/data") { @@ -595,19 +592,17 @@ TEST_CASE("Test utility functions on a regular grid", "[unittest]") { GIVEN("A grid keyword") { int nactive = rd_grid_get_nactive(grid.get()); - auto kw = make_rd_kw("PORO", nactive, RD_FLOAT); - - for (int i = 0; i < nactive; i++) { - rd_kw_iset_float(kw.get(), i, 0.2f + i * 0.01f); - } + std::vector poro_data(nactive); + for (int i = 0; i < nactive; i++) + poro_data[i] = 0.2f + i * 0.01f; + rd::KW kw{"PORO", std::move(poro_data)}; SECTION("column property") { - double prop = - rd_grid_get_property(grid.get(), kw.get(), 0, 0, 0); + double prop = rd_grid_get_property(grid.get(), &kw, 0, 0, 0); REQUIRE(prop >= 0.0); auto actual = - rd_grid_get_column_property(grid.get(), kw.get(), 0, 0); + rd_grid_get_column_property(grid.get(), &kw, 0, 0); REQUIRE(actual.size() == 2); REQUIRE_THAT(actual[0], Catch::Matchers::WithinAbs(0.2, 0.0001)); @@ -615,14 +610,14 @@ TEST_CASE("Test utility functions on a regular grid", "[unittest]") { } SECTION("Keyword copy") { - auto target_kw = make_rd_kw( - "TARGET", rd_grid_get_global_size(grid.get()), RD_FLOAT); - rd_grid_global_kw_copy(grid.get(), target_kw.get(), kw.get()); - - auto compressed_kw = make_rd_kw( - "COMP", rd_grid_get_active_size(grid.get()), RD_FLOAT); - rd_grid_compressed_kw_copy(grid.get(), compressed_kw.get(), - target_kw.get()); + rd::KW target_kw{"TARGET", rd_grid_get_global_size(grid.get()), + RD_FLOAT}; + rd_grid_global_kw_copy(grid.get(), &target_kw, &kw); + + rd::KW compressed_kw{ + "COMP", rd_grid_get_active_size(grid.get()), RD_FLOAT}; + rd_grid_compressed_kw_copy(grid.get(), &compressed_kw, + &target_kw); } } } diff --git a/lib/tests/test_rd_kw.cpp b/lib/tests/test_rd_kw.cpp index 47649aa0a..2b36d44b7 100644 --- a/lib/tests/test_rd_kw.cpp +++ b/lib/tests/test_rd_kw.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -14,277 +15,158 @@ #include #include #include +#include #include +#include "resdata/rd_util.hpp" #include "tmpdir.hpp" using Catch::Matchers::ContainsSubstring; namespace { -/* Small RAII helper so the test bodies stay leak-free regardless of the - assertion outcome. */ -rd_kw_ptr make_int_kw(const char *name, int size) { - auto kw = make_rd_kw(name, size, RD_INT); - for (int i = 0; i < size; i++) - rd_kw_iset_int(kw.get(), i, i); - return kw; +std::unique_ptr make_int_kw(const std::string &name, size_t size) { + std::vector data(size); + for (size_t i = 0; i < size; i++) + data[i] = i; + return std::make_unique(name, std::move(data)); } } // namespace TEST_CASE("rd_kw_alloc rejects negative size", "[rd_kw]") { - REQUIRE_THROWS_WITH(rd_kw_alloc("KW", -1, RD_INT), + REQUIRE_THROWS_WITH(rd::KW("KW", -1, RD_INT), ContainsSubstring("rd_kw size was negative: -1")); } -TEST_CASE("rd_kw_alloc_new rejects negative size", "[rd_kw]") { - int data[1] = {0}; - REQUIRE_THROWS_AS(rd_kw_alloc_new("KW", -1, RD_INT, data), - std::invalid_argument); -} - -TEST_CASE("rd_kw_resize rejects negative size", "[rd_kw]") { - auto kw = make_int_kw("KW", 3); - REQUIRE_THROWS_WITH(rd_kw_resize(kw.get(), -1), - ContainsSubstring("new_size was negative")); +TEST_CASE("rd::KW constructor rejects negative size", "[rd_kw]") { + REQUIRE_THROWS_AS(rd::KW("KW", -1, RD_INT), std::invalid_argument); } TEST_CASE("typed accessors validate the index", "[rd_kw]") { auto kw = make_int_kw("KW", 3); SECTION("index too large") { - REQUIRE_THROWS_WITH(rd_kw_iget_int(kw.get(), 5), + REQUIRE_THROWS_WITH(kw->at(5), ContainsSubstring("Invalid index lookup")); } SECTION("negative index") { - REQUIRE_THROWS_WITH(rd_kw_iset_int(kw.get(), -1, 0), + REQUIRE_THROWS_WITH(kw->at(-1) = 0, ContainsSubstring("Invalid index lookup")); } } TEST_CASE("typed accessors validate the type", "[rd_kw]") { - auto float_kw = make_rd_kw("KW", 3, RD_FLOAT); + rd::KW float_kw{"KW", 3, RD_FLOAT}; SECTION("iget on wrong type") { - REQUIRE_THROWS_WITH(rd_kw_iget_int(float_kw.get(), 0), + REQUIRE_THROWS_WITH(float_kw.at(0), ContainsSubstring("wrong type")); } SECTION("iset on wrong type") { - REQUIRE_THROWS_WITH(rd_kw_iset_int(float_kw.get(), 0, 1), + REQUIRE_THROWS_WITH(float_kw.at(0) = 1, ContainsSubstring("wrong type")); } SECTION("iget_as_double on non numeric type") { - auto bool_kw = make_rd_kw("KW", 3, RD_BOOL); - REQUIRE_THROWS_WITH( - rd_kw_iget_as_double(bool_kw.get(), 0), - ContainsSubstring("can not be converted to double")); + rd::KW bool_kw{"KW", 3, RD_BOOL}; + REQUIRE_THROWS_WITH(bool_kw.as_double(0), + ContainsSubstring("cannot be converted to double")); } } TEST_CASE("char/string accessors validate the type", "[rd_kw]") { auto int_kw = make_int_kw("KW", 3); SECTION("iget_char_ptr on non char type") { - REQUIRE_THROWS_WITH(rd_kw_iget_char_ptr(int_kw.get(), 0), + REQUIRE_THROWS_WITH(int_kw->at(0), ContainsSubstring("wrong type")); } SECTION("iget_string_ptr on non string type") { - REQUIRE_THROWS_WITH(rd_kw_iget_string_ptr(int_kw.get(), 0), - ContainsSubstring("wrong type")); - } - SECTION("icmp_string on non char type") { - REQUIRE_THROWS_WITH(rd_kw_icmp_string(int_kw.get(), 0, "X"), + REQUIRE_THROWS_WITH(int_kw->at(0), ContainsSubstring("wrong type")); } } -TEST_CASE("rd_kw_iset_string_ptr validates type and length", "[rd_kw]") { - SECTION("non alphabetic type") { - auto int_kw = make_int_kw("KW", 1); - REQUIRE_THROWS_WITH(rd_kw_iset_string_ptr(int_kw.get(), 0, "x"), - ContainsSubstring("Expected alphabetic data type")); +TEST_CASE("rd::pad_spaces fits strings to the requested width", "[rd_kw]") { + SECTION("shorter strings are padded with trailing spaces") { + REQUIRE(rd::pad_spaces("x", 8) == "x "); } - SECTION("string too long") { - auto str_kw = make_rd_kw("KW", 1, RD_STRING(8)); - REQUIRE_THROWS_WITH( - rd_kw_iset_string_ptr(str_kw.get(), 0, "123456789"), - ContainsSubstring("cannot hold input string of length 9")); + SECTION("longer strings are truncated") { + REQUIRE(rd::pad_spaces("123456789", 8) == "12345678"); } } -TEST_CASE("rd_kw_iget_stripped_string handles width edge cases", "[rd_kw]") { +TEST_CASE("rd::strip_spaces handles width edge cases", "[rd_kw]") { SECTION("RD_CHAR values can fill the full field width") { - auto char_kw = make_rd_kw("KW", 2, RD_CHAR); - - rd_kw_iset_char_ptr(char_kw.get(), 0, "FOPRTEST"); - rd_kw_iset_char_ptr(char_kw.get(), 1, "BPR"); + rd::KW char_kw{"KW", {"FOPRTEST", "BPR"}}; - REQUIRE(rd_kw_iget_stripped_string(char_kw.get(), 0) == "FOPRTEST"); - REQUIRE(rd_kw_iget_stripped_string(char_kw.get(), 1) == "BPR"); + REQUIRE(rd::strip_spaces(char_kw.at(0)) == "FOPRTEST"); + REQUIRE(rd::strip_spaces(char_kw.at(1)) == "BPR"); } SECTION("RD_STRING values can fill the declared field width") { - auto string_kw = make_rd_kw("KW", 1, RD_STRING(12)); + rd::KW string_kw{"KW", 1, RD_STRING(12)}; - rd_kw_iset_string_ptr(string_kw.get(), 0, "0123456789AB"); + string_kw.at(0) = "0123456789AB"; - REQUIRE(rd_kw_iget_stripped_string(string_kw.get(), 0) == + REQUIRE(rd::strip_spaces(string_kw.at(0)) == "0123456789AB"); } - - SECTION("embedded NUL stops the extracted string before field width") { - auto string_kw = make_rd_kw("KW", 1, RD_STRING(12)); - char *raw = static_cast(rd_kw_iget_ptr(string_kw.get(), 0)); - - std::memcpy(raw, "ABCD\0EFGHIJK", 12); - raw[12] = '\0'; - - REQUIRE(rd_kw_iget_stripped_string(string_kw.get(), 0) == "ABCD"); - } } -TEST_CASE("scalar_set/scale/shift validate the type", "[rd_kw]") { - auto float_kw = make_rd_kw("KW", 3, RD_FLOAT); - REQUIRE_THROWS_WITH(rd_kw_scalar_set_int(float_kw.get(), 1), - ContainsSubstring("wrong type")); - REQUIRE_THROWS_WITH(rd_kw_scale_int(float_kw.get(), 1), - ContainsSubstring("wrong type")); - REQUIRE_THROWS_WITH(rd_kw_shift_int(float_kw.get(), 1), - ContainsSubstring("wrong type")); - - auto int_kw = make_int_kw("KW", 3); - REQUIRE_THROWS_WITH(rd_kw_scalar_set_float_or_double(int_kw.get(), 1.0), - ContainsSubstring("wrong type")); - REQUIRE_THROWS_WITH(rd_kw_scale_float_or_double(int_kw.get(), 1.0), - ContainsSubstring("wrong type")); - REQUIRE_THROWS_WITH(rd_kw_shift_float_or_double(int_kw.get(), 1.0), - ContainsSubstring("wrong type")); -} - -TEST_CASE("rd_kw_alloc_slice_copy validates range and stride", "[rd_kw]") { +TEST_CASE("slice copy validates range and stride", "[rd_kw]") { auto src = make_int_kw("KW", 4); SECTION("index1 beyond size") { - REQUIRE_THROWS_WITH(rd_kw_alloc_slice_copy(src.get(), 10, 20, 1), + REQUIRE_THROWS_WITH(rd::KW(*src.get(), 10, 20, 1), ContainsSubstring("> size")); } SECTION("non positive stride") { - REQUIRE_THROWS_WITH(rd_kw_alloc_slice_copy(src.get(), 0, 4, 0), - ContainsSubstring("completely broken")); + REQUIRE_THROWS_WITH(rd::KW(*src.get(), 0, 4, 0), + ContainsSubstring("must be positive")); } } -TEST_CASE("rd_kw_alloc_sub_copy validates offset and count", "[rd_kw]") { +TEST_CASE("sub copy constructor validates offset and count", "[rd_kw]") { auto src = make_int_kw("KW", 4); SECTION("invalid offset") { - REQUIRE_THROWS_WITH(rd_kw_alloc_sub_copy(src.get(), "NEW", -1, 1), + REQUIRE_THROWS_WITH(rd::KW(*src.get(), "NEW", 100, 1), ContainsSubstring("invalid offset")); } SECTION("invalid count") { - REQUIRE_THROWS_WITH(rd_kw_alloc_sub_copy(src.get(), "NEW", 0, 100), + REQUIRE_THROWS_WITH(rd::KW(*src.get(), "NEW", 0, 100), ContainsSubstring("invalid count value")); } } -TEST_CASE("rd_kw_alloc_scatter_copy rejects unsupported type", "[rd_kw]") { - auto src = make_rd_kw("KW", 1, RD_MESS); - int mapping[1] = {0}; - REQUIRE_THROWS_WITH( - rd_kw_alloc_scatter_copy(src.get(), 1, mapping, nullptr), - ContainsSubstring("unsupported type")); -} - TEST_CASE("inplace binary ops validate size and type", "[rd_kw]") { auto a = make_int_kw("A", 3); auto b = make_int_kw("B", 4); - auto a_char = make_rd_kw("A", 3, RD_CHAR); - auto b_char = make_rd_kw("B", 3, RD_CHAR); + rd::KW a_char{"A", 3, RD_CHAR}; + rd::KW b_char{"B", 3, RD_CHAR}; SECTION("size mismatch") { - REQUIRE_THROWS_WITH(rd_kw_inplace_add(a.get(), b.get()), - ContainsSubstring("type/size")); - REQUIRE_THROWS_WITH(rd_kw_inplace_sub(a.get(), b.get()), - ContainsSubstring("type/size")); - REQUIRE_THROWS_WITH(rd_kw_inplace_mul(a.get(), b.get()), - ContainsSubstring("type/size")); - REQUIRE_THROWS_WITH(rd_kw_inplace_div(a.get(), b.get()), - ContainsSubstring("type/size")); - REQUIRE_THROWS_WITH(rd_kw_inplace_add_squared(a.get(), b.get()), + REQUIRE_THROWS_WITH(*a.get() -= *b.get(), ContainsSubstring("type/size")); } SECTION("type not implemented") { - REQUIRE_THROWS_WITH(rd_kw_inplace_add(a_char.get(), b_char.get()), - ContainsSubstring("not implemented for type")); - REQUIRE_THROWS_WITH(rd_kw_inplace_sub(a_char.get(), b_char.get()), - ContainsSubstring("not implemented for type")); - REQUIRE_THROWS_WITH(rd_kw_inplace_mul(a_char.get(), b_char.get()), - ContainsSubstring("not implemented for type")); - REQUIRE_THROWS_WITH(rd_kw_inplace_div(a_char.get(), b_char.get()), + REQUIRE_THROWS_WITH(a_char -= b_char, ContainsSubstring("not implemented for type")); } } -TEST_CASE("inplace unary ops validate type", "[rd_kw]") { - auto char_kw = make_rd_kw("KW", 3, RD_CHAR); - REQUIRE_THROWS_WITH(rd_kw_inplace_abs(char_kw.get()), - ContainsSubstring("inplace abs not implemented")); - REQUIRE_THROWS_WITH(rd_kw_inplace_sqrt(char_kw.get()), - ContainsSubstring("inplace sqrt not implemented")); -} - -TEST_CASE("indexed inplace/copy ops validate size and type", "[rd_kw]") { - std::vector index_set{0}; - - auto a = make_int_kw("A", 3); - auto b = make_int_kw("B", 4); - - REQUIRE_THROWS_WITH(rd_kw_copy_indexed(a.get(), index_set, b.get()), - ContainsSubstring("type/size")); - REQUIRE_THROWS_WITH(rd_kw_inplace_add_indexed(a.get(), index_set, b.get()), - ContainsSubstring("type/size")); - REQUIRE_THROWS_WITH(rd_kw_inplace_sub_indexed(a.get(), index_set, b.get()), - ContainsSubstring("type/size")); - REQUIRE_THROWS_WITH(rd_kw_inplace_mul_indexed(a.get(), index_set, b.get()), - ContainsSubstring("type/size")); - REQUIRE_THROWS_WITH(rd_kw_inplace_div_indexed(a.get(), index_set, b.get()), - ContainsSubstring("type/size")); -} - -TEST_CASE("rd_kw_max_min validates type", "[rd_kw]") { - auto char_kw = make_rd_kw("KW", 3, RD_CHAR); - char max[8]; - char min[8]; - REQUIRE_THROWS_WITH(rd_kw_max_min(char_kw.get(), max, min), - ContainsSubstring("invalid type for element sum")); -} - -TEST_CASE("element sum validates type", "[rd_kw]") { - auto char_kw = make_rd_kw("KW", 3, RD_CHAR); - char sum[8]; - REQUIRE_THROWS_WITH(rd_kw_element_sum(char_kw.get(), sum), - ContainsSubstring("invalid type for element sum")); - - auto int_kw = make_int_kw("KW", 3); - REQUIRE_THROWS_WITH(rd_kw_element_sum_float(int_kw.get()), - ContainsSubstring("invalid type")); - - std::vector index_set{0}; - REQUIRE_THROWS_WITH( - rd_kw_element_sum_indexed(char_kw.get(), index_set, sum), - ContainsSubstring("invalid type for element sum")); -} - TEST_CASE("rd_kw_first_different validates offset and size", "[rd_kw]") { auto a = make_int_kw("A", 3); auto b = make_int_kw("B", 4); auto c = make_int_kw("C", 3); SECTION("size mismatch") { - REQUIRE_THROWS_WITH(rd_kw_first_different(a.get(), b.get(), 0, 0, 0), + REQUIRE_THROWS_WITH(a->first_different(b.get(), 0, 0, 0), ContainsSubstring("sorry invalid comparison")); } SECTION("invalid offset") { - REQUIRE_THROWS_WITH(rd_kw_first_different(a.get(), c.get(), 5, 0, 0), - ContainsSubstring("invalid offset value")); + REQUIRE_THROWS_WITH( + a->first_different(c.get(), 5, 0, 0), + ContainsSubstring( + "offset value in first_difference exceeded size: 5")); } } @@ -293,7 +175,7 @@ TEST_CASE_METHOD(Tmpdir, "fread_alloc throws on corrupt data", "[rd_kw]") { { auto kw = make_int_kw("INTKW", 4); ERT::FortIO fortio(good, std::ios_base::out, /*fmt_file=*/true); - rd_kw_fwrite(kw.get(), fortio); + kw->fwrite(fortio); } std::string contents; @@ -313,7 +195,7 @@ TEST_CASE_METHOD(Tmpdir, "fread_alloc throws on corrupt data", "[rd_kw]") { out << corrupt; } ERT::FortIO fortio(bad, std::ios_base::in, /*fmt_file=*/true); - REQUIRE_THROWS_WITH(rd_kw_fread_alloc(fortio), + REQUIRE_THROWS_WITH(rd::KW::fread(fortio), ContainsSubstring("reading of keyword:INTKW")); } } @@ -321,11 +203,11 @@ TEST_CASE_METHOD(Tmpdir, "fread_alloc throws on corrupt data", "[rd_kw]") { TEST_CASE_METHOD(Tmpdir, "fread_alloc rejects bad logical value", "[rd_kw]") { auto good = (dirname / "GOOD.txt").string(); { - auto kw = make_rd_kw("BKW", 3, RD_BOOL); - for (int i = 0; i < 3; i++) - rd_kw_iset_bool(kw.get(), i, true); + rd::KW kw{"BKW", 3, RD_BOOL}; + for (size_t i = 0; i < 3; i++) + kw.at(i) = true; ERT::FortIO fortio(good, std::ios_base::out, /*fmt_file=*/true); - rd_kw_fwrite(kw.get(), fortio); + kw.fwrite(fortio); } std::string contents; @@ -345,24 +227,10 @@ TEST_CASE_METHOD(Tmpdir, "fread_alloc rejects bad logical value", "[rd_kw]") { } ERT::FortIO fortio(bad, std::ios_base::in, /*fmt_file=*/true); - REQUIRE_THROWS_WITH(rd_kw_fread_alloc(fortio), + REQUIRE_THROWS_WITH(rd::KW::fread(fortio), ContainsSubstring("Logical value: [Q] not recogniced")); } -TEST_CASE_METHOD(Tmpdir, "fseek_kw throws on missing keyword", "[rd_kw]") { - auto path = (dirname / "FILE").string(); - { - auto kw = make_int_kw("INTKW", 4); - ERT::FortIO fortio(path, std::ios_base::out); - rd_kw_fwrite(kw.get(), fortio); - } - - ERT::FortIO fortio(path, std::ios_base::in); - REQUIRE_THROWS_WITH(rd_kw_fseek_kw("MISSING", /*rewind=*/false, - /*abort_on_error=*/true, fortio), - ContainsSubstring("failed to locate keyword:MISSING")); -} - TEST_CASE_METHOD(Tmpdir, "FileKW::read guards against buffer_size overflow", "[rd_kw]") { auto path = (dirname / "FILE").string(); diff --git a/lib/tests/test_rd_region.cpp b/lib/tests/test_rd_region.cpp index ef15f6984..79e165d59 100644 --- a/lib/tests/test_rd_region.cpp +++ b/lib/tests/test_rd_region.cpp @@ -7,6 +7,7 @@ #include #include #include +#include int num_selected(rd_region_type *region) { return rd_region_get_global_list(region).size(); @@ -107,87 +108,77 @@ TEST_CASE("rd_region", "[rd_region]") { } SECTION("select with int kw") { - rd_kw_type *int_kw = rd_kw_alloc("INTGR", 1000, RD_INT); + rd::KW int_kw{"INTGR", 1000, RD_INT}; - for (int i = 0; i < 500; i++) - rd_kw_iset_int(int_kw, i, 1); - for (int i = 500; i < 1000; i++) - rd_kw_iset_int(int_kw, i, 2); + for (size_t i = 0; i < 500; i++) + int_kw.at(i) = 1; + for (size_t i = 500; i < 1000; i++) + int_kw.at(i) = 2; - rd_region_select_equal(region, int_kw, 1); + rd_region_select_equal(region, &int_kw, 1); REQUIRE(num_selected(region) == 500); - rd_region_deselect_equal(region, int_kw, 1); + rd_region_deselect_equal(region, &int_kw, 1); REQUIRE(num_selected(region) == 0); - - rd_kw_free(int_kw); } SECTION("select with bool kw") { - rd_kw_type *bool_kw = rd_kw_alloc("BOOL", 1000, RD_BOOL); + rd::KW bool_kw{"BOOL", 1000, RD_BOOL}; - for (int i = 0; i < 500; i++) - rd_kw_iset_bool(bool_kw, i, true); - for (int i = 500; i < 1000; i++) - rd_kw_iset_bool(bool_kw, i, false); + for (size_t i = 0; i < 500; i++) + bool_kw.at(i) = true; + for (size_t i = 500; i < 1000; i++) + bool_kw.at(i) = false; - rd_region_select_true(region, bool_kw); + rd_region_select_true(region, &bool_kw); REQUIRE(num_selected(region) == 500); - rd_region_select_false(region, bool_kw); + rd_region_select_false(region, &bool_kw); REQUIRE(num_selected(region) == 1000); - - rd_kw_free(bool_kw); } SECTION("select with float kw") { - rd_kw_type *float_kw = rd_kw_alloc("FLOAT", 1000, RD_FLOAT); + rd::KW float_kw{"FLOAT", 1000, RD_FLOAT}; - for (int i = 0; i < 1000; i++) - rd_kw_iset_float(float_kw, i, i * 0.1f); + for (size_t i = 0; i < 1000; i++) + float_kw.at(i) = i * 0.1f; SECTION("Select in interval") { - rd_region_select_in_interval(region, float_kw, 10.0, 50.0); + rd_region_select_in_interval(region, &float_kw, 10.0, 50.0); REQUIRE(num_selected(region) == 400); - rd_region_deselect_in_interval(region, float_kw, 10.0, 50.0); + rd_region_deselect_in_interval(region, &float_kw, 10.0, 50.0); REQUIRE(num_selected(region) == 0); } SECTION("Select comparison") { - rd_region_select_smaller(region, float_kw, 50.0f); + rd_region_select_smaller(region, &float_kw, 50.0f); REQUIRE(num_selected(region) == 500); - rd_region_deselect_smaller(region, float_kw, 50.0f); + rd_region_deselect_smaller(region, &float_kw, 50.0f); REQUIRE(num_selected(region) == 0); } SECTION("Select larger") { - rd_region_select_larger(region, float_kw, 49.9f); + rd_region_select_larger(region, &float_kw, 49.9f); REQUIRE(num_selected(region) == 501); - rd_region_deselect_larger(region, float_kw, 49.9f); + rd_region_deselect_larger(region, &float_kw, 49.9f); REQUIRE(num_selected(region) == 0); } SECTION("comparison select") { - rd_kw_type *cmp_kw = rd_kw_alloc("KW2", 1000, RD_FLOAT); - - for (int i = 0; i < 1000; i++) - rd_kw_iset_float(cmp_kw, i, 50.0f); + rd::KW cmp_kw{"KW2", std::vector(1000, 50.0f)}; SECTION("Compare less") { - rd_region_cmp_select_less(region, float_kw, cmp_kw); + rd_region_cmp_select_less(region, &float_kw, &cmp_kw); REQUIRE(num_selected(region) == 500); - rd_region_cmp_deselect_less(region, float_kw, cmp_kw); + rd_region_cmp_deselect_less(region, &float_kw, &cmp_kw); REQUIRE(num_selected(region) == 0); } SECTION("Compare more") { - rd_region_cmp_select_more(region, float_kw, cmp_kw); + rd_region_cmp_select_more(region, &float_kw, &cmp_kw); REQUIRE(num_selected(region) == 500); - rd_region_cmp_deselect_more(region, float_kw, cmp_kw); + rd_region_cmp_deselect_more(region, &float_kw, &cmp_kw); REQUIRE(num_selected(region) == 0); } - - rd_kw_free(cmp_kw); } - rd_kw_free(float_kw); } SECTION("select active") { @@ -376,149 +367,103 @@ TEST_CASE("rd_region", "[rd_region]") { rd_region_select_i1i2(region, 0, 4); SECTION("Set keyword int") { - rd_kw_type *kw = rd_kw_alloc("TEST", 1000, RD_INT); - rd_region_set_kw_int(region, kw, 42, false); + rd::KW kw{"TEST", 1000, RD_INT}; + rd_region_set_kw(region, &kw, 42, false); const auto list = rd_region_get_global_list(region); - REQUIRE(rd_kw_iget_int(kw, list.at(0)) == 42); - rd_kw_free(kw); + REQUIRE(kw.at(list.at(0)) == 42); } SECTION("Set keyword float") { - rd_kw_type *kw = rd_kw_alloc("TEST", 1000, RD_FLOAT); - rd_region_set_kw_float(region, kw, 3.14f, false); + rd::KW kw{"TEST", 1000, RD_FLOAT}; + rd_region_set_kw(region, &kw, 3.14f, false); const auto list = rd_region_get_global_list(region); - REQUIRE_THAT(rd_kw_iget_float(kw, list.at(0)), + REQUIRE_THAT(kw.at(list.at(0)), Catch::Matchers::WithinAbs(3.14f, 0.01f)); - rd_kw_free(kw); } SECTION("Set keyword double") { - rd_kw_type *kw = rd_kw_alloc("TEST", 1000, RD_DOUBLE); - rd_region_set_kw_double(region, kw, 2.71, false); + rd::KW kw{"TEST", 1000, RD_DOUBLE}; + rd_region_set_kw(region, &kw, 2.71, false); const auto list = rd_region_get_global_list(region); - REQUIRE_THAT(rd_kw_iget_double(kw, list.at(0)), + REQUIRE_THAT(kw.at(list.at(0)), Catch::Matchers::WithinAbs(2.71, 0.01)); - rd_kw_free(kw); } SECTION("Shift keyword int") { - rd_kw_type *kw = rd_kw_alloc("TEST", 1000, RD_INT); - for (int i = 0; i < 1000; i++) - rd_kw_iset_int(kw, i, 10); - rd_region_shift_kw_int(region, kw, 5, false); + rd::KW kw{"TEST", std::vector(1000, 10)}; + rd_region_shift_kw(region, &kw, 5, false); const auto list = rd_region_get_global_list(region); - REQUIRE(rd_kw_iget_int(kw, list.at(0)) == 15); - rd_kw_free(kw); + REQUIRE(kw.at(list.at(0)) == 15); } SECTION("Scale keyword float") { - rd_kw_type *kw = rd_kw_alloc("TEST", 1000, RD_FLOAT); - for (int i = 0; i < 1000; i++) - rd_kw_iset_float(kw, i, 10.0f); - rd_region_scale_kw_float(region, kw, 2.0f, false); + rd::KW kw{"TEST", std::vector(1000, 10.0f)}; + rd_region_scale_kw(region, &kw, 2.0f, false); const auto list = rd_region_get_global_list(region); - REQUIRE_THAT(rd_kw_iget_float(kw, list.at(0)), + REQUIRE_THAT(kw.at(list.at(0)), Catch::Matchers::WithinAbs(20.0f, 0.01f)); - rd_kw_free(kw); } SECTION("Keyword copy") { - rd_kw_type *kw_src = rd_kw_alloc("SRC", 1000, RD_INT); - rd_kw_type *kw_dst = rd_kw_alloc("DST", 1000, RD_INT); - for (int i = 0; i < 1000; i++) - rd_kw_iset_int(kw_src, i, 99); - rd_region_kw_copy(region, kw_dst, kw_src, false); + rd::KW kw_src{"SRC", std::vector(1000, 99)}; + rd::KW kw_dst{"DST", 1000, RD_INT}; + rd_region_kw_copy(region, &kw_dst, &kw_src, false); const auto list = rd_region_get_global_list(region); - REQUIRE(rd_kw_iget_int(kw_dst, list.at(0)) == 99); - rd_kw_free(kw_src); - rd_kw_free(kw_dst); + REQUIRE(kw_dst.at(list.at(0)) == 99); } SECTION("Keyword iadd") { - rd_kw_type *kw1 = rd_kw_alloc("KW1", 1000, RD_FLOAT); - rd_kw_type *kw2 = rd_kw_alloc("KW2", 1000, RD_FLOAT); - for (int i = 0; i < 1000; i++) { - rd_kw_iset_float(kw1, i, 10.0f); - rd_kw_iset_float(kw2, i, 5.0f); - } - rd_region_kw_iadd(region, kw1, kw2, false); + rd::KW kw1{"KW1", std::vector(1000, 10.0f)}; + rd::KW kw2{"KW2", std::vector(1000, 5.0f)}; + rd_region_kw_iadd(region, &kw1, &kw2, false); const auto list = rd_region_get_global_list(region); - REQUIRE_THAT(rd_kw_iget_float(kw1, list.at(0)), + REQUIRE_THAT(kw1.at(list.at(0)), Catch::Matchers::WithinAbs(15.0f, 0.01)); - rd_kw_free(kw1); - rd_kw_free(kw2); } SECTION("Keyword isub") { - rd_kw_type *kw1 = rd_kw_alloc("KW1", 1000, RD_FLOAT); - rd_kw_type *kw2 = rd_kw_alloc("KW2", 1000, RD_FLOAT); - for (int i = 0; i < 1000; i++) { - rd_kw_iset_float(kw1, i, 10.0f); - rd_kw_iset_float(kw2, i, 3.0f); - } - rd_region_kw_isub(region, kw1, kw2, false); + rd::KW kw1{"KW1", std::vector(1000, 10.0f)}; + rd::KW kw2{"KW2", std::vector(1000, 3.0f)}; + rd_region_kw_isub(region, &kw1, &kw2, false); const auto list = rd_region_get_global_list(region); - REQUIRE_THAT(rd_kw_iget_float(kw1, list.at(0)), + REQUIRE_THAT(kw1.at(list.at(0)), Catch::Matchers::WithinAbs(7.0f, 0.01f)); - rd_kw_free(kw1); - rd_kw_free(kw2); } SECTION("Keyword imul") { - rd_kw_type *kw1 = rd_kw_alloc("KW1", 1000, RD_FLOAT); - rd_kw_type *kw2 = rd_kw_alloc("KW2", 1000, RD_FLOAT); - for (int i = 0; i < 1000; i++) { - rd_kw_iset_float(kw1, i, 10.0f); - rd_kw_iset_float(kw2, i, 2.0f); - } - rd_region_kw_imul(region, kw1, kw2, false); + rd::KW kw1{"KW1", std::vector(1000, 10.0f)}; + rd::KW kw2{"KW2", std::vector(1000, 2.0f)}; + rd_region_kw_imul(region, &kw1, &kw2, false); const auto list = rd_region_get_global_list(region); - REQUIRE_THAT(rd_kw_iget_float(kw1, list.at(0)), + REQUIRE_THAT(kw1.at(list.at(0)), Catch::Matchers::WithinAbs(20.0f, 0.01f)); - rd_kw_free(kw1); - rd_kw_free(kw2); } SECTION("Keyword idiv") { - rd_kw_type *kw1 = rd_kw_alloc("KW1", 1000, RD_FLOAT); - rd_kw_type *kw2 = rd_kw_alloc("KW2", 1000, RD_FLOAT); - for (int i = 0; i < 1000; i++) { - rd_kw_iset_float(kw1, i, 20.0f); - rd_kw_iset_float(kw2, i, 4.0f); - } - rd_region_kw_idiv(region, kw1, kw2, false); + rd::KW kw1{"KW1", std::vector(1000, 20.0f)}; + rd::KW kw2{"KW2", std::vector(1000, 4.0f)}; + rd_region_kw_idiv(region, &kw1, &kw2, false); const auto list = rd_region_get_global_list(region); - REQUIRE_THAT(rd_kw_iget_float(kw1, list.at(0)), + REQUIRE_THAT(kw1.at(list.at(0)), Catch::Matchers::WithinAbs(5.0f, 0.01f)); - rd_kw_free(kw1); - rd_kw_free(kw2); } SECTION("Sum keyword int") { - rd_kw_type *kw = rd_kw_alloc("TEST", 1000, RD_INT); - for (int i = 0; i < 1000; i++) - rd_kw_iset_int(kw, i, 2); - int sum = rd_region_sum_kw_int(region, kw, false); + rd::KW kw{"TEST", std::vector(1000, 2)}; + int sum = rd_region_sum_kw(region, &kw, false); REQUIRE(sum == 1000); - rd_kw_free(kw); } SECTION("Sum keyword float") { - rd_kw_type *kw = rd_kw_alloc("TEST", 1000, RD_FLOAT); - for (int i = 0; i < 1000; i++) - rd_kw_iset_float(kw, i, 2.5f); - float sum = rd_region_sum_kw_float(region, kw, false); + rd::KW kw{"TEST", std::vector(1000, 2.5f)}; + float sum = rd_region_sum_kw(region, &kw, false); REQUIRE_THAT(sum, Catch::Matchers::WithinAbs(1250.0f, 0.01f)); - rd_kw_free(kw); } SECTION("Sum keyword double") { - rd_kw_type *kw = rd_kw_alloc("TEST", 1000, RD_DOUBLE); - for (int i = 0; i < 1000; i++) - rd_kw_iset_double(kw, i, 2.5); - double sum = rd_region_sum_kw_double(region, kw, false); + rd::KW kw{"TEST", std::vector(1000, 2.5)}; + double sum = rd_region_sum_kw(region, &kw, false); REQUIRE_THAT(sum, Catch::Matchers::WithinAbs(1250.0, 0.01f)); - rd_kw_free(kw); } } rd_region_free(region); diff --git a/lib/tests/test_rd_sum.cpp b/lib/tests/test_rd_sum.cpp index d085d7620..3a3284137 100644 --- a/lib/tests/test_rd_sum.cpp +++ b/lib/tests/test_rd_sum.cpp @@ -31,6 +31,7 @@ #include "detail/resdata/rd_unsmry_loader.hpp" #include "resdata/FortIO.hpp" +#include "resdata/rd_type.hpp" #include "resdata/smspec_node.hpp" #include "tmpdir.hpp" @@ -103,15 +104,13 @@ time_t write_test_summary(const std::string &case_path, const WriteSpec &spec, void write_single_string_kw(ERT::FortIO &fortio, const char *name, const char *value) { - auto kw = make_rd_kw(name, 1, RD_CHAR); - rd_kw_iset_string8(kw.get(), 0, value); - rd_kw_fwrite(kw.get(), fortio); + rd::KW kw{name, {std::string(value)}}; + kw.fwrite(fortio); } void write_single_int_kw(ERT::FortIO &fortio, const char *name, int value) { - auto kw = make_rd_kw(name, 1, RD_INT); - rd_kw_iset_int(kw.get(), 0, value); - rd_kw_fwrite(kw.get(), fortio); + rd::KW kw{name, std::vector{value}}; + kw.fwrite(fortio); } void write_malformed_lgr_smspec(const fs::path &path, bool with_lgrs, @@ -120,35 +119,25 @@ void write_malformed_lgr_smspec(const fs::path &path, bool with_lgrs, constexpr int n = 1; ERT::FortIO fortio(path.string(), std::ios_base::out, false); - auto dimens = make_rd_kw(DIMENS_KW, DIMENS_SIZE, RD_INT); - rd_kw_scalar_set_int(dimens.get(), 0); - rd_kw_iset_int(dimens.get(), DIMENS_SMSPEC_SIZE_INDEX, n); - rd_kw_iset_int(dimens.get(), DIMENS_SMSPEC_NX_INDEX, 10); - rd_kw_iset_int(dimens.get(), DIMENS_SMSPEC_NY_INDEX, 10); - rd_kw_iset_int(dimens.get(), DIMENS_SMSPEC_NZ_INDEX, 10); - rd_kw_iset_int(dimens.get(), DIMENS_SMSPEC_RESTART_STEP_INDEX, 0); - rd_kw_fwrite(dimens.get(), fortio); - - auto keywords_kw = make_rd_kw(KEYWORDS_KW, n, RD_CHAR); - auto wgnames_kw = make_rd_kw(WGNAMES_KW, n, RD_CHAR); - auto units_kw = make_rd_kw(UNITS_KW, n, RD_CHAR); - auto nums_kw = make_rd_kw(NUMS_KW, n, RD_INT); - - rd_kw_iset_string8(keywords_kw.get(), 0, "LBPR"); - rd_kw_iset_string8(wgnames_kw.get(), 0, ""); - rd_kw_iset_string8(units_kw.get(), 0, "BARS"); - rd_kw_iset_int(nums_kw.get(), 0, 0); - - rd_kw_fwrite(keywords_kw.get(), fortio); - rd_kw_fwrite(wgnames_kw.get(), fortio); - rd_kw_fwrite(nums_kw.get(), fortio); - rd_kw_fwrite(units_kw.get(), fortio); - - auto startdat = make_rd_kw(STARTDAT_KW, 3, RD_INT); - rd_kw_iset_int(startdat.get(), STARTDAT_DAY_INDEX, 1); - rd_kw_iset_int(startdat.get(), STARTDAT_MONTH_INDEX, 1); - rd_kw_iset_int(startdat.get(), STARTDAT_YEAR_INDEX, 2010); - rd_kw_fwrite(startdat.get(), fortio); + rd::KW dimens{DIMENS_KW, std::vector{n, 10, 10, 10, 0, 0}}; + dimens.fwrite(fortio); + + rd::KW keywords_kw{KEYWORDS_KW, n, RD_CHAR}; + rd::KW wgnames_kw{WGNAMES_KW, n, RD_CHAR}; + rd::KW units_kw{UNITS_KW, n, RD_CHAR}; + rd::KW nums_kw{NUMS_KW, std::vector{0}}; + + keywords_kw.set_padded(0, "LBPR"); + wgnames_kw.set_padded(0, ""); + units_kw.set_padded(0, "BARS"); + + keywords_kw.fwrite(fortio); + wgnames_kw.fwrite(fortio); + nums_kw.fwrite(fortio); + units_kw.fwrite(fortio); + + rd::KW startdat{STARTDAT_KW, std::vector{1, 1, 2010}}; + startdat.fwrite(fortio); if (with_lgrs) write_single_string_kw(fortio, LGRS_KW, "LGR1"); @@ -747,12 +736,10 @@ TEST_CASE_METHOD(Tmpdir, "Restart writer writes has restart kw") { REQUIRE(view->has_kw(RESTART_KW)); SECTION("Parent case name is padded across 8-char blocks") { - 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 "); - REQUIRE(std::string(static_cast( - rd_kw_iget_ptr(restart_kw, 1))) == " "); + rd::KW *restart_kw = view->get_kw(RESTART_KW, 0); + REQUIRE(restart_kw->size() == 8); + REQUIRE(restart_kw->at(0) == "CASE1 "); + REQUIRE(restart_kw->at(1) == " "); } SECTION("Loading with include_restart inserts the parent's FOPT values") { @@ -786,11 +773,11 @@ TEST_CASE_METHOD(Tmpdir, "Restart case names are split across the 8 blocks") { auto smspec_file = rd::File::open(name + ".SMSPEC"); auto view = smspec_file->get_global_view(); 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); + rd::KW *restart_kw = view->get_kw(RESTART_KW, 0); + REQUIRE(restart_kw->size() == 8); for (int n = 0; n < 8; ++n) { const std::string expected = "WWWWGGG" + std::to_string(n); - REQUIRE(std::string(rd_kw_iget_char_ptr(restart_kw, n)) == expected); + REQUIRE(restart_kw->at(n) == expected); } } @@ -1372,31 +1359,31 @@ SCENARIO_METHOD(Tmpdir, "Loading Restarts") { auto smspec_in = rd::File::open(case3_path + ".SMSPEC"); auto sum_in = rd::File::open(case3_path + ".UNSMRY"); - rd_kw_type *keywords = smspec_in->get_kw("KEYWORDS", 0); - rd_kw_resize(keywords, 5); - rd_kw_iset_char_ptr(keywords, 3, "WTPRWI1"); - rd_kw_iset_char_ptr(keywords, 4, "BPR"); + rd::KW *keywords = smspec_in->get_kw("KEYWORDS", 0); + keywords->resize(5); + keywords->set_padded(3, "WTPRWI1"); + keywords->set_padded(4, "BPR"); - rd_kw_type *nums = smspec_in->get_kw("NUMS", 0); - rd_kw_resize(nums, 5); - int *nums_ptr = rd_kw_get_int_ptr(nums); + rd::KW *nums = smspec_in->get_kw("NUMS", 0); + nums->resize(5); + int *nums_ptr = nums->get_vector().data(); nums_ptr[3] = 5; nums_ptr[4] = 8; - rd_kw_type *wgnames = smspec_in->get_kw("WGNAMES", 0); - rd_kw_resize(wgnames, 5); - rd_kw_iset_char_ptr(wgnames, 4, ":+:+:+:+"); + rd::KW *wgnames = smspec_in->get_kw("WGNAMES", 0); + wgnames->resize(5); + wgnames->at(4) = ":+:+:+:+"; - rd_kw_type *units = smspec_in->get_kw("UNITS", 0); - rd_kw_resize(units, 5); - rd_kw_iset_char_ptr(units, 4, "BARS"); + rd::KW *units = smspec_in->get_kw("UNITS", 0); + units->resize(5); + units->at(4) = rd::pad_spaces("BARS", 8); for (size_t i = 0; i < sum_in->num_named_kw("PARAMS"); ++i) { - rd_kw_type *params_kw = sum_in->get_kw("PARAMS", i); - rd_kw_resize(params_kw, 5); - auto *ptr = static_cast(rd_kw_get_void_ptr(params_kw)); - ptr[4] = ptr[3]; - ptr[3] = -1.0f; + rd::KW *params_kw = sum_in->get_kw("PARAMS", i); + params_kw->resize(5); + auto &vec = params_kw->get_vector(); + vec[4] = vec[3]; + vec[3] = -1.0f; } { diff --git a/lib/tests/test_well_info.cpp b/lib/tests/test_well_info.cpp index b091dc363..5ffae7672 100644 --- a/lib/tests/test_well_info.cpp +++ b/lib/tests/test_well_info.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "grid_fixtures.hpp" #include "tmpdir.hpp" @@ -28,18 +29,14 @@ namespace { void write_int_kw(ERT::FortIO &fortio, const char *name, const std::vector &data) { - auto kw = make_rd_kw(name, static_cast(data.size()), RD_INT); - for (size_t i = 0; i < data.size(); ++i) - rd_kw_iset_int(kw.get(), static_cast(i), data[i]); - rd_kw_fwrite(kw.get(), fortio); + rd::KW kw{name, data}; + kw.fwrite(fortio); } void write_double_kw(ERT::FortIO &fortio, const char *name, const std::vector &data) { - auto kw = make_rd_kw(name, static_cast(data.size()), RD_DOUBLE); - for (size_t i = 0; i < data.size(); ++i) - rd_kw_iset_double(kw.get(), static_cast(i), data[i]); - rd_kw_fwrite(kw.get(), fortio); + rd::KW kw{name, data}; + kw.fwrite(fortio); } struct RestartLayout { @@ -81,9 +78,9 @@ void write_restart_file(const std::string &path, const RestartLayout &layout) { 0)); if (layout.with_zwel) { - auto zwel = make_rd_kw(ZWEL_KW, layout.nzwelz * layout.nwells, RD_CHAR); - rd_kw_iset_string_ptr(zwel.get(), 0, "WELL-1"); - rd_kw_fwrite(zwel.get(), fortio); + rd::KW zwel{ZWEL_KW, layout.nzwelz * layout.nwells, RD_CHAR}; + zwel.set_padded(0, "WELL-1"); + zwel.fwrite(fortio); } fortio.fflush(); diff --git a/lib/tests/test_well_keyword_validation.cpp b/lib/tests/test_well_keyword_validation.cpp index 2b774b085..be8d0c8b8 100644 --- a/lib/tests/test_well_keyword_validation.cpp +++ b/lib/tests/test_well_keyword_validation.cpp @@ -1,8 +1,11 @@ #include +#include +#include #include #include #include #include +#include #include #include @@ -29,132 +32,122 @@ namespace { * contain every index the loader reads. */ struct Dims { - int nx = 3; - int ny = 3; - int nz = 3; - int nactive = 27; - int nwells = 1; - int ncwmax = 1; - int niwelz = 72; - int nzwelz = 3; - int nxwelz = 8; - int niconz = 16; - int nsconz = 2; - int nxconz = 52; - int nisegz = 8; - int nsegmx = 1; - int nrsegz = 12; - int nlbrmx = 1; - int nilbrz = 2; + size_t nx = 3; + size_t ny = 3; + size_t nz = 3; + size_t nactive = 27; + size_t nwells = 1; + size_t ncwmax = 1; + size_t niwelz = 72; + size_t nzwelz = 3; + size_t nxwelz = 8; + size_t niconz = 16; + size_t nsconz = 2; + size_t nxconz = 52; + size_t nisegz = 8; + size_t nsegmx = 1; + size_t nrsegz = 12; + size_t nlbrmx = 1; + size_t nilbrz = 2; }; -rd_kw_ptr build_intehead(const Dims &d) { - auto kw = make_rd_kw(INTEHEAD_KW, 412, RD_INT); - rd_kw_scalar_set_int(kw.get(), 0); - rd_kw_iset_int(kw.get(), INTEHEAD_UNIT_INDEX, INTEHEAD_METRIC_VALUE); - rd_kw_iset_int(kw.get(), INTEHEAD_NX_INDEX, d.nx); - rd_kw_iset_int(kw.get(), INTEHEAD_NY_INDEX, d.ny); - rd_kw_iset_int(kw.get(), INTEHEAD_NZ_INDEX, d.nz); - rd_kw_iset_int(kw.get(), INTEHEAD_NACTIVE_INDEX, d.nactive); - rd_kw_iset_int(kw.get(), INTEHEAD_NWELLS_INDEX, d.nwells); - rd_kw_iset_int(kw.get(), INTEHEAD_NCWMAX_INDEX, d.ncwmax); - rd_kw_iset_int(kw.get(), INTEHEAD_NIWELZ_INDEX, d.niwelz); - rd_kw_iset_int(kw.get(), INTEHEAD_NXWELZ_INDEX, d.nxwelz); - rd_kw_iset_int(kw.get(), INTEHEAD_NZWELZ_INDEX, d.nzwelz); - rd_kw_iset_int(kw.get(), INTEHEAD_NICONZ_INDEX, d.niconz); - rd_kw_iset_int(kw.get(), INTEHEAD_NSCONZ_INDEX, d.nsconz); - rd_kw_iset_int(kw.get(), INTEHEAD_NXCONZ_INDEX, d.nxconz); - rd_kw_iset_int(kw.get(), INTEHEAD_NISEGZ_INDEX, d.nisegz); - rd_kw_iset_int(kw.get(), INTEHEAD_NSEGMX_INDEX, d.nsegmx); - rd_kw_iset_int(kw.get(), INTEHEAD_NSWLMX_INDEX, 1); - rd_kw_iset_int(kw.get(), INTEHEAD_NLBRMX_INDEX, d.nlbrmx); - rd_kw_iset_int(kw.get(), INTEHEAD_NILBRZ_INDEX, d.nilbrz); - rd_kw_iset_int(kw.get(), INTEHEAD_NRSEGZ_INDEX, d.nrsegz); - return kw; +std::unique_ptr build_intehead(const Dims &d) { + std::vector data(412, 0); + data[INTEHEAD_UNIT_INDEX] = INTEHEAD_METRIC_VALUE; + data[INTEHEAD_NX_INDEX] = static_cast(d.nx); + data[INTEHEAD_NY_INDEX] = static_cast(d.ny); + data[INTEHEAD_NZ_INDEX] = static_cast(d.nz); + data[INTEHEAD_NACTIVE_INDEX] = static_cast(d.nactive); + data[INTEHEAD_NWELLS_INDEX] = static_cast(d.nwells); + data[INTEHEAD_NCWMAX_INDEX] = static_cast(d.ncwmax); + data[INTEHEAD_NIWELZ_INDEX] = static_cast(d.niwelz); + data[INTEHEAD_NXWELZ_INDEX] = static_cast(d.nxwelz); + data[INTEHEAD_NZWELZ_INDEX] = static_cast(d.nzwelz); + data[INTEHEAD_NICONZ_INDEX] = static_cast(d.niconz); + data[INTEHEAD_NSCONZ_INDEX] = static_cast(d.nsconz); + data[INTEHEAD_NXCONZ_INDEX] = static_cast(d.nxconz); + data[INTEHEAD_NISEGZ_INDEX] = static_cast(d.nisegz); + data[INTEHEAD_NSEGMX_INDEX] = static_cast(d.nsegmx); + data[INTEHEAD_NSWLMX_INDEX] = 1; + data[INTEHEAD_NLBRMX_INDEX] = static_cast(d.nlbrmx); + data[INTEHEAD_NILBRZ_INDEX] = static_cast(d.nilbrz); + data[INTEHEAD_NRSEGZ_INDEX] = static_cast(d.nrsegz); + return std::make_unique(INTEHEAD_KW, std::move(data)); } -rd_kw_ptr build_logihead() { - auto kw = make_rd_kw(LOGIHEAD_KW, LOGIHEAD_RESTART_SIZE, RD_BOOL); - for (int i = 0; i < LOGIHEAD_RESTART_SIZE; ++i) - rd_kw_iset_bool(kw.get(), i, false); - return kw; +std::unique_ptr build_logihead() { + return std::make_unique(LOGIHEAD_KW, LOGIHEAD_RESTART_SIZE, + RD_BOOL); } -rd_kw_ptr build_doubhead() { - auto kw = make_rd_kw(DOUBHEAD_KW, 1, RD_DOUBLE); - rd_kw_iset_double(kw.get(), DOUBHEAD_DAYS_INDEX, 0.0); - return kw; +std::unique_ptr build_doubhead() { + return std::make_unique(DOUBHEAD_KW, std::vector{0.0}); } -rd_kw_ptr build_iwel(const Dims &d) { - auto kw = make_rd_kw(IWEL_KW, d.niwelz * d.nwells, RD_INT); - rd_kw_scalar_set_int(kw.get(), 0); - rd_kw_iset_int(kw.get(), IWEL_HEADI_INDEX, 1); - rd_kw_iset_int(kw.get(), IWEL_HEADJ_INDEX, 1); - rd_kw_iset_int(kw.get(), IWEL_HEADK_INDEX, 1); - rd_kw_iset_int(kw.get(), IWEL_CONNECTIONS_INDEX, 1); - rd_kw_iset_int(kw.get(), IWEL_TYPE_INDEX, IWEL_PRODUCER); - rd_kw_iset_int(kw.get(), IWEL_STATUS_INDEX, 1); - rd_kw_iset_int(kw.get(), IWEL_SEGMENTED_WELL_NR_INDEX, 1); - return kw; +std::unique_ptr build_iwel(const Dims &d) { + std::vector data(d.niwelz * d.nwells, 0); + data[IWEL_HEADI_INDEX] = 1; + data[IWEL_HEADJ_INDEX] = 1; + data[IWEL_HEADK_INDEX] = 1; + data[IWEL_CONNECTIONS_INDEX] = 1; + data[IWEL_TYPE_INDEX] = IWEL_PRODUCER; + data[IWEL_STATUS_INDEX] = 1; + data[IWEL_SEGMENTED_WELL_NR_INDEX] = 1; + return std::make_unique(IWEL_KW, std::move(data)); } -rd_kw_ptr build_zwel(const Dims &d) { - auto kw = make_rd_kw(ZWEL_KW, d.nzwelz * d.nwells, RD_CHAR); - rd_kw_iset_string_ptr(kw.get(), 0, "WELL-1"); +std::unique_ptr build_zwel(const Dims &d) { + auto kw = std::make_unique(ZWEL_KW, d.nzwelz * d.nwells, RD_CHAR); + kw->set_padded(0, "WELL-1"); return kw; } -rd_kw_ptr build_icon(const Dims &d) { - auto kw = make_rd_kw(ICON_KW, d.niconz * d.ncwmax * d.nwells, RD_INT); - rd_kw_scalar_set_int(kw.get(), 0); - rd_kw_iset_int(kw.get(), ICON_IC_INDEX, 1); - rd_kw_iset_int(kw.get(), ICON_I_INDEX, 1); - rd_kw_iset_int(kw.get(), ICON_J_INDEX, 1); - rd_kw_iset_int(kw.get(), ICON_K_INDEX, 1); - rd_kw_iset_int(kw.get(), ICON_STATUS_INDEX, 1); - rd_kw_iset_int(kw.get(), ICON_DIRECTION_INDEX, ICON_DIRZ); - rd_kw_iset_int(kw.get(), ICON_SEGMENT_INDEX, 0); - return kw; +std::unique_ptr build_icon(const Dims &d) { + std::vector data(d.niconz * d.ncwmax * d.nwells, 0); + data[ICON_IC_INDEX] = 1; + data[ICON_I_INDEX] = 1; + data[ICON_J_INDEX] = 1; + data[ICON_K_INDEX] = 1; + data[ICON_STATUS_INDEX] = 1; + data[ICON_DIRECTION_INDEX] = ICON_DIRZ; + data[ICON_SEGMENT_INDEX] = 0; + return std::make_unique(ICON_KW, std::move(data)); } -rd_kw_ptr build_scon(const Dims &d) { - auto kw = make_rd_kw(SCON_KW, d.nsconz * d.ncwmax * d.nwells, RD_DOUBLE); - rd_kw_scalar_set_double(kw.get(), 0.0); - rd_kw_iset_double(kw.get(), SCON_CF_INDEX, 1.0); - return kw; +std::unique_ptr build_scon(const Dims &d) { + std::vector data(d.nsconz * d.ncwmax * d.nwells, 0.0); + data[SCON_CF_INDEX] = 1.0; + return std::make_unique(SCON_KW, std::move(data)); } -rd_kw_ptr build_xcon(const Dims &d) { - auto kw = make_rd_kw(XCON_KW, d.nxconz * d.ncwmax * d.nwells, RD_DOUBLE); - rd_kw_scalar_set_double(kw.get(), 0.0); +std::unique_ptr build_xcon(const Dims &d) { + auto kw = std::make_unique(XCON_KW, d.nxconz * d.ncwmax * d.nwells, + RD_DOUBLE); + kw->scalar_set(0.0); return kw; } -rd_kw_ptr build_iseg(const Dims &d) { - auto kw = make_rd_kw(ISEG_KW, d.nisegz * d.nsegmx, RD_INT); - rd_kw_scalar_set_int(kw.get(), 0); +std::unique_ptr build_iseg(const Dims &d) { + std::vector data(d.nisegz * d.nsegmx, 0); // Make the single segment inactive (branch -> INACTIVE) - rd_kw_iset_int(kw.get(), ISEG_OUTLET_INDEX, 0); - rd_kw_iset_int(kw.get(), ISEG_BRANCH_INDEX, -1); - return kw; + data[ISEG_OUTLET_INDEX] = 0; + data[ISEG_BRANCH_INDEX] = -1; + return std::make_unique(ISEG_KW, std::move(data)); } -rd_kw_ptr build_rseg(const Dims &d) { - auto kw = make_rd_kw(RSEG_KW, d.nrsegz * d.nsegmx, RD_DOUBLE); - rd_kw_scalar_set_double(kw.get(), 0.0); - return kw; +std::unique_ptr build_rseg(const Dims &d) { + return std::make_unique( + RSEG_KW, std::vector(d.nrsegz * d.nsegmx, 0.0)); } -rd_kw_ptr build_xwel(const Dims &d) { - auto kw = make_rd_kw(XWEL_KW, d.nxwelz * d.nwells, RD_DOUBLE); - rd_kw_scalar_set_double(kw.get(), 0.0); - return kw; +std::unique_ptr build_xwel(const Dims &d) { + return std::make_unique( + XWEL_KW, std::vector(d.nxwelz * d.nwells, 0.0)); } struct NamedKw { std::string name; - rd_kw_ptr kw; + std::unique_ptr kw; }; std::vector build_all(const Dims &d) { @@ -177,7 +170,7 @@ void write_file(const std::string &path, const std::vector &kws) { ERT::FortIO fortio(path, std::ios_base::out); for (const auto &nk : kws) { if (nk.kw) - rd_kw_fwrite(nk.kw.get(), fortio); + nk.kw->fwrite(fortio); } fortio.fflush(); } @@ -206,20 +199,20 @@ void mutate(std::vector &kws, const std::string &name, Mode mode) { auto it = std::find_if(kws.begin(), kws.end(), [&](const NamedKw &nk) { return nk.name == name; }); REQUIRE(it != kws.end()); - int size = rd_kw_get_size(it->kw.get()); + size_t size = it->kw->size(); const Spec &spec = kw_specs().at(name); switch (mode) { case Mode::MISSING: it->kw.reset(); break; case Mode::WRONG_TYPE: - it->kw = make_rd_kw(name.c_str(), size, spec.wrong); + it->kw = std::make_unique(name, size, spec.wrong); break; case Mode::EMPTY: - it->kw = make_rd_kw(name.c_str(), 0, spec.type); + it->kw = std::make_unique(name, 0, spec.type); break; case Mode::SHORT: - it->kw = make_rd_kw(name.c_str(), 1, spec.type); + it->kw = std::make_unique(name, 1, spec.type); break; } } @@ -242,13 +235,13 @@ struct Case { const char *kw; Mode mode; bool throws; - int wells; + size_t wells; }; std::vector all_cases() { return { {INTEHEAD_KW, Mode::MISSING, true, 0}, - {INTEHEAD_KW, Mode::WRONG_TYPE, false, 0}, // Should throw but doesn't + {INTEHEAD_KW, Mode::WRONG_TYPE, true, 0}, {INTEHEAD_KW, Mode::EMPTY, false, 0}, {INTEHEAD_KW, Mode::SHORT, false, 0}, @@ -268,7 +261,7 @@ std::vector all_cases() { {IWEL_KW, Mode::SHORT, true, 0}, {ZWEL_KW, Mode::MISSING, true, 0}, - {ZWEL_KW, Mode::WRONG_TYPE, false, 1}, // Should throw but doesn't + {ZWEL_KW, Mode::WRONG_TYPE, true, 0}, {ZWEL_KW, Mode::EMPTY, true, 0}, {ZWEL_KW, Mode::SHORT, false, 1}, @@ -309,7 +302,9 @@ TEST_CASE_METHOD(Tmpdir, "well keyword failure conditions", "[well][wellkw]") { CAPTURE(c.kw, mode_name(c.mode)); Dims d; - auto grid = make_rectangular_grid(d.nx, d.ny, d.nz, 1.0, 1.0, 1.0, nullptr); + auto grid = + make_rectangular_grid(static_cast(d.nx), static_cast(d.ny), + static_cast(d.nz), 1.0, 1.0, 1.0, nullptr); auto kws = build_all(d); mutate(kws, c.kw, c.mode); diff --git a/lib/util/util.cpp b/lib/util/util.cpp index 7a17828d1..bcecc5410 100644 --- a/lib/util/util.cpp +++ b/lib/util/util.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -1216,22 +1217,6 @@ size_t util_fd_size(int fd) { return buffer.st_size; } -bool util_ftruncate(FILE *stream, long size) { - int fd = fileno(stream); - int int_return; - -#ifdef HAVE_FTRUNCATE - int_return = ftruncate(fd, size); -#else - int_return = _chsize(fd, size); -#endif - - if (int_return == 0) - return true; - else - return false; -} - /* The windows stat structure has the inode element, but it is not set. Actually - this is a property of the filesystem, and not the diff --git a/python/resdata/resfile/rd_kw.py b/python/resdata/resfile/rd_kw.py index fc7f2ad13..f3c591e38 100644 --- a/python/resdata/resfile/rd_kw.py +++ b/python/resdata/resfile/rd_kw.py @@ -747,18 +747,14 @@ def sum(self, mask=None, force_active=False): Bool: The number of true values """ if mask is None: - if self.data_type.is_int(): - return _kw._int_sum(self) - elif self.data_type.is_float(): - return _kw._float_sum(self) - elif self.data_type.is_double(): - return _kw._float_sum(self) - elif self.data_type.is_bool(): - _sum = 0 - for elm in self: - if elm: - _sum += 1 - return _sum + if ( + self.data_type.is_int() + or self.data_type.is_float() + or self.data_type.is_double() + or self.data_type.is_bool() + ): + view = self.numpy_view() + return np.sum(view, dtype=view.dtype) else: raise ValueError( 'The keyword "%s" is of string type - sum is not implemented' diff --git a/tests/rd_tests/test_rd_kw.py b/tests/rd_tests/test_rd_kw.py index 93103601d..b5051abc4 100644 --- a/tests/rd_tests/test_rd_kw.py +++ b/tests/rd_tests/test_rd_kw.py @@ -1521,7 +1521,7 @@ def first_different_self(self, kw): def test_create_negative_size_raises(): - with pytest.raises(ValueError, match="rd_kw size was negative"): + with pytest.raises(TypeError): ResdataKW("KW", -1, ResDataType.RD_INT)