diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp index ecc7a6324..c91aa13ea 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp @@ -302,20 +302,34 @@ template class Dataset { } } - void add_attribute_buffer(std::string_view component, std::string_view attribute, Data* data) { - Idx const idx = find_component(component, true); - Buffer& buffer = buffers_[idx]; - if (!is_columnar(buffer)) { - throw DatasetError{"Cannot add attribute buffers to row-based dataset!\n"}; - } - if (std::ranges::find_if(buffer.attributes, [&attribute](auto const& buffer_attribute) { - return buffer_attribute.meta_attribute->name == attribute; - }) != buffer.attributes.end()) { - throw DatasetError{"Cannot have duplicated attribute buffers!\n"}; - } - AttributeBuffer attribute_buffer{ - .data = data, .meta_attribute = &dataset_info_.component_info[idx].component->get_attribute(attribute)}; - buffer.attributes.emplace_back(attribute_buffer); + void add_attribute_buffer(std::string_view component, std::string_view attribute, Data* data) + requires(!is_indptr_mutable_v) + { + add_attribute_buffer_impl(component, attribute, data); + } + + /* + we decided to go with the same behavior between `add_attribute_buffer` and `set_attribute_buffer` (but different + entrypoints). The behavior of `set_attribute_buffer` therefore differs from the one of `set_buffer`. The reasoning + is as follows: + + For components: + - the deserializer tells the user via the dataset info that a certain component is present in the serialized + data. + - It is possible to efficiently determine whether that is the case. + - The user can then only call `set_buffer` for those components that are already present + For attributes: + - the deserializer would need to go over the entire dataset to look for components with the map serialization + representation to determine whether an attribute is present. + - this is expensive. + - the deserializer therefore cannot let the user know beforehand which attributes are present. + - `set_attribute_buffer` therefore should only be called if it has not been set yet. + - this is the same behavior as `add_attribute_buffer`. + */ + void set_attribute_buffer(std::string_view component, std::string_view attribute, Data* data) + requires is_indptr_mutable_v + { + add_attribute_buffer_impl(component, attribute, data); } // get buffer by component type @@ -442,6 +456,22 @@ template class Dataset { buffers_.push_back(Buffer{}); } + void add_attribute_buffer_impl(std::string_view component, std::string_view attribute, Data* data) { + Idx const idx = find_component(component, true); + Buffer& buffer = buffers_[idx]; + if (!is_columnar(buffer)) { + throw DatasetError{"Cannot add attribute buffers to row-based dataset!\n"}; + } + if (std::ranges::find_if(buffer.attributes, [&attribute](auto const& buffer_attribute) { + return buffer_attribute.meta_attribute->name == attribute; + }) != buffer.attributes.end()) { + throw DatasetError{"Cannot have duplicated attribute buffers!\n"}; + } + AttributeBuffer const attribute_buffer{ + .data = data, .meta_attribute = &dataset_info_.component_info[idx].component->get_attribute(attribute)}; + buffer.attributes.emplace_back(attribute_buffer); + } + template RangeType get_span_impl(RangeType const& total_range, Idx scenario, Buffer const& buffer, ComponentInfo const& info) const { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp index c1705a8ef..6e29885fb 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp @@ -720,9 +720,7 @@ class MainModelImpl, ComponentLis return true; } - auto const is_component_update_independent = [&update_data]() -> bool { - // get span of all the update data - auto const all_spans = update_data.get_buffer_span_all_scenarios(); + auto const process_buffer_span = [](auto const& all_spans) -> bool { // Remember the first batch size, then loop over the remaining batches and check if they are of the same // length auto const elements_per_scenario = static_cast(all_spans.front().size()); @@ -747,6 +745,16 @@ class MainModelImpl, ComponentLis }); }; + auto const is_component_update_independent = [&update_data, &process_buffer_span]() -> bool { + // get span of all the update data + if (update_data.is_columnar(CT::name)) { + return process_buffer_span.template operator()( + update_data.get_columnar_buffer_span_all_scenarios()); + } + return process_buffer_span.template operator()( + update_data.get_buffer_span_all_scenarios()); + }; + // check all components auto const update_independent = run_functor_with_all_types_return_array(is_component_update_independent); return std::ranges::all_of(update_independent, [](bool const is_independent) { return is_independent; }); @@ -828,7 +836,7 @@ class MainModelImpl, ComponentLis void output_result(MathOutput> const& math_output, MutableDataset const& result_data, Idx pos = 0) const { auto const output_func = [this, &math_output, &result_data, pos]() { - auto process_output = [this, &math_output](auto const& span) { + auto process_output_span = [this, &math_output](auto const& span) { if (std::empty(span)) { return; } @@ -838,11 +846,11 @@ class MainModelImpl, ComponentLis if (result_data.is_columnar(CT::name)) { auto const span = result_data.get_columnar_buffer_span::type, CT>(pos); - process_output(span); + process_output_span(span); } else { auto const span = result_data.get_buffer_span::type, CT>(pos); - process_output(span); + process_output_span(span); } }; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index 41c9622fd..43a59cff6 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -120,11 +120,8 @@ inline std::vector> check_indistguishable(Idx co } inline bool in_graph(std::pair const& e, std::map const& d) { - if (auto edges_it = d.find(e.first); - edges_it != d.cend() && std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) { - return true; - } - return false; + auto edges_it = d.find(e.first); + return edges_it != d.cend() && std::ranges::find(edges_it->second, e.second) != edges_it->second.cend(); } inline IdxVector remove_vertices_update_degrees(Idx const u, std::map& d, DegreeLookup& dgd, diff --git a/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset.h b/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset.h index 98c0e463e..cffb87bc0 100644 --- a/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset.h +++ b/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset.h @@ -140,13 +140,25 @@ PGM_API void PGM_destroy_dataset_const(PGM_ConstDataset* dataset); * If the component is not uniform, indptr must point to an array of size (batch_size + 1). * The values in the array must be not decreasing. * And we must have indptr[0] = 0, indptr[batch_size] = total_elements. - * @param data A void pointer to the buffer data. + * @param data A void pointer to the row based buffer data or a nullptr for columnar data. * @return */ PGM_API void PGM_dataset_const_add_buffer(PGM_Handle* handle, PGM_ConstDataset* dataset, char const* component, PGM_Idx elements_per_scenario, PGM_Idx total_elements, PGM_Idx const* indptr, void const* data); +/** + * @brief Add a attribute buffer to an instance of PGM_ConstDataset/component. + * @param handle + * @param dataset The pointer to the PGM_ConstDataset. + * @param component The name of the component. + * @param attribute The name of the attribute. + * @param data A void pointer to the buffer data. + * @return + */ +PGM_API void PGM_dataset_const_add_attribute_buffer(PGM_Handle* handle, PGM_ConstDataset* dataset, + char const* component, char const* attribute, void const* data); + /** * @brief Get the dataset info of the instance PGM_ConstDataset. * @param handle @@ -173,12 +185,24 @@ PGM_API PGM_DatasetInfo const* PGM_dataset_writable_get_info(PGM_Handle* handle, * @param indptr A pointer to an array of indptr of a non-uniform component. * If the component is uniform, indptr must be NULL. * If the component is not uniform, indptr must point to an array of size (batch_size + 1). - * @param data A void pointer to the buffer data. + * @param data A void pointer to the row based buffer data or a nullptr for columnar data. * @return */ PGM_API void PGM_dataset_writable_set_buffer(PGM_Handle* handle, PGM_WritableDataset* dataset, char const* component, PGM_Idx* indptr, void* data); +/** + * @brief Set buffer into the instance PGM_WritableDataset. + * @param handle + * @param dataset A pointer to the PGM_WritableDataset. + * @param component The name of the component. + * @param attribute The name of the attribute. + * @param data A void pointer to the buffer data. + * @return + */ +PGM_API void PGM_dataset_writable_set_attribute_buffer(PGM_Handle* handle, PGM_WritableDataset* dataset, + char const* component, char const* attribute, void* data); + /** * @brief Create an instance of PGM_MutableDataset. * @param handle @@ -213,13 +237,25 @@ PGM_API void PGM_destroy_dataset_mutable(PGM_MutableDataset* dataset); * If the component is not uniform, indptr must point to an array of size (batch_size + 1). * The values in the array must be not decreasing. * And we must have indptr[0] = 0, indptr[batch_size] = total_elements. - * @param data A void pointer to the buffer data. + * @param data A void pointer to the row based buffer data or a nullptr for columnar data. * @return */ PGM_API void PGM_dataset_mutable_add_buffer(PGM_Handle* handle, PGM_MutableDataset* dataset, char const* component, PGM_Idx elements_per_scenario, PGM_Idx total_elements, PGM_Idx const* indptr, void* data); +/** + * @brief Add a attribute buffer to an instance of PGM_MutableDataset/component. + * @param handle + * @param dataset The pointer to the PGM_MutableDataset. + * @param component The name of the component. + * @param attribute The name of the attribute. + * @param data A void pointer to the buffer data. + * @return + */ +PGM_API void PGM_dataset_mutable_add_attribute_buffer(PGM_Handle* handle, PGM_MutableDataset* dataset, + char const* component, char const* attribute, void* data); + /** * @brief Get the dataset info of the instance PGM_MutableDataset. * @param handle diff --git a/power_grid_model_c/power_grid_model_c/src/dataset.cpp b/power_grid_model_c/power_grid_model_c/src/dataset.cpp index 8af04f0b6..3b19492b7 100644 --- a/power_grid_model_c/power_grid_model_c/src/dataset.cpp +++ b/power_grid_model_c/power_grid_model_c/src/dataset.cpp @@ -79,6 +79,13 @@ void PGM_dataset_const_add_buffer(PGM_Handle* handle, PGM_ConstDataset* dataset, PGM_regular_error); } +void PGM_dataset_const_add_attribute_buffer(PGM_Handle* handle, PGM_ConstDataset* dataset, char const* component, + char const* attribute, void const* data) { + call_with_catch( + handle, [dataset, component, attribute, data]() { dataset->add_attribute_buffer(component, attribute, data); }, + PGM_regular_error); +} + PGM_DatasetInfo const* PGM_dataset_const_get_info(PGM_Handle* /*unused*/, PGM_ConstDataset const* dataset) { return &dataset->get_description(); } @@ -96,6 +103,13 @@ void PGM_dataset_writable_set_buffer(PGM_Handle* handle, PGM_WritableDataset* da PGM_regular_error); } +void PGM_dataset_writable_set_attribute_buffer(PGM_Handle* handle, PGM_WritableDataset* dataset, char const* component, + char const* attribute, void* data) { + call_with_catch( + handle, [dataset, component, attribute, data]() { dataset->set_attribute_buffer(component, attribute, data); }, + PGM_regular_error); +} + // mutable dataset PGM_MutableDataset* PGM_create_dataset_mutable(PGM_Handle* handle, char const* dataset, PGM_Idx is_batch, @@ -121,6 +135,13 @@ void PGM_dataset_mutable_add_buffer(PGM_Handle* handle, PGM_MutableDataset* data PGM_regular_error); } +void PGM_dataset_mutable_add_attribute_buffer(PGM_Handle* handle, PGM_MutableDataset* dataset, char const* component, + char const* attribute, void* data) { + call_with_catch( + handle, [dataset, component, attribute, data]() { dataset->add_attribute_buffer(component, attribute, data); }, + PGM_regular_error); +} + PGM_DatasetInfo const* PGM_dataset_mutable_get_info(PGM_Handle* /*unused*/, PGM_MutableDataset const* dataset) { return &dataset->get_description(); } diff --git a/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/buffer.hpp b/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/buffer.hpp index e1b44d5c7..9f96024ef 100644 --- a/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/buffer.hpp +++ b/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/buffer.hpp @@ -33,14 +33,14 @@ class Buffer { buffer.handle_.call_with(PGM_buffer_set_value, attribute, buffer.buffer_.get(), src_ptr, buffer_offset, size, src_stride); } - void set_value(MetaAttribute const* attribute, RawDataConstPtr src_ptr, Idx src_stride) const { + void set_value(MetaAttribute const* attribute, RawDataConstPtr src_ptr, Idx src_stride) { set_value(attribute, *this, src_ptr, 0, size_, src_stride); } - void set_value(MetaAttribute const* attribute, RawDataConstPtr src_ptr, Idx buffer_offset, Idx src_stride) const { + void set_value(MetaAttribute const* attribute, RawDataConstPtr src_ptr, Idx buffer_offset, Idx src_stride) { set_value(attribute, *this, src_ptr, buffer_offset, 1, src_stride); } void set_value(MetaAttribute const* attribute, RawDataConstPtr src_ptr, Idx buffer_offset, Idx size, - Idx src_stride) const { + Idx src_stride) { set_value(attribute, *this, src_ptr, buffer_offset, size, src_stride); } diff --git a/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/dataset.hpp b/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/dataset.hpp index bc9291755..4f4112851 100644 --- a/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/dataset.hpp +++ b/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/dataset.hpp @@ -95,6 +95,24 @@ class DatasetWritable { set_buffer(*this, component, indptr, data); } + static void set_attribute_buffer(DatasetWritable& dataset, std::string const& component, + std::string const& attribute, RawDataPtr data) { + dataset.handle_.call_with(PGM_dataset_writable_set_attribute_buffer, dataset.dataset_, component.c_str(), + attribute.c_str(), data); + } + void set_attribute_buffer(std::string const& component, std::string const& attribute, RawDataPtr data) { + set_attribute_buffer(*this, component, attribute, data); + } + + static void set_attribute_buffer(DatasetWritable& dataset, std::string const& component, + std::string const& attribute, Buffer const& data) { + dataset.handle_.call_with(PGM_dataset_writable_set_attribute_buffer, dataset.dataset_, component.c_str(), + attribute.c_str(), data.get()); + } + void set_attribute_buffer(std::string const& component, std::string const& attribute, Buffer const& data) { + set_attribute_buffer(*this, component, attribute, data); + } + private: Handle handle_{}; RawWritableDataset* dataset_; @@ -115,8 +133,8 @@ class DatasetMutable { elements_per_scenario, total_elements, indptr, data); } void add_buffer(std::string const& component, Idx elements_per_scenario, Idx total_elements, Idx const* indptr, - RawDataPtr data) const { - add_buffer(*this, component.c_str(), elements_per_scenario, total_elements, indptr, data); + RawDataPtr data) { // NOSONAR: no const + add_buffer(*this, component, elements_per_scenario, total_elements, indptr, data); } static void add_buffer(DatasetMutable const& dataset, std::string const& component, Idx elements_per_scenario, @@ -125,10 +143,30 @@ class DatasetMutable { elements_per_scenario, total_elements, indptr, data.get()); } void add_buffer(std::string const& component, Idx elements_per_scenario, Idx total_elements, Idx const* indptr, - Buffer const& data) const { + Buffer const& data) { // NOSONAR: no const add_buffer(*this, component, elements_per_scenario, total_elements, indptr, data); } + static void add_attribute_buffer(DatasetMutable const& dataset, std::string const& component, + std::string const& attribute, RawDataPtr data) { + dataset.handle_.call_with(PGM_dataset_mutable_add_attribute_buffer, dataset.dataset_.get(), component.c_str(), + attribute.c_str(), data); + } + void add_attribute_buffer(std::string const& component, std::string const& attribute, + RawDataPtr data) { // NOSONAR: no const + add_attribute_buffer(*this, component, attribute, data); + } + + static void add_attribute_buffer(DatasetMutable const& dataset, std::string const& component, + std::string const& attribute, Buffer const& data) { + dataset.handle_.call_with(PGM_dataset_mutable_add_attribute_buffer, dataset.dataset_.get(), component.c_str(), + attribute.c_str(), data.get()); + } + void add_attribute_buffer(std::string const& component, std::string const& attribute, + Buffer const& data) { // NOSONAR: no const: no const + add_attribute_buffer(*this, component, attribute, data); + } + static DatasetInfo const& get_info(DatasetMutable const& dataset) { return dataset.info_; } DatasetInfo const& get_info() const { return get_info(*this); } @@ -158,7 +196,7 @@ class DatasetConst { elements_per_scenario, total_elements, indptr, data); } void add_buffer(std::string const& component, Idx elements_per_scenario, Idx total_elements, Idx const* indptr, - RawDataConstPtr data) const { + RawDataConstPtr data) { // NOSONAR: no const add_buffer(*this, component, elements_per_scenario, total_elements, indptr, data); } @@ -168,10 +206,30 @@ class DatasetConst { elements_per_scenario, total_elements, indptr, data.get()); } void add_buffer(std::string const& component, Idx elements_per_scenario, Idx total_elements, Idx const* indptr, - Buffer const& data) const { + Buffer const& data) { // NOSONAR: no const add_buffer(*this, component, elements_per_scenario, total_elements, indptr, data); } + static void add_attribute_buffer(DatasetConst const& dataset, std::string const& component, + std::string const& attribute, RawDataConstPtr data) { + dataset.handle_.call_with(PGM_dataset_const_add_attribute_buffer, dataset.dataset_.get(), component.c_str(), + attribute.c_str(), data); + } + void add_attribute_buffer(std::string const& component, std::string const& attribute, + RawDataConstPtr data) { // NOSONAR: no const + add_attribute_buffer(*this, component, attribute, data); + } + + static void add_attribute_buffer(DatasetConst const& dataset, std::string const& component, + std::string const& attribute, Buffer const& data) { + dataset.handle_.call_with(PGM_dataset_const_add_attribute_buffer, dataset.dataset_.get(), component.c_str(), + attribute.c_str(), data.get()); + } + void add_attribute_buffer(std::string const& component, std::string const& attribute, + Buffer const& data) { // NOSONAR: no const + add_attribute_buffer(*this, component, attribute, data); + } + static DatasetInfo const& get_info(DatasetConst const& dataset) { return dataset.info_; } DatasetInfo const& get_info() const { return get_info(*this); } diff --git a/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/handle.hpp b/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/handle.hpp index 6111f0cc8..84ec8283b 100644 --- a/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/handle.hpp +++ b/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/handle.hpp @@ -13,7 +13,7 @@ namespace power_grid_model_cpp { class PowerGridError : public std::exception { public: - PowerGridError(const std::string& message) : message_(message) {} + PowerGridError(std::string message) : message_(std::move(message)) {} const char* what() const noexcept override { return message_.c_str(); } virtual Idx error_code() const noexcept { return PGM_regular_error; }; @@ -58,8 +58,8 @@ class Handle { static void check_error(Handle const& handle) { RawHandle const* handle_ptr = handle.get(); - Idx error_code = PGM_error_code(handle_ptr); - std::string error_message = error_code == PGM_no_error ? "" : PGM_error_message(handle_ptr); + Idx const error_code = PGM_error_code(handle_ptr); + std::string const error_message = error_code == PGM_no_error ? "" : PGM_error_message(handle_ptr); switch (error_code) { case PGM_no_error: return; @@ -69,8 +69,8 @@ class Handle { case PGM_batch_error: { Idx const n_failed_scenarios = PGM_n_failed_scenarios(handle_ptr); std::vector failed_scenarios(n_failed_scenarios); - auto const failed_scenario_seqs = PGM_failed_scenarios(handle_ptr); - auto const failed_scenario_messages = PGM_batch_errors(handle_ptr); + auto const* const failed_scenario_seqs = PGM_failed_scenarios(handle_ptr); + auto const* const failed_scenario_messages = PGM_batch_errors(handle_ptr); for (Idx i = 0; i < n_failed_scenarios; ++i) { failed_scenarios[i] = PowerGridBatchError::FailedScenario{failed_scenario_seqs[i], failed_scenario_messages[i]}; diff --git a/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/meta_data.hpp b/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/meta_data.hpp index 2f6d89eff..4736bdb82 100644 --- a/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/meta_data.hpp +++ b/power_grid_model_c/power_grid_model_cpp/include/power_grid_model_cpp/meta_data.hpp @@ -15,88 +15,88 @@ namespace power_grid_model_cpp { class MetaData { public: static Idx n_datasets() { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_n_datasets); } static MetaDataset const* get_dataset_by_idx(Idx idx) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_get_dataset_by_idx, idx); } static MetaDataset const* get_dataset_by_name(std::string const& dataset) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_get_dataset_by_name, dataset.c_str()); } static std::string dataset_name(MetaDataset const* dataset) { - Handle handle{}; + Handle const handle{}; return std::string{handle.call_with(PGM_meta_dataset_name, dataset)}; } static Idx n_components(MetaDataset const* dataset) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_n_components, dataset); } static MetaComponent const* get_component_by_idx(MetaDataset const* dataset, Idx idx) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_get_component_by_idx, dataset, idx); } static MetaComponent const* get_component_by_name(std::string const& dataset, std::string const& component) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_get_component_by_name, dataset.c_str(), component.c_str()); } static std::string component_name(MetaComponent const* component) { - Handle handle{}; + Handle const handle{}; return std::string{handle.call_with(PGM_meta_component_name, component)}; } static size_t component_size(MetaComponent const* component) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_component_size, component); } static size_t component_alignment(MetaComponent const* component) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_component_alignment, component); } static Idx n_attributes(MetaComponent const* component) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_n_attributes, component); } static MetaAttribute const* get_attribute_by_idx(MetaComponent const* component, Idx idx) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_get_attribute_by_idx, component, idx); } static MetaAttribute const* get_attribute_by_name(std::string const& dataset, std::string const& component, std::string const& attribute) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_get_attribute_by_name, dataset.c_str(), component.c_str(), attribute.c_str()); } static std::string attribute_name(MetaAttribute const* attribute) { - Handle handle{}; + Handle const handle{}; return std::string{handle.call_with(PGM_meta_attribute_name, attribute)}; } static Idx attribute_ctype(MetaAttribute const* attribute) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_attribute_ctype, attribute); } static size_t attribute_offset(MetaAttribute const* attribute) { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_meta_attribute_offset, attribute); } static int is_little_endian() { - Handle handle{}; + Handle const handle{}; return handle.call_with(PGM_is_little_endian); } }; diff --git a/tests/cpp_unit_tests/test_dataset.cpp b/tests/cpp_unit_tests/test_dataset.cpp index aceec0b06..b674718c7 100644 --- a/tests/cpp_unit_tests/test_dataset.cpp +++ b/tests/cpp_unit_tests/test_dataset.cpp @@ -332,7 +332,13 @@ TEST_CASE_TEMPLATE("Test dataset (common)", DatasetType, ConstDataset, MutableDa } }; auto const add_attribute_buffer = [](DatasetType& dataset, std::string_view name, std::string_view attribute, - auto* data) { dataset.add_attribute_buffer(name, attribute, data); }; + auto* data) { + if constexpr (std::same_as) { + dataset.set_attribute_buffer(name, attribute, data); + } else { + dataset.add_attribute_buffer(name, attribute, data); + } + }; auto const add_homogeneous_buffer = [&add_buffer](DatasetType& dataset, std::string_view name, Idx elements_per_scenario, void* data) { add_buffer(dataset, name, elements_per_scenario, elements_per_scenario * dataset.batch_size(), nullptr, data); diff --git a/tests/cpp_unit_tests/test_deserializer.cpp b/tests/cpp_unit_tests/test_deserializer.cpp index 1eb4d7650..ea0563234 100644 --- a/tests/cpp_unit_tests/test_deserializer.cpp +++ b/tests/cpp_unit_tests/test_deserializer.cpp @@ -358,23 +358,23 @@ TEST_CASE("Deserializer") { auto& info = deserializer.get_dataset_info(); info.set_buffer("node", nullptr, nullptr); - info.add_attribute_buffer("node", "id", node_id.data()); - info.add_attribute_buffer("node", "u_rated", node_u_rated.data()); + info.set_attribute_buffer("node", "id", node_id.data()); + info.set_attribute_buffer("node", "u_rated", node_u_rated.data()); info.set_buffer("line", nullptr, nullptr); - info.add_attribute_buffer("line", "id", line_id.data()); - info.add_attribute_buffer("line", "r1", line_r1.data()); - info.add_attribute_buffer("line", "r0", line_r0.data()); - info.add_attribute_buffer("line", "x1", line_x1.data()); - info.add_attribute_buffer("line", "x0", line_x0.data()); + info.set_attribute_buffer("line", "id", line_id.data()); + info.set_attribute_buffer("line", "r1", line_r1.data()); + info.set_attribute_buffer("line", "r0", line_r0.data()); + info.set_attribute_buffer("line", "x1", line_x1.data()); + info.set_attribute_buffer("line", "x0", line_x0.data()); info.set_buffer("source", nullptr, nullptr); - info.add_attribute_buffer("source", "id", source_id.data()); - info.add_attribute_buffer("source", "u_ref", source_u_ref.data()); - info.add_attribute_buffer("source", "sk", source_sk.data()); - info.add_attribute_buffer("source", "rx_ratio", source_rx_ratio.data()); + info.set_attribute_buffer("source", "id", source_id.data()); + info.set_attribute_buffer("source", "u_ref", source_u_ref.data()); + info.set_attribute_buffer("source", "sk", source_sk.data()); + info.set_attribute_buffer("source", "rx_ratio", source_rx_ratio.data()); info.set_buffer("sym_load", nullptr, nullptr); - info.add_attribute_buffer("sym_load", "id", sym_load_id.data()); - info.add_attribute_buffer("sym_load", "p_specified", sym_load_p_specified.data()); - info.add_attribute_buffer("sym_load", "q_specified", sym_load_q_specified.data()); + info.set_attribute_buffer("sym_load", "id", sym_load_id.data()); + info.set_attribute_buffer("sym_load", "p_specified", sym_load_p_specified.data()); + info.set_attribute_buffer("sym_load", "q_specified", sym_load_q_specified.data()); deserializer.parse(); // check node @@ -498,15 +498,15 @@ TEST_CASE("Deserializer") { auto& info = deserializer.get_dataset_info(); info.set_buffer("sym_load", sym_load_indptr.data(), nullptr); - info.add_attribute_buffer("sym_load", "id", sym_load_id.data()); - info.add_attribute_buffer("sym_load", "status", sym_load_status.data()); - info.add_attribute_buffer("sym_load", "p_specified", sym_load_p_specified.data()); - info.add_attribute_buffer("sym_load", "q_specified", sym_load_q_specified.data()); + info.set_attribute_buffer("sym_load", "id", sym_load_id.data()); + info.set_attribute_buffer("sym_load", "status", sym_load_status.data()); + info.set_attribute_buffer("sym_load", "p_specified", sym_load_p_specified.data()); + info.set_attribute_buffer("sym_load", "q_specified", sym_load_q_specified.data()); info.set_buffer("asym_load", nullptr, nullptr); - info.add_attribute_buffer("asym_load", "id", asym_load_id.data()); - info.add_attribute_buffer("asym_load", "status", asym_load_status.data()); - info.add_attribute_buffer("asym_load", "p_specified", asym_load_p_specified.data()); - info.add_attribute_buffer("asym_load", "q_specified", asym_load_q_specified.data()); + info.set_attribute_buffer("asym_load", "id", asym_load_id.data()); + info.set_attribute_buffer("asym_load", "status", asym_load_status.data()); + info.set_attribute_buffer("asym_load", "p_specified", asym_load_p_specified.data()); + info.set_attribute_buffer("asym_load", "q_specified", asym_load_q_specified.data()); deserializer.parse(); diff --git a/tests/cpp_unit_tests/test_observability.cpp b/tests/cpp_unit_tests/test_observability.cpp index 7892ec983..21006a09e 100644 --- a/tests/cpp_unit_tests/test_observability.cpp +++ b/tests/cpp_unit_tests/test_observability.cpp @@ -11,7 +11,7 @@ namespace power_grid_model { namespace { -void check_not_observable(MathModelTopology const& topo, MathModelParam param, +void check_not_observable(MathModelTopology const& topo, MathModelParam const& param, StateEstimationInput const& se_input) { auto topo_ptr = std::make_shared(topo); auto param_ptr = std::make_shared const>(param); diff --git a/tests/cpp_unit_tests/test_transformer_tap_regulator.cpp b/tests/cpp_unit_tests/test_transformer_tap_regulator.cpp index cd5e423d5..a16aba9b0 100644 --- a/tests/cpp_unit_tests/test_transformer_tap_regulator.cpp +++ b/tests/cpp_unit_tests/test_transformer_tap_regulator.cpp @@ -20,7 +20,7 @@ void check_nan_preserving_equality(std::floating_point auto actual, std::floatin TEST_CASE("Test transformer tap regulator") { TransformerTapRegulatorInput const input{.id = 1, .regulated_object = 2, - .status = true, + .status = 1, .control_side = ControlSide::from, .u_set = 10.0e3, .u_band = 1.0e3, @@ -63,7 +63,7 @@ TEST_CASE("Test transformer tap regulator") { SUBCASE("Test update") { SUBCASE("Set all values") { TransformerTapRegulatorUpdate const update{.id = 1, - .status = false, + .status = 0, .u_set = 11.0e3, .u_band = 2.0e3, .line_drop_compensation_r = 2.0, @@ -144,7 +144,7 @@ TEST_CASE("Test transformer tap regulator") { SUBCASE("multiple") { update.id = 1; - update.status = false; + update.status = 0; update.u_set = 11.0e3; update.u_band = 2.0e3; update.line_drop_compensation_r = 2.0; @@ -201,7 +201,7 @@ TEST_CASE("Test transformer tap regulator") { SUBCASE("Test default line drop compensation") { TransformerTapRegulator regulator{{.id = 1, .regulated_object = 2, - .status = true, + .status = 1, .control_side = ControlSide::from, .u_set = 10.0e3, .u_band = 1.0e3}, diff --git a/tests/native_api_tests/test_api_model.cpp b/tests/native_api_tests/test_api_model.cpp index e04beea28..8deba7a59 100644 --- a/tests/native_api_tests/test_api_model.cpp +++ b/tests/native_api_tests/test_api_model.cpp @@ -46,27 +46,37 @@ void check_exception(PowerGridError const& e, PGM_ErrorCode const& reference_err TEST_CASE("API Model") { using namespace std::string_literals; - Options options{}; + Options const options{}; // input data DatasetConst input_dataset{"input", 0, 1}; // node buffer - ID node_id = 0; - double node_u_rated = 100.0; - Buffer node_buffer{PGM_def_input_node, 1}; - // set nan from offset to size + std::vector const node_id{0, 4}; + std::vector const node_u_rated{100.0, 100.0}; + Buffer node_buffer{PGM_def_input_node, 2}; node_buffer.set_nan(0, node_buffer.size()); - node_buffer.set_value(PGM_def_input_node_id, &node_id, -1); - node_buffer.set_value(PGM_def_input_node_u_rated, &node_u_rated, -1); + node_buffer.set_value(PGM_def_input_node_id, node_id.data(), -1); + node_buffer.set_value(PGM_def_input_node_u_rated, node_u_rated.data(), -1); + + std::vector const line_id{5, 6}; + std::vector const line_from_node{0, 4}; + std::vector const line_to_node{4, 0}; + std::vector const line_from_status{0, 1}; + std::vector const line_to_status{1, 0}; + std::vector const batch_line_id{5, 6, 5, 6}; + std::vector const batch_line_from_node{0, 4, 0, 4}; + std::vector const batch_line_to_node{4, 0, 4, 0}; + std::vector const batch_line_from_status{0, 1, 0, 1}; + std::vector const batch_line_to_status{1, 0, 1, 0}; // source buffer - ID source_id = 1; - ID source_node = 0; - int8_t source_status = 1; - double source_u_ref = 1.0; - double source_sk = 1000.0; - double source_rx_ratio = 0.0; + ID const source_id = 1; + ID const source_node = 0; + int8_t const source_status = 1; + double const source_u_ref = 1.0; + double const source_sk = 1000.0; + double const source_rx_ratio = 0.0; Buffer source_buffer{PGM_def_input_source, 1}; source_buffer.set_nan(); source_buffer.set_value(PGM_def_input_source_id, &source_id, -1); @@ -78,11 +88,11 @@ TEST_CASE("API Model") { // load buffer ID load_id = 2; - ID load_node = 0; - int8_t load_status = 1; - int8_t load_type = 2; - double load_p_specified = 0.0; - double load_q_specified = 500.0; + ID const load_node = 0; + int8_t const load_status = 1; + int8_t const load_type = 2; + double const load_p_specified = 0.0; + double const load_q_specified = 500.0; Buffer load_buffer{PGM_def_input_sym_load, 1}; load_buffer.set_value(PGM_def_input_sym_load_id, &load_id, -1); load_buffer.set_value(PGM_def_input_sym_load_node, &load_node, -1); @@ -91,32 +101,47 @@ TEST_CASE("API Model") { load_buffer.set_value(PGM_def_input_sym_load_p_specified, &load_p_specified, -1); load_buffer.set_value(PGM_def_input_sym_load_q_specified, &load_q_specified, -1); - // add buffers - input_dataset.add_buffer("node", 1, 1, nullptr, node_buffer); + // add buffers - row input_dataset.add_buffer("sym_load", 1, 1, nullptr, load_buffer); input_dataset.add_buffer("source", 1, 1, nullptr, source_buffer); + // add buffers - columnar + input_dataset.add_buffer("node", 2, 2, nullptr, nullptr); + input_dataset.add_attribute_buffer("node", "id", node_id.data()); + input_dataset.add_attribute_buffer("node", "u_rated", node_u_rated.data()); + input_dataset.add_buffer("line", 2, 2, nullptr, nullptr); + input_dataset.add_attribute_buffer("line", "id", line_id.data()); + input_dataset.add_attribute_buffer("line", "from_node", line_from_node.data()); + input_dataset.add_attribute_buffer("line", "to_node", line_to_node.data()); + input_dataset.add_attribute_buffer("line", "from_status", line_from_status.data()); + input_dataset.add_attribute_buffer("line", "to_status", line_to_status.data()); + // output data - Buffer node_output{PGM_def_sym_output_node, 1}; + Buffer node_output{PGM_def_sym_output_node, 2}; node_output.set_nan(); DatasetMutable single_output_dataset{"sym_output", 0, 1}; - single_output_dataset.add_buffer("node", 1, 1, nullptr, node_output); - Buffer node_batch_output{PGM_def_sym_output_node, 2}; + single_output_dataset.add_buffer("node", 2, 2, nullptr, node_output); + Buffer node_batch_output{PGM_def_sym_output_node, 4}; node_batch_output.set_nan(); DatasetMutable batch_output_dataset{"sym_output", 1, 2}; - batch_output_dataset.add_buffer("node", 1, 2, nullptr, node_batch_output); + batch_output_dataset.add_buffer("node", 2, 4, nullptr, node_batch_output); std::vector node_result_id(2); std::vector node_result_energized(2); std::vector node_result_u(2); std::vector node_result_u_pu(2); std::vector node_result_u_angle(2); + std::vector batch_node_result_id(4); + std::vector batch_node_result_energized(4); + std::vector batch_node_result_u(4); + std::vector batch_node_result_u_pu(4); + std::vector batch_node_result_u_angle(4); // update data ID source_update_id = 1; - int8_t source_update_status = std::numeric_limits::min(); - double source_update_u_ref = 0.5; - double source_update_u_ref_angle = std::numeric_limits::quiet_NaN(); + int8_t const source_update_status = std::numeric_limits::min(); + double const source_update_u_ref = 0.5; + double const source_update_u_ref_angle = std::numeric_limits::quiet_NaN(); Buffer source_update_buffer{PGM_def_update_source, 1}; source_update_buffer.set_nan(); source_update_buffer.set_value(PGM_def_update_source_id, &source_update_id, 0, -1); @@ -134,14 +159,21 @@ TEST_CASE("API Model") { load_updates_buffer.set_value(PGM_def_update_sym_load_id, load_updates_id.data(), -1); load_updates_buffer.set_value(PGM_def_update_sym_load_q_specified, load_updates_q_specified.data(), 0, -1); load_updates_buffer.set_value(PGM_def_update_sym_load_q_specified, load_updates_q_specified.data(), 1, -1); - // dataset DatasetConst single_update_dataset{"update", 0, 1}; single_update_dataset.add_buffer("source", 1, 1, nullptr, source_update_buffer); single_update_dataset.add_buffer("sym_load", 1, 1, nullptr, load_updates_buffer.get()); + single_update_dataset.add_buffer("line", 2, 2, nullptr, nullptr); + single_update_dataset.add_attribute_buffer("line", "id", line_id.data()); + single_update_dataset.add_attribute_buffer("line", "from_status", line_from_status.data()); + single_update_dataset.add_attribute_buffer("line", "to_status", line_to_status.data()); DatasetConst batch_update_dataset{"update", 1, 2}; batch_update_dataset.add_buffer("source", -1, 1, source_update_indptr.data(), source_update_buffer.get()); batch_update_dataset.add_buffer("sym_load", 1, 2, nullptr, load_updates_buffer); + batch_update_dataset.add_buffer("line", 2, 4, nullptr, nullptr); + batch_update_dataset.add_attribute_buffer("line", "id", batch_line_id.data()); + batch_update_dataset.add_attribute_buffer("line", "from_status", batch_line_from_status.data()); + batch_update_dataset.add_attribute_buffer("line", "to_status", batch_line_to_status.data()); // create model Model model{50.0, input_dataset}; @@ -162,6 +194,11 @@ TEST_CASE("API Model") { CHECK(node_result_u[0] == doctest::Approx(50.0)); CHECK(node_result_u_pu[0] == doctest::Approx(0.5)); CHECK(node_result_u_angle[0] == doctest::Approx(0.0)); + CHECK(node_result_id[1] == 4); + CHECK(node_result_energized[1] == 0); + CHECK(node_result_u[1] == doctest::Approx(0.0)); + CHECK(node_result_u_pu[1] == doctest::Approx(0.0)); + CHECK(node_result_u_angle[1] == doctest::Approx(0.0)); } SUBCASE("Simple update") { @@ -177,6 +214,11 @@ TEST_CASE("API Model") { CHECK(node_result_u[0] == doctest::Approx(40.0)); CHECK(node_result_u_pu[0] == doctest::Approx(0.4)); CHECK(node_result_u_angle[0] == doctest::Approx(0.0)); + CHECK(node_result_id[1] == 4); + CHECK(node_result_energized[1] == 0); + CHECK(node_result_u[1] == doctest::Approx(0.0)); + CHECK(node_result_u_pu[1] == doctest::Approx(0.0)); + CHECK(node_result_u_angle[1] == doctest::Approx(0.0)); } SUBCASE("Copy model") { @@ -192,6 +234,11 @@ TEST_CASE("API Model") { CHECK(node_result_u[0] == doctest::Approx(50.0)); CHECK(node_result_u_pu[0] == doctest::Approx(0.5)); CHECK(node_result_u_angle[0] == doctest::Approx(0.0)); + CHECK(node_result_id[1] == 4); + CHECK(node_result_energized[1] == 0); + CHECK(node_result_u[1] == doctest::Approx(0.0)); + CHECK(node_result_u_pu[1] == doctest::Approx(0.0)); + CHECK(node_result_u_angle[1] == doctest::Approx(0.0)); } SUBCASE("Get indexer") { @@ -206,28 +253,38 @@ TEST_CASE("API Model") { SUBCASE("Batch power flow") { model.calculate(options, batch_output_dataset, batch_update_dataset); - node_batch_output.get_value(PGM_def_sym_output_node_id, node_result_id.data(), -1); - node_batch_output.get_value(PGM_def_sym_output_node_energized, node_result_energized.data(), -1); - node_batch_output.get_value(PGM_def_sym_output_node_u, node_result_u.data(), -1); - node_batch_output.get_value(PGM_def_sym_output_node_u_pu, node_result_u_pu.data(), -1); - node_batch_output.get_value(PGM_def_sym_output_node_u_angle, node_result_u_angle.data(), -1); - CHECK(node_result_id[0] == 0); - CHECK(node_result_energized[0] == 1); - CHECK(node_result_u[0] == doctest::Approx(40.0)); - CHECK(node_result_u_pu[0] == doctest::Approx(0.4)); - CHECK(node_result_u_angle[0] == doctest::Approx(0.0)); - CHECK(node_result_id[1] == 0); - CHECK(node_result_energized[1] == 1); - CHECK(node_result_u[1] == doctest::Approx(70.0)); - CHECK(node_result_u_pu[1] == doctest::Approx(0.7)); - CHECK(node_result_u_angle[1] == doctest::Approx(0.0)); + node_batch_output.get_value(PGM_def_sym_output_node_id, batch_node_result_id.data(), -1); + node_batch_output.get_value(PGM_def_sym_output_node_energized, batch_node_result_energized.data(), -1); + node_batch_output.get_value(PGM_def_sym_output_node_u, batch_node_result_u.data(), -1); + node_batch_output.get_value(PGM_def_sym_output_node_u_pu, batch_node_result_u_pu.data(), -1); + node_batch_output.get_value(PGM_def_sym_output_node_u_angle, batch_node_result_u_angle.data(), -1); + CHECK(batch_node_result_id[0] == 0); + CHECK(batch_node_result_energized[0] == 1); + CHECK(batch_node_result_u[0] == doctest::Approx(40.0)); + CHECK(batch_node_result_u_pu[0] == doctest::Approx(0.4)); + CHECK(batch_node_result_u_angle[0] == doctest::Approx(0.0)); + CHECK(batch_node_result_id[1] == 4); + CHECK(batch_node_result_energized[1] == 0); + CHECK(batch_node_result_u[1] == doctest::Approx(0.0)); + CHECK(batch_node_result_u_pu[1] == doctest::Approx(0.0)); + CHECK(batch_node_result_u_angle[1] == doctest::Approx(0.0)); + CHECK(batch_node_result_id[2] == 0); + CHECK(batch_node_result_energized[2] == 1); + CHECK(batch_node_result_u[2] == doctest::Approx(70.0)); + CHECK(batch_node_result_u_pu[2] == doctest::Approx(0.7)); + CHECK(batch_node_result_u_angle[2] == doctest::Approx(0.0)); + CHECK(batch_node_result_id[3] == 4); + CHECK(batch_node_result_energized[3] == 0); + CHECK(batch_node_result_u[3] == doctest::Approx(0.0)); + CHECK(batch_node_result_u_pu[3] == doctest::Approx(0.0)); + CHECK(batch_node_result_u_angle[3] == doctest::Approx(0.0)); } SUBCASE("Input error handling") { SUBCASE("Construction error") { load_id = 0; try { - Model wrong_model{50.0, input_dataset}; + Model const wrong_model{50.0, input_dataset}; } catch (PowerGridRegularError const& e) { check_exception(e, PGM_regular_error, "Conflicting id detected:"s); } @@ -302,16 +359,31 @@ TEST_CASE("API Model") { CHECK(err_msg.find("The id cannot be found:"s) != std::string::npos); } // valid results for batch 0 - node_batch_output.get_value(PGM_def_sym_output_node_id, node_result_id.data(), -1); - node_batch_output.get_value(PGM_def_sym_output_node_energized, node_result_energized.data(), -1); - node_batch_output.get_value(PGM_def_sym_output_node_u, node_result_u.data(), -1); - node_batch_output.get_value(PGM_def_sym_output_node_u_pu, node_result_u_pu.data(), -1); - node_batch_output.get_value(PGM_def_sym_output_node_u_angle, node_result_u_angle.data(), -1); - CHECK(node_result_id[0] == 0); - CHECK(node_result_energized[0] == 1); - CHECK(node_result_u[0] == doctest::Approx(40.0)); - CHECK(node_result_u_pu[0] == doctest::Approx(0.4)); - CHECK(node_result_u_angle[0] == doctest::Approx(0.0)); + node_batch_output.get_value(PGM_def_sym_output_node_id, batch_node_result_id.data(), -1); + node_batch_output.get_value(PGM_def_sym_output_node_energized, batch_node_result_energized.data(), -1); + node_batch_output.get_value(PGM_def_sym_output_node_u, batch_node_result_u.data(), -1); + node_batch_output.get_value(PGM_def_sym_output_node_u_pu, batch_node_result_u_pu.data(), -1); + node_batch_output.get_value(PGM_def_sym_output_node_u_angle, batch_node_result_u_angle.data(), -1); + CHECK(batch_node_result_id[0] == 0); + CHECK(batch_node_result_energized[0] == 1); + CHECK(batch_node_result_u[0] == doctest::Approx(40.0)); + CHECK(batch_node_result_u_pu[0] == doctest::Approx(0.4)); + CHECK(batch_node_result_u_angle[0] == doctest::Approx(0.0)); + CHECK(batch_node_result_id[1] == 4); + CHECK(batch_node_result_energized[1] == 0); + CHECK(batch_node_result_u[1] == doctest::Approx(0.0)); + CHECK(batch_node_result_u_pu[1] == doctest::Approx(0.0)); + CHECK(batch_node_result_u_angle[1] == doctest::Approx(0.0)); + CHECK(batch_node_result_id[2] == 0); + CHECK(batch_node_result_energized[2] == 1); + CHECK(batch_node_result_u[2] == doctest::Approx(70.0)); + CHECK(batch_node_result_u_pu[2] == doctest::Approx(0.7)); + CHECK(batch_node_result_u_angle[2] == doctest::Approx(0.0)); + CHECK(batch_node_result_id[3] == 4); + CHECK(batch_node_result_energized[3] == 0); + CHECK(batch_node_result_u[3] == doctest::Approx(0.0)); + CHECK(batch_node_result_u_pu[3] == doctest::Approx(0.0)); + CHECK(batch_node_result_u_angle[3] == doctest::Approx(0.0)); } } } diff --git a/tests/native_api_tests/test_api_serialization.cpp b/tests/native_api_tests/test_api_serialization.cpp index 3530c30cd..7eb77e3cd 100644 --- a/tests/native_api_tests/test_api_serialization.cpp +++ b/tests/native_api_tests/test_api_serialization.cpp @@ -51,7 +51,9 @@ TEST_CASE("API Serialization and Deserialization") { Idx const batch_size = 1; Idx const is_batch = 0; std::vector const elements_per_scenario = {1, 2}; + std::vector const elements_per_scenario_complete = {1, 1}; std::vector const total_elements = {1, 2}; + std::vector const total_elements_complete = {1, 1}; SUBCASE("Serializer") { DatasetConst dataset{"input", is_batch, batch_size}; @@ -59,7 +61,7 @@ TEST_CASE("API Serialization and Deserialization") { dataset.add_buffer("source", elements_per_scenario[1], total_elements[1], nullptr, source_buffer); SUBCASE("JSON") { - Serializer json_serializer{dataset, 0}; + Serializer const json_serializer{dataset, 0}; SUBCASE("To zero-terminated string") { std::string json_result = json_serializer.get_to_zero_terminated_string(0, -1); @@ -77,7 +79,7 @@ TEST_CASE("API Serialization and Deserialization") { } SUBCASE("MessagePack") { - Serializer msgpack_serializer{dataset, 1}; + Serializer const msgpack_serializer{dataset, 1}; SUBCASE("Round trip") { std::vector msgpack_data{}; @@ -94,7 +96,7 @@ TEST_CASE("API Serialization and Deserialization") { SUBCASE("Invalid serialization format") { try { - Serializer unknown_serializer{dataset, -1}; + Serializer const unknown_serializer{dataset, -1}; } catch (PowerGridSerializationError const& e) { CHECK(e.error_code() == PGM_serialization_error); } @@ -130,7 +132,7 @@ TEST_CASE("API Serialization and Deserialization") { auto check_deserializer = [&](Deserializer& deserializer) { // get dataset auto& dataset = deserializer.get_dataset(); - auto& info = dataset.get_info(); + auto const& info = dataset.get_info(); // check meta data check_metadata(info); // set buffer @@ -155,12 +157,66 @@ TEST_CASE("API Serialization and Deserialization") { check_deserializer(msgpack_deserializer); } + SUBCASE("Deserializer with columnar data") { + // msgpack data + auto const json_document = nlohmann::json::parse(complete_json_data); + std::vector msgpack_data; + + nlohmann::json::to_msgpack(json_document, msgpack_data); + + // test move-ability + Deserializer json_deserializer{complete_json_data, 0}; + Deserializer json_dummy{std::move(json_deserializer)}; + json_deserializer = std::move(json_dummy); + Deserializer msgpack_deserializer{msgpack_data, 1}; + + auto check_metadata = [&](DatasetInfo const& info) { + CHECK(info.name() == "input"s); + CHECK(info.is_batch() == is_batch); + CHECK(info.batch_size() == batch_size); + CHECK(info.n_components() == n_components); + CHECK(info.component_name(0) == "node"s); + CHECK(info.component_name(1) == "source"s); + for (Idx const idx : {0, 1}) { + CHECK(info.component_elements_per_scenario(idx) == elements_per_scenario_complete[idx]); + CHECK(info.component_total_elements(idx) == total_elements_complete[idx]); + } + }; + + auto check_deserializer = [&](Deserializer& deserializer) { + // get dataset + auto& dataset = deserializer.get_dataset(); + auto const& info = dataset.get_info(); + // check meta data + check_metadata(info); + ID node_id_2{0}; + double node_u_rated_2; + // set buffer + Buffer source_buffer_columnar{PGM_def_input_source, 1}; + dataset.set_buffer("node", nullptr, nullptr); + dataset.set_attribute_buffer("node", "id", &node_id_2); + dataset.set_attribute_buffer("node", "u_rated", &node_u_rated_2); + dataset.set_buffer("source", nullptr, source_buffer_columnar); + // parse + deserializer.parse_to_buffer(); + // check + ID source_2_id; + source_buffer_columnar.get_value(PGM_def_input_source_id, &source_2_id, -1); + CHECK(node_id_2 == 5); + CHECK(node_u_rated_2 == doctest::Approx(10.5e3)); + CHECK(source_2_id == 6); + }; + + check_deserializer(json_deserializer); + check_deserializer(msgpack_deserializer); + } + SUBCASE("Use deserialized dataset") { Deserializer deserializer_json(complete_json_data, 0); // get dataset auto& dataset = deserializer_json.get_dataset(); - auto& info = dataset.get_info(); + auto const& info = dataset.get_info(); // check meta data CHECK(info.name() == "input"s); CHECK(info.is_batch() == is_batch); @@ -174,8 +230,8 @@ TEST_CASE("API Serialization and Deserialization") { // parse deserializer_json.parse_to_buffer(); // create model from deserialized dataset - DatasetConst input_dataset{dataset}; - Model model{50.0, input_dataset}; + DatasetConst const input_dataset{dataset}; + Model const model{50.0, input_dataset}; } }