20#include <nlohmann/json.hpp>
35 virtual nlohmann::json
to_json()
const = 0;
47template <
typename T, std::
size_t N>
48inline auto to_json(
const torch::TensorAccessor<T, N> &accessor) {
49 auto json = nlohmann::json::array();
51 if constexpr (N == 1) {
52 for (int64_t i = 0; i < accessor.size(0); ++i)
53 json.push_back(accessor[i]);
54 }
else if constexpr (N == 2) {
55 for (int64_t i = 0; i < accessor.size(0); ++i)
56 for (int64_t j = 0; j < accessor.size(1); ++j)
57 json.push_back(accessor[i][j]);
58 }
else if constexpr (N == 3) {
59 for (int64_t i = 0; i < accessor.size(0); ++i)
60 for (int64_t j = 0; j < accessor.size(1); ++j)
61 for (int64_t k = 0; k < accessor.size(2); ++k)
62 json.push_back(accessor[i][j][k]);
63 }
else if constexpr (N == 4) {
64 for (int64_t i = 0; i < accessor.size(0); ++i)
65 for (int64_t j = 0; j < accessor.size(1); ++j)
66 for (int64_t k = 0; k < accessor.size(2); ++k)
67 for (int64_t l = 0; l < accessor.size(3); ++l)
68 json.push_back(accessor[i][j][k][l]);
79template <
typename T, std::
size_t N>
80inline auto to_json(
const torch::Tensor &tensor) {
81 if (tensor.is_cuda()) {
82 auto [tensor_cpu, accessor] = to_tensorAccessor<T, N>(tensor, torch::kCPU);
85 auto accessor = to_tensorAccessor<T, N>(tensor);
97template <
typename T, std::
size_t N, std::
size_t M>
99 auto json = nlohmann::json::array();
101 for (std::size_t i = 0; i < M; ++i) {
102 if (tensors[i].is_cuda()) {
103 auto [tensor_cpu, accessor] =
104 to_tensorAccessor<T, N>(tensors[i], torch::kCPU);
105 json.push_back(to_json<T, N>(accessor));
107 auto accessor = to_tensorAccessor<T, N>(tensors[i]);
108 json.push_back(to_json<T, N>(accessor));
115#ifdef IGANET_WITH_GISMO
117template <
typename T,
int Rows,
int Cols,
int Options>
118inline auto to_json(
const gismo::gsMatrix<T, Rows, Cols, Options> &matrix,
119 bool flatten =
false,
bool transpose =
false) {
120 auto json = nlohmann::json::array();
122 if constexpr (
Options == gismo::RowMajor) {
125 for (std::size_t j = 0; j < matrix.cols(); ++j)
126 for (std::size_t i = 0; i < matrix.rows(); ++i)
127 json.push_back(matrix(i, j));
129 for (std::size_t i = 0; i < matrix.rows(); ++i)
130 for (std::size_t j = 0; j < matrix.cols(); ++j)
131 json.push_back(matrix(i, j));
135 for (std::size_t j = 0; j < matrix.cols(); ++j) {
136 auto data = nlohmann::json::array();
137 for (std::size_t i = 0; i < matrix.rows(); ++i) {
138 data.push_back(matrix(i, j));
140 json.emplace_back(data);
143 for (std::size_t i = 0; i < matrix.rows(); ++i) {
144 auto data = nlohmann::json::array();
145 for (std::size_t j = 0; j < matrix.cols(); ++j) {
146 data.push_back(matrix(i, j));
148 json.emplace_back(data);
153 }
else if constexpr (Options == gismo::ColMajor) {
156 for (std::size_t i = 0; i < matrix.rows(); ++i)
157 for (std::size_t j = 0; j < matrix.cols(); ++j)
158 json.push_back(matrix(i, j));
160 for (std::size_t j = 0; j < matrix.cols(); ++j)
161 for (std::size_t i = 0; i < matrix.rows(); ++i)
162 json.push_back(matrix(i, j));
166 for (std::size_t i = 0; i < matrix.rows(); ++i) {
167 auto data = nlohmann::json::array();
168 for (std::size_t j = 0; j < matrix.cols(); ++j) {
169 data.push_back(matrix(i, j));
171 json.emplace_back(data);
174 for (std::size_t j = 0; j < matrix.cols(); ++j) {
175 auto data = nlohmann::json::array();
176 for (std::size_t i = 0; i < matrix.rows(); ++i) {
177 data.push_back(matrix(i, j));
179 json.emplace_back(data);
185 throw std::runtime_error(
"Invalid matrix options");
191template <
typename T>
inline auto to_json(
const gismo::gsBSpline<T> &bspline) {
192 auto json = nlohmann::json();
194 json[
"degrees"] = nlohmann::json::array();
196 for (std::size_t i = 0; i < bspline.parDim(); ++i)
197 json[
"degrees"].push_back(bspline.degree(i));
199 json[
"geoDim"] = bspline.geoDim();
200 json[
"parDim"] = bspline.parDim();
202 json[
"ncoeffs"] = nlohmann::json::array();
203 for (std::size_t i = 0; i < bspline.parDim(); ++i)
204 json[
"ncoeffs"].push_back(bspline.basis().size(i));
208 json[
"nknots"] = nlohmann::json::array();
209 for (std::size_t i = 0; i < bspline.parDim(); ++i)
210 json[
"nknots"].push_back(bspline.knots(i).size());
212 json[
"knots"] = nlohmann::json::array();
213 for (std::size_t i = 0; i < bspline.parDim(); ++i)
214 json[
"knots"].push_back(bspline.knots(i));
220template <
int d,
typename T>
221inline auto to_json(
const gismo::gsTensorBSpline<d, T> &bspline) {
222 auto json = nlohmann::json();
224 json[
"degrees"] = nlohmann::json::array();
226 for (std::size_t i = 0; i < bspline.parDim(); ++i)
227 json[
"degrees"].push_back(bspline.degree(i));
229 json[
"geoDim"] = bspline.geoDim();
230 json[
"parDim"] = bspline.parDim();
232 json[
"ncoeffs"] = nlohmann::json::array();
233 for (std::size_t i = 0; i < bspline.parDim(); ++i)
234 json[
"ncoeffs"].push_back(bspline.basis().size(i));
238 json[
"nknots"] = nlohmann::json::array();
239 for (std::size_t i = 0; i < bspline.parDim(); ++i)
240 json[
"nknots"].push_back(bspline.knots(i).size());
242 json[
"knots"] = nlohmann::json::array();
243 for (std::size_t i = 0; i < bspline.parDim(); ++i)
244 json[
"knots"].push_back(bspline.knots(i));
251inline auto to_json(
const gismo::gsGeometry<T> &geometry) {
253 if (
auto patch =
dynamic_cast<const gismo::gsBSpline<T> *
>(&geometry))
255 else if (
auto patch =
256 dynamic_cast<const gismo::gsTensorBSpline<2, T> *
>(&geometry))
258 else if (
auto patch =
259 dynamic_cast<const gismo::gsTensorBSpline<3, T> *
>(&geometry))
261 else if (
auto patch =
262 dynamic_cast<const gismo::gsTensorBSpline<4, T> *
>(&geometry))
265 return nlohmann::json(
"{ Invalid patch type }");
271to_json(
const typename gismo::gsMultiPatch<T>::ifContainer &interfaces) {
273 auto json = nlohmann::json::array();
275 for (
auto const &interface : interfaces) {
276 auto interface_json = nlohmann::json();
278 interface_json[
"patches"] = {interface.first().patchIndex(),
279 interface.second().patchIndex()};
280 interface_json[
"sides"] = {interface.first().side().index(),
281 interface.second().side().index()};
282 interface_json[
"direction"] =
"NOT IMPLEMENTED YET";
283 interface_json[
"orientation"] =
"NOT IMPLEMENTED YET";
285 json.push_back(interface_json);
294to_json(
const typename gismo::gsMultiPatch<T>::bContainer &boundaries) {
296 auto json = nlohmann::json::array();
298 for (
auto const &
boundary : boundaries) {
299 auto boundary_json = nlohmann::json();
301 boundary_json[
"patch"] =
boundary.patchIndex();
302 boundary_json[
"side"] =
boundary.side().index();
304 json.push_back(boundary_json);
312inline auto to_json(
const gismo::gsMultiPatch<T> &mp,
bool verbose =
false) {
314 auto json = nlohmann::json();
317 auto patches_json = nlohmann::json::array();
318 for (std::size_t i = 0; i < mp.nPatches(); ++i)
319 patches_json.push_back(i);
321 json[
"patches"] = patches_json;
322 json[
"interfaces"] = to_json<T>(mp.interfaces());
323 json[
"boundaries"] = to_json<T>(mp.boundaries());
326 auto patches_json = nlohmann::json::array();
328 for (std::size_t i = 0; i < mp.nPatches(); ++i)
329 patches_json.push_back(
to_json(mp.patch(i)));
331 json[
"patches"] = patches_json;
338template <
typename T, std::
size_t N>
339inline pugi::xml_node &
to_xml(
const torch::TensorAccessor<T, N> &accessor,
340 torch::IntArrayRef sizes, pugi::xml_node &root,
341 std::string tag =
"Matrix",
int id = 0,
342 const std::string &label =
"",
int index = -1);
354template <
typename T, std::
size_t N>
355inline pugi::xml_document
to_xml(
const torch::TensorAccessor<T, N> &accessor,
356 torch::IntArrayRef sizes,
357 std::string tag =
"Matrix",
int id = 0,
358 const std::string &label =
"",
int index = -1) {
359 pugi::xml_document doc;
360 pugi::xml_node root = doc.append_child(
"xml");
361 to_xml(accessor, sizes, root, tag,
id, label, index);
377template <
typename T, std::
size_t N>
378inline pugi::xml_node &
to_xml(
const torch::TensorAccessor<T, N> &accessor,
379 torch::IntArrayRef sizes, pugi::xml_node &root,
380 std::string tag,
int id,
const std::string &label,
384 pugi::xml_node node = root.append_child(tag.c_str());
387 node.append_attribute(
"id") = id;
390 node.append_attribute(
"index") = index;
393 node.append_attribute(
"label") = label.c_str();
396 if (tag ==
"Matrix") {
397 if constexpr (N == 1) {
398 node.append_attribute(
"rows") = sizes[0];
399 node.append_attribute(
"cols") = 1;
401 std::stringstream ss;
402 for (std::size_t i = 0; i < sizes[0]; ++i)
403 ss << std::to_string(accessor[i]) << (i < sizes[0] - 1 ?
" " :
"");
404 node.append_child(pugi::node_pcdata).set_value(ss.str().c_str());
405 }
else if constexpr (N == 2) {
406 node.append_attribute(
"rows") = sizes[0];
407 node.append_attribute(
"cols") = sizes[1];
409 std::stringstream ss;
410 for (std::size_t i = 0; i < sizes[0]; ++i)
411 for (std::size_t j = 0; j < sizes[1]; ++j)
412 ss << std::to_string(accessor[i][j])
413 << (j < sizes[1] - 1 ?
" " : (i < sizes[0] - 1 ?
" " :
""));
414 node.append_child(pugi::node_pcdata).set_value(ss.str().c_str());
416 throw std::runtime_error(
417 "Tag \"Matrix\" only supports 1- and 2-dimensional tensors");
419 std::stringstream ss;
420 for (
const auto &size : sizes)
421 ss << std::to_string(size) <<
" ";
423 pugi::xml_node dims = node.append_child(
"Dimensions");
424 dims.append_child(pugi::node_pcdata).set_value(ss.str().c_str());
427 if constexpr (N == 1) {
428 for (std::size_t i = 0; i < sizes[0]; ++i)
429 ss << std::to_string(accessor[i]) <<
" ";
430 }
else if constexpr (N == 2) {
431 for (std::size_t i = 0; i < sizes[0]; ++i)
432 for (std::size_t j = 0; j < sizes[1]; ++j)
433 ss << std::to_string(accessor[i][j]) <<
" ";
434 }
else if constexpr (N == 3) {
435 for (std::size_t i = 0; i < sizes[0]; ++i)
436 for (std::size_t j = 0; j < sizes[1]; ++j)
437 for (std::size_t k = 0; k < sizes[2]; ++k)
438 ss << std::to_string(accessor[i][j][k]) <<
" ";
439 }
else if constexpr (N == 4) {
440 for (std::size_t i = 0; i < sizes[0]; ++i)
441 for (std::size_t j = 0; j < sizes[1]; ++j)
442 for (std::size_t k = 0; k < sizes[2]; ++k)
443 for (std::size_t l = 0; l < sizes[3]; ++l)
444 ss << std::to_string(accessor[i][j][k][l]) <<
" ";
446 }
else if constexpr (N == 5) {
447 for (std::size_t i = 0; i < sizes[0]; ++i)
448 for (std::size_t j = 0; j < sizes[1]; ++j)
449 for (std::size_t k = 0; k < sizes[2]; ++k)
450 for (std::size_t l = 0; l < sizes[3]; ++l)
451 for (std::size_t m = 0; m < sizes[4]; ++m)
452 ss << std::to_string(accessor[i][j][k][l][m]) <<
" ";
453 }
else if constexpr (N == 6) {
454 for (std::size_t i = 0; i < sizes[0]; ++i)
455 for (std::size_t j = 0; j < sizes[1]; ++j)
456 for (std::size_t k = 0; k < sizes[2]; ++k)
457 for (std::size_t l = 0; l < sizes[3]; ++l)
458 for (std::size_t m = 0; m < sizes[4]; ++m)
459 for (std::size_t n = 0; n < sizes[5]; ++n)
460 ss << std::to_string(accessor[i][j][k][l][m][n]) <<
" ";
462 throw std::runtime_error(
463 "Dimensions higher than 6 are not implemented yet");
465 pugi::xml_node data = node.append_child(
"Data");
466 data.append_child(pugi::node_pcdata).set_value(ss.str().c_str());
472template <
typename T, std::
size_t N>
473inline pugi::xml_node &
to_xml(
const torch::Tensor &tensor,
474 pugi::xml_node &root,
475 std::string tag =
"Matrix",
int id = 0,
476 const std::string &label =
"",
int index = -1);
487template <
typename T, std::
size_t N>
488inline pugi::xml_document
to_xml(
const torch::Tensor &tensor,
489 std::string tag =
"Matrix",
int id = 0,
490 const std::string &label =
"",
int index = -1) {
491 pugi::xml_document doc;
492 pugi::xml_node root = doc.append_child(
"xml");
493 to_xml<T, N>(tensor, root, tag,
id, label, index);
508template <
typename T, std::
size_t N>
509inline pugi::xml_node &
to_xml(
const torch::Tensor &tensor, pugi::xml_node &root,
510 std::string tag,
int id,
const std::string &label,
513 if (tensor.is_cuda()) {
514 auto [tensor_cpu, accessor] = to_tensorAccessor<T, N>(tensor, torch::kCPU);
515 return to_xml(accessor, tensor.sizes(), root, tag,
id, label, index);
517 auto accessor = to_tensorAccessor<T, N>(tensor);
518 return to_xml(accessor, tensor.sizes(), root, tag,
id, label, index);
522template <
typename T, std::
size_t N, std::
size_t M>
524 pugi::xml_node &root,
525 std::string tag =
"Matrix",
int id = 0,
526 const std::string &label =
"");
539template <
typename T, std::
size_t N, std::
size_t M>
541 std::string tag =
"Matrix",
int id = 0,
542 const std::string &label =
"",
int index = -1) {
543 pugi::xml_document doc;
544 pugi::xml_node root = doc.append_child(
"xml");
545 to_xml<T, N>(tensors, root, tag,
id, label);
561template <
typename T, std::
size_t N, std::
size_t M>
563 pugi::xml_node &root, std::string tag,
int id,
564 const std::string &label) {
566 for (std::size_t i = 0; i < M; ++i) {
567 if (tensors[i].is_cuda()) {
568 auto [tensor_cpu, accessor] =
569 to_tensorAccessor<T, N>(tensors[i], torch::kCPU);
570 to_xml(accessor, tensors[i].sizes(), root, tag,
id, label, i);
572 auto accessor = to_tensorAccessor<T, N>(tensors[i]);
573 to_xml(accessor, tensors[i].sizes(), root, tag,
id, label, i);
591template <
typename T, std::
size_t N>
592inline torch::TensorAccessor<T, N> &
593from_xml(
const pugi::xml_document &doc, torch::TensorAccessor<T, N> &accessor,
594 torch::IntArrayRef sizes, std::string tag =
"Matrix",
int id = 0,
595 const std::string &label =
"",
int index = -1) {
596 return from_xml(doc.child(
"xml"), accessor, sizes, tag,
id, label, index);
610template <
typename T, std::
size_t N>
611inline torch::TensorAccessor<T, N> &
612from_xml(
const pugi::xml_node &root, torch::TensorAccessor<T, N> &accessor,
613 torch::IntArrayRef sizes, std::string tag =
"Matrix",
int id = 0,
614 const std::string &label =
"",
int index = -1) {
619template <
typename T, std::
size_t N>
620inline torch::Tensor &
from_xml(
const pugi::xml_node &root,
621 torch::Tensor &tensor,
622 std::string tag =
"Matrix",
int id = 0,
623 const std::string &label =
"",
bool alloc =
true,
637template <
typename T, std::
size_t N>
638inline torch::Tensor &
639from_xml(
const pugi::xml_document &doc, torch::Tensor &tensor,
640 std::string tag =
"Matrix",
int id = 0,
641 const std::string &label =
"",
642 bool alloc =
true,
int index = -1) {
643 return from_xml<T, N>(doc.child(
"xml"), tensor, tag,
id, label, alloc,
658template <
typename T, std::
size_t N>
659inline torch::Tensor &
660from_xml(
const pugi::xml_node &root, torch::Tensor &tensor,
661 std::string tag,
int id,
const std::string &label,
bool alloc,
665 for (pugi::xml_node node : root.children(tag.c_str())) {
667 if ((
id >= 0 ? node.attribute(
"id").as_int() ==
id :
true) &&
668 (index >= 0 ? node.attribute(
"index").as_int() == index :
true) &&
669 (!label.empty() ? node.attribute(
"label").value() == label :
true)) {
671 if (tag ==
"Matrix") {
673 int64_t rows = node.attribute(
"rows").as_int();
674 int64_t cols = node.attribute(
"cols").as_int();
676 if constexpr (N == 1) {
678 throw std::runtime_error(
"Invalid matrix dimensions");
679 if (!alloc && (tensor.dim() != 1 || tensor.size(0) != rows))
680 throw std::runtime_error(
"Invalid matrix dimensions");
681 if (alloc && (tensor.dim() != 1 || tensor.size(0) != rows))
682 tensor = torch::zeros({rows}, tensor.options());
683 }
else if constexpr (N == 2) {
685 (tensor.dim() != 2 || tensor.size(0) != rows ||
686 tensor.size(1) != cols))
687 throw std::runtime_error(
"Invalid matrix dimensions");
689 (tensor.dim() != 2 || tensor.size(0) != rows ||
690 tensor.size(1) != cols))
691 tensor = torch::zeros({rows, cols}, tensor.options());
693 throw std::runtime_error(
694 "Tag \"Matrix\" only supports 1- and 2-dimensional tensors");
697 std::string values = std::regex_replace(
698 node.text().get(), std::regex(
"[\t\r\n\a]+| +"),
" ");
700 auto [tensor_cpu, accessor] =
701 to_tensorAccessor<T, N>(tensor, torch::kCPU);
702 auto value = strtok(&values[0],
" ");
704 if constexpr (N == 1) {
705 for (int64_t i = 0; i < rows; ++i) {
706 if (value ==
nullptr)
707 throw std::runtime_error(
708 "XML object does not provide enough coefficients");
709 accessor[i] =
static_cast<T
>(std::stod(value));
710 value = strtok(
nullptr,
" ");
712 }
else if constexpr (N == 2) {
713 for (int64_t i = 0; i < rows; ++i)
714 for (int64_t j = 0; j < cols; ++j) {
715 if (value ==
nullptr)
716 throw std::runtime_error(
717 "XML object does not provide enough coefficients");
718 accessor[i][j] =
static_cast<T
>(std::stod(value));
719 value = strtok(
nullptr,
" ");
723 if (value !=
nullptr)
724 throw std::runtime_error(
"XML object provides too many coefficients");
726 if (tensor.device().type() != torch::kCPU)
727 tensor = std::move(tensor_cpu);
734 if (pugi::xml_node dims = node.child(
"Dimensions")) {
735 std::vector<int64_t> sizes;
737 std::string values = std::regex_replace(
738 dims.text().get(), std::regex(
"[\t\r\n\a]+| +"),
" ");
739 for (
auto value = strtok(&values[0],
" "); value !=
nullptr;
740 value = strtok(
nullptr,
" "))
741 sizes.push_back(
static_cast<std::size_t
>(std::stoi(value)));
743 if (!alloc && (tensor.sizes() != sizes))
744 throw std::runtime_error(
"Invalid tensor dimensions");
746 else if (alloc && (tensor.sizes() != sizes))
747 tensor = torch::zeros(torch::IntArrayRef{sizes}, tensor.options());
749 if (sizes.size() != N)
750 throw std::runtime_error(
"Invalid tensor dimensions");
753 if (pugi::xml_node data = node.child(
"Data")) {
754 std::string values = std::regex_replace(
755 data.text().get(), std::regex(
"[\t\r\n\a]+| +"),
" ");
757 auto [tensor_cpu, accessor] =
758 to_tensorAccessor<T, N>(tensor, torch::kCPU);
759 auto value = strtok(&values[0],
" ");
761 if constexpr (N == 1) {
762 for (int64_t i = 0; i < sizes[0]; ++i) {
763 if (value ==
nullptr)
764 throw std::runtime_error(
765 "XML object does not provide enough coefficients");
767 accessor[i] =
static_cast<T
>(std::stod(value));
768 value = strtok(
nullptr,
" ");
770 }
else if constexpr (N == 2) {
771 for (int64_t i = 0; i < sizes[0]; ++i)
772 for (int64_t j = 0; j < sizes[1]; ++j) {
773 if (value ==
nullptr)
774 throw std::runtime_error(
775 "XML object does not provide enough coefficients");
777 accessor[i][j] =
static_cast<T
>(std::stod(value));
778 value = strtok(
nullptr,
" ");
780 }
else if constexpr (N == 3) {
781 for (int64_t i = 0; i < sizes[0]; ++i)
782 for (int64_t j = 0; j < sizes[1]; ++j)
783 for (int64_t k = 0; k < sizes[2]; ++k) {
784 if (value ==
nullptr)
785 throw std::runtime_error(
786 "XML object does not provide enough coefficients");
788 accessor[i][j][k] =
static_cast<T
>(std::stod(value));
789 value = strtok(
nullptr,
" ");
791 }
else if constexpr (N == 4) {
792 for (int64_t i = 0; i < sizes[0]; ++i)
793 for (int64_t j = 0; j < sizes[1]; ++j)
794 for (int64_t k = 0; k < sizes[2]; ++k)
795 for (int64_t l = 0; l < sizes[3]; ++l) {
796 if (value ==
nullptr)
797 throw std::runtime_error(
798 "XML object does not provide enough coefficients");
800 accessor[i][j][k][l] =
static_cast<T
>(std::stod(value));
801 value = strtok(
nullptr,
" ");
803 }
else if constexpr (N == 5) {
804 for (int64_t i = 0; i < sizes[0]; ++i)
805 for (int64_t j = 0; j < sizes[1]; ++j)
806 for (int64_t k = 0; k < sizes[2]; ++k)
807 for (int64_t l = 0; l < sizes[3]; ++l)
808 for (int64_t m = 0; m < sizes[4]; ++m) {
809 if (value ==
nullptr)
810 throw std::runtime_error(
811 "XML object does not provide enough "
814 accessor[i][j][k][l][m] =
815 static_cast<T
>(std::stod(value));
816 value = strtok(
nullptr,
" ");
818 }
else if constexpr (N == 6) {
819 for (int64_t i = 0; i < sizes[0]; ++i)
820 for (int64_t j = 0; j < sizes[1]; ++j)
821 for (int64_t k = 0; k < sizes[2]; ++k)
822 for (int64_t l = 0; l < sizes[3]; ++l)
823 for (int64_t m = 0; m < sizes[4]; ++m)
824 for (int64_t n = 0; n < sizes[5]; ++n) {
825 if (value ==
nullptr)
826 throw std::runtime_error(
827 "XML object does not provide enough "
830 accessor[i][j][k][l][m][n] =
831 static_cast<T
>(std::stod(value));
832 value = strtok(
nullptr,
" ");
836 if (value !=
nullptr)
837 throw std::runtime_error(
838 "XML object provides too many coefficients");
840 if (tensor.device().type() != torch::kCPU)
841 tensor = std::move(tensor_cpu);
847 throw std::runtime_error(
848 "XML object does not provide a \"Dimensions\" tag");
856 throw std::runtime_error(
857 "XML object does not provide tag with given id, index, and/or label");
861template <
typename T, std::
size_t N, std::
size_t M>
864 std::string tag =
"Matrix",
int id = 0,
bool alloc =
true,
865 const std::string &label =
"");
879template <
typename T, std::
size_t N, std::
size_t M>
882 std::string tag =
"Matrix",
int id = 0,
bool alloc =
true,
883 const std::string &label =
"") {
885 return from_xml<T, N>(doc.child(
"xml"), tensors, tag,
id, alloc, label);
899template <
typename T, std::
size_t N, std::
size_t M>
902 std::string tag,
int id,
bool alloc,
const std::string &label) {
904 for (std::size_t i = 0; i < M; ++i) {
905 from_xml<T, N>(root, tensors[i], tag,
id, label, alloc, i);
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:47
Definition blocktensor.hpp:24
auto to_json(const torch::TensorAccessor< T, N > &accessor)
Converts a torch::TensorAccessor object to a JSON object.
Definition serialize.hpp:48
pugi::xml_node & to_xml(const torch::TensorAccessor< T, N > &accessor, torch::IntArrayRef sizes, pugi::xml_node &root, std::string tag="Matrix", int id=0, const std::string &label="", int index=-1)
Converts a torch::TensorAccessor object to an XML object.
Definition serialize.hpp:378
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:26
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, const std::string &label="", int index=-1)
Converts an XML document object to a torch::TensorAccessor object.
Definition serialize.hpp:593
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.