|
9 | 9 | #include "basics.hpp" |
10 | 10 | #include "buffer.hpp" |
11 | 11 | #include "handle.hpp" |
| 12 | +#include "utils.hpp" |
12 | 13 |
|
13 | 14 | #include "power_grid_model_c/dataset.h" |
14 | 15 |
|
| 16 | +#include <map> |
| 17 | +#include <set> |
| 18 | +#include <variant> |
| 19 | + |
15 | 20 | namespace power_grid_model_cpp { |
16 | 21 | class ComponentTypeNotFound : public PowerGridError { |
17 | 22 | public: |
@@ -210,14 +215,139 @@ class DatasetConst { |
210 | 215 | DatasetInfo info_; |
211 | 216 | }; |
212 | 217 |
|
| 218 | +class AttributeBuffer { |
| 219 | + private: |
| 220 | + using VariantType = std::variant<std::monostate, std::vector<ID>, std::vector<IntS>, std::vector<double>, |
| 221 | + std::vector<std::array<double, 3>>>; |
| 222 | + |
| 223 | + struct BufferCreator { |
| 224 | + Idx size; |
| 225 | + template <class T> VariantType operator()() const { return std::vector<T>(size, nan_value<T>()); } |
| 226 | + }; |
| 227 | + |
| 228 | + struct PtrGetter { |
| 229 | + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) |
| 230 | + AttributeBuffer& buffer; |
| 231 | + template <class T> RawDataPtr operator()() const { return std::get<std::vector<T>>(buffer.buffer_).data(); } |
| 232 | + }; |
| 233 | + |
| 234 | + public: |
| 235 | + AttributeBuffer() = default; |
| 236 | + |
| 237 | + explicit AttributeBuffer(MetaAttribute const* attribute, Idx size) |
| 238 | + : attribute_{attribute}, |
| 239 | + buffer_{pgm_type_func_selector(MetaData::attribute_ctype(attribute), BufferCreator{size})} {} |
| 240 | + |
| 241 | + RawDataPtr get() { return pgm_type_func_selector(MetaData::attribute_ctype(attribute_), PtrGetter{*this}); } |
| 242 | + |
| 243 | + private: |
| 244 | + MetaAttribute const* attribute_{nullptr}; |
| 245 | + VariantType buffer_; |
| 246 | +}; |
| 247 | + |
213 | 248 | struct OwningMemory { |
214 | 249 | std::vector<Buffer> buffers; |
215 | 250 | std::vector<std::vector<Idx>> indptrs; |
| 251 | + std::vector<std::vector<AttributeBuffer>> attribute_buffers; |
216 | 252 | }; |
217 | 253 |
|
218 | 254 | struct OwningDataset { |
219 | 255 | DatasetMutable dataset; |
220 | 256 | OwningMemory storage{}; |
| 257 | + |
| 258 | + OwningDataset(DatasetWritable& writable_dataset, bool enable_columnar_buffers = false) |
| 259 | + : dataset{writable_dataset.get_info().name(), writable_dataset.get_info().is_batch(), |
| 260 | + writable_dataset.get_info().batch_size()}, |
| 261 | + storage{} { |
| 262 | + auto const& info = writable_dataset.get_info(); |
| 263 | + Idx const batch_size = info.batch_size(); |
| 264 | + auto const& dataset_name = info.name(); |
| 265 | + |
| 266 | + for (Idx component_idx{}; component_idx < info.n_components(); ++component_idx) { |
| 267 | + auto const& component_name = info.component_name(component_idx); |
| 268 | + auto const* const component_meta = MetaData::get_component_by_name(dataset_name, component_name); |
| 269 | + Idx const component_size = info.component_total_elements(component_idx); |
| 270 | + Idx const elements_per_scenario = info.component_elements_per_scenario(component_idx); |
| 271 | + |
| 272 | + auto& current_indptr = storage.indptrs.emplace_back(elements_per_scenario < 0 ? batch_size + 1 : 0); |
| 273 | + if (!current_indptr.empty()) { |
| 274 | + current_indptr.at(0) = 0; |
| 275 | + current_indptr.at(batch_size) = component_size; |
| 276 | + } |
| 277 | + Idx* const indptr = current_indptr.empty() ? nullptr : current_indptr.data(); |
| 278 | + if (info.has_attribute_indications(component_idx) && enable_columnar_buffers) { |
| 279 | + auto& current_buffer = storage.buffers.emplace_back(); |
| 280 | + writable_dataset.set_buffer(component_name, indptr, current_buffer); |
| 281 | + dataset.add_buffer(component_name, elements_per_scenario, component_size, indptr, current_buffer); |
| 282 | + auto const& attribute_indications = info.attribute_indications(component_idx); |
| 283 | + auto& current_attribute_buffers = storage.attribute_buffers.emplace_back(); |
| 284 | + for (auto const& attribute_name : attribute_indications) { |
| 285 | + auto const* const attribute_meta = |
| 286 | + MetaData::get_attribute_by_name(dataset_name, component_name, attribute_name); |
| 287 | + current_attribute_buffers.emplace_back(attribute_meta, component_size); |
| 288 | + writable_dataset.set_attribute_buffer(component_name, attribute_name, |
| 289 | + current_attribute_buffers.back().get()); |
| 290 | + dataset.add_attribute_buffer(component_name, attribute_name, |
| 291 | + current_attribute_buffers.back().get()); |
| 292 | + } |
| 293 | + } else { |
| 294 | + auto& current_buffer = storage.buffers.emplace_back(component_meta, component_size); |
| 295 | + storage.attribute_buffers.emplace_back(); // empty attribute buffers |
| 296 | + writable_dataset.set_buffer(component_name, indptr, current_buffer); |
| 297 | + dataset.add_buffer(component_name, elements_per_scenario, component_size, indptr, current_buffer); |
| 298 | + } |
| 299 | + } |
| 300 | + } |
| 301 | + |
| 302 | + OwningDataset( |
| 303 | + OwningDataset const& ref_dataset, std::string const& dataset_name, bool is_batch = false, Idx batch_size = 1, |
| 304 | + std::map<MetaComponent const*, std::set<MetaAttribute const*>> const& output_component_attribute_filters = {}) |
| 305 | + : dataset{dataset_name, is_batch, batch_size}, storage{} { |
| 306 | + DatasetInfo const& ref_info = ref_dataset.dataset.get_info(); |
| 307 | + bool const enable_filters = !output_component_attribute_filters.empty(); |
| 308 | + |
| 309 | + for (Idx component_idx{}; component_idx != ref_info.n_components(); ++component_idx) { |
| 310 | + auto const& component_name = ref_info.component_name(component_idx); |
| 311 | + auto const& component_meta = MetaData::get_component_by_name(dataset_name, component_name); |
| 312 | + // skip components not in the filter |
| 313 | + if (enable_filters && |
| 314 | + output_component_attribute_filters.find(component_meta) == output_component_attribute_filters.end()) { |
| 315 | + continue; |
| 316 | + } |
| 317 | + |
| 318 | + // get size info from reference dataset |
| 319 | + Idx const component_elements_per_scenario = ref_info.component_elements_per_scenario(component_idx); |
| 320 | + if (component_elements_per_scenario < 0) { |
| 321 | + throw PowerGridError{"Cannot create result dataset for component with variable size per scenario"}; |
| 322 | + } |
| 323 | + Idx const component_size = component_elements_per_scenario * batch_size; |
| 324 | + storage.indptrs.emplace_back(); |
| 325 | + |
| 326 | + auto const component_filter_it = output_component_attribute_filters.find(component_meta); |
| 327 | + std::set<MetaAttribute const*> const& attribute_filter = |
| 328 | + component_filter_it != output_component_attribute_filters.end() ? component_filter_it->second |
| 329 | + : std::set<MetaAttribute const*>{}; |
| 330 | + if (attribute_filter.empty()) { |
| 331 | + // create full row buffer |
| 332 | + auto& component_buffer = storage.buffers.emplace_back(component_meta, component_size); |
| 333 | + storage.attribute_buffers.emplace_back(); // empty attribute buffers |
| 334 | + dataset.add_buffer(component_name, component_elements_per_scenario, component_size, nullptr, |
| 335 | + component_buffer); |
| 336 | + } else { |
| 337 | + // push nullptr as row buffer, and start attribute buffers |
| 338 | + auto& component_buffer = storage.buffers.emplace_back(); |
| 339 | + storage.attribute_buffers.emplace_back(); |
| 340 | + dataset.add_buffer(component_name, component_elements_per_scenario, component_size, nullptr, |
| 341 | + component_buffer); |
| 342 | + for (auto const* const attribute_meta : attribute_filter) { |
| 343 | + auto const attribute_name = MetaData::attribute_name(attribute_meta); |
| 344 | + auto& attribute_buffer = |
| 345 | + storage.attribute_buffers.back().emplace_back(attribute_meta, component_size); |
| 346 | + dataset.add_attribute_buffer(component_name, attribute_name, attribute_buffer.get()); |
| 347 | + } |
| 348 | + } |
| 349 | + } |
| 350 | + } |
221 | 351 | }; |
222 | 352 | } // namespace power_grid_model_cpp |
223 | 353 |
|
|
0 commit comments