IgANet
IGAnets - Isogeometric Analysis Networks
Loading...
Searching...
No Matches
serialize.hpp
Go to the documentation of this file.
1
15#pragma once
16
17#include <core/core.hpp>
18#include <utils/tensorarray.hpp>
19
20#include <nlohmann/json.hpp>
21#include <pugixml.hpp>
22
23namespace iganet::utils {
24
31 virtual ~Serializable() = default;
32
34 virtual nlohmann::json to_json() const = 0;
35
37 virtual void pretty_print(std::ostream &os = Log(log::info)) const = 0;
38};
39
41template <typename T, std::size_t N>
42inline auto to_json(const torch::TensorAccessor<T, N> &accessor) {
43 auto json = nlohmann::json::array();
44
45 if constexpr (N == 1) {
46 for (int64_t i = 0; i < accessor.size(0); ++i)
47 json.push_back(accessor[i]);
48 } else if constexpr (N == 2) {
49 for (int64_t i = 0; i < accessor.size(0); ++i)
50 for (int64_t j = 0; j < accessor.size(1); ++j)
51 json.push_back(accessor[i][j]);
52 } else if constexpr (N == 3) {
53 for (int64_t i = 0; i < accessor.size(0); ++i)
54 for (int64_t j = 0; j < accessor.size(1); ++j)
55 for (int64_t k = 0; k < accessor.size(2); ++k)
56 json.push_back(accessor[i][j][k]);
57 } else if constexpr (N == 4) {
58 for (int64_t i = 0; i < accessor.size(0); ++i)
59 for (int64_t j = 0; j < accessor.size(1); ++j)
60 for (int64_t k = 0; k < accessor.size(2); ++k)
61 for (int64_t l = 0; l < accessor.size(3); ++l)
62 json.push_back(accessor[i][j][k][l]);
63 }
64
65 return json;
66}
67
69template <typename T, std::size_t N>
70inline auto to_json(const torch::Tensor &tensor) {
71 if (tensor.is_cuda()) {
72 auto [tensor_cpu, accessor] = to_tensorAccessor<T, N>(tensor, torch::kCPU);
73 return to_json(accessor);
74 } else {
75 auto accessor = to_tensorAccessor<T, N>(tensor);
76 return to_json(accessor);
77 }
78}
79
82template <typename T, std::size_t N, std::size_t M>
83inline auto to_json(const utils::TensorArray<M> &tensors) {
84 auto json = nlohmann::json::array();
85
86 for (std::size_t i = 0; i < M; ++i) {
87 if (tensors[i].is_cuda()) {
88 auto [tensor_cpu, accessor] =
89 to_tensorAccessor<T, N>(tensors[i], torch::kCPU);
90 json.push_back(to_json<T, N>(accessor));
91 } else {
92 auto accessor = to_tensorAccessor<T, N>(tensors[i]);
93 json.push_back(to_json<T, N>(accessor));
94 }
95 }
96
97 return json;
98}
99
100#ifdef IGANET_WITH_GISMO
102template <typename T, int Rows, int Cols, int Options>
103inline auto to_json(const gismo::gsMatrix<T, Rows, Cols, Options> &matrix,
104 bool flatten = false, bool transpose = false) {
105 auto json = nlohmann::json::array();
106
107 if constexpr (Options == gismo::RowMajor) {
108 if (flatten) {
109 if (transpose) {
110 for (std::size_t j = 0; j < matrix.cols(); ++j)
111 for (std::size_t i = 0; i < matrix.rows(); ++i)
112 json.push_back(matrix(i, j));
113 } else {
114 for (std::size_t i = 0; i < matrix.rows(); ++i)
115 for (std::size_t j = 0; j < matrix.cols(); ++j)
116 json.push_back(matrix(i, j));
117 }
118 } else {
119 if (transpose) {
120 for (std::size_t j = 0; j < matrix.cols(); ++j) {
121 auto data = nlohmann::json::array();
122 for (std::size_t i = 0; i < matrix.rows(); ++i) {
123 data.push_back(matrix(i, j));
124 }
125 json.emplace_back(data);
126 }
127 } else {
128 for (std::size_t i = 0; i < matrix.rows(); ++i) {
129 auto data = nlohmann::json::array();
130 for (std::size_t j = 0; j < matrix.cols(); ++j) {
131 data.push_back(matrix(i, j));
132 }
133 json.emplace_back(data);
134 }
135 }
136 }
137
138 } else if constexpr (Options == gismo::ColMajor) {
139 if (flatten) {
140 if (transpose) {
141 for (std::size_t i = 0; i < matrix.rows(); ++i)
142 for (std::size_t j = 0; j < matrix.cols(); ++j)
143 json.push_back(matrix(i, j));
144 } else {
145 for (std::size_t j = 0; j < matrix.cols(); ++j)
146 for (std::size_t i = 0; i < matrix.rows(); ++i)
147 json.push_back(matrix(i, j));
148 }
149 } else {
150 if (transpose) {
151 for (std::size_t i = 0; i < matrix.rows(); ++i) {
152 auto data = nlohmann::json::array();
153 for (std::size_t j = 0; j < matrix.cols(); ++j) {
154 data.push_back(matrix(i, j));
155 }
156 json.emplace_back(data);
157 }
158 } else {
159 for (std::size_t j = 0; j < matrix.cols(); ++j) {
160 auto data = nlohmann::json::array();
161 for (std::size_t i = 0; i < matrix.rows(); ++i) {
162 data.push_back(matrix(i, j));
163 }
164 json.emplace_back(data);
165 }
166 }
167 }
168
169 } else
170 throw std::runtime_error("Invalid matrix options");
171
172 return json;
173}
174
176template <typename T> inline auto to_json(const gismo::gsBSpline<T> &bspline) {
177 auto json = nlohmann::json();
178
179 json["degrees"] = nlohmann::json::array();
180
181 for (std::size_t i = 0; i < bspline.parDim(); ++i)
182 json["degrees"].push_back(bspline.degree(i));
183
184 json["geoDim"] = bspline.geoDim();
185 json["parDim"] = bspline.parDim();
186
187 json["ncoeffs"] = nlohmann::json::array();
188 for (std::size_t i = 0; i < bspline.parDim(); ++i)
189 json["ncoeffs"].push_back(bspline.basis().size(i));
190
191 json["coeffs"] = to_json(bspline.coefs());
192
193 json["nknots"] = nlohmann::json::array();
194 for (std::size_t i = 0; i < bspline.parDim(); ++i)
195 json["nknots"].push_back(bspline.knots(i).size());
196
197 json["knots"] = nlohmann::json::array();
198 for (std::size_t i = 0; i < bspline.parDim(); ++i)
199 json["knots"].push_back(bspline.knots(i));
200
201 return json;
202}
203
205template <int d, typename T>
206inline auto to_json(const gismo::gsTensorBSpline<d, T> &bspline) {
207 auto json = nlohmann::json();
208
209 json["degrees"] = nlohmann::json::array();
210
211 for (std::size_t i = 0; i < bspline.parDim(); ++i)
212 json["degrees"].push_back(bspline.degree(i));
213
214 json["geoDim"] = bspline.geoDim();
215 json["parDim"] = bspline.parDim();
216
217 json["ncoeffs"] = nlohmann::json::array();
218 for (std::size_t i = 0; i < bspline.parDim(); ++i)
219 json["ncoeffs"].push_back(bspline.basis().size(i));
220
221 json["coeffs"] = to_json(bspline.coefs());
222
223 json["nknots"] = nlohmann::json::array();
224 for (std::size_t i = 0; i < bspline.parDim(); ++i)
225 json["nknots"].push_back(bspline.knots(i).size());
226
227 json["knots"] = nlohmann::json::array();
228 for (std::size_t i = 0; i < bspline.parDim(); ++i)
229 json["knots"].push_back(bspline.knots(i));
230
231 return json;
232}
233
235template <typename T>
236inline auto to_json(const gismo::gsGeometry<T> &geometry) {
237
238 if (auto patch = dynamic_cast<const gismo::gsBSpline<T> *>(&geometry))
239 return to_json(*patch);
240 else if (auto patch =
241 dynamic_cast<const gismo::gsTensorBSpline<2, T> *>(&geometry))
242 return to_json(*patch);
243 else if (auto patch =
244 dynamic_cast<const gismo::gsTensorBSpline<3, T> *>(&geometry))
245 return to_json(*patch);
246 else if (auto patch =
247 dynamic_cast<const gismo::gsTensorBSpline<4, T> *>(&geometry))
248 return to_json(*patch);
249 else
250 return nlohmann::json("{ Invalid patch type }");
251}
252
254template <typename T>
255inline auto
256to_json(const typename gismo::gsMultiPatch<T>::ifContainer &interfaces) {
257
258 auto json = nlohmann::json::array();
259
260 for (auto const &interface : interfaces) {
261 auto interface_json = nlohmann::json();
262
263 interface_json["patches"] = {interface.first().patchIndex(),
264 interface.second().patchIndex()};
265 interface_json["sides"] = {interface.first().side().index(),
266 interface.second().side().index()};
267 interface_json["direction"] = "NOT IMPLEMENTED YET";
268 interface_json["orientation"] = "NOT IMPLEMENTED YET";
269
270 json.push_back(interface_json);
271 }
272
273 return json;
274}
275
277template <typename T>
278inline auto
279to_json(const typename gismo::gsMultiPatch<T>::bContainer &boundaries) {
280
281 auto json = nlohmann::json::array();
282
283 for (auto const &boundary : boundaries) {
284 auto boundary_json = nlohmann::json();
285
286 boundary_json["patch"] = boundary.patchIndex();
287 boundary_json["side"] = boundary.side().index();
288
289 json.push_back(boundary_json);
290 }
291
292 return json;
293}
294
296template <typename T>
297inline auto to_json(const gismo::gsMultiPatch<T> &mp, bool verbose = false) {
298
299 auto json = nlohmann::json();
300
301 // Create list of patch indices
302 auto patches_json = nlohmann::json::array();
303 for (std::size_t i = 0; i < mp.nPatches(); ++i)
304 patches_json.push_back(i);
305
306 json["patches"] = patches_json;
307 json["interfaces"] = to_json<T>(mp.interfaces());
308 json["boundaries"] = to_json<T>(mp.boundaries());
309
310 if (verbose) {
311 auto patches_json = nlohmann::json::array();
312
313 for (std::size_t i = 0; i < mp.nPatches(); ++i)
314 patches_json.push_back(to_json(mp.patch(i)));
315
316 json["patches"] = patches_json;
317 }
318
319 return json;
320}
321#endif
322
324template <typename T, std::size_t N>
325inline pugi::xml_document to_xml(const torch::TensorAccessor<T, N> &accessor,
326 torch::IntArrayRef sizes,
327 std::string tag = "Matrix", int id = 0,
328 std::string label = "", int index = -1) {
329 pugi::xml_document doc;
330 pugi::xml_node root = doc.append_child("xml");
331 to_xml(accessor, sizes, root, id, label, index);
332
333 return doc;
334}
335
337template <typename T, std::size_t N>
338inline pugi::xml_node &to_xml(const torch::TensorAccessor<T, N> &accessor,
339 torch::IntArrayRef sizes, pugi::xml_node &root,
340 std::string tag = "Matrix", int id = 0,
341 std::string label = "", int index = -1) {
342
343 // add node
344 pugi::xml_node node = root.append_child(tag.c_str());
345
346 if (id >= 0)
347 node.append_attribute("id") = id;
348
349 if (index >= 0)
350 node.append_attribute("index") = index;
351
352 if (!label.empty())
353 node.append_attribute("label") = label.c_str();
354
355 // add rows/cols or dimensions
356 if (tag == "Matrix") {
357 if constexpr (N == 1) {
358 node.append_attribute("rows") = sizes[0];
359 node.append_attribute("cols") = 1;
360
361 std::stringstream ss;
362 for (std::size_t i = 0; i < sizes[0]; ++i)
363 ss << std::to_string(accessor[i]) << (i < sizes[0] - 1 ? " " : "");
364 node.append_child(pugi::node_pcdata).set_value(ss.str().c_str());
365 } else if constexpr (N == 2) {
366 node.append_attribute("rows") = sizes[0];
367 node.append_attribute("cols") = sizes[1];
368
369 std::stringstream ss;
370 for (std::size_t i = 0; i < sizes[0]; ++i)
371 for (std::size_t j = 0; j < sizes[1]; ++j)
372 ss << std::to_string(accessor[i][j])
373 << (j < sizes[1] - 1 ? " " : (i < sizes[0] - 1 ? " " : ""));
374 node.append_child(pugi::node_pcdata).set_value(ss.str().c_str());
375 } else
376 throw std::runtime_error(
377 "Tag \"Matrix\" only supports 1- and 2-dimensional tensors");
378 } else {
379 std::stringstream ss;
380 for (const auto &size : sizes)
381 ss << std::to_string(size) << " ";
382
383 pugi::xml_node dims = node.append_child("Dimensions");
384 dims.append_child(pugi::node_pcdata).set_value(ss.str().c_str());
385
386 ss.str("");
387 if constexpr (N == 1) {
388 for (std::size_t i = 0; i < sizes[0]; ++i)
389 ss << std::to_string(accessor[i]) << " ";
390 } else if constexpr (N == 2) {
391 for (std::size_t i = 0; i < sizes[0]; ++i)
392 for (std::size_t j = 0; j < sizes[1]; ++j)
393 ss << std::to_string(accessor[i][j]) << " ";
394 } else if constexpr (N == 3) {
395 for (std::size_t i = 0; i < sizes[0]; ++i)
396 for (std::size_t j = 0; j < sizes[1]; ++j)
397 for (std::size_t k = 0; j < sizes[2]; ++k)
398 ss << std::to_string(accessor[i][j][k]) << " ";
399 } else if constexpr (N == 4) {
400 for (std::size_t i = 0; i < sizes[0]; ++i)
401 for (std::size_t j = 0; j < sizes[1]; ++j)
402 for (std::size_t k = 0; k < sizes[2]; ++k)
403 for (std::size_t l = 0; l < sizes[3]; ++l)
404 ss << std::to_string(accessor[i][j][k][l]) << " ";
405
406 } else if constexpr (N == 5) {
407 for (std::size_t i = 0; i < sizes[0]; ++i)
408 for (std::size_t j = 0; j < sizes[1]; ++j)
409 for (std::size_t k = 0; k < sizes[2]; ++k)
410 for (std::size_t l = 0; l < sizes[3]; ++l)
411 for (std::size_t m = 0; m < sizes[4]; ++m)
412 ss << std::to_string(accessor[i][j][k][l][m]) << " ";
413 } else if constexpr (N == 6) {
414 for (std::size_t i = 0; i < sizes[0]; ++i)
415 for (std::size_t j = 0; j < sizes[1]; ++j)
416 for (std::size_t k = 0; k < sizes[2]; ++k)
417 for (std::size_t l = 0; l < sizes[3]; ++l)
418 for (std::size_t m = 0; m < sizes[4]; ++m)
419 for (std::size_t n = 0; n < sizes[5]; ++n)
420 ss << std::to_string(accessor[i][j][k][l][m][n]) << " ";
421 } else
422 throw std::runtime_error(
423 "Dimensions higher than 4 are not implemented yet");
424
425 pugi::xml_node data = node.append_child("Data");
426 data.append_child(pugi::node_pcdata).set_value(ss.str().c_str());
427 }
428
429 return root;
430}
431
433template <typename T, std::size_t N>
434inline pugi::xml_document to_xml(const torch::Tensor &tensor,
435 std::string tag = "Matrix", int id = 0,
436 std::string label = "", int index = -1) {
437 pugi::xml_document doc;
438 pugi::xml_node root = doc.append_child("xml");
439 to_xml<T, N>(tensor, root, id, label, index);
440
441 return doc;
442}
443
445template <typename T, std::size_t N>
446inline pugi::xml_node &to_xml(const torch::Tensor &tensor, pugi::xml_node &root,
447 std::string tag = "Matrix", int id = 0,
448 std::string label = "", int index = -1) {
449
450 if (tensor.is_cuda()) {
451 auto [tensor_cpu, accessor] = to_tensorAccessor<T, N>(tensor, torch::kCPU);
452 return to_xml(accessor, tensor.sizes(), root, tag, id, label, index);
453 } else {
454 auto accessor = to_tensorAccessor<T, N>(tensor);
455 return to_xml(accessor, tensor.sizes(), root, tag, id, label, index);
456 }
457}
458
461template <typename T, std::size_t N, std::size_t M>
462inline pugi::xml_document to_xml(const utils::TensorArray<M> &tensors,
463 std::string tag = "Matrix", int id = 0,
464 std::string label = "", int index = -1) {
465 pugi::xml_document doc;
466 pugi::xml_node root = doc.append_child("xml");
467 to_xml<T, N>(tensors, root, id, label, index);
468
469 return doc;
470}
471
474template <typename T, std::size_t N, std::size_t M>
475inline pugi::xml_node &to_xml(const utils::TensorArray<M> &tensors,
476 pugi::xml_node &root, std::string tag = "Matrix",
477 int id = 0, std::string label = "") {
478
479 for (std::size_t i = 0; i < M; ++i) {
480 if (tensors[i].is_cuda()) {
481 auto [tensor_cpu, accessor] =
482 to_tensorAccessor<T, N>(tensors[i], torch::kCPU);
483 to_xml(accessor, tensors[i].sizes(), root, tag, id, label, i);
484 } else {
485 auto accessor = to_tensorAccessor<T, N>(tensors[i]);
486 to_xml(accessor, tensors[i].sizes(), root, tag, id, label, i);
487 }
488 }
489
490 return root;
491}
492
494template <typename T, std::size_t N>
495inline torch::TensorAccessor<T, N> &
496from_xml(const pugi::xml_document &doc, torch::TensorAccessor<T, N> &accessor,
497 torch::IntArrayRef sizes, std::string tag = "Matrix", int id = 0,
498 std::string label = "", int index = -1) {
499 return from_xml(doc.child("xml"), accessor, sizes, tag, id, label, index);
500}
501
503template <typename T, std::size_t N>
504inline torch::TensorAccessor<T, N> &
505from_xml(const pugi::xml_node &root, torch::TensorAccessor<T, N> &accessor,
506 torch::IntArrayRef sizes, std::string tag = "Matrix", int id = 0,
507 std::string label = "", int index = -1) {
508
509 return accessor;
510}
511
513template <typename T, std::size_t N>
514inline torch::Tensor &
515from_xml(const pugi::xml_document &doc, torch::Tensor &tensor,
516 std::string tag = "Matrix", int id = 0, std::string label = "",
517 bool alloc = true, int index = -1) {
518 return from_xml<T, N>(doc.child("xml"), tensor, tag, id, label, index);
519}
520
522template <typename T, std::size_t N>
523inline torch::Tensor &
524from_xml(const pugi::xml_node &root, torch::Tensor &tensor,
525 std::string tag = "Matrix", int id = 0, std::string label = "",
526 bool alloc = true, int index = -1) {
527
528 // Loop through all nodes
529 for (pugi::xml_node node : root.children(tag.c_str())) {
530
531 if ((id >= 0 ? node.attribute("id").as_int() == id : true) &&
532 (index >= 0 ? node.attribute("index").as_int() == index : true) &&
533 (!label.empty() ? node.attribute("label").value() == label : true)) {
534
535 if (tag == "Matrix") {
536
537 int64_t rows = node.attribute("rows").as_int();
538 int64_t cols = node.attribute("cols").as_int();
539
540 if (!alloc && (tensor.size(0) != rows || tensor.size(1) != cols))
541 throw std::runtime_error("Invalid matrix dimensions");
542
543 else if (alloc && (tensor.size(0) != rows || tensor.size(1) != cols))
544 tensor = torch::zeros({rows, cols}, tensor.options());
545
546 std::string values = std::regex_replace(
547 node.text().get(), std::regex("[\t\r\n\a]+| +"), " ");
548
549 auto [tensor_cpu, accessor] =
550 to_tensorAccessor<T, N>(tensor, torch::kCPU);
551 auto value = strtok(&values[0], " ");
552
553 for (int64_t i = 0; i < rows; ++i)
554 for (int64_t j = 0; j < cols; ++j) {
555 if (value == nullptr)
556 throw std::runtime_error(
557 "XML object does not provide enough coefficients");
558
559 accessor[i][j] = static_cast<T>(std::stod(value));
560 value = strtok(nullptr, " ");
561 }
562
563 if (value != nullptr)
564 throw std::runtime_error("XML object provides too many coefficients");
565
566 if (tensor.device().type() != torch::kCPU)
567 tensor = std::move(tensor_cpu);
568
569 return tensor;
570
571 } else {
572
573 // Check for "Dimensions"
574 if (pugi::xml_node dims = node.child("Dimensions")) {
575 std::vector<int64_t> sizes;
576
577 std::string values = std::regex_replace(
578 dims.text().get(), std::regex("[\t\r\n\a]+| +"), " ");
579 for (auto value = strtok(&values[0], " "); value != nullptr;
580 value = strtok(nullptr, " "))
581 sizes.push_back(static_cast<std::size_t>(std::stoi(value)));
582
583 if (!alloc && (tensor.sizes() != sizes))
584 throw std::runtime_error("Invalid tensor dimensions");
585
586 else if (alloc && (tensor.sizes() != sizes))
587 tensor = torch::zeros(torch::IntArrayRef{sizes}, tensor.options());
588
589 if (sizes.size() != N)
590 throw std::runtime_error("Invalid tensor dimensions");
591
592 // Check for "Data"
593 if (pugi::xml_node data = node.child("Data")) {
594 std::string values = std::regex_replace(
595 data.text().get(), std::regex("[\t\r\n\a]+| +"), " ");
596
597 auto [tensor_cpu, accessor] =
598 to_tensorAccessor<T, N>(tensor, torch::kCPU);
599 auto value = strtok(&values[0], " ");
600
601 if constexpr (N == 1) {
602 for (int64_t i = 0; i < sizes[0]; ++i) {
603 if (value == nullptr)
604 throw std::runtime_error(
605 "XML object does not provide enough coefficients");
606
607 accessor[i] = static_cast<T>(std::stod(value));
608 value = strtok(nullptr, " ");
609 }
610 } else if constexpr (N == 2) {
611 for (int64_t i = 0; i < sizes[0]; ++i)
612 for (int64_t j = 0; j < sizes[1]; ++j) {
613 if (value == nullptr)
614 throw std::runtime_error(
615 "XML object does not provide enough coefficients");
616
617 accessor[i][j] = static_cast<T>(std::stod(value));
618 value = strtok(nullptr, " ");
619 }
620 } else if constexpr (N == 3) {
621 for (int64_t i = 0; i < sizes[0]; ++i)
622 for (int64_t j = 0; j < sizes[1]; ++j)
623 for (int64_t k = 0; k < sizes[2]; ++k) {
624 if (value == nullptr)
625 throw std::runtime_error(
626 "XML object does not provide enough coefficients");
627
628 accessor[i][j][k] = static_cast<T>(std::stod(value));
629 value = strtok(nullptr, " ");
630 }
631 } else if constexpr (N == 4) {
632 for (int64_t i = 0; i < sizes[0]; ++i)
633 for (int64_t j = 0; j < sizes[1]; ++j)
634 for (int64_t k = 0; k < sizes[2]; ++k)
635 for (int64_t l = 0; l < sizes[3]; ++l) {
636 if (value == nullptr)
637 throw std::runtime_error(
638 "XML object does not provide enough coefficients");
639
640 accessor[i][j][k][l] = static_cast<T>(std::stod(value));
641 value = strtok(nullptr, " ");
642 }
643 } else if constexpr (N == 5) {
644 for (int64_t i = 0; i < sizes[0]; ++i)
645 for (int64_t j = 0; j < sizes[1]; ++j)
646 for (int64_t k = 0; k < sizes[2]; ++k)
647 for (int64_t l = 0; l < sizes[3]; ++l)
648 for (int64_t m = 0; m < sizes[4]; ++m) {
649 if (value == nullptr)
650 throw std::runtime_error(
651 "XML object does not provide enough "
652 "coefficients");
653
654 accessor[i][j][k][l][m] =
655 static_cast<T>(std::stod(value));
656 value = strtok(nullptr, " ");
657 }
658 } else if constexpr (N == 6) {
659 for (int64_t i = 0; i < sizes[0]; ++i)
660 for (int64_t j = 0; j < sizes[1]; ++j)
661 for (int64_t k = 0; k < sizes[2]; ++k)
662 for (int64_t l = 0; l < sizes[3]; ++l)
663 for (int64_t m = 0; m < sizes[4]; ++m)
664 for (int64_t n = 0; n < sizes[5]; ++n) {
665 if (value == nullptr)
666 throw std::runtime_error(
667 "XML object does not provide enough "
668 "coefficients");
669
670 accessor[i][j][k][l][m][n] =
671 static_cast<T>(std::stod(value));
672 value = strtok(nullptr, " ");
673 }
674 }
675
676 if (value != nullptr)
677 throw std::runtime_error(
678 "XML object provides too many coefficients");
679
680 if (tensor.device().type() != torch::kCPU)
681 tensor = std::move(tensor_cpu);
682
683 return tensor;
684 } // "Data"
685 } // "Dimenions"
686
687 throw std::runtime_error(
688 "XML object does not provide a \"Dimensions\" tag");
689
690 return tensor;
691 }
692
693 } // try next node
694 } // "tag"
695
696 throw std::runtime_error(
697 "XML object does not provide tag with given id, index, and/or label");
698 return tensor;
699}
700
703template <typename T, std::size_t N, std::size_t M>
705from_xml(const pugi::xml_document &doc, utils::TensorArray<M> &tensors,
706 std::string tag = "Matrix", int id = 0, bool alloc = true,
707 std::string label = "") {
708
709 return from_xml<T, N>(doc.child("xml"), tensors, tag, id, label, alloc);
710}
711
713template <typename T, std::size_t N, std::size_t M>
715from_xml(const pugi::xml_node &root, utils::TensorArray<M> &tensors,
716 std::string tag = "Matrix", int id = 0, bool alloc = true,
717 std::string label = "") {
718
719 for (std::size_t i = 0; i < M; ++i) {
720 from_xml<T, N>(root, tensors[i], tag, id, label, alloc, i);
721 }
722
723 return tensors;
724}
725
726} // namespace iganet::utils
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:104
Core components.
Definition blocktensor.hpp:24
pugi::xml_document to_xml(const torch::TensorAccessor< T, N > &accessor, torch::IntArrayRef sizes, std::string tag="Matrix", int id=0, std::string label="", int index=-1)
Converts a torch::TensorAccessor object to an XML document object.
Definition serialize.hpp:325
auto to_json(const torch::TensorAccessor< T, N > &accessor)
Converts a torch::TensorAccessor object to a JSON object.
Definition serialize.hpp:42
torch::TensorAccessor< T, N > & from_xml(const pugi::xml_document &doc, torch::TensorAccessor< T, N > &accessor, torch::IntArrayRef sizes, std::string tag="Matrix", int id=0, std::string label="", int index=-1)
Converts an XML documentobject to a torch::TensorAccessor object.
Definition serialize.hpp:496
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:26
struct iganet::@0 Log
Logger.
Serialization prototype.
Definition serialize.hpp:29
virtual void pretty_print(std::ostream &os=Log(log::info)) const =0
Returns a string representation of the object.
virtual nlohmann::json to_json() const =0
Returns the object as JSON object.
virtual ~Serializable()=default
Destructor.
TensorArray utility functions.