19#include <nlohmann/json.hpp>
22#include <torch/torch.h>
33 virtual nlohmann::json
to_json()
const = 0;
40template <
typename T, std::
size_t N>
42 auto json = nlohmann::json::array();
44 if constexpr (
N == 1) {
47 }
else if constexpr (
N == 2) {
51 }
else if constexpr (
N == 3) {
56 }
else if constexpr (
N == 4) {
68template <
typename T, std::
size_t N>
81template <
typename T, std::
size_t N, std::
size_t M>
83 auto json = nlohmann::json::array();
85 for (std::size_t
i = 0;
i <
M; ++
i) {
99#ifdef IGANET_WITH_GISMO
101template <
typename T,
int Rows,
int Cols,
int Options>
102inline auto to_json(
const gismo::gsMatrix<T, Rows, Cols, Options> &
matrix,
104 auto json = nlohmann::json::array();
106 if constexpr (
Options == gismo::RowMajor) {
109 for (std::size_t
j = 0;
j <
matrix.cols(); ++
j)
110 for (std::size_t
i = 0;
i <
matrix.rows(); ++
i)
113 for (std::size_t
i = 0;
i <
matrix.rows(); ++
i)
114 for (std::size_t
j = 0;
j <
matrix.cols(); ++
j)
119 for (std::size_t
j = 0;
j <
matrix.cols(); ++
j) {
120 auto data = nlohmann::json::array();
121 for (std::size_t
i = 0;
i <
matrix.rows(); ++
i) {
124 json.emplace_back(data);
127 for (std::size_t
i = 0;
i <
matrix.rows(); ++
i) {
128 auto data = nlohmann::json::array();
129 for (std::size_t
j = 0;
j <
matrix.cols(); ++
j) {
132 json.emplace_back(data);
137 }
else if constexpr (Options == gismo::ColMajor) {
140 for (std::size_t
i = 0;
i <
matrix.rows(); ++
i)
141 for (std::size_t
j = 0;
j <
matrix.cols(); ++
j)
144 for (std::size_t
j = 0;
j <
matrix.cols(); ++
j)
145 for (std::size_t
i = 0;
i <
matrix.rows(); ++
i)
150 for (std::size_t
i = 0;
i <
matrix.rows(); ++
i) {
151 auto data = nlohmann::json::array();
152 for (std::size_t
j = 0;
j <
matrix.cols(); ++
j) {
155 json.emplace_back(data);
158 for (std::size_t
j = 0;
j <
matrix.cols(); ++
j) {
159 auto data = nlohmann::json::array();
160 for (std::size_t
i = 0;
i <
matrix.rows(); ++
i) {
163 json.emplace_back(data);
169 throw std::runtime_error(
"Invalid matrix options");
175template <
typename T>
inline auto to_json(
const gismo::gsBSpline<T> &
bspline) {
176 auto json = nlohmann::json();
178 json[
"degrees"] = nlohmann::json::array();
180 for (std::size_t
i = 0;
i <
bspline.parDim(); ++
i)
186 json[
"ncoeffs"] = nlohmann::json::array();
187 for (std::size_t
i = 0;
i <
bspline.parDim(); ++
i)
192 json[
"nknots"] = nlohmann::json::array();
193 for (std::size_t
i = 0;
i <
bspline.parDim(); ++
i)
196 json[
"knots"] = nlohmann::json::array();
197 for (std::size_t
i = 0;
i <
bspline.parDim(); ++
i)
204template <
int d,
typename T>
206 auto json = nlohmann::json();
208 json[
"degrees"] = nlohmann::json::array();
210 for (std::size_t
i = 0;
i <
bspline.parDim(); ++
i)
216 json[
"ncoeffs"] = nlohmann::json::array();
217 for (std::size_t
i = 0;
i <
bspline.parDim(); ++
i)
222 json[
"nknots"] = nlohmann::json::array();
223 for (std::size_t
i = 0;
i <
bspline.parDim(); ++
i)
226 json[
"knots"] = nlohmann::json::array();
227 for (std::size_t
i = 0;
i <
bspline.parDim(); ++
i)
237 if (
auto patch =
dynamic_cast<const gismo::gsBSpline<T> *
>(&
geometry))
239 else if (
auto patch =
dynamic_cast<const gismo::gsTensorBSpline<2, T> *
>(&
geometry))
241 else if (
auto patch =
dynamic_cast<const gismo::gsTensorBSpline<3, T> *
>(&
geometry))
243 else if (
auto patch =
dynamic_cast<const gismo::gsTensorBSpline<4, T> *
>(&
geometry))
246 return nlohmann::json(
"{ Invalid patch type }");
251inline auto to_json(
const typename gismo::gsMultiPatch<T>::ifContainer &
interfaces) {
253 auto json = nlohmann::json::array();
271inline auto to_json(
const typename gismo::gsMultiPatch<T>::bContainer &
boundaries) {
273 auto json = nlohmann::json::array();
288 template <
typename T>
inline auto to_json(
const gismo::gsMultiPatch<T> &
mp,
bool verbose=
false) {
290 auto json = nlohmann::json();
294 for (std::size_t
i = 0;
i <
mp.nPatches(); ++
i)
304 for (std::size_t
i = 0;
i <
mp.nPatches(); ++
i)
315template <
typename T, std::
size_t N>
317 torch::IntArrayRef
sizes,
318 std::string
tag =
"Matrix",
int id = 0,
319 std::string
label =
"",
int index = -1) {
320 pugi::xml_document
doc;
321 pugi::xml_node
root =
doc.append_child(
"xml");
328template <
typename T, std::
size_t N>
330 torch::IntArrayRef
sizes, pugi::xml_node &
root,
331 std::string
tag =
"Matrix",
int id = 0,
332 std::string
label =
"",
int index = -1) {
335 pugi::xml_node
node =
root.append_child(
tag.c_str());
338 node.append_attribute(
"id") =
id;
341 node.append_attribute(
"index") = index;
344 node.append_attribute(
"label") =
label.c_str();
347 if (
tag ==
"Matrix") {
348 if constexpr (
N == 1) {
349 node.append_attribute(
"rows") =
sizes[0];
350 node.append_attribute(
"cols") = 1;
352 std::stringstream
ss;
353 for (std::size_t
i = 0;
i <
sizes[0]; ++
i)
355 node.append_child(pugi::node_pcdata).set_value(
ss.str().c_str());
356 }
else if constexpr (
N == 2) {
357 node.append_attribute(
"rows") =
sizes[0];
358 node.append_attribute(
"cols") =
sizes[1];
360 std::stringstream
ss;
361 for (std::size_t
i = 0;
i <
sizes[0]; ++
i)
362 for (std::size_t
j = 0;
j <
sizes[1]; ++
j)
364 << (
j <
sizes[1] - 1 ?
" " : (
i <
sizes[0] - 1 ?
" " :
""));
365 node.append_child(pugi::node_pcdata).set_value(
ss.str().c_str());
367 throw std::runtime_error(
368 "Tag \"Matrix\" only supports 1- and 2-dimensional tensors");
370 std::stringstream
ss;
371 for (
const auto &size :
sizes)
372 ss << std::to_string(size) <<
" ";
374 pugi::xml_node dims =
node.append_child(
"Dimensions");
375 dims.append_child(pugi::node_pcdata).set_value(
ss.str().c_str());
378 if constexpr (
N == 1) {
379 for (std::size_t
i = 0;
i <
sizes[0]; ++
i)
381 }
else if constexpr (
N == 2) {
382 for (std::size_t
i = 0;
i <
sizes[0]; ++
i)
383 for (std::size_t
j = 0;
j <
sizes[1]; ++
j)
385 }
else if constexpr (
N == 3) {
386 for (std::size_t
i = 0;
i <
sizes[0]; ++
i)
387 for (std::size_t
j = 0;
j <
sizes[1]; ++
j)
388 for (std::size_t
k = 0;
j <
sizes[2]; ++
k)
390 }
else if constexpr (
N == 4) {
391 for (std::size_t
i = 0;
i <
sizes[0]; ++
i)
392 for (std::size_t
j = 0;
j <
sizes[1]; ++
j)
393 for (std::size_t
k = 0;
k <
sizes[2]; ++
k)
394 for (std::size_t
l = 0;
l <
sizes[3]; ++
l)
397 }
else if constexpr (
N == 5) {
398 for (std::size_t
i = 0;
i <
sizes[0]; ++
i)
399 for (std::size_t
j = 0;
j <
sizes[1]; ++
j)
400 for (std::size_t
k = 0;
k <
sizes[2]; ++
k)
401 for (std::size_t
l = 0;
l <
sizes[3]; ++
l)
402 for (std::size_t
m = 0;
m <
sizes[4]; ++
m)
404 }
else if constexpr (
N == 6) {
405 for (std::size_t
i = 0;
i <
sizes[0]; ++
i)
406 for (std::size_t
j = 0;
j <
sizes[1]; ++
j)
407 for (std::size_t
k = 0;
k <
sizes[2]; ++
k)
408 for (std::size_t
l = 0;
l <
sizes[3]; ++
l)
409 for (std::size_t
m = 0;
m <
sizes[4]; ++
m)
410 for (std::size_t
n = 0;
n <
sizes[5]; ++
n)
413 throw std::runtime_error(
414 "Dimensions higher than 4 are not implemented yet");
416 pugi::xml_node data =
node.append_child(
"Data");
417 data.append_child(pugi::node_pcdata).set_value(
ss.str().c_str());
424template <
typename T, std::
size_t N>
426 std::string
tag =
"Matrix",
int id = 0,
427 std::string
label =
"",
int index = -1) {
428 pugi::xml_document
doc;
429 pugi::xml_node
root =
doc.append_child(
"xml");
436template <
typename T, std::
size_t N>
438 std::string
tag =
"Matrix",
int id = 0,
439 std::string
label =
"",
int index = -1) {
452template <
typename T, std::
size_t N, std::
size_t M>
454 std::string
tag =
"Matrix",
int id = 0,
455 std::string
label =
"",
int index = -1) {
456 pugi::xml_document
doc;
457 pugi::xml_node
root =
doc.append_child(
"xml");
465template <
typename T, std::
size_t N, std::
size_t M>
467 pugi::xml_node &
root, std::string
tag =
"Matrix",
468 int id = 0, std::string
label =
"") {
470 for (std::size_t
i = 0;
i <
M; ++
i) {
485template <
typename T, std::
size_t N>
486inline torch::TensorAccessor<T, N> &
488 torch::IntArrayRef
sizes, std::string
tag =
"Matrix",
int id = 0,
489 std::string
label =
"",
int index = -1) {
494template <
typename T, std::
size_t N>
495inline torch::TensorAccessor<T, N> &
497 torch::IntArrayRef
sizes, std::string
tag =
"Matrix",
int id = 0,
498 std::string
label =
"",
int index = -1) {
504template <
typename T, std::
size_t N>
505inline torch::Tensor &
507 std::string
tag =
"Matrix",
int id = 0, std::string
label =
"",
508 bool alloc =
true,
int index = -1) {
513template <
typename T, std::
size_t N>
514inline torch::Tensor &
516 std::string
tag =
"Matrix",
int id = 0, std::string
label =
"",
517 bool alloc =
true,
int index = -1) {
520 for (pugi::xml_node
node :
root.children(
tag.c_str())) {
522 if ((
id >= 0 ?
node.attribute(
"id").as_int() ==
id :
true) &&
523 (index >= 0 ?
node.attribute(
"index").as_int() == index :
true) &&
524 (!
label.empty() ?
node.attribute(
"label").value() ==
label :
true)) {
526 if (
tag ==
"Matrix") {
532 throw std::runtime_error(
"Invalid matrix dimensions");
537 std::string
values = std::regex_replace(
538 node.text().get(), std::regex(
"[\t\r\n\a]+| +"),
" ");
547 throw std::runtime_error(
548 "XML object does not provide enough coefficients");
550 accessor[
i][
j] =
static_cast<T
>(std::stod(value));
555 throw std::runtime_error(
"XML object provides too many coefficients");
557 if (
tensor.device().type() != torch::kCPU)
564 std::vector<int64_t>
sizes;
567 if (pugi::xml_node dims =
node.child(
"Dimensions")) {
569 std::string
values = std::regex_replace(
570 dims.text().get(), std::regex(
"[\t\r\n\a]+| +"),
" ");
573 sizes.push_back(
static_cast<std::size_t
>(std::stoi(value)));
576 throw std::runtime_error(
"Invalid tensor dimensions");
582 throw std::runtime_error(
"Invalid tensor dimensions");
585 if (pugi::xml_node data =
node.child(
"Data")) {
586 std::string
values = std::regex_replace(
587 data.text().get(), std::regex(
"[\t\r\n\a]+| +"),
" ");
593 if constexpr (
N == 1) {
596 throw std::runtime_error(
597 "XML object does not provide enough coefficients");
599 accessor[
i] =
static_cast<T
>(std::stod(value));
602 }
else if constexpr (
N == 2) {
606 throw std::runtime_error(
607 "XML object does not provide enough coefficients");
609 accessor[
i][
j] =
static_cast<T
>(std::stod(value));
612 }
else if constexpr (
N == 3) {
617 throw std::runtime_error(
618 "XML object does not provide enough coefficients");
620 accessor[
i][
j][
k] =
static_cast<T
>(std::stod(value));
623 }
else if constexpr (
N == 4) {
629 throw std::runtime_error(
630 "XML object does not provide enough coefficients");
632 accessor[
i][
j][
k][
l] =
static_cast<T
>(std::stod(value));
635 }
else if constexpr (
N == 5) {
642 throw std::runtime_error(
643 "XML object does not provide enough "
647 static_cast<T
>(std::stod(value));
650 }
else if constexpr (
N == 6) {
658 throw std::runtime_error(
659 "XML object does not provide enough "
663 static_cast<T
>(std::stod(value));
669 throw std::runtime_error(
670 "XML object provides too many coefficients");
672 if (
tensor.device().type() != torch::kCPU)
679 throw std::runtime_error(
680 "XML object does not provide a \"Dimensions\" tag");
688 throw std::runtime_error(
689 "XML object does not provide tag with given id, index, and/or label");
695template <
typename T, std::
size_t N, std::
size_t M>
698 std::string
tag =
"Matrix",
int id = 0,
bool alloc =
true,
699 std::string
label =
"") {
705template <
typename T, std::
size_t N, std::
size_t M>
708 std::string
tag =
"Matrix",
int id = 0,
bool alloc =
true,
709 std::string
label =
"") {
711 for (std::size_t
i = 0;
i <
M; ++
i) {
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:90
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:316
auto to_json(const torch::TensorAccessor< T, N > &accessor)
Converts a torch::TensorAccessor object to a JSON object.
Definition serialize.hpp:41
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:487
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:28
Definition boundary.hpp:22
constexpr bool is_SplineType_v
Alias to the value of is_SplineType.
Definition bspline.hpp:3243
struct iganet::@0 Log
Logger.
Serialization prototype.
Definition serialize.hpp:31
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.
TensorArray utility functions.