IgANet
IGAnets - Isogeometric Analysis Networks
Loading...
Searching...
No Matches
boundary.hpp
Go to the documentation of this file.
1
15#pragma once
16
17#include <boost/preprocessor/cat.hpp>
18#include <boost/preprocessor/seq/for_each.hpp>
19
20#include <splines/bspline.hpp>
21
22namespace iganet {
23
25enum side {
26 west = 1,
27 east = 2,
28 south = 3,
29 north = 4,
30 front = 5,
31 back = 6,
32 stime = 7,
33 etime = 8,
34 left = 1,
35 right = 2,
36 down = 3,
37 up = 4,
38 none = 0
39};
40
42template <typename Spline, short_t>
43 requires SplineType<Spline>
45
51template <typename Spline>
52 requires SplineType<Spline>
53class BoundaryCore<Spline, /* parDim */ 1> : public utils::Serializable,
55
57 template <typename BoundaryCore> friend class BoundaryCommon;
58
59protected:
61 using spline_type = Spline;
62
65 Spline::template derived_self_type<typename Spline::value_type,
66 Spline::geoDim()>;
67
70 template <typename real_t>
72 Spline::template derived_self_type<real_t, Spline::geoDim()>;
73
75 std::tuple<boundary_spline_type, boundary_spline_type> bdr_;
76
77public:
79 using value_type = Spline::value_type;
80
82 using boundary_type = decltype(bdr_);
83
85 using eval_type = std::tuple<torch::Tensor, torch::Tensor>;
86
90 : bdr_({boundary_spline_type(options), boundary_spline_type(options)}) {}
91
93 explicit BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
94
96 explicit BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
97
99 BoundaryCore(const BoundaryCore &other, bool clone)
100 : bdr_(clone ? std::apply(
101 [](const auto &...bspline) {
102 return std::make_tuple(bspline.clone()...);
103 },
104 other.sides())
105 : other.sides()) {}
106
108 explicit BoundaryCore(const std::array<int64_t, 1> &,
109 enum init init = init::zeros,
112 : bdr_({boundary_spline_type(std::array<int64_t, 0>{}, init, options),
113 boundary_spline_type(std::array<int64_t, 0>{}, init, options)}) {}
114
116 explicit BoundaryCore(
117 const std::array<std::vector<typename Spline::value_type>, 1> &,
118 enum init init = init::zeros,
121 : bdr_({boundary_spline_type(std::array<int64_t, 0>{}, init, options),
122 boundary_spline_type(std::array<int64_t, 0>{}, init, options)}) {}
123
125 ~BoundaryCore() override = default;
126
133 inline auto &from_full_tensor(const torch::Tensor &tensor) {
134
135 if (tensor.dim() > 1) {
136 auto tensor_view = tensor.view({Spline::geoDim(), -1, tensor.size(-1)});
137
138 side<west>().from_tensor(tensor_view.index({torch::indexing::Slice(), 0})
139 .reshape({-1, tensor.size(-1)}));
140 side<east>().from_tensor(tensor_view.index({torch::indexing::Slice(), -1})
141 .reshape({-1, tensor.size(-1)}));
142 } else {
143 auto tensor_view = tensor.view({Spline::geoDim(), -1});
144
145 side<west>().from_tensor(
146 tensor_view.index({torch::indexing::Slice(), 0}).flatten());
147 side<east>().from_tensor(
148 tensor_view.index({torch::indexing::Slice(), -1}).flatten());
149 }
150 return *this;
151 }
152
154 inline static constexpr short_t nsides() { return side::east; }
155
157 template <short_t s> inline constexpr auto &side() const {
158 static_assert(s > none && s <= nsides());
159 return std::get<s - 1>(bdr_);
160 }
161
163 template <short_t s> inline constexpr auto &side() {
164 static_assert(s > none && s <= nsides());
165 return std::get<s - 1>(bdr_);
166 }
167
170 inline constexpr auto &sides() const { return bdr_; }
171
174 inline constexpr auto &sides() { return bdr_; }
175
177 inline int64_t ncumcoeffs() const {
178 int64_t s = 0;
179 s += side<west>().ncumcoeffs();
180 s += side<east>().ncumcoeffs();
181
182 return s;
183 }
184
186 inline void pretty_print(std::ostream &os) const noexcept override {
187 os << name() << "(\n"
188 << "west = " << side<west>() << "\n"
189 << "east = " << side<east>() << "\n)";
190 }
191
193 inline nlohmann::json to_json() const override {
194 nlohmann::json json;
195 json["west"] = side<west>().to_json();
196 json["east"] = side<east>().to_json();
197
198 return json;
199 }
200
202 inline BoundaryCore &from_json(const nlohmann::json &json) {
203 side<west>().from_json(json["west"]);
204 side<east>().from_json(json["east"]);
205
206 return *this;
207 }
208
210 inline eval_type greville() const {
211 return eval_type{side<west>().greville(), side<east>().greville()};
212 }
213};
214
222template <typename Spline>
223 requires SplineType<Spline>
224class BoundaryCore<Spline, /* parDim */ 2> : public utils::Serializable,
226
228 template <typename BoundaryCore> friend class BoundaryCommon;
229
230protected:
232 using spline_type = Spline;
233
235 using boundary_spline_type = std::tuple<
236 typename Spline::template derived_self_type<
237 typename Spline::value_type, Spline::geoDim(), Spline::degree(1)>,
238 typename Spline::template derived_self_type<
239 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>;
240
243 template <typename real_t>
245 std::tuple<typename Spline::template derived_self_type<
246 real_t, Spline::geoDim(), Spline::degree(1)>,
247 typename Spline::template derived_self_type<
248 real_t, Spline::geoDim(), Spline::degree(0)>>;
249
251 std::tuple<std::tuple_element_t<0, boundary_spline_type>,
252 std::tuple_element_t<0, boundary_spline_type>,
253 std::tuple_element_t<1, boundary_spline_type>,
254 std::tuple_element_t<1, boundary_spline_type>>
256
257public:
259 using value_type = Spline::value_type;
260
262 using boundary_type = decltype(bdr_);
263
265 using eval_type = std::tuple<utils::TensorArray<1>, utils::TensorArray<1>,
267
271 : bdr_({std::tuple_element_t<0, boundary_spline_type>(options),
272 std::tuple_element_t<0, boundary_spline_type>(options),
273 std::tuple_element_t<1, boundary_spline_type>(options),
274 std::tuple_element_t<1, boundary_spline_type>(options)}) {}
275
277 explicit BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
278
280 explicit BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
281
283 BoundaryCore(const BoundaryCore &other, bool clone)
284 : bdr_(clone ? std::apply(
285 [](const auto &...bspline) {
286 return std::make_tuple(bspline.clone()...);
287 },
288 other.sides())
289 : other.sides()) {}
290
292 explicit BoundaryCore(const std::array<int64_t, 2> &ncoeffs,
293 enum init init = init::zeros,
296 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
297 std::array<int64_t, 1>({ncoeffs[1]}), init, options),
298 std::tuple_element_t<0, boundary_spline_type>(
299 std::array<int64_t, 1>({ncoeffs[1]}), init, options),
300 std::tuple_element_t<1, boundary_spline_type>(
301 std::array<int64_t, 1>({ncoeffs[0]}), init, options),
302 std::tuple_element_t<1, boundary_spline_type>(
303 std::array<int64_t, 1>({ncoeffs[0]}), init, options)}) {}
304
306 explicit BoundaryCore(
307 const std::array<std::vector<typename Spline::value_type>, 2> &kv,
308 enum init init = init::zeros,
311 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
312 std::array<std::vector<typename Spline::value_type>, 1>(
313 {kv[1]}),
314 init, options),
315 std::tuple_element_t<0, boundary_spline_type>(
316 std::array<std::vector<typename Spline::value_type>, 1>(
317 {kv[1]}),
318 init, options),
319 std::tuple_element_t<1, boundary_spline_type>(
320 std::array<std::vector<typename Spline::value_type>, 1>(
321 {kv[0]}),
322 init, options),
323 std::tuple_element_t<1, boundary_spline_type>(
324 std::array<std::vector<typename Spline::value_type>, 1>(
325 {kv[0]}),
326 init, options)}) {}
327
329 ~BoundaryCore() override = default;
330
337 inline auto &from_full_tensor(const torch::Tensor &tensor) {
338
339 if (tensor.dim() > 1) {
340 auto tensor_view =
341 tensor.view({-1, side<west>().ncoeffs(0), side<south>().ncoeffs(0),
342 tensor.size(-1)});
343
344 side<west>().from_tensor(
345 tensor_view
346 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0})
347 .reshape({-1, tensor.size(-1)}));
348 side<east>().from_tensor(
349 tensor_view
350 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1})
351 .reshape({-1, tensor.size(-1)}));
352 side<south>().from_tensor(
353 tensor_view
354 .index({torch::indexing::Slice(), 0, torch::indexing::Slice()})
355 .reshape({-1, tensor.size(-1)}));
356 side<north>().from_tensor(
357 tensor_view
358 .index({torch::indexing::Slice(), -1, torch::indexing::Slice()})
359 .reshape({-1, tensor.size(-1)}));
360 } else {
361 auto tensor_view =
362 tensor.view({-1, side<west>().ncoeffs(0), side<south>().ncoeffs(0)});
363
364 side<west>().from_tensor(
365 tensor_view
366 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0})
367 .flatten());
368 side<east>().from_tensor(
369 tensor_view
370 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1})
371 .flatten());
372 side<south>().from_tensor(
373 tensor_view
374 .index({torch::indexing::Slice(), 0, torch::indexing::Slice()})
375 .flatten());
376 side<north>().from_tensor(
377 tensor_view
378 .index({torch::indexing::Slice(), -1, torch::indexing::Slice()})
379 .flatten());
380 }
381 return *this;
382 }
383
385 inline static constexpr short_t nsides() { return side::north; }
386
388 template <short_t s> inline constexpr auto &side() const {
389 static_assert(s > none && s <= nsides());
390 return std::get<s - 1>(bdr_);
391 }
392
394 template <short_t s> inline constexpr auto &side() {
395 static_assert(s > none && s <= nsides());
396 return std::get<s - 1>(bdr_);
397 }
398
400 inline constexpr auto &sides() const { return bdr_; }
401
403 inline constexpr auto &sides() { return bdr_; }
404
406 inline int64_t ncumcoeffs() const {
407 int64_t s = 0;
408 s += side<west>().ncumcoeffs();
409 s += side<east>().ncumcoeffs();
410 s += side<south>().ncumcoeffs();
411 s += side<north>().ncumcoeffs();
412
413 return s;
414 }
415
417 inline void pretty_print(std::ostream &os) const noexcept override {
418 os << name() << "(\n"
419 << "west = " << side<west>() << "\n"
420 << "east = " << side<east>() << "\n"
421 << "south = " << side<south>() << "\n"
422 << "north = " << side<north>() << "\n)";
423 }
424
426 inline nlohmann::json to_json() const override {
427 nlohmann::json json;
428 json["west"] = side<west>().to_json();
429 json["east"] = side<east>().to_json();
430 json["south"] = side<south>().to_json();
431 json["north"] = side<north>().to_json();
432
433 return json;
434 }
435
437 inline BoundaryCore &from_json(const nlohmann::json &json) {
438 side<west>().from_json(json["west"]);
439 side<east>().from_json(json["east"]);
440 side<south>().from_json(json["south"]);
441 side<north>().from_json(json["north"]);
442
443 return *this;
444 }
445
447 inline eval_type greville() const {
448 return eval_type{side<west>().greville(), side<east>().greville(),
449 side<south>().greville(), side<north>().greville()};
450 }
451};
452
462template <typename Spline>
463 requires SplineType<Spline>
464class BoundaryCore<Spline, /* parDim */ 3> : public utils::Serializable,
466
468 template <typename BoundaryCore> friend class BoundaryCommon;
469
470protected:
472 using spline_type = Spline;
473
476 std::tuple<typename Spline::template derived_self_type<
477 typename Spline::value_type, Spline::geoDim(),
478 Spline::degree(1), Spline::degree(2)>,
479 typename Spline::template derived_self_type<
480 typename Spline::value_type, Spline::geoDim(),
481 Spline::degree(0), Spline::degree(2)>,
482 typename Spline::template derived_self_type<
483 typename Spline::value_type, Spline::geoDim(),
484 Spline::degree(0), Spline::degree(1)>>;
485
488 template <typename real_t>
490 typename Spline::template derived_self_type<
491 real_t, Spline::geoDim(), Spline::degree(1), Spline::degree(2)>,
492 typename Spline::template derived_self_type<
493 real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(2)>,
494 typename Spline::template derived_self_type<
495 real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(1)>>;
496
498 std::tuple<std::tuple_element_t<0, boundary_spline_type>,
499 std::tuple_element_t<0, boundary_spline_type>,
500 std::tuple_element_t<1, boundary_spline_type>,
501 std::tuple_element_t<1, boundary_spline_type>,
502 std::tuple_element_t<2, boundary_spline_type>,
503 std::tuple_element_t<2, boundary_spline_type>>
505
506public:
508 using value_type = Spline::value_type;
509
511 using boundary_type = decltype(bdr_);
512
514 using eval_type = std::tuple<utils::TensorArray<2>, utils::TensorArray<2>,
517
521 : bdr_({std::tuple_element_t<0, boundary_spline_type>(options),
522 std::tuple_element_t<0, boundary_spline_type>(options),
523 std::tuple_element_t<1, boundary_spline_type>(options),
524 std::tuple_element_t<1, boundary_spline_type>(options),
525 std::tuple_element_t<2, boundary_spline_type>(options),
526 std::tuple_element_t<2, boundary_spline_type>(options)}) {}
527
529 explicit BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
530
532 explicit BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
533
535 BoundaryCore(const BoundaryCore &other, bool clone)
536 : bdr_(clone ? std::apply(
537 [](const auto &...bspline) {
538 return std::make_tuple(bspline.clone()...);
539 },
540 other.sides())
541 : other.sides()) {}
542
544 explicit BoundaryCore(const std::array<int64_t, 3> &ncoeffs,
545 enum init init = init::zeros,
548 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
549 std::array<int64_t, 2>({ncoeffs[1], ncoeffs[2]}), init,
550 options),
551 std::tuple_element_t<0, boundary_spline_type>(
552 std::array<int64_t, 2>({ncoeffs[1], ncoeffs[2]}), init,
553 options),
554 std::tuple_element_t<1, boundary_spline_type>(
555 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[2]}), init,
556 options),
557 std::tuple_element_t<1, boundary_spline_type>(
558 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[2]}), init,
559 options),
560 std::tuple_element_t<2, boundary_spline_type>(
561 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[1]}), init,
562 options),
563 std::tuple_element_t<2, boundary_spline_type>(
564 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[1]}), init,
565 options)}) {}
566
568 explicit BoundaryCore(
569 const std::array<std::vector<typename Spline::value_type>, 3> &kv,
570 enum init init = init::zeros,
573 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
574 std::array<std::vector<typename Spline::value_type>, 2>(
575 {kv[1], kv[2]}),
576 init, options),
577 std::tuple_element_t<0, boundary_spline_type>(
578 std::array<std::vector<typename Spline::value_type>, 2>(
579 {kv[1], kv[2]}),
580 init, options),
581 std::tuple_element_t<1, boundary_spline_type>(
582 std::array<std::vector<typename Spline::value_type>, 2>(
583 {kv[0], kv[2]}),
584 init, options),
585 std::tuple_element_t<1, boundary_spline_type>(
586 std::array<std::vector<typename Spline::value_type>, 2>(
587 {kv[0], kv[2]}),
588 init, options),
589 std::tuple_element_t<2, boundary_spline_type>(
590 std::array<std::vector<typename Spline::value_type>, 2>(
591 {kv[0], kv[1]}),
592 init, options),
593 std::tuple_element_t<2, boundary_spline_type>(
594 std::array<std::vector<typename Spline::value_type>, 2>(
595 {kv[0], kv[1]}),
596 init, options)}) {}
597
599 ~BoundaryCore() override = default;
600
607 inline auto &from_full_tensor(const torch::Tensor &tensor) {
608
609 if (tensor.dim() > 1) {
610 auto tensor_view =
611 tensor.view({-1, side<west>().ncoeffs(1), side<west>().ncoeffs(0),
612 side<south>().ncoeffs(0), tensor.size(-1)});
613
614 side<west>().from_tensor(
615 tensor_view
616 .index({torch::indexing::Slice(), torch::indexing::Slice(),
617 torch::indexing::Slice(), 0})
618 .reshape({-1, tensor.size(-1)}));
619 side<east>().from_tensor(
620 tensor_view
621 .index({torch::indexing::Slice(), torch::indexing::Slice(),
622 torch::indexing::Slice(), -1})
623 .reshape({-1, tensor.size(-1)}));
624 side<south>().from_tensor(
625 tensor_view
626 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
627 torch::indexing::Slice()})
628 .reshape({-1, tensor.size(-1)}));
629 side<north>().from_tensor(
630 tensor_view
631 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
632 torch::indexing::Slice()})
633 .reshape({-1, tensor.size(-1)}));
634 side<front>().from_tensor(
635 tensor_view
636 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
637 torch::indexing::Slice()})
638 .reshape({-1, tensor.size(-1)}));
639 side<back>().from_tensor(
640 tensor_view
641 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
642 torch::indexing::Slice()})
643 .reshape({-1, tensor.size(-1)}));
644 } else {
645 auto tensor_view =
646 tensor.view({-1, side<west>().ncoeffs(1), side<west>().ncoeffs(0),
647 side<south>().ncoeffs(0)});
648
649 side<west>().from_tensor(
650 tensor_view
651 .index({torch::indexing::Slice(), torch::indexing::Slice(),
652 torch::indexing::Slice(), 0})
653 .flatten());
654 side<east>().from_tensor(
655 tensor_view
656 .index({torch::indexing::Slice(), torch::indexing::Slice(),
657 torch::indexing::Slice(), -1})
658 .flatten());
659
660 side<south>().from_tensor(
661 tensor_view
662 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
663 torch::indexing::Slice()})
664 .flatten());
665 side<north>().from_tensor(
666 tensor_view
667 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
668 torch::indexing::Slice()})
669 .flatten());
670
671 side<front>().from_tensor(
672 tensor_view
673 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
674 torch::indexing::Slice()})
675 .flatten());
676 side<back>().from_tensor(
677 tensor_view
678 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
679 torch::indexing::Slice()})
680 .flatten());
681 }
682 return *this;
683 }
684
686 inline static constexpr short_t nsides() { return side::back; }
687
689 template <short_t s> inline constexpr auto &side() const {
690 static_assert(s > none && s <= nsides());
691 return std::get<s - 1>(bdr_);
692 }
693
695 template <short_t s> inline constexpr auto &side() {
696 static_assert(s > none && s <= nsides());
697 return std::get<s - 1>(bdr_);
698 }
699
701 inline constexpr auto &sides() const { return bdr_; }
702
704 inline constexpr auto &sides() { return bdr_; }
705
707 inline int64_t ncumcoeffs() const {
708 int64_t s = 0;
709 s += side<west>().ncumcoeffs();
710 s += side<east>().ncumcoeffs();
711 s += side<south>().ncumcoeffs();
712 s += side<north>().ncumcoeffs();
713 s += side<front>().ncumcoeffs();
714 s += side<back>().ncumcoeffs();
715
716 return s;
717 }
718
720 inline void pretty_print(std::ostream &os) const noexcept override {
721 os << name() << "(\n"
722 << "west = " << side<west>() << "\n"
723 << "east = " << side<east>() << "\n"
724 << "south = " << side<south>() << "\n"
725 << "north = " << side<north>() << "\n"
726 << "front = " << side<front>() << "\n"
727 << "back = " << side<back>() << "\n)";
728 }
729
731 inline nlohmann::json to_json() const override {
732 nlohmann::json json;
733 json["west"] = side<west>().to_json();
734 json["east"] = side<east>().to_json();
735 json["south"] = side<south>().to_json();
736 json["north"] = side<north>().to_json();
737 json["front"] = side<front>().to_json();
738 json["back"] = side<back>().to_json();
739
740 return json;
741 }
742
744 inline BoundaryCore &from_json(const nlohmann::json &json) {
745 side<west>().from_json(json["west"]);
746 side<east>().from_json(json["east"]);
747 side<south>().from_json(json["south"]);
748 side<north>().from_json(json["north"]);
749 side<front>().from_json(json["front"]);
750 side<back>().from_json(json["back"]);
751
752 return *this;
753 }
754
756 inline eval_type greville() const {
757 return eval_type{side<west>().greville(), side<east>().greville(),
758 side<south>().greville(), side<north>().greville(),
759 side<front>().greville(), side<back>().greville()};
760 }
761};
762
774template <typename Spline>
775 requires SplineType<Spline>
776class BoundaryCore<Spline, /* parDim */ 4> : public utils::Serializable,
778
780 template <typename BoundaryCore> friend class BoundaryCommon;
781
782protected:
784 using spline_type = Spline;
785
788 std::tuple<typename Spline::template derived_self_type<
789 typename Spline::value_type, Spline::geoDim(),
790 Spline::degree(1), Spline::degree(2), Spline::degree(3)>,
791 typename Spline::template derived_self_type<
792 typename Spline::value_type, Spline::geoDim(),
793 Spline::degree(0), Spline::degree(2), Spline::degree(3)>,
794 typename Spline::template derived_self_type<
795 typename Spline::value_type, Spline::geoDim(),
796 Spline::degree(0), Spline::degree(1), Spline::degree(3)>,
797 typename Spline::template derived_self_type<
798 typename Spline::value_type, Spline::geoDim(),
799 Spline::degree(0), Spline::degree(1), Spline::degree(2)>>;
800
803 template <typename real_t>
805 std::tuple<typename Spline::template derived_self_type<
806 real_t, Spline::geoDim(), Spline::degree(1),
807 Spline::degree(2), Spline::degree(3)>,
808 typename Spline::template derived_self_type<
809 real_t, Spline::geoDim(), Spline::degree(0),
810 Spline::degree(2), Spline::degree(3)>,
811 typename Spline::template derived_self_type<
812 real_t, Spline::geoDim(), Spline::degree(0),
813 Spline::degree(1), Spline::degree(3)>,
814 typename Spline::template derived_self_type<
815 real_t, Spline::geoDim(), Spline::degree(0),
816 Spline::degree(1), Spline::degree(2)>>;
817
819 std::tuple<std::tuple_element_t<0, boundary_spline_type>,
820 std::tuple_element_t<0, boundary_spline_type>,
821 std::tuple_element_t<1, boundary_spline_type>,
822 std::tuple_element_t<1, boundary_spline_type>,
823 std::tuple_element_t<2, boundary_spline_type>,
824 std::tuple_element_t<2, boundary_spline_type>,
825 std::tuple_element_t<3, boundary_spline_type>,
826 std::tuple_element_t<3, boundary_spline_type>>
828
829public:
831 using value_type = Spline::value_type;
832
834 using boundary_type = decltype(bdr_);
835
837 using eval_type = std::tuple<utils::TensorArray<3>, utils::TensorArray<3>,
841
845 : bdr_({std::tuple_element_t<0, boundary_spline_type>(options),
846 std::tuple_element_t<0, boundary_spline_type>(options),
847 std::tuple_element_t<1, boundary_spline_type>(options),
848 std::tuple_element_t<1, boundary_spline_type>(options),
849 std::tuple_element_t<2, boundary_spline_type>(options),
850 std::tuple_element_t<2, boundary_spline_type>(options),
851 std::tuple_element_t<3, boundary_spline_type>(options),
852 std::tuple_element_t<3, boundary_spline_type>(options)}) {}
853
855 explicit BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
856
858 explicit BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
859
861 BoundaryCore(const BoundaryCore &other, bool clone)
862 : bdr_(clone ? std::apply(
863 [](const auto &...bspline) {
864 return std::make_tuple(bspline.clone()...);
865 },
866 other.sides())
867 : other.sides()) {}
868
870 explicit BoundaryCore(const std::array<int64_t, 4> &ncoeffs,
871 enum init init = init::zeros,
874 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
875 std::array<int64_t, 3>({ncoeffs[1], ncoeffs[2], ncoeffs[3]}),
876 init, options),
877 std::tuple_element_t<0, boundary_spline_type>(
878 std::array<int64_t, 3>({ncoeffs[1], ncoeffs[2], ncoeffs[3]}),
879 init, options),
880 std::tuple_element_t<1, boundary_spline_type>(
881 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[2], ncoeffs[3]}),
882 init, options),
883 std::tuple_element_t<1, boundary_spline_type>(
884 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[2], ncoeffs[3]}),
885 init, options),
886 std::tuple_element_t<2, boundary_spline_type>(
887 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[3]}),
888 init, options),
889 std::tuple_element_t<2, boundary_spline_type>(
890 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[3]}),
891 init, options),
892 std::tuple_element_t<3, boundary_spline_type>(
893 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[2]}),
894 init, options),
895 std::tuple_element_t<3, boundary_spline_type>(
896 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[2]}),
897 init, options)}) {}
898
900 explicit BoundaryCore(
901 const std::array<std::vector<typename Spline::value_type>, 4> &kv,
902 enum init init = init::zeros,
905 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
906 std::array<std::vector<typename Spline::value_type>, 3>(
907 {kv[1], kv[2], kv[3]}),
908 init, options),
909 std::tuple_element_t<0, boundary_spline_type>(
910 std::array<std::vector<typename Spline::value_type>, 3>(
911 {kv[1], kv[2], kv[3]}),
912 init, options),
913 std::tuple_element_t<1, boundary_spline_type>(
914 std::array<std::vector<typename Spline::value_type>, 3>(
915 {kv[0], kv[2], kv[3]}),
916 init, options),
917 std::tuple_element_t<1, boundary_spline_type>(
918 std::array<std::vector<typename Spline::value_type>, 3>(
919 {kv[0], kv[2], kv[3]}),
920 init, options),
921 std::tuple_element_t<2, boundary_spline_type>(
922 std::array<std::vector<typename Spline::value_type>, 3>(
923 {kv[0], kv[1], kv[3]}),
924 init, options),
925 std::tuple_element_t<2, boundary_spline_type>(
926 std::array<std::vector<typename Spline::value_type>, 3>(
927 {kv[0], kv[1], kv[3]}),
928 init, options),
929 std::tuple_element_t<3, boundary_spline_type>(
930 std::array<std::vector<typename Spline::value_type>, 3>(
931 {kv[0], kv[1], kv[2]}),
932 init, options),
933 std::tuple_element_t<3, boundary_spline_type>(
934 std::array<std::vector<typename Spline::value_type>, 3>(
935 {kv[0], kv[1], kv[2]}),
936 init, options)}) {}
937
939 ~BoundaryCore() override = default;
940
947 inline auto &from_full_tensor(const torch::Tensor &tensor) {
948
949 if (tensor.dim() > 1) {
950 auto tensor_view = tensor.view(
951 {-1, side<west>().ncoeffs(2), side<west>().ncoeffs(1),
952 side<west>().ncoeffs(0), side<south>().ncoeffs(0), tensor.size(-1)});
953
954 side<west>().from_tensor(
955 tensor_view
956 .index({torch::indexing::Slice(), torch::indexing::Slice(),
957 torch::indexing::Slice(), torch::indexing::Slice(), 0})
958 .reshape({-1, tensor.size(-1)}));
959 side<east>().from_tensor(
960 tensor_view
961 .index({torch::indexing::Slice(), torch::indexing::Slice(),
962 torch::indexing::Slice(), torch::indexing::Slice(), -1})
963 .reshape({-1, tensor.size(-1)}));
964 side<south>().from_tensor(
965 tensor_view
966 .index({torch::indexing::Slice(), torch::indexing::Slice(),
967 torch::indexing::Slice(), 0, torch::indexing::Slice()})
968 .reshape({-1, tensor.size(-1)}));
969 side<north>().from_tensor(
970 tensor_view
971 .index({torch::indexing::Slice(), torch::indexing::Slice(),
972 torch::indexing::Slice(), -1, torch::indexing::Slice()})
973 .reshape({-1, tensor.size(-1)}));
974 side<front>().from_tensor(
975 tensor_view
976 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
977 torch::indexing::Slice(), torch::indexing::Slice()})
978 .reshape({-1, tensor.size(-1)}));
979 side<back>().from_tensor(
980 tensor_view
981 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
982 torch::indexing::Slice(), torch::indexing::Slice()})
983 .reshape({-1, tensor.size(-1)}));
984 side<stime>().from_tensor(
985 tensor_view
986 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
987 torch::indexing::Slice(), torch::indexing::Slice()})
988 .reshape({-1, tensor.size(-1)}));
989 side<etime>().from_tensor(
990 tensor_view
991 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
992 torch::indexing::Slice(), torch::indexing::Slice()})
993 .reshape({-1, tensor.size(-1)}));
994 } else {
995 auto tensor_view =
996 tensor.view({-1, side<west>().ncoeffs(2), side<west>().ncoeffs(1),
997 side<west>().ncoeffs(0), side<south>().ncoeffs(0)});
998
999 side<west>().from_tensor(
1000 tensor_view
1001 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1002 torch::indexing::Slice(), torch::indexing::Slice(), 0})
1003 .flatten());
1004 side<east>().from_tensor(
1005 tensor_view
1006 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1007 torch::indexing::Slice(), torch::indexing::Slice(), -1})
1008 .flatten());
1009
1010 side<south>().from_tensor(
1011 tensor_view
1012 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1013 torch::indexing::Slice(), 0, torch::indexing::Slice()})
1014 .flatten());
1015 side<north>().from_tensor(
1016 tensor_view
1017 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1018 torch::indexing::Slice(), -1, torch::indexing::Slice()})
1019 .flatten());
1020
1021 side<front>().from_tensor(
1022 tensor_view
1023 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
1024 torch::indexing::Slice(), torch::indexing::Slice()})
1025 .flatten());
1026 side<back>().from_tensor(
1027 tensor_view
1028 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
1029 torch::indexing::Slice(), torch::indexing::Slice()})
1030 .flatten());
1031
1032 side<stime>().from_tensor(
1033 tensor_view
1034 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
1035 torch::indexing::Slice(), torch::indexing::Slice()})
1036 .flatten());
1037 side<etime>().from_tensor(
1038 tensor_view
1039 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
1040 torch::indexing::Slice(), torch::indexing::Slice()})
1041 .flatten());
1042 }
1043 return *this;
1044 }
1045
1047 inline static constexpr short_t nsides() { return side::etime; }
1048
1050 template <short_t s> inline constexpr auto &side() const {
1051 static_assert(s > none && s <= nsides());
1052 return std::get<s - 1>(bdr_);
1053 }
1054
1056 template <short_t s> inline constexpr auto &side() {
1057 static_assert(s > none && s <= nsides());
1058 return std::get<s - 1>(bdr_);
1059 }
1060
1062 inline constexpr auto &sides() const { return bdr_; }
1063
1065 inline constexpr auto &ides() { return bdr_; }
1066
1068 inline int64_t ncumcoeffs() const {
1069 int64_t s = 0;
1070 s += side<west>().ncumcoeffs();
1071 s += side<east>().ncumcoeffs();
1072 s += side<south>().ncumcoeffs();
1073 s += side<north>().ncumcoeffs();
1074 s += side<front>().ncumcoeffs();
1075 s += side<back>().ncumcoeffs();
1076 s += side<stime>().ncumcoeffs();
1077 s += side<etime>().ncumcoeffs();
1078
1079 return s;
1080 }
1081
1083 inline void pretty_print(std::ostream &os) const noexcept override {
1084 os << name() << "(\n"
1085 << "west = " << side<west>() << "\n"
1086 << "east = " << side<east>() << "\n"
1087 << "south = " << side<south>() << "\n"
1088 << "north = " << side<north>() << "\n"
1089 << "front = " << side<front>() << "\n"
1090 << "back = " << side<back>() << "\n"
1091 << "stime = " << side<stime>() << "\n"
1092 << "etime = " << side<etime>() << "\n)";
1093 }
1094
1096 inline nlohmann::json to_json() const override {
1097 nlohmann::json json;
1098 json["west"] = side<west>().to_json();
1099 json["east"] = side<east>().to_json();
1100 json["south"] = side<south>().to_json();
1101 json["north"] = side<north>().to_json();
1102 json["front"] = side<front>().to_json();
1103 json["back"] = side<back>().to_json();
1104 json["stime"] = side<stime>().to_json();
1105 json["etime"] = side<etime>().to_json();
1106
1107 return json;
1108 }
1109
1111 inline BoundaryCore &from_json(const nlohmann::json &json) {
1112 side<west>().from_json(json["west"]);
1113 side<east>().from_json(json["east"]);
1114 side<south>().from_json(json["south"]);
1115 side<north>().from_json(json["north"]);
1116 side<front>().from_json(json["front"]);
1117 side<back>().from_json(json["back"]);
1118 side<stime>().from_json(json["stime"]);
1119 side<etime>().from_json(json["etime"]);
1120
1121 return *this;
1122 }
1123
1125 inline eval_type greville() const {
1126 return eval_type{side<west>().greville(), side<east>().greville(),
1127 side<south>().greville(), side<north>().greville(),
1128 side<front>().greville(), side<back>().greville(),
1129 side<stime>().greville(), side<etime>().greville()};
1130 }
1131};
1132
1134class Boundary_ {};
1135
1138template <typename T>
1139concept BoundaryType = std::is_base_of_v<Boundary_, T>;
1140
1142template <typename BoundaryCore>
1143class BoundaryCommon : public Boundary_, public BoundaryCore {
1144public:
1146 using BoundaryCore::BoundaryCore;
1147
1149 BoundaryCommon clone() const { return BoundaryCommon(*this); }
1150
1151private:
1156 template <std::size_t... Is>
1157 inline torch::Tensor as_tensor_(std::index_sequence<Is...>) const {
1158 return torch::cat({std::get<Is>(BoundaryCore::bdr_).as_tensor()...});
1159 }
1160
1161public:
1166 [[nodiscard]] inline torch::Tensor as_tensor() const {
1167 return as_tensor_(std::make_index_sequence<BoundaryCore::nsides()>{});
1168 }
1169
1170private:
1175 template <std::size_t... Is>
1176 inline int64_t as_tensor_size_(std::index_sequence<Is...>) const {
1177 return std::apply(
1178 [](auto... size) { return (size + ...); },
1179 std::make_tuple(std::get<Is>(BoundaryCore::bdr_).as_tensor_size()...));
1180 }
1181
1182public:
1185 //
1187 [[nodiscard]] inline int64_t as_tensor_size() const {
1188 return as_tensor_size_(std::make_index_sequence<BoundaryCore::nsides()>{});
1189 }
1190
1191private:
1198 template <std::size_t... Is>
1199 inline auto &from_tensor_(std::index_sequence<Is...>,
1200 const torch::Tensor &tensor) {
1201
1202 std::size_t start(0);
1203 auto end = [&start](std::size_t inc) { return start += inc; };
1204
1205 (std::get<Is>(BoundaryCore::bdr_)
1206 .from_tensor(tensor.index({torch::indexing::Slice(
1207 start, end(std::get<Is>(BoundaryCore::bdr_).ncumcoeffs() *
1208 std::get<Is>(BoundaryCore::bdr_).geoDim()))})),
1209 ...);
1210
1211 return *this;
1212 }
1213
1214public:
1221 inline auto &from_tensor(const torch::Tensor &tensor) {
1222 return from_tensor_(std::make_index_sequence<BoundaryCore::nsides()>{},
1223 tensor);
1224 }
1225
1226private:
1229 template <deriv deriv = deriv::func, bool memory_optimized = false,
1230 size_t... Is, typename... Xi>
1231 inline auto eval_(std::index_sequence<Is...>,
1232 const std::tuple<Xi...> &xi) const {
1233 return std::tuple(
1234 std::get<Is>(BoundaryCore::bdr_)
1235 .template eval<deriv, memory_optimized>(std::get<Is>(xi))...);
1236 }
1237
1238 template <deriv deriv = deriv::func, bool memory_optimized = false,
1239 size_t... Is, typename... Xi, typename... Indices>
1240 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
1241 const std::tuple<Indices...> &indices) const {
1242 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1243 .template eval<deriv, memory_optimized>(
1244 std::get<Is>(xi), std::get<Is>(indices))...);
1245 }
1246
1247 template <deriv deriv = deriv::func, bool memory_optimized = false,
1248 size_t... Is, typename... Xi, typename... Indices,
1249 typename... Coeff_Indices>
1250 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
1251 const std::tuple<Indices...> &indices,
1252 const std::tuple<Coeff_Indices...> &coeff_indices) const {
1253 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1254 .template eval<deriv, memory_optimized>(
1255 std::get<Is>(xi), std::get<Is>(indices),
1256 std::get<Is>(coeff_indices))...);
1257 }
1259
1260public:
1263 template <deriv deriv = deriv::func, bool memory_optimized = false,
1264 typename... Xi>
1265 inline auto eval(const std::tuple<Xi...> &xi) const {
1266 return eval_<deriv, memory_optimized>(
1267 std::make_index_sequence<BoundaryCore::nsides()>{}, xi);
1268 }
1269
1270 template <deriv deriv = deriv::func, bool memory_optimized = false,
1271 typename... Xi, typename... Indices>
1272 inline auto eval(const std::tuple<Xi...> &xi,
1273 const std::tuple<Indices...> &indices) const {
1274 static_assert(sizeof...(Xi) == sizeof...(Indices));
1275 return eval_<deriv, memory_optimized>(
1276 std::make_index_sequence<BoundaryCore::nsides()>{}, xi, indices);
1277 }
1278
1279 template <deriv deriv = deriv::func, bool memory_optimized = false,
1280 typename... Xi, typename... Indices, typename... Coeff_Indices>
1281 inline auto eval(const std::tuple<Xi...> &xi,
1282 const std::tuple<Indices...> &indices,
1283 const std::tuple<Coeff_Indices...> &coeff_indices) const {
1284 static_assert(sizeof...(Xi) == sizeof...(Indices) &&
1285 sizeof...(Xi) == sizeof...(Coeff_Indices));
1286 return eval_<deriv, memory_optimized>(
1287 std::make_index_sequence<BoundaryCore::nsides()>{}, xi, indices,
1288 coeff_indices);
1289 }
1291
1292private:
1295 template <size_t... Is, typename... Basfunc, typename... Coeff_Indices,
1296 typename... Numeval, typename... Sizes>
1297 inline auto
1298 eval_from_precomputed_(std::index_sequence<Is...>,
1299 const std::tuple<Basfunc...> &basfunc,
1300 const std::tuple<Coeff_Indices...> &coeff_indices,
1301 const std::tuple<Numeval...> &numeval,
1302 const std::tuple<Sizes...> &sizes) const {
1303 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1304 .eval_from_precomputed(std::get<Is>(basfunc),
1305 std::get<Is>(coeff_indices),
1306 std::get<Is>(numeval),
1307 std::get<Is>(sizes))...);
1308 }
1309
1310 template <size_t... Is, typename... Basfunc, typename... Coeff_Indices,
1311 typename... Xi>
1312 inline auto
1313 eval_from_precomputed_(std::index_sequence<Is...>,
1314 const std::tuple<Basfunc...> &basfunc,
1315 const std::tuple<Coeff_Indices...> &coeff_indices,
1316 const std::tuple<Xi...> &xi) const {
1317 return std::tuple(
1318 std::get<Is>(BoundaryCore::bdr_)
1320 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
1321 std::get<Is>(xi)[0].numel(), std::get<Is>(xi)[0].sizes())...);
1322 }
1324
1325public:
1328 template <typename... Basfunc, typename... Coeff_Indices, typename... Numeval,
1329 typename... Sizes>
1330 inline auto
1331 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
1332 const std::tuple<Coeff_Indices...> &coeff_indices,
1333 const std::tuple<Numeval...> &numeval,
1334 const std::tuple<Sizes...> &sizes) const {
1335 static_assert(sizeof...(Basfunc) == sizeof...(Coeff_Indices) &&
1336 sizeof...(Basfunc) == sizeof...(Numeval) &&
1337 sizeof...(Basfunc) == sizeof...(Sizes));
1339 std::make_index_sequence<BoundaryCore::nsides()>{}, basfunc,
1340 coeff_indices, numeval, sizes);
1341 }
1342
1343 template <typename... Basfunc, typename... Coeff_Indices, typename... Xi>
1344 inline auto
1345 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
1346 const std::tuple<Coeff_Indices...> &coeff_indices,
1347 const std::tuple<Xi...> &xi) const {
1348 static_assert(sizeof...(Basfunc) == sizeof...(Coeff_Indices) &&
1349 sizeof...(Basfunc) == sizeof...(Xi));
1351 std::make_index_sequence<BoundaryCore::nsides()>{}, basfunc,
1352 coeff_indices, xi);
1353 }
1355
1356private:
1359 template <size_t... Is, typename... Xi>
1360 inline auto find_knot_indices_(std::index_sequence<Is...>,
1361 const std::tuple<Xi...> &xi) const {
1362 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1363 .find_knot_indices(std::get<Is>(xi))...);
1364 }
1365
1366public:
1368 template <typename... Xi>
1369 inline auto find_knot_indices(const std::tuple<Xi...> &xi) const {
1370 return find_knot_indices_(
1371 std::make_index_sequence<BoundaryCore::nsides()>{}, xi);
1372 }
1373
1374private:
1378 template <deriv deriv = deriv::func, bool memory_optimized = false,
1379 size_t... Is, typename... Xi>
1380 inline auto eval_basfunc_(std::index_sequence<Is...>,
1381 const std::tuple<Xi...> &xi) const {
1382 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1383 .template eval_basfunc<deriv, memory_optimized>(
1384 std::get<Is>(xi))...);
1385 }
1386
1387 template <deriv deriv = deriv::func, bool memory_optimized = false,
1388 size_t... Is, typename... Xi, typename... Indices>
1389 inline auto eval_basfunc_(std::index_sequence<Is...>,
1390 const std::tuple<Xi...> &xi,
1391 const std::tuple<Indices...> &indices) const {
1392 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1393 .template eval_basfunc<deriv, memory_optimized>(
1394 std::get<Is>(xi), std::get<Is>(indices))...);
1395 }
1397
1398public:
1401 template <deriv deriv = deriv::func, bool memory_optimized = false,
1402 typename... Xi>
1403 inline auto eval_basfunc(const std::tuple<Xi...> &xi) const {
1404 return eval_basfunc_<deriv, memory_optimized>(
1405 std::make_index_sequence<BoundaryCore::nsides()>{}, xi);
1406 }
1407
1408 template <deriv deriv = deriv::func, bool memory_optimized = false,
1409 typename... Xi, typename... Indices>
1410 inline auto eval_basfunc(const std::tuple<Xi...> &xi,
1411 const std::tuple<Indices...> &indices) const {
1412 static_assert(sizeof...(Xi) == sizeof...(Indices));
1413 return eval_basfunc_<deriv, memory_optimized>(
1414 std::make_index_sequence<BoundaryCore::nsides()>{}, xi, indices);
1415 }
1417
1418private:
1421 template <bool memory_optimized = false, size_t... Is, typename... Indices>
1422 inline auto find_coeff_indices_(std::index_sequence<Is...>,
1423 const std::tuple<Indices...> &indices) const {
1424 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1425 .template find_coeff_indices<memory_optimized>(
1426 std::get<Is>(indices))...);
1427 }
1428
1429public:
1432 template <bool memory_optimized = false, typename... Indices>
1433 inline auto find_coeff_indices(const std::tuple<Indices...> &indices) const {
1434 return find_coeff_indices_<memory_optimized>(
1435 std::make_index_sequence<BoundaryCore::nsides()>{}, indices);
1436 }
1437
1438private:
1441 template <size_t... Is>
1442 inline auto &uniform_refine_(std::index_sequence<Is...>, int numRefine = 1,
1443 int dim = -1) {
1444 (std::get<Is>(BoundaryCore::bdr_).uniform_refine(numRefine, dim), ...);
1445 return *this;
1446 }
1447
1448public:
1451 inline auto &uniform_refine(int numRefine = 1, int dim = -1) {
1452 if (dim == -1) {
1453 if constexpr (BoundaryCore::spline_type::parDim() > 1)
1454 uniform_refine_(std::make_index_sequence<BoundaryCore::nsides()>{},
1455 numRefine, dim);
1456 } else if (dim == 0) {
1457 if constexpr (BoundaryCore::nsides() == 2) {
1458 // We do not refine the boundary of a curve
1459 } else if constexpr (BoundaryCore::nsides() == 4) {
1460 std::get<side::south - 1>(BoundaryCore::bdr_)
1461 .uniform_refine(numRefine, 0);
1462 std::get<side::north - 1>(BoundaryCore::bdr_)
1463 .uniform_refine(numRefine, 0);
1464 } else if constexpr (BoundaryCore::nsides() == 6) {
1465 std::get<side::south - 1>(BoundaryCore::bdr_)
1466 .uniform_refine(numRefine, 0);
1467 std::get<side::north - 1>(BoundaryCore::bdr_)
1468 .uniform_refine(numRefine, 0);
1469 std::get<side::front - 1>(BoundaryCore::bdr_)
1470 .uniform_refine(numRefine, 0);
1471 std::get<side::back - 1>(BoundaryCore::bdr_)
1472 .uniform_refine(numRefine, 0);
1473 } else if constexpr (BoundaryCore::nsides() == 8) {
1474 std::get<side::south - 1>(BoundaryCore::bdr_)
1475 .uniform_refine(numRefine, 0);
1476 std::get<side::north - 1>(BoundaryCore::bdr_)
1477 .uniform_refine(numRefine, 0);
1478 std::get<side::front - 1>(BoundaryCore::bdr_)
1479 .uniform_refine(numRefine, 0);
1480 std::get<side::back - 1>(BoundaryCore::bdr_)
1481 .uniform_refine(numRefine, 0);
1482 std::get<side::stime - 1>(BoundaryCore::bdr_)
1483 .uniform_refine(numRefine, 0);
1484 std::get<side::etime - 1>(BoundaryCore::bdr_)
1485 .uniform_refine(numRefine, 0);
1486 } else
1487 throw std::runtime_error("Invalid dimension");
1488 } else if (dim == 1) {
1489 if constexpr (BoundaryCore::nsides() == 4) {
1490 std::get<side::east - 1>(BoundaryCore::bdr_)
1491 .uniform_refine(numRefine, 0);
1492 std::get<side::west - 1>(BoundaryCore::bdr_)
1493 .uniform_refine(numRefine, 0);
1494 } else if constexpr (BoundaryCore::nsides() == 6) {
1495 std::get<side::east - 1>(BoundaryCore::bdr_)
1496 .uniform_refine(numRefine, 0);
1497 std::get<side::west - 1>(BoundaryCore::bdr_)
1498 .uniform_refine(numRefine, 0);
1499 std::get<side::front - 1>(BoundaryCore::bdr_)
1500 .uniform_refine(numRefine, 1);
1501 std::get<side::back - 1>(BoundaryCore::bdr_)
1502 .uniform_refine(numRefine, 1);
1503
1504 } else if constexpr (BoundaryCore::nsides() == 8) {
1505 std::get<side::east - 1>(BoundaryCore::bdr_)
1506 .uniform_refine(numRefine, 0);
1507 std::get<side::west - 1>(BoundaryCore::bdr_)
1508 .uniform_refine(numRefine, 0);
1509 std::get<side::front - 1>(BoundaryCore::bdr_)
1510 .uniform_refine(numRefine, 1);
1511 std::get<side::back - 1>(BoundaryCore::bdr_)
1512 .uniform_refine(numRefine, 1);
1513 std::get<side::stime - 1>(BoundaryCore::bdr_)
1514 .uniform_refine(numRefine, 1);
1515 std::get<side::etime - 1>(BoundaryCore::bdr_)
1516 .uniform_refine(numRefine, 1);
1517 } else
1518 throw std::runtime_error("Invalid dimension");
1519 } else if (dim == 2) {
1520 if constexpr (BoundaryCore::nsides() == 6) {
1521 std::get<side::east - 1>(BoundaryCore::bdr_)
1522 .uniform_refine(numRefine, 1);
1523 std::get<side::west - 1>(BoundaryCore::bdr_)
1524 .uniform_refine(numRefine, 1);
1525 std::get<side::north - 1>(BoundaryCore::bdr_)
1526 .uniform_refine(numRefine, 1);
1527 std::get<side::south - 1>(BoundaryCore::bdr_)
1528 .uniform_refine(numRefine, 1);
1529 } else if constexpr (BoundaryCore::nsides() == 8) {
1530 std::get<side::west - 1>(BoundaryCore::bdr_)
1531 .uniform_refine(numRefine, 1);
1532 std::get<side::east - 1>(BoundaryCore::bdr_)
1533 .uniform_refine(numRefine, 1);
1534 std::get<side::south - 1>(BoundaryCore::bdr_)
1535 .uniform_refine(numRefine, 1);
1536 std::get<side::north - 1>(BoundaryCore::bdr_)
1537 .uniform_refine(numRefine, 1);
1538 std::get<side::stime - 1>(BoundaryCore::bdr_)
1539 .uniform_refine(numRefine, 2);
1540 std::get<side::etime - 1>(BoundaryCore::bdr_)
1541 .uniform_refine(numRefine, 2);
1542 } else
1543 throw std::runtime_error("Invalid dimension");
1544 } else if (dim == 3) {
1545 if constexpr (BoundaryCore::nsides() == 8) {
1546 std::get<side::west - 1>(BoundaryCore::bdr_)
1547 .uniform_refine(numRefine, 2);
1548 std::get<side::east - 1>(BoundaryCore::bdr_)
1549 .uniform_refine(numRefine, 2);
1550 std::get<side::south - 1>(BoundaryCore::bdr_)
1551 .uniform_refine(numRefine, 2);
1552 std::get<side::north - 1>(BoundaryCore::bdr_)
1553 .uniform_refine(numRefine, 2);
1554 std::get<side::front - 1>(BoundaryCore::bdr_)
1555 .uniform_refine(numRefine, 2);
1556 std::get<side::back - 1>(BoundaryCore::bdr_)
1557 .uniform_refine(numRefine, 2);
1558 } else
1559 throw std::runtime_error("Invalid dimension");
1560 } else
1561 throw std::runtime_error("Invalid dimension");
1562 return *this;
1563 }
1564
1565private:
1568 template <size_t... Is>
1569 inline torch::serialize::OutputArchive &
1570 write_(std::index_sequence<Is...>, torch::serialize::OutputArchive &archive,
1571 const std::string &key = "boundary") const {
1572 (std::get<Is>(BoundaryCore::bdr_)
1573 .write(archive, key + ".bdr[" + std::to_string(Is) + "]"),
1574 ...);
1575 return archive;
1576 }
1577
1578public:
1580 inline void save(const std::string &filename,
1581 const std::string &key = "boundary") const {
1582 torch::serialize::OutputArchive archive;
1583 write(archive, key).save_to(filename);
1584 }
1585
1588 inline torch::serialize::OutputArchive &
1589 write(torch::serialize::OutputArchive &archive,
1590 const std::string &key = "boundary") const {
1591 write_(std::make_index_sequence<BoundaryCore::nsides()>{}, archive, key);
1592 return archive;
1593 }
1594
1595private:
1598 template <size_t... Is>
1599 inline torch::serialize::InputArchive &
1600 read_(std::index_sequence<Is...>, torch::serialize::InputArchive &archive,
1601 const std::string &key = "boundary") {
1602 (std::get<Is>(BoundaryCore::bdr_)
1603 .read(archive, key + ".bdr[" + std::to_string(Is) + "]"),
1604 ...);
1605 return archive;
1606 }
1607
1608public:
1610 inline void load(const std::string &filename,
1611 const std::string &key = "boundary") {
1612 torch::serialize::InputArchive archive;
1613 archive.load_from(filename);
1614 read(archive, key);
1615 }
1616
1619 inline torch::serialize::InputArchive &
1620 read(torch::serialize::InputArchive &archive,
1621 const std::string &key = "boundary") {
1622 read_(std::make_index_sequence<BoundaryCore::nsides()>{}, archive, key);
1623 return archive;
1624 }
1625
1627 [[nodiscard]] inline pugi::xml_document
1628 to_xml(int id = 0, const std::string &label = "", int index = -1) const {
1629 pugi::xml_document doc;
1630 pugi::xml_node root = doc.append_child("xml");
1631 to_xml(root, id, label, index);
1632
1633 return doc;
1634 }
1635
1637 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
1638 const std::string &label = "",
1639 int index = -1) const {
1640 // add Boundary node
1641 pugi::xml_node bdr = root.append_child("Boundary");
1642
1643 if (id >= 0)
1644 bdr.append_attribute("id") = id;
1645
1646 if (index >= 0)
1647 bdr.append_attribute("index") = index;
1648
1649 if (!label.empty())
1650 bdr.append_attribute("label") = label.c_str();
1651
1652 int index_ = 0;
1653 std::apply(
1654 [&bdr, &index_](const auto &...bspline) {
1655 (bspline.to_xml(bdr, -1, "", index_++), ...);
1656 },
1657 BoundaryCore::bdr_);
1658
1659 return root;
1660 }
1661
1663 inline BoundaryCommon &from_xml(const pugi::xml_document &doc, int id = 0,
1664 const std::string &label = "",
1665 int index = -1) {
1666 return from_xml(doc.child("xml"), id, label, index);
1667 }
1668
1670 inline BoundaryCommon &from_xml(const pugi::xml_node &root, int id = 0,
1671 const std::string &label = "",
1672 int index = -1) {
1673
1674 // Loop through all boundary nodes
1675 for (pugi::xml_node bdr : root.children("Boundary")) {
1676
1677 // Check for "Boundary" with given id, index, label
1678 if ((id >= 0 ? bdr.attribute("id").as_int() == id : true) &&
1679 (index >= 0 ? bdr.attribute("index").as_int() == index : true) &&
1680 (!label.empty() ? bdr.attribute("label").value() == label : true)) {
1681
1682 int index_ = 0;
1683 std::apply(
1684 [&bdr, &index_](auto &...bspline) {
1685 (bspline.from_xml(bdr, -1, "", index_++), ...);
1686 },
1687 BoundaryCore::bdr_);
1688
1689 return *this;
1690 } else
1691 continue; // try next "Boundary"
1692 }
1693
1694 throw std::runtime_error("XML object does not provide geometry with given "
1695 "id, index, and/or label");
1696 return *this;
1697 }
1698
1699private:
1702 template <typename BoundaryCore_, size_t... Is>
1703 inline bool isequal_(std::index_sequence<Is...>,
1704 const BoundaryCommon<BoundaryCore_> &other) const {
1705 return ((std::get<Is>(BoundaryCore::bdr_) == std::get<Is>(other.sides())) &&
1706 ...);
1707 }
1708
1709public:
1711 template <typename BoundaryCore_>
1712 inline bool operator==(const BoundaryCommon<BoundaryCore_> &other) const {
1713 return isequal_(std::make_index_sequence<BoundaryCore::nsides()>{}, other);
1714 }
1715
1717 template <typename BoundaryCore_>
1718 inline bool operator!=(const BoundaryCommon<BoundaryCore_> &other) const {
1719 return !(
1720 *this ==
1721 other); // Do not change this to (*this != other) is it does not work
1722 }
1723
1724private:
1727 template <typename BoundaryCore_, size_t... Is>
1728 inline bool isclose_(std::index_sequence<Is...>,
1729 const BoundaryCommon<BoundaryCore_> &other,
1730 BoundaryCore::spline_type::value_type rtol,
1731 BoundaryCore::spline_type::value_type atol) const {
1732 return ((std::get<Is>(BoundaryCore::bdr_)
1733 .isclose(std::get<Is>(other.sides()))) &&
1734 ...);
1735 }
1736
1737public:
1740 template <typename BoundaryCore_>
1741 inline bool
1743 BoundaryCore::spline_type::value_type rtol =
1744 typename BoundaryCore::spline_type::value_type{1e-5},
1745 BoundaryCore::spline_type::value_type atol =
1746 typename BoundaryCore::spline_type::value_type{1e-8}) const {
1747 return isclose_(std::make_index_sequence<BoundaryCore::nsides()>{}, other,
1748 rtol, atol);
1749 }
1750
1751#define GENERATE_EXPR_MACRO(r, data, name) \
1752private: \
1753 template <bool memory_optimized = false, size_t... Is, typename... Xi> \
1754 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
1755 const std::tuple<Xi...> &xi) const { \
1756 return std::tuple( \
1757 std::get<Is>(BoundaryCore::bdr_) \
1758 .template name<memory_optimized>(std::get<Is>(xi))...); \
1759 } \
1760 \
1761 template <bool memory_optimized = false, size_t... Is, typename... Xi, \
1762 typename... Indices> \
1763 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
1764 const std::tuple<Xi...> &xi, \
1765 const std::tuple<Indices...> &indices) \
1766 const { \
1767 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1768 .template name<memory_optimized>( \
1769 std::get<Is>(xi), std::get<Is>(indices))...); \
1770 } \
1771 \
1772 template <bool memory_optimized = false, size_t... Is, typename... Xi, \
1773 typename... Indices, typename... Coeff_Indices> \
1774 inline auto BOOST_PP_CAT(name, _)( \
1775 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
1776 const std::tuple<Indices...> &indices, \
1777 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
1778 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1779 .template name<memory_optimized>( \
1780 std::get<Is>(xi), std::get<Is>(indices), \
1781 std::get<Is>(coeff_indices))...); \
1782 } \
1783 \
1784public: \
1785 template <bool memory_optimized = false, typename... Args> \
1786 inline auto name(const Args &...args) const { \
1787 return BOOST_PP_CAT(name, _)<memory_optimized>( \
1788 std::make_index_sequence<BoundaryCore::nsides()>{}, args...); \
1789 }
1790
1793 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
1795#undef GENERATE_EXPR_MACRO
1796
1797#define GENERATE_IEXPR_MACRO(r, data, name) \
1798private: \
1799 template <bool memory_optimized = false, size_t... Is, typename... Geometry, \
1800 typename... Xi> \
1801 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
1802 const std::tuple<Geometry...> &G, \
1803 const std::tuple<Xi...> &xi) const { \
1804 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1805 .template name<memory_optimized>( \
1806 std::get<Is>(G), std::get<Is>(xi))...); \
1807 } \
1808 \
1809 template <bool memory_optimized = false, size_t... Is, typename... Geometry, \
1810 typename... Xi, typename... Indices> \
1811 inline auto BOOST_PP_CAT(name, _)( \
1812 std::index_sequence<Is...>, const std::tuple<Geometry...> &G, \
1813 const std::tuple<Xi...> &xi, const std::tuple<Indices...> &indices) \
1814 const { \
1815 return std::tuple( \
1816 std::get<Is>(BoundaryCore::bdr_) \
1817 .template name<memory_optimized>( \
1818 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(indices))...); \
1819 } \
1820 \
1821 template <bool memory_optimized = false, size_t... Is, typename... Geometry, \
1822 typename... Xi, typename... Indices, typename... Coeff_Indices> \
1823 inline auto BOOST_PP_CAT(name, _)( \
1824 std::index_sequence<Is...>, const std::tuple<Geometry...> &G, \
1825 const std::tuple<Xi...> &xi, const std::tuple<Indices...> &indices, \
1826 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
1827 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1828 .template name<memory_optimized>( \
1829 std::get<Is>(G), std::get<Is>(xi), \
1830 std::get<Is>(indices), \
1831 std::get<Is>(coeff_indices))...); \
1832 } \
1833 \
1834public: \
1835 template <bool memory_optimized = false, typename... Args> \
1836 inline auto name(const Args &...args) const { \
1837 return BOOST_PP_CAT(name, _)<memory_optimized>( \
1838 std::make_index_sequence<BoundaryCore::nsides()>{}, args...); \
1839 }
1840
1843 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
1845#undef GENERATE_IEXPR_MACRO
1846
1848 auto device() const noexcept {
1849 return std::apply(
1850 [](const auto &...bspline) {
1851 return std::make_tuple(bspline.device()...);
1852 },
1853 BoundaryCore::bdr_);
1854 }
1855
1857 auto device_index() const noexcept {
1858 return std::apply(
1859 [](const auto &...bspline) {
1860 return std::make_tuple(bspline.device_index()...);
1861 },
1862 BoundaryCore::bdr_);
1863 }
1864
1866 auto dtype() const noexcept {
1867 return std::apply(
1868 [](const auto &...bspline) {
1869 return std::make_tuple(bspline.dtype()...);
1870 },
1871 BoundaryCore::bdr_);
1872 }
1873
1875 auto layout() const noexcept {
1876 return std::apply(
1877 [](const auto &...bspline) {
1878 return std::make_tuple(bspline.layout()...);
1879 },
1880 BoundaryCore::bdr_);
1881 }
1882
1884 auto requires_grad() const noexcept {
1885 return std::apply(
1886 [](const auto &...bspline) {
1887 return std::make_tuple(bspline.requires_grad()...);
1888 },
1889 BoundaryCore::bdr_);
1890 }
1891
1893 auto pinned_memory() const noexcept {
1894 return std::apply(
1895 [](const auto &...bspline) {
1896 return std::make_tuple(bspline.pinned_memory()...);
1897 },
1898 BoundaryCore::bdr_);
1899 }
1900
1902 auto is_sparse() const noexcept {
1903 return std::apply(
1904 [](const auto &...bspline) {
1905 return std::make_tuple(bspline.is_sparse()...);
1906 },
1907 BoundaryCore::bdr_);
1908 }
1909
1911 auto is_uniform() const noexcept {
1912 return std::apply(
1913 [](const auto &...bspline) {
1914 return std::make_tuple(bspline.is_uniform()...);
1915 },
1916 BoundaryCore::bdr_);
1917 }
1918
1920 auto is_nonuniform() const noexcept {
1921 return std::apply(
1922 [](const auto &...bspline) {
1923 return std::make_tuple(bspline.is_nonuniform()...);
1924 },
1925 BoundaryCore::bdr_);
1926 }
1927
1930 std::apply(
1931 [requires_grad](const auto &...bspline) {
1932 (bspline.set_requires_grad(requires_grad), ...);
1933 },
1934 BoundaryCore::bdr_);
1935
1936 return *this;
1937 }
1938
1940 template <typename real_t> inline auto to(Options<real_t> options) const {
1941 using boundary_type = BoundaryCommon<iganet::BoundaryCore<
1942 decltype(typename BoundaryCore::spline_type{}.to(options)),
1943 BoundaryCore::spline_type::parDim()>>;
1944
1945 return boundary_type(std::apply(
1946 [&options](const auto &...bspline) {
1947 return std::make_tuple(bspline.to(options)...);
1948 },
1949 BoundaryCore::bdr_));
1950 }
1951
1953 inline auto to(torch::Device device) const {
1954 return BoundaryCommon(std::apply(
1955 [&device](const auto &...bspline) {
1956 return std::make_tuple(bspline.to(device)...);
1957 },
1958 BoundaryCore::bdr_));
1959 }
1960
1962 template <typename real_t> inline auto to() const {
1963 using boundary_type = BoundaryCommon<iganet::BoundaryCore<
1964 decltype(typename BoundaryCore::spline_type{}.template to<real_t>()),
1965 BoundaryCore::spline_type::parDim()>>;
1966
1967 return boundary_type(std::apply(
1968 [](const auto &...bspline) {
1969 return std::make_tuple(bspline.template to<real_t>()...);
1970 },
1971 BoundaryCore::bdr_));
1972 }
1973};
1974
1976template <typename Spline>
1977 requires SplineType<Spline>
1978using Boundary = BoundaryCommon<BoundaryCore<Spline, Spline::parDim()>>;
1979
1981template <typename Spline>
1982 requires SplineType<Spline>
1983inline std::ostream &operator<<(std::ostream &os, const Boundary<Spline> &obj) {
1984 obj.pretty_print(os);
1985 return os;
1986}
1987
1988} // namespace iganet
#define GENERATE_IEXPR_MACRO(r, data, name)
Auto-generated functions.
Definition boundary.hpp:1797
#define GENERATE_EXPR_MACRO(r, data, name)
Definition boundary.hpp:1751
Multivariate B-splines.
#define GENERATE_EXPR_SEQ
Sequence of expression (parametric coordinates)
Definition bspline.hpp:40
#define GENERATE_IEXPR_SEQ
Sequence of expression (physical coordinates)
Definition bspline.hpp:46
Boundary base class.
Definition boundary.hpp:1134
Boundary (common high-level functionality)
Definition boundary.hpp:1143
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition boundary.hpp:1369
BoundaryCommon & from_xml(const pugi::xml_node &root, int id=0, const std::string &label="", int index=-1)
Updates the boundary object from XML node.
Definition boundary.hpp:1670
auto to(torch::Device device) const
Returns a copy of the boundary object with settings from device.
Definition boundary.hpp:1953
auto dtype() const noexcept
Returns the dtype property of all splines.
Definition boundary.hpp:1866
auto eval_from_precomputed(const std::tuple< Basfunc... > &basfunc, const std::tuple< Coeff_Indices... > &coeff_indices, const std::tuple< Numeval... > &numeval, const std::tuple< Sizes... > &sizes) const
Returns the value of the spline objects from precomputed basis function.
Definition boundary.hpp:1331
auto pinned_memory() const noexcept
Returns the pinned_memory property of all splines.
Definition boundary.hpp:1893
bool isequal_(std::index_sequence< Is... >, const BoundaryCommon< BoundaryCore_ > &other) const
Returns true if both boundary spline objects are the same.
Definition boundary.hpp:1703
auto eval_basfunc(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects' basis functions in the points xi
Definition boundary.hpp:1403
torch::serialize::InputArchive & read(torch::serialize::InputArchive &archive, const std::string &key="boundary")
Loads the boundary spline object from a torch::serialize::InputArchive object.
Definition boundary.hpp:1620
BoundaryCommon & from_xml(const pugi::xml_document &doc, int id=0, const std::string &label="", int index=-1)
Updates the boundary object from XML object.
Definition boundary.hpp:1663
auto eval(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects in the points xi
Definition boundary.hpp:1265
auto eval_from_precomputed_(std::index_sequence< Is... >, const std::tuple< Basfunc... > &basfunc, const std::tuple< Coeff_Indices... > &coeff_indices, const std::tuple< Numeval... > &numeval, const std::tuple< Sizes... > &sizes) const
Returns the value of the boundary spline objects from precomputed basis function.
Definition boundary.hpp:1298
auto to() const
Returns a copy of the boundary object with real_t type.
Definition boundary.hpp:1962
auto to(Options< real_t > options) const
Returns a copy of the boundary object with settings from options.
Definition boundary.hpp:1940
auto device_index() const noexcept
Returns the device_index property of all splines.
Definition boundary.hpp:1857
auto is_uniform() const noexcept
Returns true if the B-spline is uniform of all splines.
Definition boundary.hpp:1911
torch::Tensor as_tensor_(std::index_sequence< Is... >) const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1157
bool isclose(const BoundaryCommon< BoundaryCore_ > &other, BoundaryCore::spline_type::value_type rtol=typename BoundaryCore::spline_type::value_type{1e-5}, BoundaryCore::spline_type::value_type atol=typename BoundaryCore::spline_type::value_type{1e-8}) const
Returns true if both boundary objects are close up to the given tolerances.
Definition boundary.hpp:1742
int64_t as_tensor_size_(std::index_sequence< Is... >) const
Returns the size of the single tensor representation of all spline objects.
Definition boundary.hpp:1176
auto eval_basfunc_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the values of the boundary spline object's basis functions in the points xi
Definition boundary.hpp:1380
auto find_knot_indices_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the knot indicies of boundary spline object's knot spans containing xi
Definition boundary.hpp:1360
auto & uniform_refine_(std::index_sequence< Is... >, int numRefine=1, int dim=-1)
Returns the boundary spline object with uniformly refined knot and coefficient vectors.
Definition boundary.hpp:1442
torch::serialize::OutputArchive & write_(std::index_sequence< Is... >, torch::serialize::OutputArchive &archive, const std::string &key="boundary") const
Writes the boundary spline object into a torch::serialize::OutputArchive object.
Definition boundary.hpp:1570
auto is_nonuniform() const noexcept
Returns true if the B-spline is non-uniform if all splines.
Definition boundary.hpp:1920
auto eval_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi, const std::tuple< Indices... > &indices, const std::tuple< Coeff_Indices... > &coeff_indices) const
Returns the values of the boundary spline objects in the points xi
Definition boundary.hpp:1250
auto find_coeff_indices(const std::tuple< Indices... > &indices) const
Returns the indices of the spline objects' coefficients corresponding to the knot indices indices
Definition boundary.hpp:1433
auto requires_grad() const noexcept
Returns the requires_grad property of all splines.
Definition boundary.hpp:1884
auto eval(const std::tuple< Xi... > &xi, const std::tuple< Indices... > &indices) const
Returns the values of the spline objects in the points xi
Definition boundary.hpp:1272
BoundaryCommon clone() const
Returns a clone of the boundary object.
Definition boundary.hpp:1149
auto eval_basfunc(const std::tuple< Xi... > &xi, const std::tuple< Indices... > &indices) const
Returns the values of the spline objects' basis functions in the points xi
Definition boundary.hpp:1410
auto & from_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor.
Definition boundary.hpp:1221
auto & from_tensor_(std::index_sequence< Is... >, const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor.
Definition boundary.hpp:1199
auto eval(const std::tuple< Xi... > &xi, const std::tuple< Indices... > &indices, const std::tuple< Coeff_Indices... > &coeff_indices) const
Returns the values of the spline objects in the points xi
Definition boundary.hpp:1281
pugi::xml_document to_xml(int id=0, const std::string &label="", int index=-1) const
Returns the boundary object as XML object.
Definition boundary.hpp:1628
void load(const std::string &filename, const std::string &key="boundary")
Loads the boundary spline object from file.
Definition boundary.hpp:1610
torch::Tensor as_tensor() const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1166
auto eval_basfunc_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi, const std::tuple< Indices... > &indices) const
Returns the values of the boundary spline object's basis functions in the points xi
Definition boundary.hpp:1389
BoundaryCommon & set_requires_grad(bool requires_grad)
Sets the boundary object's requires_grad property.
Definition boundary.hpp:1929
auto eval_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the values of the boundary spline objects in the points xi
Definition boundary.hpp:1231
pugi::xml_node & to_xml(pugi::xml_node &root, int id=0, const std::string &label="", int index=-1) const
Returns the boundary object as XML node.
Definition boundary.hpp:1637
auto & uniform_refine(int numRefine=1, int dim=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition boundary.hpp:1451
auto eval_from_precomputed_(std::index_sequence< Is... >, const std::tuple< Basfunc... > &basfunc, const std::tuple< Coeff_Indices... > &coeff_indices, const std::tuple< Xi... > &xi) const
Returns the value of the boundary spline objects from precomputed basis function.
Definition boundary.hpp:1313
int64_t as_tensor_size() const
Returns the size of the single tensor representation of all spline objects.
Definition boundary.hpp:1187
auto eval_from_precomputed(const std::tuple< Basfunc... > &basfunc, const std::tuple< Coeff_Indices... > &coeff_indices, const std::tuple< Xi... > &xi) const
Returns the value of the spline objects from precomputed basis function.
Definition boundary.hpp:1345
bool operator==(const BoundaryCommon< BoundaryCore_ > &other) const
Returns true if both boundary objects are the same.
Definition boundary.hpp:1712
auto find_coeff_indices_(std::index_sequence< Is... >, const std::tuple< Indices... > &indices) const
Returns the indices of the boundary spline object's coefficients corresponding to the knot indices in...
Definition boundary.hpp:1422
auto layout() const noexcept
Returns the layout property of all splines.
Definition boundary.hpp:1875
torch::serialize::OutputArchive & write(torch::serialize::OutputArchive &archive, const std::string &key="boundary") const
Writes the boundary spline object into a torch::serialize::OutputArchive object.
Definition boundary.hpp:1589
bool isclose_(std::index_sequence< Is... >, const BoundaryCommon< BoundaryCore_ > &other, BoundaryCore::spline_type::value_type rtol, BoundaryCore::spline_type::value_type atol) const
Returns true if both boundary spline objects are close up to the given tolerances.
Definition boundary.hpp:1728
torch::serialize::InputArchive & read_(std::index_sequence< Is... >, torch::serialize::InputArchive &archive, const std::string &key="boundary")
Loads the function space object from a torch::serialize::InputArchive object.
Definition boundary.hpp:1600
auto eval_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi, const std::tuple< Indices... > &indices) const
Returns the values of the boundary spline objects in the points xi
Definition boundary.hpp:1240
void save(const std::string &filename, const std::string &key="boundary") const
Saves the boundary spline to file.
Definition boundary.hpp:1580
auto device() const noexcept
Auto-generated functions.
Definition boundary.hpp:1848
bool operator!=(const BoundaryCommon< BoundaryCore_ > &other) const
Returns true if both boundary objects are different.
Definition boundary.hpp:1718
auto is_sparse() const noexcept
Returns if the layout is sparse of all splines.
Definition boundary.hpp:1902
constexpr auto & side() const
Returns constant reference to side-th Spline.
Definition boundary.hpp:157
BoundaryCore(const std::array< int64_t, 1 > &, enum init init=init::zeros, Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Constructor.
Definition boundary.hpp:108
constexpr auto & sides()
Returns a non-constant reference to the tuple of boundary sides.
Definition boundary.hpp:174
std::tuple< boundary_spline_type, boundary_spline_type > bdr_
Tuple of splines.
Definition boundary.hpp:75
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:186
Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim()> boundary_spline_type
Boundary spline type.
Definition boundary.hpp:66
std::tuple< torch::Tensor, torch::Tensor > eval_type
Evaluation type.
Definition boundary.hpp:85
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:99
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:93
BoundaryCore(const std::array< std::vector< typename Spline::value_type >, 1 > &, enum init init=init::zeros, Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Constructor.
Definition boundary.hpp:116
~BoundaryCore() override=default
Destructor.
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:154
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:88
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:177
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:202
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:96
constexpr auto & side()
Returns non-constant reference to side-th Spline.
Definition boundary.hpp:163
Spline::value_type value_type
Value type.
Definition boundary.hpp:79
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:193
Spline spline_type
Spline type.
Definition boundary.hpp:61
constexpr auto & sides() const
Returns a constant reference to the tuple of boundary sides.
Definition boundary.hpp:170
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:82
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:210
auto & from_full_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor that holds both boundary and inner c...
Definition boundary.hpp:133
Spline::template derived_self_type< real_t, Spline::geoDim()> real_derived_boundary_spline_type
Deduces the derived boundary spline type when exposed to a different class template parameter real_t
Definition boundary.hpp:72
std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(1)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)> > boundary_spline_type
Boundary spline type.
Definition boundary.hpp:239
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:417
constexpr auto & sides() const
Returns a constant reference to the tuple of boundary sides.
Definition boundary.hpp:400
constexpr auto & side()
Returns non-constant reference to the s-th side's spline.
Definition boundary.hpp:394
std::tuple< utils::TensorArray< 1 >, utils::TensorArray< 1 >, utils::TensorArray< 1 >, utils::TensorArray< 1 > > eval_type
Evaluation type.
Definition boundary.hpp:266
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:385
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:447
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:283
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:426
constexpr auto & sides()
Returns a non-constant reference to the tuple of boundary sides.
Definition boundary.hpp:403
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:437
Spline spline_type
Spline type.
Definition boundary.hpp:232
auto & from_full_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor that holds both boundary and inner c...
Definition boundary.hpp:337
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:262
std::tuple< std::tuple_element_t< 0, boundary_spline_type >, std::tuple_element_t< 0, boundary_spline_type >, std::tuple_element_t< 1, boundary_spline_type >, std::tuple_element_t< 1, boundary_spline_type > > bdr_
Tuple of splines.
Definition boundary.hpp:255
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:269
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:277
Spline::value_type value_type
Value type.
Definition boundary.hpp:259
std::tuple< typename Spline::template derived_self_type< real_t, Spline::geoDim(), Spline::degree(1)>, typename Spline::template derived_self_type< real_t, Spline::geoDim(), Spline::degree(0)> > real_derived_boundary_spline_type
Deduces the derived boundary spline type when exposed to a different class template parameter real_t
Definition boundary.hpp:248
BoundaryCore(const std::array< int64_t, 2 > &ncoeffs, enum init init=init::zeros, Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Constructor.
Definition boundary.hpp:292
constexpr auto & side() const
Returns constant reference to the s-th side's spline.
Definition boundary.hpp:388
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:406
BoundaryCore(const std::array< std::vector< typename Spline::value_type >, 2 > &kv, enum init init=init::zeros, Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Constructor.
Definition boundary.hpp:306
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:280
~BoundaryCore() override=default
Destructor.
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:744
constexpr auto & sides() const
Returns a constant reference to the tuple of boundary sides.
Definition boundary.hpp:701
Spline::value_type value_type
Value type.
Definition boundary.hpp:508
~BoundaryCore() override=default
Destructor.
constexpr auto & side() const
Returns constant reference to side-th spline.
Definition boundary.hpp:689
BoundaryCore(const std::array< std::vector< typename Spline::value_type >, 3 > &kv, enum init init=init::zeros, Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Constructor.
Definition boundary.hpp:568
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:529
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:511
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:535
Spline spline_type
Spline type.
Definition boundary.hpp:472
std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(1), Spline::degree(2)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(2)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)> > boundary_spline_type
Boundary spline type.
Definition boundary.hpp:484
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:532
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:519
constexpr auto & sides()
Returns a non-constant reference to the tuple of sides.
Definition boundary.hpp:704
BoundaryCore(const std::array< int64_t, 3 > &ncoeffs, enum init init=init::zeros, Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Constructor.
Definition boundary.hpp:544
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:707
auto & from_full_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor that holds both boundary and inner c...
Definition boundary.hpp:607
std::tuple< std::tuple_element_t< 0, boundary_spline_type >, std::tuple_element_t< 0, boundary_spline_type >, std::tuple_element_t< 1, boundary_spline_type >, std::tuple_element_t< 1, boundary_spline_type >, std::tuple_element_t< 2, boundary_spline_type >, std::tuple_element_t< 2, boundary_spline_type > > bdr_
Tuple of splines.
Definition boundary.hpp:504
std::tuple< typename Spline::template derived_self_type< real_t, Spline::geoDim(), Spline::degree(1), Spline::degree(2)>, typename Spline::template derived_self_type< real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(2)>, typename Spline::template derived_self_type< real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(1)> > real_derived_boundary_spline_type
Deduces the derived boundary spline type when exposed to a different class template parameter real_t
Definition boundary.hpp:495
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:731
constexpr auto & side()
Returns non-constant reference to side-th spline.
Definition boundary.hpp:695
std::tuple< utils::TensorArray< 2 >, utils::TensorArray< 2 >, utils::TensorArray< 2 >, utils::TensorArray< 2 >, utils::TensorArray< 2 >, utils::TensorArray< 2 > > eval_type
Evaluation type.
Definition boundary.hpp:516
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:686
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:720
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:756
BoundaryCore(const std::array< int64_t, 4 > &ncoeffs, enum init init=init::zeros, Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Constructor.
Definition boundary.hpp:870
constexpr auto & side()
Returns non-constant reference to side-th spline.
Definition boundary.hpp:1056
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:1111
auto & from_full_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor that holds both boundary and inner c...
Definition boundary.hpp:947
std::tuple< std::tuple_element_t< 0, boundary_spline_type >, std::tuple_element_t< 0, boundary_spline_type >, std::tuple_element_t< 1, boundary_spline_type >, std::tuple_element_t< 1, boundary_spline_type >, std::tuple_element_t< 2, boundary_spline_type >, std::tuple_element_t< 2, boundary_spline_type >, std::tuple_element_t< 3, boundary_spline_type >, std::tuple_element_t< 3, boundary_spline_type > > bdr_
Tuple of splines.
Definition boundary.hpp:827
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:1125
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:1068
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:858
Spline::value_type value_type
Value type.
Definition boundary.hpp:831
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:1047
~BoundaryCore() override=default
Destructor.
std::tuple< utils::TensorArray< 3 >, utils::TensorArray< 3 >, utils::TensorArray< 3 >, utils::TensorArray< 3 >, utils::TensorArray< 3 >, utils::TensorArray< 3 >, utils::TensorArray< 3 >, utils::TensorArray< 3 > > eval_type
Evaluation type.
Definition boundary.hpp:840
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:861
Spline spline_type
Spline type.
Definition boundary.hpp:784
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:855
constexpr auto & ides()
Returns a non-constant reference to the tuple of boundary sides.
Definition boundary.hpp:1065
constexpr auto & side() const
Returns constant reference to side-th spline.
Definition boundary.hpp:1050
BoundaryCore(const std::array< std::vector< typename Spline::value_type >, 4 > &kv, enum init init=init::zeros, Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Constructor.
Definition boundary.hpp:900
std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(1), Spline::degree(2), Spline::degree(3)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(2), Spline::degree(3)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(3)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)> > boundary_spline_type
Array storing the degrees.
Definition boundary.hpp:799
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:1096
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:1083
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:843
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:834
constexpr auto & sides() const
Returns a constant reference to the tuple of boundary sides.
Definition boundary.hpp:1062
std::tuple< typename Spline::template derived_self_type< real_t, Spline::geoDim(), Spline::degree(1), Spline::degree(2), Spline::degree(3)>, typename Spline::template derived_self_type< real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(2), Spline::degree(3)>, typename Spline::template derived_self_type< real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(3)>, typename Spline::template derived_self_type< real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)> > real_derived_boundary_spline_type
Deduces the derived boundary spline type when exposed to a different class template parameter real_t
Definition boundary.hpp:816
BoundaryCore.
Definition boundary.hpp:44
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:104
Full qualified name descriptor.
Definition fqn.hpp:22
Concept to identify template parameters that are derived from iganet::Boundary_.
Definition boundary.hpp:1139
Concept to identify template parameters that are derived from iganet::Spline_.
Definition bspline.hpp:3582
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:26
Definition core.hpp:72
deriv
Enumerator for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:72
std::ostream & operator<<(std::ostream &os, const MemoryDebugger< id > &obj)
Print (as string) a memory debugger object.
Definition memory.hpp:125
init
Enumerator for specifying the initialization of B-spline coefficients.
Definition bspline.hpp:55
side
Identifiers for topological sides.
Definition boundary.hpp:25
@ stime
Definition boundary.hpp:32
@ down
Definition boundary.hpp:36
@ right
Definition boundary.hpp:35
@ left
Definition boundary.hpp:34
@ back
Definition boundary.hpp:31
@ east
Definition boundary.hpp:27
@ etime
Definition boundary.hpp:33
@ front
Definition boundary.hpp:30
@ north
Definition boundary.hpp:29
@ south
Definition boundary.hpp:28
@ west
Definition boundary.hpp:26
@ up
Definition boundary.hpp:37
@ none
Definition boundary.hpp:38
short int short_t
Definition core.hpp:74
STL namespace.
Serialization prototype.
Definition serialize.hpp:29