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
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
91 : bdr_({boundary_spline_type(options), boundary_spline_type(options)}) {}
92
95 explicit BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
96
99 explicit BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
100
104 BoundaryCore(const BoundaryCore &other, bool clone)
105 : bdr_(clone ? std::apply(
106 [](const auto &...bspline) {
107 return std::make_tuple(bspline.clone()...);
108 },
109 other.sides())
110 : other.sides()) {}
111
115 explicit BoundaryCore(const std::array<int64_t, 1> &,
116 enum init init = init::zeros,
119 : bdr_({boundary_spline_type(std::array<int64_t, 0>{}, init, options),
120 boundary_spline_type(std::array<int64_t, 0>{}, init, options)}) {}
121
125 explicit BoundaryCore(
126 const std::array<std::vector<typename Spline::value_type>, 1> &,
127 enum init init = init::zeros,
130 : bdr_({boundary_spline_type(std::array<int64_t, 0>{}, init, options),
131 boundary_spline_type(std::array<int64_t, 0>{}, init, options)}) {}
132
134 ~BoundaryCore() override = default;
135
142 inline auto &from_full_tensor(const torch::Tensor &tensor) {
143
144 if (tensor.dim() > 1) {
145 auto tensor_view = tensor.view({Spline::geoDim(), -1, tensor.size(-1)});
146
147 side<west>().from_tensor(tensor_view.index({torch::indexing::Slice(), 0})
148 .reshape({-1, tensor.size(-1)}));
149 side<east>().from_tensor(tensor_view.index({torch::indexing::Slice(), -1})
150 .reshape({-1, tensor.size(-1)}));
151 } else {
152 auto tensor_view = tensor.view({Spline::geoDim(), -1});
153
154 side<west>().from_tensor(
155 tensor_view.index({torch::indexing::Slice(), 0}).flatten());
156 side<east>().from_tensor(
157 tensor_view.index({torch::indexing::Slice(), -1}).flatten());
158 }
159 return *this;
160 }
161
164 inline static constexpr short_t nsides() { return side::east; }
165
169 template <short_t s> inline constexpr auto &side() const {
170 static_assert(s > none && s <= nsides());
171 return std::get<s - 1>(bdr_);
172 }
173
177 template <short_t s> inline constexpr auto &side() {
178 static_assert(s > none && s <= nsides());
179 return std::get<s - 1>(bdr_);
180 }
181
185 inline constexpr auto &sides() const { return bdr_; }
186
190 inline constexpr auto &sides() { return bdr_; }
191
194 inline int64_t ncumcoeffs() const {
195 int64_t s = 0;
196 s += side<west>().ncumcoeffs();
197 s += side<east>().ncumcoeffs();
198
199 return s;
200 }
201
204 inline void pretty_print(std::ostream &os) const noexcept override {
205 os << name() << "(\n"
206 << "west = " << side<west>() << "\n"
207 << "east = " << side<east>() << "\n)";
208 }
209
212 inline nlohmann::json to_json() const override {
213 nlohmann::json json;
214 json["west"] = side<west>().to_json();
215 json["east"] = side<east>().to_json();
216
217 return json;
218 }
219
223 inline BoundaryCore &from_json(const nlohmann::json &json) {
224 side<west>().from_json(json["west"]);
225 side<east>().from_json(json["east"]);
226
227 return *this;
228 }
229
232 inline eval_type greville() const {
233 return eval_type{side<west>().greville(), side<east>().greville()};
234 }
235};
236
244template <typename Spline>
245 requires SplineType<Spline>
246class BoundaryCore<Spline, /* parDim */ 2> : public utils::Serializable,
248
250 template <typename BoundaryCore> friend class BoundaryCommon;
251
252protected:
254 using spline_type = Spline;
255
257 using boundary_spline_type = std::tuple<
258 typename Spline::template derived_self_type<
259 typename Spline::value_type, Spline::geoDim(), Spline::degree(1)>,
260 typename Spline::template derived_self_type<
261 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>;
262
265 template <typename real_t>
267 std::tuple<typename Spline::template derived_self_type<
268 real_t, Spline::geoDim(), Spline::degree(1)>,
269 typename Spline::template derived_self_type<
270 real_t, Spline::geoDim(), Spline::degree(0)>>;
271
273 std::tuple<std::tuple_element_t<0, boundary_spline_type>,
274 std::tuple_element_t<0, boundary_spline_type>,
275 std::tuple_element_t<1, boundary_spline_type>,
276 std::tuple_element_t<1, boundary_spline_type>>
278
279public:
281 using value_type = Spline::value_type;
282
284 using boundary_type = decltype(bdr_);
285
287 using eval_type = std::tuple<utils::TensorArray<1>, utils::TensorArray<1>,
289
294 : bdr_({std::tuple_element_t<0, boundary_spline_type>(options),
295 std::tuple_element_t<0, boundary_spline_type>(options),
296 std::tuple_element_t<1, boundary_spline_type>(options),
297 std::tuple_element_t<1, boundary_spline_type>(options)}) {}
298
301 explicit BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
302
305 explicit BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
306
310 BoundaryCore(const BoundaryCore &other, bool clone)
311 : bdr_(clone ? std::apply(
312 [](const auto &...bspline) {
313 return std::make_tuple(bspline.clone()...);
314 },
315 other.sides())
316 : other.sides()) {}
317
322 explicit BoundaryCore(const std::array<int64_t, 2> &ncoeffs,
323 enum init init = init::zeros,
326 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
327 std::array<int64_t, 1>({ncoeffs[1]}), init, options),
328 std::tuple_element_t<0, boundary_spline_type>(
329 std::array<int64_t, 1>({ncoeffs[1]}), init, options),
330 std::tuple_element_t<1, boundary_spline_type>(
331 std::array<int64_t, 1>({ncoeffs[0]}), init, options),
332 std::tuple_element_t<1, boundary_spline_type>(
333 std::array<int64_t, 1>({ncoeffs[0]}), init, options)}) {}
334
339 explicit BoundaryCore(
340 const std::array<std::vector<typename Spline::value_type>, 2> &kv,
341 enum init init = init::zeros,
344 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
345 std::array<std::vector<typename Spline::value_type>, 1>(
346 {kv[1]}),
347 init, options),
348 std::tuple_element_t<0, boundary_spline_type>(
349 std::array<std::vector<typename Spline::value_type>, 1>(
350 {kv[1]}),
351 init, options),
352 std::tuple_element_t<1, boundary_spline_type>(
353 std::array<std::vector<typename Spline::value_type>, 1>(
354 {kv[0]}),
355 init, options),
356 std::tuple_element_t<1, boundary_spline_type>(
357 std::array<std::vector<typename Spline::value_type>, 1>(
358 {kv[0]}),
359 init, options)}) {}
360
362 ~BoundaryCore() override = default;
363
370 inline auto &from_full_tensor(const torch::Tensor &tensor) {
371
372 if (tensor.dim() > 1) {
373 auto tensor_view =
374 tensor.view({-1, side<west>().ncoeffs(0), side<south>().ncoeffs(0),
375 tensor.size(-1)});
376
377 side<west>().from_tensor(
378 tensor_view
379 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0})
380 .reshape({-1, tensor.size(-1)}));
381 side<east>().from_tensor(
382 tensor_view
383 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1})
384 .reshape({-1, tensor.size(-1)}));
385 side<south>().from_tensor(
386 tensor_view
387 .index({torch::indexing::Slice(), 0, torch::indexing::Slice()})
388 .reshape({-1, tensor.size(-1)}));
389 side<north>().from_tensor(
390 tensor_view
391 .index({torch::indexing::Slice(), -1, torch::indexing::Slice()})
392 .reshape({-1, tensor.size(-1)}));
393 } else {
394 auto tensor_view =
395 tensor.view({-1, side<west>().ncoeffs(0), side<south>().ncoeffs(0)});
396
397 side<west>().from_tensor(
398 tensor_view
399 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0})
400 .flatten());
401 side<east>().from_tensor(
402 tensor_view
403 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1})
404 .flatten());
405 side<south>().from_tensor(
406 tensor_view
407 .index({torch::indexing::Slice(), 0, torch::indexing::Slice()})
408 .flatten());
409 side<north>().from_tensor(
410 tensor_view
411 .index({torch::indexing::Slice(), -1, torch::indexing::Slice()})
412 .flatten());
413 }
414 return *this;
415 }
416
419 inline static constexpr short_t nsides() { return side::north; }
420
424 template <short_t s> inline constexpr auto &side() const {
425 static_assert(s > none && s <= nsides());
426 return std::get<s - 1>(bdr_);
427 }
428
432 template <short_t s> inline constexpr auto &side() {
433 static_assert(s > none && s <= nsides());
434 return std::get<s - 1>(bdr_);
435 }
436
439 inline constexpr auto &sides() const { return bdr_; }
440
443 inline constexpr auto &sides() { return bdr_; }
444
447 inline int64_t ncumcoeffs() const {
448 int64_t s = 0;
449 s += side<west>().ncumcoeffs();
450 s += side<east>().ncumcoeffs();
451 s += side<south>().ncumcoeffs();
452 s += side<north>().ncumcoeffs();
453
454 return s;
455 }
456
459 inline void pretty_print(std::ostream &os) const noexcept override {
460 os << name() << "(\n"
461 << "west = " << side<west>() << "\n"
462 << "east = " << side<east>() << "\n"
463 << "south = " << side<south>() << "\n"
464 << "north = " << side<north>() << "\n)";
465 }
466
469 inline nlohmann::json to_json() const override {
470 nlohmann::json json;
471 json["west"] = side<west>().to_json();
472 json["east"] = side<east>().to_json();
473 json["south"] = side<south>().to_json();
474 json["north"] = side<north>().to_json();
475
476 return json;
477 }
478
482 inline BoundaryCore &from_json(const nlohmann::json &json) {
483 side<west>().from_json(json["west"]);
484 side<east>().from_json(json["east"]);
485 side<south>().from_json(json["south"]);
486 side<north>().from_json(json["north"]);
487
488 return *this;
489 }
490
493 inline eval_type greville() const {
494 return eval_type{side<west>().greville(), side<east>().greville(),
495 side<south>().greville(), side<north>().greville()};
496 }
497};
498
508template <typename Spline>
509 requires SplineType<Spline>
510class BoundaryCore<Spline, /* parDim */ 3> : public utils::Serializable,
512
514 template <typename BoundaryCore> friend class BoundaryCommon;
515
516protected:
518 using spline_type = Spline;
519
522 std::tuple<typename Spline::template derived_self_type<
523 typename Spline::value_type, Spline::geoDim(),
524 Spline::degree(1), Spline::degree(2)>,
525 typename Spline::template derived_self_type<
526 typename Spline::value_type, Spline::geoDim(),
527 Spline::degree(0), Spline::degree(2)>,
528 typename Spline::template derived_self_type<
529 typename Spline::value_type, Spline::geoDim(),
530 Spline::degree(0), Spline::degree(1)>>;
531
534 template <typename real_t>
536 typename Spline::template derived_self_type<
537 real_t, Spline::geoDim(), Spline::degree(1), Spline::degree(2)>,
538 typename Spline::template derived_self_type<
539 real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(2)>,
540 typename Spline::template derived_self_type<
541 real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(1)>>;
542
544 std::tuple<std::tuple_element_t<0, boundary_spline_type>,
545 std::tuple_element_t<0, boundary_spline_type>,
546 std::tuple_element_t<1, boundary_spline_type>,
547 std::tuple_element_t<1, boundary_spline_type>,
548 std::tuple_element_t<2, boundary_spline_type>,
549 std::tuple_element_t<2, boundary_spline_type>>
551
552public:
554 using value_type = Spline::value_type;
555
557 using boundary_type = decltype(bdr_);
558
560 using eval_type = std::tuple<utils::TensorArray<2>, utils::TensorArray<2>,
563
568 : bdr_({std::tuple_element_t<0, boundary_spline_type>(options),
569 std::tuple_element_t<0, boundary_spline_type>(options),
570 std::tuple_element_t<1, boundary_spline_type>(options),
571 std::tuple_element_t<1, boundary_spline_type>(options),
572 std::tuple_element_t<2, boundary_spline_type>(options),
573 std::tuple_element_t<2, boundary_spline_type>(options)}) {}
574
577 explicit BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
578
581 explicit BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
582
586 BoundaryCore(const BoundaryCore &other, bool clone)
587 : bdr_(clone ? std::apply(
588 [](const auto &...bspline) {
589 return std::make_tuple(bspline.clone()...);
590 },
591 other.sides())
592 : other.sides()) {}
593
598 explicit BoundaryCore(const std::array<int64_t, 3> &ncoeffs,
599 enum init init = init::zeros,
602 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
603 std::array<int64_t, 2>({ncoeffs[1], ncoeffs[2]}), init,
604 options),
605 std::tuple_element_t<0, boundary_spline_type>(
606 std::array<int64_t, 2>({ncoeffs[1], ncoeffs[2]}), init,
607 options),
608 std::tuple_element_t<1, boundary_spline_type>(
609 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[2]}), init,
610 options),
611 std::tuple_element_t<1, boundary_spline_type>(
612 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[2]}), init,
613 options),
614 std::tuple_element_t<2, boundary_spline_type>(
615 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[1]}), init,
616 options),
617 std::tuple_element_t<2, boundary_spline_type>(
618 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[1]}), init,
619 options)}) {}
620
625 explicit BoundaryCore(
626 const std::array<std::vector<typename Spline::value_type>, 3> &kv,
627 enum init init = init::zeros,
630 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
631 std::array<std::vector<typename Spline::value_type>, 2>(
632 {kv[1], kv[2]}),
633 init, options),
634 std::tuple_element_t<0, boundary_spline_type>(
635 std::array<std::vector<typename Spline::value_type>, 2>(
636 {kv[1], kv[2]}),
637 init, options),
638 std::tuple_element_t<1, boundary_spline_type>(
639 std::array<std::vector<typename Spline::value_type>, 2>(
640 {kv[0], kv[2]}),
641 init, options),
642 std::tuple_element_t<1, boundary_spline_type>(
643 std::array<std::vector<typename Spline::value_type>, 2>(
644 {kv[0], kv[2]}),
645 init, options),
646 std::tuple_element_t<2, boundary_spline_type>(
647 std::array<std::vector<typename Spline::value_type>, 2>(
648 {kv[0], kv[1]}),
649 init, options),
650 std::tuple_element_t<2, boundary_spline_type>(
651 std::array<std::vector<typename Spline::value_type>, 2>(
652 {kv[0], kv[1]}),
653 init, options)}) {}
654
656 ~BoundaryCore() override = default;
657
664 inline auto &from_full_tensor(const torch::Tensor &tensor) {
665
666 if (tensor.dim() > 1) {
667 auto tensor_view =
668 tensor.view({-1, side<west>().ncoeffs(1), side<west>().ncoeffs(0),
669 side<south>().ncoeffs(0), tensor.size(-1)});
670
671 side<west>().from_tensor(
672 tensor_view
673 .index({torch::indexing::Slice(), torch::indexing::Slice(),
674 torch::indexing::Slice(), 0})
675 .reshape({-1, tensor.size(-1)}));
676 side<east>().from_tensor(
677 tensor_view
678 .index({torch::indexing::Slice(), torch::indexing::Slice(),
679 torch::indexing::Slice(), -1})
680 .reshape({-1, tensor.size(-1)}));
681 side<south>().from_tensor(
682 tensor_view
683 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
684 torch::indexing::Slice()})
685 .reshape({-1, tensor.size(-1)}));
686 side<north>().from_tensor(
687 tensor_view
688 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
689 torch::indexing::Slice()})
690 .reshape({-1, tensor.size(-1)}));
691 side<front>().from_tensor(
692 tensor_view
693 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
694 torch::indexing::Slice()})
695 .reshape({-1, tensor.size(-1)}));
696 side<back>().from_tensor(
697 tensor_view
698 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
699 torch::indexing::Slice()})
700 .reshape({-1, tensor.size(-1)}));
701 } else {
702 auto tensor_view =
703 tensor.view({-1, side<west>().ncoeffs(1), side<west>().ncoeffs(0),
704 side<south>().ncoeffs(0)});
705
706 side<west>().from_tensor(
707 tensor_view
708 .index({torch::indexing::Slice(), torch::indexing::Slice(),
709 torch::indexing::Slice(), 0})
710 .flatten());
711 side<east>().from_tensor(
712 tensor_view
713 .index({torch::indexing::Slice(), torch::indexing::Slice(),
714 torch::indexing::Slice(), -1})
715 .flatten());
716
717 side<south>().from_tensor(
718 tensor_view
719 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
720 torch::indexing::Slice()})
721 .flatten());
722 side<north>().from_tensor(
723 tensor_view
724 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
725 torch::indexing::Slice()})
726 .flatten());
727
728 side<front>().from_tensor(
729 tensor_view
730 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
731 torch::indexing::Slice()})
732 .flatten());
733 side<back>().from_tensor(
734 tensor_view
735 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
736 torch::indexing::Slice()})
737 .flatten());
738 }
739 return *this;
740 }
741
744 inline static constexpr short_t nsides() { return side::back; }
745
749 template <short_t s> inline constexpr auto &side() const {
750 static_assert(s > none && s <= nsides());
751 return std::get<s - 1>(bdr_);
752 }
753
757 template <short_t s> inline constexpr auto &side() {
758 static_assert(s > none && s <= nsides());
759 return std::get<s - 1>(bdr_);
760 }
761
764 inline constexpr auto &sides() const { return bdr_; }
765
768 inline constexpr auto &sides() { return bdr_; }
769
772 inline int64_t ncumcoeffs() const {
773 int64_t s = 0;
774 s += side<west>().ncumcoeffs();
775 s += side<east>().ncumcoeffs();
776 s += side<south>().ncumcoeffs();
777 s += side<north>().ncumcoeffs();
778 s += side<front>().ncumcoeffs();
779 s += side<back>().ncumcoeffs();
780
781 return s;
782 }
783
786 inline void pretty_print(std::ostream &os) const noexcept override {
787 os << name() << "(\n"
788 << "west = " << side<west>() << "\n"
789 << "east = " << side<east>() << "\n"
790 << "south = " << side<south>() << "\n"
791 << "north = " << side<north>() << "\n"
792 << "front = " << side<front>() << "\n"
793 << "back = " << side<back>() << "\n)";
794 }
795
798 inline nlohmann::json to_json() const override {
799 nlohmann::json json;
800 json["west"] = side<west>().to_json();
801 json["east"] = side<east>().to_json();
802 json["south"] = side<south>().to_json();
803 json["north"] = side<north>().to_json();
804 json["front"] = side<front>().to_json();
805 json["back"] = side<back>().to_json();
806
807 return json;
808 }
809
813 inline BoundaryCore &from_json(const nlohmann::json &json) {
814 side<west>().from_json(json["west"]);
815 side<east>().from_json(json["east"]);
816 side<south>().from_json(json["south"]);
817 side<north>().from_json(json["north"]);
818 side<front>().from_json(json["front"]);
819 side<back>().from_json(json["back"]);
820
821 return *this;
822 }
823
826 inline eval_type greville() const {
827 return eval_type{side<west>().greville(), side<east>().greville(),
828 side<south>().greville(), side<north>().greville(),
829 side<front>().greville(), side<back>().greville()};
830 }
831};
832
844template <typename Spline>
845 requires SplineType<Spline>
846class BoundaryCore<Spline, /* parDim */ 4> : public utils::Serializable,
848
850 template <typename BoundaryCore> friend class BoundaryCommon;
851
852protected:
854 using spline_type = Spline;
855
858 std::tuple<typename Spline::template derived_self_type<
859 typename Spline::value_type, Spline::geoDim(),
860 Spline::degree(1), Spline::degree(2), Spline::degree(3)>,
861 typename Spline::template derived_self_type<
862 typename Spline::value_type, Spline::geoDim(),
863 Spline::degree(0), Spline::degree(2), Spline::degree(3)>,
864 typename Spline::template derived_self_type<
865 typename Spline::value_type, Spline::geoDim(),
866 Spline::degree(0), Spline::degree(1), Spline::degree(3)>,
867 typename Spline::template derived_self_type<
868 typename Spline::value_type, Spline::geoDim(),
869 Spline::degree(0), Spline::degree(1), Spline::degree(2)>>;
870
873 template <typename real_t>
875 std::tuple<typename Spline::template derived_self_type<
876 real_t, Spline::geoDim(), Spline::degree(1),
877 Spline::degree(2), Spline::degree(3)>,
878 typename Spline::template derived_self_type<
879 real_t, Spline::geoDim(), Spline::degree(0),
880 Spline::degree(2), Spline::degree(3)>,
881 typename Spline::template derived_self_type<
882 real_t, Spline::geoDim(), Spline::degree(0),
883 Spline::degree(1), Spline::degree(3)>,
884 typename Spline::template derived_self_type<
885 real_t, Spline::geoDim(), Spline::degree(0),
886 Spline::degree(1), Spline::degree(2)>>;
887
889 std::tuple<std::tuple_element_t<0, boundary_spline_type>,
890 std::tuple_element_t<0, boundary_spline_type>,
891 std::tuple_element_t<1, boundary_spline_type>,
892 std::tuple_element_t<1, boundary_spline_type>,
893 std::tuple_element_t<2, boundary_spline_type>,
894 std::tuple_element_t<2, boundary_spline_type>,
895 std::tuple_element_t<3, boundary_spline_type>,
896 std::tuple_element_t<3, boundary_spline_type>>
898
899public:
901 using value_type = Spline::value_type;
902
904 using boundary_type = decltype(bdr_);
905
907 using eval_type = std::tuple<utils::TensorArray<3>, utils::TensorArray<3>,
911
916 : bdr_({std::tuple_element_t<0, boundary_spline_type>(options),
917 std::tuple_element_t<0, boundary_spline_type>(options),
918 std::tuple_element_t<1, boundary_spline_type>(options),
919 std::tuple_element_t<1, boundary_spline_type>(options),
920 std::tuple_element_t<2, boundary_spline_type>(options),
921 std::tuple_element_t<2, boundary_spline_type>(options),
922 std::tuple_element_t<3, boundary_spline_type>(options),
923 std::tuple_element_t<3, boundary_spline_type>(options)}) {}
924
927 explicit BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
928
931 explicit BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
932
936 BoundaryCore(const BoundaryCore &other, bool clone)
937 : bdr_(clone ? std::apply(
938 [](const auto &...bspline) {
939 return std::make_tuple(bspline.clone()...);
940 },
941 other.sides())
942 : other.sides()) {}
943
948 explicit BoundaryCore(const std::array<int64_t, 4> &ncoeffs,
949 enum init init = init::zeros,
952 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
953 std::array<int64_t, 3>({ncoeffs[1], ncoeffs[2], ncoeffs[3]}),
954 init, options),
955 std::tuple_element_t<0, boundary_spline_type>(
956 std::array<int64_t, 3>({ncoeffs[1], ncoeffs[2], ncoeffs[3]}),
957 init, options),
958 std::tuple_element_t<1, boundary_spline_type>(
959 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[2], ncoeffs[3]}),
960 init, options),
961 std::tuple_element_t<1, boundary_spline_type>(
962 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[2], ncoeffs[3]}),
963 init, options),
964 std::tuple_element_t<2, boundary_spline_type>(
965 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[3]}),
966 init, options),
967 std::tuple_element_t<2, boundary_spline_type>(
968 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[3]}),
969 init, options),
970 std::tuple_element_t<3, boundary_spline_type>(
971 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[2]}),
972 init, options),
973 std::tuple_element_t<3, boundary_spline_type>(
974 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[2]}),
975 init, options)}) {}
976
981 explicit BoundaryCore(
982 const std::array<std::vector<typename Spline::value_type>, 4> &kv,
983 enum init init = init::zeros,
986 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
987 std::array<std::vector<typename Spline::value_type>, 3>(
988 {kv[1], kv[2], kv[3]}),
989 init, options),
990 std::tuple_element_t<0, boundary_spline_type>(
991 std::array<std::vector<typename Spline::value_type>, 3>(
992 {kv[1], kv[2], kv[3]}),
993 init, options),
994 std::tuple_element_t<1, boundary_spline_type>(
995 std::array<std::vector<typename Spline::value_type>, 3>(
996 {kv[0], kv[2], kv[3]}),
997 init, options),
998 std::tuple_element_t<1, boundary_spline_type>(
999 std::array<std::vector<typename Spline::value_type>, 3>(
1000 {kv[0], kv[2], kv[3]}),
1001 init, options),
1002 std::tuple_element_t<2, boundary_spline_type>(
1003 std::array<std::vector<typename Spline::value_type>, 3>(
1004 {kv[0], kv[1], kv[3]}),
1005 init, options),
1006 std::tuple_element_t<2, boundary_spline_type>(
1007 std::array<std::vector<typename Spline::value_type>, 3>(
1008 {kv[0], kv[1], kv[3]}),
1009 init, options),
1010 std::tuple_element_t<3, boundary_spline_type>(
1011 std::array<std::vector<typename Spline::value_type>, 3>(
1012 {kv[0], kv[1], kv[2]}),
1013 init, options),
1014 std::tuple_element_t<3, boundary_spline_type>(
1015 std::array<std::vector<typename Spline::value_type>, 3>(
1016 {kv[0], kv[1], kv[2]}),
1017 init, options)}) {}
1018
1020 ~BoundaryCore() override = default;
1021
1028 inline auto &from_full_tensor(const torch::Tensor &tensor) {
1029
1030 if (tensor.dim() > 1) {
1031 auto tensor_view = tensor.view(
1032 {-1, side<west>().ncoeffs(2), side<west>().ncoeffs(1),
1033 side<west>().ncoeffs(0), side<south>().ncoeffs(0), tensor.size(-1)});
1034
1035 side<west>().from_tensor(
1036 tensor_view
1037 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1038 torch::indexing::Slice(), torch::indexing::Slice(), 0})
1039 .reshape({-1, tensor.size(-1)}));
1040 side<east>().from_tensor(
1041 tensor_view
1042 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1043 torch::indexing::Slice(), torch::indexing::Slice(), -1})
1044 .reshape({-1, tensor.size(-1)}));
1045 side<south>().from_tensor(
1046 tensor_view
1047 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1048 torch::indexing::Slice(), 0, torch::indexing::Slice()})
1049 .reshape({-1, tensor.size(-1)}));
1050 side<north>().from_tensor(
1051 tensor_view
1052 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1053 torch::indexing::Slice(), -1, torch::indexing::Slice()})
1054 .reshape({-1, tensor.size(-1)}));
1055 side<front>().from_tensor(
1056 tensor_view
1057 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
1058 torch::indexing::Slice(), torch::indexing::Slice()})
1059 .reshape({-1, tensor.size(-1)}));
1060 side<back>().from_tensor(
1061 tensor_view
1062 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
1063 torch::indexing::Slice(), torch::indexing::Slice()})
1064 .reshape({-1, tensor.size(-1)}));
1065 side<stime>().from_tensor(
1066 tensor_view
1067 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
1068 torch::indexing::Slice(), torch::indexing::Slice()})
1069 .reshape({-1, tensor.size(-1)}));
1070 side<etime>().from_tensor(
1071 tensor_view
1072 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
1073 torch::indexing::Slice(), torch::indexing::Slice()})
1074 .reshape({-1, tensor.size(-1)}));
1075 } else {
1076 auto tensor_view =
1077 tensor.view({-1, side<west>().ncoeffs(2), side<west>().ncoeffs(1),
1078 side<west>().ncoeffs(0), side<south>().ncoeffs(0)});
1079
1080 side<west>().from_tensor(
1081 tensor_view
1082 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1083 torch::indexing::Slice(), torch::indexing::Slice(), 0})
1084 .flatten());
1085 side<east>().from_tensor(
1086 tensor_view
1087 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1088 torch::indexing::Slice(), torch::indexing::Slice(), -1})
1089 .flatten());
1090
1091 side<south>().from_tensor(
1092 tensor_view
1093 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1094 torch::indexing::Slice(), 0, torch::indexing::Slice()})
1095 .flatten());
1096 side<north>().from_tensor(
1097 tensor_view
1098 .index({torch::indexing::Slice(), torch::indexing::Slice(),
1099 torch::indexing::Slice(), -1, torch::indexing::Slice()})
1100 .flatten());
1101
1102 side<front>().from_tensor(
1103 tensor_view
1104 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
1105 torch::indexing::Slice(), torch::indexing::Slice()})
1106 .flatten());
1107 side<back>().from_tensor(
1108 tensor_view
1109 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
1110 torch::indexing::Slice(), torch::indexing::Slice()})
1111 .flatten());
1112
1113 side<stime>().from_tensor(
1114 tensor_view
1115 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
1116 torch::indexing::Slice(), torch::indexing::Slice()})
1117 .flatten());
1118 side<etime>().from_tensor(
1119 tensor_view
1120 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
1121 torch::indexing::Slice(), torch::indexing::Slice()})
1122 .flatten());
1123 }
1124 return *this;
1125 }
1126
1129 inline static constexpr short_t nsides() { return side::etime; }
1130
1134 template <short_t s> inline constexpr auto &side() const {
1135 static_assert(s > none && s <= nsides());
1136 return std::get<s - 1>(bdr_);
1137 }
1138
1142 template <short_t s> inline constexpr auto &side() {
1143 static_assert(s > none && s <= nsides());
1144 return std::get<s - 1>(bdr_);
1145 }
1146
1149 inline constexpr auto &sides() const { return bdr_; }
1150
1153 inline constexpr auto &ides() { return bdr_; }
1154
1157 inline int64_t ncumcoeffs() const {
1158 int64_t s = 0;
1159 s += side<west>().ncumcoeffs();
1160 s += side<east>().ncumcoeffs();
1161 s += side<south>().ncumcoeffs();
1162 s += side<north>().ncumcoeffs();
1163 s += side<front>().ncumcoeffs();
1164 s += side<back>().ncumcoeffs();
1165 s += side<stime>().ncumcoeffs();
1166 s += side<etime>().ncumcoeffs();
1167
1168 return s;
1169 }
1170
1173 inline void pretty_print(std::ostream &os) const noexcept override {
1174 os << name() << "(\n"
1175 << "west = " << side<west>() << "\n"
1176 << "east = " << side<east>() << "\n"
1177 << "south = " << side<south>() << "\n"
1178 << "north = " << side<north>() << "\n"
1179 << "front = " << side<front>() << "\n"
1180 << "back = " << side<back>() << "\n"
1181 << "stime = " << side<stime>() << "\n"
1182 << "etime = " << side<etime>() << "\n)";
1183 }
1184
1187 inline nlohmann::json to_json() const override {
1188 nlohmann::json json;
1189 json["west"] = side<west>().to_json();
1190 json["east"] = side<east>().to_json();
1191 json["south"] = side<south>().to_json();
1192 json["north"] = side<north>().to_json();
1193 json["front"] = side<front>().to_json();
1194 json["back"] = side<back>().to_json();
1195 json["stime"] = side<stime>().to_json();
1196 json["etime"] = side<etime>().to_json();
1197
1198 return json;
1199 }
1200
1204 inline BoundaryCore &from_json(const nlohmann::json &json) {
1205 side<west>().from_json(json["west"]);
1206 side<east>().from_json(json["east"]);
1207 side<south>().from_json(json["south"]);
1208 side<north>().from_json(json["north"]);
1209 side<front>().from_json(json["front"]);
1210 side<back>().from_json(json["back"]);
1211 side<stime>().from_json(json["stime"]);
1212 side<etime>().from_json(json["etime"]);
1213
1214 return *this;
1215 }
1216
1219 inline eval_type greville() const {
1220 return eval_type{side<west>().greville(), side<east>().greville(),
1221 side<south>().greville(), side<north>().greville(),
1222 side<front>().greville(), side<back>().greville(),
1223 side<stime>().greville(), side<etime>().greville()};
1224 }
1225};
1226
1228class Boundary_ {};
1229
1232template <typename T>
1233concept BoundaryType = std::is_base_of_v<Boundary_, T>;
1234
1236template <typename BoundaryCore>
1237class BoundaryCommon : public Boundary_, public BoundaryCore {
1238public:
1240 using BoundaryCore::BoundaryCore;
1241
1244 BoundaryCommon clone() const { return BoundaryCommon(*this); }
1245
1246private:
1251 template <std::size_t... Is>
1252 inline torch::Tensor as_tensor_(std::index_sequence<Is...>) const {
1253 return torch::cat({std::get<Is>(BoundaryCore::bdr_).as_tensor()...});
1254 }
1255
1256public:
1261 [[nodiscard]] inline torch::Tensor as_tensor() const {
1262 return as_tensor_(std::make_index_sequence<BoundaryCore::nsides()>{});
1263 }
1264
1265private:
1270 template <std::size_t... Is>
1271 inline int64_t as_tensor_size_(std::index_sequence<Is...>) const {
1272 return std::apply(
1273 [](auto... size) { return (size + ...); },
1274 std::make_tuple(std::get<Is>(BoundaryCore::bdr_).as_tensor_size()...));
1275 }
1276
1277public:
1280 //
1282 [[nodiscard]] inline int64_t as_tensor_size() const {
1283 return as_tensor_size_(std::make_index_sequence<BoundaryCore::nsides()>{});
1284 }
1285
1286private:
1293 template <std::size_t... Is>
1294 inline auto &from_tensor_(std::index_sequence<Is...>,
1295 const torch::Tensor &tensor) {
1296
1297 std::size_t start(0);
1298 auto end = [&start](std::size_t inc) { return start += inc; };
1299
1300 (std::get<Is>(BoundaryCore::bdr_)
1301 .from_tensor(tensor.index({torch::indexing::Slice(
1302 start, end(std::get<Is>(BoundaryCore::bdr_).ncumcoeffs() *
1303 std::get<Is>(BoundaryCore::bdr_).geoDim()))})),
1304 ...);
1305
1306 return *this;
1307 }
1308
1309public:
1316 inline auto &from_tensor(const torch::Tensor &tensor) {
1317 return from_tensor_(std::make_index_sequence<BoundaryCore::nsides()>{},
1318 tensor);
1319 }
1320
1321private:
1324 template <deriv deriv = deriv::func, bool memory_optimized = false,
1325 size_t... Is, typename... Xi>
1326 inline auto eval_(std::index_sequence<Is...>,
1327 const std::tuple<Xi...> &xi) const {
1328 return std::tuple(
1329 std::get<Is>(BoundaryCore::bdr_)
1330 .template eval<deriv, memory_optimized>(std::get<Is>(xi))...);
1331 }
1332
1333 template <deriv deriv = deriv::func, bool memory_optimized = false,
1334 size_t... Is, typename... Xi, typename... Indices>
1335 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
1336 const std::tuple<Indices...> &indices) const {
1337 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1338 .template eval<deriv, memory_optimized>(
1339 std::get<Is>(xi), std::get<Is>(indices))...);
1340 }
1341
1342 template <deriv deriv = deriv::func, bool memory_optimized = false,
1343 size_t... Is, typename... Xi, typename... Indices,
1344 typename... Coeff_Indices>
1345 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
1346 const std::tuple<Indices...> &indices,
1347 const std::tuple<Coeff_Indices...> &coeff_indices) const {
1348 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1349 .template eval<deriv, memory_optimized>(
1350 std::get<Is>(xi), std::get<Is>(indices),
1351 std::get<Is>(coeff_indices))...);
1352 }
1354
1355public:
1360 template <deriv deriv = deriv::func, bool memory_optimized = false,
1361 typename... Xi>
1362 inline auto eval(const std::tuple<Xi...> &xi) const {
1363 return eval_<deriv, memory_optimized>(
1364 std::make_index_sequence<BoundaryCore::nsides()>{}, xi);
1365 }
1366
1371 template <deriv deriv = deriv::func, bool memory_optimized = false,
1372 typename... Xi, typename... Indices>
1373 inline auto eval(const std::tuple<Xi...> &xi,
1374 const std::tuple<Indices...> &indices) const {
1375 static_assert(sizeof...(Xi) == sizeof...(Indices));
1376 return eval_<deriv, memory_optimized>(
1377 std::make_index_sequence<BoundaryCore::nsides()>{}, xi, indices);
1378 }
1379
1385 template <deriv deriv = deriv::func, bool memory_optimized = false,
1386 typename... Xi, typename... Indices, typename... Coeff_Indices>
1387 inline auto eval(const std::tuple<Xi...> &xi,
1388 const std::tuple<Indices...> &indices,
1389 const std::tuple<Coeff_Indices...> &coeff_indices) const {
1390 static_assert(sizeof...(Xi) == sizeof...(Indices) &&
1391 sizeof...(Xi) == sizeof...(Coeff_Indices));
1392 return eval_<deriv, memory_optimized>(
1393 std::make_index_sequence<BoundaryCore::nsides()>{}, xi, indices,
1394 coeff_indices);
1395 }
1397
1398private:
1401 template <size_t... Is, typename... Basfunc, typename... Coeff_Indices,
1402 typename... Numeval, typename... Sizes>
1403 inline auto
1404 eval_from_precomputed_(std::index_sequence<Is...>,
1405 const std::tuple<Basfunc...> &basfunc,
1406 const std::tuple<Coeff_Indices...> &coeff_indices,
1407 const std::tuple<Numeval...> &numeval,
1408 const std::tuple<Sizes...> &sizes) const {
1409 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1410 .eval_from_precomputed(std::get<Is>(basfunc),
1411 std::get<Is>(coeff_indices),
1412 std::get<Is>(numeval),
1413 std::get<Is>(sizes))...);
1414 }
1415
1416 template <size_t... Is, typename... Basfunc, typename... Coeff_Indices,
1417 typename... Xi>
1418 inline auto
1419 eval_from_precomputed_(std::index_sequence<Is...>,
1420 const std::tuple<Basfunc...> &basfunc,
1421 const std::tuple<Coeff_Indices...> &coeff_indices,
1422 const std::tuple<Xi...> &xi) const {
1423 return std::tuple(
1424 std::get<Is>(BoundaryCore::bdr_)
1426 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
1427 std::get<Is>(xi)[0].numel(), std::get<Is>(xi)[0].sizes())...);
1428 }
1430
1431public:
1439 template <typename... Basfunc, typename... Coeff_Indices, typename... Numeval,
1440 typename... Sizes>
1441 inline auto
1442 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
1443 const std::tuple<Coeff_Indices...> &coeff_indices,
1444 const std::tuple<Numeval...> &numeval,
1445 const std::tuple<Sizes...> &sizes) const {
1446 static_assert(sizeof...(Basfunc) == sizeof...(Coeff_Indices) &&
1447 sizeof...(Basfunc) == sizeof...(Numeval) &&
1448 sizeof...(Basfunc) == sizeof...(Sizes));
1450 std::make_index_sequence<BoundaryCore::nsides()>{}, basfunc,
1451 coeff_indices, numeval, sizes);
1452 }
1453
1462 template <typename... Basfunc, typename... Coeff_Indices, typename... Xi>
1463 inline auto
1464 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
1465 const std::tuple<Coeff_Indices...> &coeff_indices,
1466 const std::tuple<Xi...> &xi) const {
1467 static_assert(sizeof...(Basfunc) == sizeof...(Coeff_Indices) &&
1468 sizeof...(Basfunc) == sizeof...(Xi));
1470 std::make_index_sequence<BoundaryCore::nsides()>{}, basfunc,
1471 coeff_indices, xi);
1472 }
1474
1475private:
1478 template <size_t... Is, typename... Xi>
1479 inline auto find_knot_indices_(std::index_sequence<Is...>,
1480 const std::tuple<Xi...> &xi) const {
1481 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1482 .find_knot_indices(std::get<Is>(xi))...);
1483 }
1484
1485public:
1490 template <typename... Xi>
1491 inline auto find_knot_indices(const std::tuple<Xi...> &xi) const {
1492 return find_knot_indices_(
1493 std::make_index_sequence<BoundaryCore::nsides()>{}, xi);
1494 }
1495
1496private:
1500 template <deriv deriv = deriv::func, bool memory_optimized = false,
1501 size_t... Is, typename... Xi>
1502 inline auto eval_basfunc_(std::index_sequence<Is...>,
1503 const std::tuple<Xi...> &xi) const {
1504 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1505 .template eval_basfunc<deriv, memory_optimized>(
1506 std::get<Is>(xi))...);
1507 }
1508
1509 template <deriv deriv = deriv::func, bool memory_optimized = false,
1510 size_t... Is, typename... Xi, typename... Indices>
1511 inline auto eval_basfunc_(std::index_sequence<Is...>,
1512 const std::tuple<Xi...> &xi,
1513 const std::tuple<Indices...> &indices) const {
1514 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1515 .template eval_basfunc<deriv, memory_optimized>(
1516 std::get<Is>(xi), std::get<Is>(indices))...);
1517 }
1519
1520public:
1525 template <deriv deriv = deriv::func, bool memory_optimized = false,
1526 typename... Xi>
1527 inline auto eval_basfunc(const std::tuple<Xi...> &xi) const {
1528 return eval_basfunc_<deriv, memory_optimized>(
1529 std::make_index_sequence<BoundaryCore::nsides()>{}, xi);
1530 }
1531
1536 template <deriv deriv = deriv::func, bool memory_optimized = false,
1537 typename... Xi, typename... Indices>
1538 inline auto eval_basfunc(const std::tuple<Xi...> &xi,
1539 const std::tuple<Indices...> &indices) const {
1540 static_assert(sizeof...(Xi) == sizeof...(Indices));
1541 return eval_basfunc_<deriv, memory_optimized>(
1542 std::make_index_sequence<BoundaryCore::nsides()>{}, xi, indices);
1543 }
1545
1546private:
1549 template <bool memory_optimized = false, size_t... Is, typename... Indices>
1550 inline auto find_coeff_indices_(std::index_sequence<Is...>,
1551 const std::tuple<Indices...> &indices) const {
1552 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1553 .template find_coeff_indices<memory_optimized>(
1554 std::get<Is>(indices))...);
1555 }
1556
1557public:
1564 template <bool memory_optimized = false, typename... Indices>
1565 inline auto find_coeff_indices(const std::tuple<Indices...> &indices) const {
1566 return find_coeff_indices_<memory_optimized>(
1567 std::make_index_sequence<BoundaryCore::nsides()>{}, indices);
1568 }
1569
1570private:
1573 template <size_t... Is>
1574 inline auto &uniform_refine_(std::index_sequence<Is...>, int numRefine = 1,
1575 int dim = -1) {
1576 (std::get<Is>(BoundaryCore::bdr_).uniform_refine(numRefine, dim), ...);
1577 return *this;
1578 }
1579
1580public:
1586 inline auto &uniform_refine(int numRefine = 1, int dim = -1) {
1587 if (dim == -1) {
1588 if constexpr (BoundaryCore::spline_type::parDim() > 1)
1589 uniform_refine_(std::make_index_sequence<BoundaryCore::nsides()>{},
1590 numRefine, dim);
1591 } else if (dim == 0) {
1592 if constexpr (BoundaryCore::nsides() == 2) {
1593 // We do not refine the boundary of a curve
1594 } else if constexpr (BoundaryCore::nsides() == 4) {
1595 std::get<side::south - 1>(BoundaryCore::bdr_)
1596 .uniform_refine(numRefine, 0);
1597 std::get<side::north - 1>(BoundaryCore::bdr_)
1598 .uniform_refine(numRefine, 0);
1599 } else if constexpr (BoundaryCore::nsides() == 6) {
1600 std::get<side::south - 1>(BoundaryCore::bdr_)
1601 .uniform_refine(numRefine, 0);
1602 std::get<side::north - 1>(BoundaryCore::bdr_)
1603 .uniform_refine(numRefine, 0);
1604 std::get<side::front - 1>(BoundaryCore::bdr_)
1605 .uniform_refine(numRefine, 0);
1606 std::get<side::back - 1>(BoundaryCore::bdr_)
1607 .uniform_refine(numRefine, 0);
1608 } else if constexpr (BoundaryCore::nsides() == 8) {
1609 std::get<side::south - 1>(BoundaryCore::bdr_)
1610 .uniform_refine(numRefine, 0);
1611 std::get<side::north - 1>(BoundaryCore::bdr_)
1612 .uniform_refine(numRefine, 0);
1613 std::get<side::front - 1>(BoundaryCore::bdr_)
1614 .uniform_refine(numRefine, 0);
1615 std::get<side::back - 1>(BoundaryCore::bdr_)
1616 .uniform_refine(numRefine, 0);
1617 std::get<side::stime - 1>(BoundaryCore::bdr_)
1618 .uniform_refine(numRefine, 0);
1619 std::get<side::etime - 1>(BoundaryCore::bdr_)
1620 .uniform_refine(numRefine, 0);
1621 } else
1622 throw std::runtime_error("Invalid dimension");
1623 } else if (dim == 1) {
1624 if constexpr (BoundaryCore::nsides() == 4) {
1625 std::get<side::east - 1>(BoundaryCore::bdr_)
1626 .uniform_refine(numRefine, 0);
1627 std::get<side::west - 1>(BoundaryCore::bdr_)
1628 .uniform_refine(numRefine, 0);
1629 } else if constexpr (BoundaryCore::nsides() == 6) {
1630 std::get<side::east - 1>(BoundaryCore::bdr_)
1631 .uniform_refine(numRefine, 0);
1632 std::get<side::west - 1>(BoundaryCore::bdr_)
1633 .uniform_refine(numRefine, 0);
1634 std::get<side::front - 1>(BoundaryCore::bdr_)
1635 .uniform_refine(numRefine, 1);
1636 std::get<side::back - 1>(BoundaryCore::bdr_)
1637 .uniform_refine(numRefine, 1);
1638
1639 } else if constexpr (BoundaryCore::nsides() == 8) {
1640 std::get<side::east - 1>(BoundaryCore::bdr_)
1641 .uniform_refine(numRefine, 0);
1642 std::get<side::west - 1>(BoundaryCore::bdr_)
1643 .uniform_refine(numRefine, 0);
1644 std::get<side::front - 1>(BoundaryCore::bdr_)
1645 .uniform_refine(numRefine, 1);
1646 std::get<side::back - 1>(BoundaryCore::bdr_)
1647 .uniform_refine(numRefine, 1);
1648 std::get<side::stime - 1>(BoundaryCore::bdr_)
1649 .uniform_refine(numRefine, 1);
1650 std::get<side::etime - 1>(BoundaryCore::bdr_)
1651 .uniform_refine(numRefine, 1);
1652 } else
1653 throw std::runtime_error("Invalid dimension");
1654 } else if (dim == 2) {
1655 if constexpr (BoundaryCore::nsides() == 6) {
1656 std::get<side::east - 1>(BoundaryCore::bdr_)
1657 .uniform_refine(numRefine, 1);
1658 std::get<side::west - 1>(BoundaryCore::bdr_)
1659 .uniform_refine(numRefine, 1);
1660 std::get<side::north - 1>(BoundaryCore::bdr_)
1661 .uniform_refine(numRefine, 1);
1662 std::get<side::south - 1>(BoundaryCore::bdr_)
1663 .uniform_refine(numRefine, 1);
1664 } else if constexpr (BoundaryCore::nsides() == 8) {
1665 std::get<side::west - 1>(BoundaryCore::bdr_)
1666 .uniform_refine(numRefine, 1);
1667 std::get<side::east - 1>(BoundaryCore::bdr_)
1668 .uniform_refine(numRefine, 1);
1669 std::get<side::south - 1>(BoundaryCore::bdr_)
1670 .uniform_refine(numRefine, 1);
1671 std::get<side::north - 1>(BoundaryCore::bdr_)
1672 .uniform_refine(numRefine, 1);
1673 std::get<side::stime - 1>(BoundaryCore::bdr_)
1674 .uniform_refine(numRefine, 2);
1675 std::get<side::etime - 1>(BoundaryCore::bdr_)
1676 .uniform_refine(numRefine, 2);
1677 } else
1678 throw std::runtime_error("Invalid dimension");
1679 } else if (dim == 3) {
1680 if constexpr (BoundaryCore::nsides() == 8) {
1681 std::get<side::west - 1>(BoundaryCore::bdr_)
1682 .uniform_refine(numRefine, 2);
1683 std::get<side::east - 1>(BoundaryCore::bdr_)
1684 .uniform_refine(numRefine, 2);
1685 std::get<side::south - 1>(BoundaryCore::bdr_)
1686 .uniform_refine(numRefine, 2);
1687 std::get<side::north - 1>(BoundaryCore::bdr_)
1688 .uniform_refine(numRefine, 2);
1689 std::get<side::front - 1>(BoundaryCore::bdr_)
1690 .uniform_refine(numRefine, 2);
1691 std::get<side::back - 1>(BoundaryCore::bdr_)
1692 .uniform_refine(numRefine, 2);
1693 } else
1694 throw std::runtime_error("Invalid dimension");
1695 } else
1696 throw std::runtime_error("Invalid dimension");
1697 return *this;
1698 }
1699
1700private:
1703 template <size_t... Is>
1704 inline torch::serialize::OutputArchive &
1705 write_(std::index_sequence<Is...>, torch::serialize::OutputArchive &archive,
1706 const std::string &key = "boundary") const {
1707 (std::get<Is>(BoundaryCore::bdr_)
1708 .write(archive, key + ".bdr[" + std::to_string(Is) + "]"),
1709 ...);
1710 return archive;
1711 }
1712
1713public:
1717 inline void save(const std::string &filename,
1718 const std::string &key = "boundary") const {
1719 torch::serialize::OutputArchive archive;
1720 write(archive, key).save_to(filename);
1721 }
1722
1728 inline torch::serialize::OutputArchive &
1729 write(torch::serialize::OutputArchive &archive,
1730 const std::string &key = "boundary") const {
1731 write_(std::make_index_sequence<BoundaryCore::nsides()>{}, archive, key);
1732 return archive;
1733 }
1734
1735private:
1738 template <size_t... Is>
1739 inline torch::serialize::InputArchive &
1740 read_(std::index_sequence<Is...>, torch::serialize::InputArchive &archive,
1741 const std::string &key = "boundary") {
1742 (std::get<Is>(BoundaryCore::bdr_)
1743 .read(archive, key + ".bdr[" + std::to_string(Is) + "]"),
1744 ...);
1745 return archive;
1746 }
1747
1748public:
1752 inline void load(const std::string &filename,
1753 const std::string &key = "boundary") {
1754 torch::serialize::InputArchive archive;
1755 archive.load_from(filename);
1756 read(archive, key);
1757 }
1758
1764 inline torch::serialize::InputArchive &
1765 read(torch::serialize::InputArchive &archive,
1766 const std::string &key = "boundary") {
1767 read_(std::make_index_sequence<BoundaryCore::nsides()>{}, archive, key);
1768 return archive;
1769 }
1770
1776 [[nodiscard]] inline pugi::xml_document
1777 to_xml(int id = 0, const std::string &label = "", int index = -1) const {
1778 pugi::xml_document doc;
1779 pugi::xml_node root = doc.append_child("xml");
1780 to_xml(root, id, label, index);
1781
1782 return doc;
1783 }
1784
1791 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
1792 const std::string &label = "",
1793 int index = -1) const {
1794 // add Boundary node
1795 pugi::xml_node bdr = root.append_child("Boundary");
1796
1797 if (id >= 0)
1798 bdr.append_attribute("id") = id;
1799
1800 if (index >= 0)
1801 bdr.append_attribute("index") = index;
1802
1803 if (!label.empty())
1804 bdr.append_attribute("label") = label.c_str();
1805
1806 int index_ = 0;
1807 std::apply(
1808 [&bdr, &index_](const auto &...bspline) {
1809 (bspline.to_xml(bdr, -1, "", index_++), ...);
1810 },
1811 BoundaryCore::bdr_);
1812
1813 return root;
1814 }
1815
1822 inline BoundaryCommon &from_xml(const pugi::xml_document &doc, int id = 0,
1823 const std::string &label = "",
1824 int index = -1) {
1825 return from_xml(doc.child("xml"), id, label, index);
1826 }
1827
1834 inline BoundaryCommon &from_xml(const pugi::xml_node &root, int id = 0,
1835 const std::string &label = "",
1836 int index = -1) {
1837
1838 // Loop through all boundary nodes
1839 for (pugi::xml_node bdr : root.children("Boundary")) {
1840
1841 // Check for "Boundary" with given id, index, label
1842 if ((id >= 0 ? bdr.attribute("id").as_int() == id : true) &&
1843 (index >= 0 ? bdr.attribute("index").as_int() == index : true) &&
1844 (!label.empty() ? bdr.attribute("label").value() == label : true)) {
1845
1846 int index_ = 0;
1847 std::apply(
1848 [&bdr, &index_](auto &...bspline) {
1849 (bspline.from_xml(bdr, -1, "", index_++), ...);
1850 },
1851 BoundaryCore::bdr_);
1852
1853 return *this;
1854 } else
1855 continue; // try next "Boundary"
1856 }
1857
1858 throw std::runtime_error("XML object does not provide geometry with given "
1859 "id, index, and/or label");
1860 return *this;
1861 }
1862
1863private:
1866 template <typename BoundaryCore_, size_t... Is>
1867 inline bool isequal_(std::index_sequence<Is...>,
1868 const BoundaryCommon<BoundaryCore_> &other) const {
1869 return ((std::get<Is>(BoundaryCore::bdr_) == std::get<Is>(other.sides())) &&
1870 ...);
1871 }
1872
1873public:
1878 template <typename BoundaryCore_>
1879 inline bool operator==(const BoundaryCommon<BoundaryCore_> &other) const {
1880 return isequal_(std::make_index_sequence<BoundaryCore::nsides()>{}, other);
1881 }
1882
1887 template <typename BoundaryCore_>
1888 inline bool operator!=(const BoundaryCommon<BoundaryCore_> &other) const {
1889 return !(
1890 *this ==
1891 other); // Do not change this to (*this != other) is it does not work
1892 }
1893
1894private:
1897 template <typename BoundaryCore_, size_t... Is>
1898 inline bool isclose_(std::index_sequence<Is...>,
1899 const BoundaryCommon<BoundaryCore_> &other,
1900 BoundaryCore::spline_type::value_type rtol,
1901 BoundaryCore::spline_type::value_type atol) const {
1902 return ((std::get<Is>(BoundaryCore::bdr_)
1903 .isclose(std::get<Is>(other.sides()))) &&
1904 ...);
1905 }
1906
1907public:
1915 template <typename BoundaryCore_>
1916 inline bool
1918 BoundaryCore::spline_type::value_type rtol =
1919 typename BoundaryCore::spline_type::value_type{1e-5},
1920 BoundaryCore::spline_type::value_type atol =
1921 typename BoundaryCore::spline_type::value_type{1e-8}) const {
1922 return isclose_(std::make_index_sequence<BoundaryCore::nsides()>{}, other,
1923 rtol, atol);
1924 }
1925
1926#define GENERATE_EXPR_MACRO(r, data, name) \
1927private: \
1928 template <bool memory_optimized = false, size_t... Is, typename... Xi> \
1929 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
1930 const std::tuple<Xi...> &xi) const { \
1931 return std::tuple( \
1932 std::get<Is>(BoundaryCore::bdr_) \
1933 .template name<memory_optimized>(std::get<Is>(xi))...); \
1934 } \
1935 \
1936 template <bool memory_optimized = false, size_t... Is, typename... Xi, \
1937 typename... Indices> \
1938 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
1939 const std::tuple<Xi...> &xi, \
1940 const std::tuple<Indices...> &indices) \
1941 const { \
1942 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1943 .template name<memory_optimized>( \
1944 std::get<Is>(xi), std::get<Is>(indices))...); \
1945 } \
1946 \
1947 template <bool memory_optimized = false, size_t... Is, typename... Xi, \
1948 typename... Indices, typename... Coeff_Indices> \
1949 inline auto BOOST_PP_CAT(name, _)( \
1950 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
1951 const std::tuple<Indices...> &indices, \
1952 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
1953 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1954 .template name<memory_optimized>( \
1955 std::get<Is>(xi), std::get<Is>(indices), \
1956 std::get<Is>(coeff_indices))...); \
1957 } \
1958 \
1959public: \
1960 template <bool memory_optimized = false, typename... Args> \
1961 inline auto name(const Args &...args) const { \
1962 return BOOST_PP_CAT(name, _)<memory_optimized>( \
1963 std::make_index_sequence<BoundaryCore::nsides()>{}, args...); \
1964 }
1965
1968 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
1970#undef GENERATE_EXPR_MACRO
1971
1972#define GENERATE_IEXPR_MACRO(r, data, name) \
1973private: \
1974 template <bool memory_optimized = false, size_t... Is, typename... Geometry, \
1975 typename... Xi> \
1976 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
1977 const std::tuple<Geometry...> &G, \
1978 const std::tuple<Xi...> &xi) const { \
1979 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1980 .template name<memory_optimized>( \
1981 std::get<Is>(G), std::get<Is>(xi))...); \
1982 } \
1983 \
1984 template <bool memory_optimized = false, size_t... Is, typename... Geometry, \
1985 typename... Xi, typename... Indices> \
1986 inline auto BOOST_PP_CAT(name, _)( \
1987 std::index_sequence<Is...>, const std::tuple<Geometry...> &G, \
1988 const std::tuple<Xi...> &xi, const std::tuple<Indices...> &indices) \
1989 const { \
1990 return std::tuple( \
1991 std::get<Is>(BoundaryCore::bdr_) \
1992 .template name<memory_optimized>( \
1993 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(indices))...); \
1994 } \
1995 \
1996 template <bool memory_optimized = false, size_t... Is, typename... Geometry, \
1997 typename... Xi, typename... Indices, typename... Coeff_Indices> \
1998 inline auto BOOST_PP_CAT(name, _)( \
1999 std::index_sequence<Is...>, const std::tuple<Geometry...> &G, \
2000 const std::tuple<Xi...> &xi, const std::tuple<Indices...> &indices, \
2001 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
2002 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
2003 .template name<memory_optimized>( \
2004 std::get<Is>(G), std::get<Is>(xi), \
2005 std::get<Is>(indices), \
2006 std::get<Is>(coeff_indices))...); \
2007 } \
2008 \
2009public: \
2010 template <bool memory_optimized = false, typename... Args> \
2011 inline auto name(const Args &...args) const { \
2012 return BOOST_PP_CAT(name, _)<memory_optimized>( \
2013 std::make_index_sequence<BoundaryCore::nsides()>{}, args...); \
2014 }
2015
2018 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
2020#undef GENERATE_IEXPR_MACRO
2021
2024 auto device() const noexcept {
2025 return std::apply(
2026 [](const auto &...bspline) {
2027 return std::make_tuple(bspline.device()...);
2028 },
2029 BoundaryCore::bdr_);
2030 }
2031
2034 auto device_index() const noexcept {
2035 return std::apply(
2036 [](const auto &...bspline) {
2037 return std::make_tuple(bspline.device_index()...);
2038 },
2039 BoundaryCore::bdr_);
2040 }
2041
2044 auto dtype() const noexcept {
2045 return std::apply(
2046 [](const auto &...bspline) {
2047 return std::make_tuple(bspline.dtype()...);
2048 },
2049 BoundaryCore::bdr_);
2050 }
2051
2054 auto layout() const noexcept {
2055 return std::apply(
2056 [](const auto &...bspline) {
2057 return std::make_tuple(bspline.layout()...);
2058 },
2059 BoundaryCore::bdr_);
2060 }
2061
2064 auto requires_grad() const noexcept {
2065 return std::apply(
2066 [](const auto &...bspline) {
2067 return std::make_tuple(bspline.requires_grad()...);
2068 },
2069 BoundaryCore::bdr_);
2070 }
2071
2074 auto pinned_memory() const noexcept {
2075 return std::apply(
2076 [](const auto &...bspline) {
2077 return std::make_tuple(bspline.pinned_memory()...);
2078 },
2079 BoundaryCore::bdr_);
2080 }
2081
2084 auto is_sparse() const noexcept {
2085 return std::apply(
2086 [](const auto &...bspline) {
2087 return std::make_tuple(bspline.is_sparse()...);
2088 },
2089 BoundaryCore::bdr_);
2090 }
2091
2094 auto is_uniform() const noexcept {
2095 return std::apply(
2096 [](const auto &...bspline) {
2097 return std::make_tuple(bspline.is_uniform()...);
2098 },
2099 BoundaryCore::bdr_);
2100 }
2101
2104 auto is_nonuniform() const noexcept {
2105 return std::apply(
2106 [](const auto &...bspline) {
2107 return std::make_tuple(bspline.is_nonuniform()...);
2108 },
2109 BoundaryCore::bdr_);
2110 }
2111
2116 std::apply(
2117 [requires_grad](const auto &...bspline) {
2118 (bspline.set_requires_grad(requires_grad), ...);
2119 },
2120 BoundaryCore::bdr_);
2121
2122 return *this;
2123 }
2124
2129 template <typename real_t> inline auto to(Options<real_t> options) const {
2130 using boundary_type = BoundaryCommon<iganet::BoundaryCore<
2131 decltype(typename BoundaryCore::spline_type{}.to(options)),
2132 BoundaryCore::spline_type::parDim()>>;
2133
2134 return boundary_type(std::apply(
2135 [&options](const auto &...bspline) {
2136 return std::make_tuple(bspline.to(options)...);
2137 },
2138 BoundaryCore::bdr_));
2139 }
2140
2144 inline auto to(torch::Device device) const {
2145 return BoundaryCommon(std::apply(
2146 [&device](const auto &...bspline) {
2147 return std::make_tuple(bspline.to(device)...);
2148 },
2149 BoundaryCore::bdr_));
2150 }
2151
2155 template <typename real_t> inline auto to() const {
2156 using boundary_type = BoundaryCommon<iganet::BoundaryCore<
2157 decltype(typename BoundaryCore::spline_type{}.template to<real_t>()),
2158 BoundaryCore::spline_type::parDim()>>;
2159
2160 return boundary_type(std::apply(
2161 [](const auto &...bspline) {
2162 return std::make_tuple(bspline.template to<real_t>()...);
2163 },
2164 BoundaryCore::bdr_));
2165 }
2166};
2167
2169template <typename Spline>
2170 requires SplineType<Spline>
2171using Boundary = BoundaryCommon<BoundaryCore<Spline, Spline::parDim()>>;
2172
2179template <typename Spline>
2180 requires SplineType<Spline>
2181inline std::ostream &operator<<(std::ostream &os, const Boundary<Spline> &obj) {
2182 obj.pretty_print(os);
2183 return os;
2184}
2185
2186} // namespace iganet
#define GENERATE_IEXPR_MACRO(r, data, name)
Auto-generated functions.
Definition boundary.hpp:1972
#define GENERATE_EXPR_MACRO(r, data, name)
Definition boundary.hpp:1926
Multivariate B-splines.
#define GENERATE_EXPR_SEQ
Sequence of expression (parametric coordinates).
Definition bspline.hpp:43
#define GENERATE_IEXPR_SEQ
Sequence of expression (physical coordinates).
Definition bspline.hpp:49
Boundary base class.
Definition boundary.hpp:1228
Boundary (common high-level functionality).
Definition boundary.hpp:1237
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indices of knot spans containing xi.
Definition boundary.hpp:1491
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:1834
auto to(torch::Device device) const
Returns a copy of the boundary object with settings from device.
Definition boundary.hpp:2144
auto dtype() const noexcept
Returns the dtype property of all splines.
Definition boundary.hpp:2044
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:1442
auto pinned_memory() const noexcept
Returns the pinned_memory property of all splines.
Definition boundary.hpp:2074
bool isequal_(std::index_sequence< Is... >, const BoundaryCommon< BoundaryCore_ > &other) const
Returns true if both boundary spline objects are the same.
Definition boundary.hpp:1867
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:1527
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:1765
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:1822
auto eval(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects in the points xi
Definition boundary.hpp:1362
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:1404
auto to() const
Returns a copy of the boundary object with real_t type.
Definition boundary.hpp:2155
auto to(Options< real_t > options) const
Returns a copy of the boundary object with settings from options.
Definition boundary.hpp:2129
auto device_index() const noexcept
Returns the device_index property of all splines.
Definition boundary.hpp:2034
auto is_uniform() const noexcept
Returns whether each B-spline is uniform.
Definition boundary.hpp:2094
torch::Tensor as_tensor_(std::index_sequence< Is... >) const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1252
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:1917
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:1271
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:1502
auto find_knot_indices_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the knot indices of the boundary spline object knot spans containing xi.
Definition boundary.hpp:1479
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:1574
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:1705
auto is_nonuniform() const noexcept
Returns whether each B-spline is non-uniform.
Definition boundary.hpp:2104
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:1345
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:1565
auto requires_grad() const noexcept
Returns the requires_grad property of all splines.
Definition boundary.hpp:2064
auto eval(const std::tuple< Xi... > &xi, const std::tuple< Indices... > &indices) const
Provides the eval operation.
Definition boundary.hpp:1373
BoundaryCommon clone() const
Returns a clone of the boundary object.
Definition boundary.hpp:1244
auto eval_basfunc(const std::tuple< Xi... > &xi, const std::tuple< Indices... > &indices) const
Provides the eval_basfunc operation.
Definition boundary.hpp:1538
auto & from_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor.
Definition boundary.hpp:1316
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:1294
auto eval(const std::tuple< Xi... > &xi, const std::tuple< Indices... > &indices, const std::tuple< Coeff_Indices... > &coeff_indices) const
Provides the eval operation.
Definition boundary.hpp:1387
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:1777
void load(const std::string &filename, const std::string &key="boundary")
Loads the boundary spline object from file.
Definition boundary.hpp:1752
torch::Tensor as_tensor() const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1261
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:1511
BoundaryCommon & set_requires_grad(bool requires_grad)
Sets the boundary object's requires_grad property.
Definition boundary.hpp:2115
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:1326
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:1791
auto & uniform_refine(int numRefine=1, int dim=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition boundary.hpp:1586
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:1419
int64_t as_tensor_size() const
Returns the size of the single tensor representation of all spline objects.
Definition boundary.hpp:1282
auto eval_from_precomputed(const std::tuple< Basfunc... > &basfunc, const std::tuple< Coeff_Indices... > &coeff_indices, const std::tuple< Xi... > &xi) const
Provides the eval_from_precomputed operation.
Definition boundary.hpp:1464
bool operator==(const BoundaryCommon< BoundaryCore_ > &other) const
Returns true if both boundary objects are the same.
Definition boundary.hpp:1879
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:1550
auto layout() const noexcept
Returns the layout property of all splines.
Definition boundary.hpp:2054
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:1729
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:1898
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:1740
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:1335
void save(const std::string &filename, const std::string &key="boundary") const
Saves the boundary spline to file.
Definition boundary.hpp:1717
auto device() const noexcept
Auto-generated functions.
Definition boundary.hpp:2024
bool operator!=(const BoundaryCommon< BoundaryCore_ > &other) const
Returns true if both boundary objects are different.
Definition boundary.hpp:1888
auto is_sparse() const noexcept
Returns whether the layout of each spline is sparse.
Definition boundary.hpp:2084
constexpr auto & side() const
Returns constant reference to side-th Spline.
Definition boundary.hpp:169
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:115
constexpr auto & sides()
Returns a non-constant reference to the tuple of boundary sides.
Definition boundary.hpp:190
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:204
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:104
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:95
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:125
~BoundaryCore() override=default
Destructor.
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:164
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:89
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:194
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:223
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:99
constexpr auto & side()
Returns non-constant reference to side-th Spline.
Definition boundary.hpp:177
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:212
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:185
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:82
eval_type greville() const
Returns the Greville abscissae.
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:142
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:261
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:459
constexpr auto & sides() const
Returns a constant reference to the tuple of boundary sides.
Definition boundary.hpp:439
constexpr auto & side()
Returns non-constant reference to the s-th side's spline.
Definition boundary.hpp:432
std::tuple< utils::TensorArray< 1 >, utils::TensorArray< 1 >, utils::TensorArray< 1 >, utils::TensorArray< 1 > > eval_type
Evaluation type.
Definition boundary.hpp:288
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:419
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:493
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:310
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:469
constexpr auto & sides()
Returns a non-constant reference to the tuple of boundary sides.
Definition boundary.hpp:443
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:482
Spline spline_type
Spline type.
Definition boundary.hpp:254
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:370
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:284
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:277
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:292
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:301
Spline::value_type value_type
Value type.
Definition boundary.hpp:281
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:270
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:322
constexpr auto & side() const
Returns constant reference to the s-th side's spline.
Definition boundary.hpp:424
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:447
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:339
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:305
~BoundaryCore() override=default
Destructor.
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:813
constexpr auto & sides() const
Returns a constant reference to the tuple of boundary sides.
Definition boundary.hpp:764
Spline::value_type value_type
Value type.
Definition boundary.hpp:554
~BoundaryCore() override=default
Destructor.
constexpr auto & side() const
Returns constant reference to side-th spline.
Definition boundary.hpp:749
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:625
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:577
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:557
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:586
Spline spline_type
Spline type.
Definition boundary.hpp:518
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:530
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:581
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:566
constexpr auto & sides()
Returns a non-constant reference to the tuple of sides.
Definition boundary.hpp:768
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:598
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:772
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:664
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:550
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:541
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:798
constexpr auto & side()
Returns non-constant reference to side-th spline.
Definition boundary.hpp:757
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:562
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:744
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:786
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:826
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:948
constexpr auto & side()
Returns non-constant reference to side-th spline.
Definition boundary.hpp:1142
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:1204
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:1028
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:897
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:1219
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:1157
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:931
Spline::value_type value_type
Value type.
Definition boundary.hpp:901
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:1129
~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:910
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:936
Spline spline_type
Spline type.
Definition boundary.hpp:854
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:927
constexpr auto & ides()
Returns a non-constant reference to the tuple of boundary sides.
Definition boundary.hpp:1153
constexpr auto & side() const
Returns constant reference to side-th spline.
Definition boundary.hpp:1134
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:981
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:869
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:1187
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:1173
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:914
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:904
constexpr auto & sides() const
Returns a constant reference to the tuple of boundary sides.
Definition boundary.hpp:1149
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:886
BoundaryCore.
Definition boundary.hpp:44
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:47
Full qualified name descriptor.
Definition fqn.hpp:22
Concept to identify template parameters that are derived from iganet::Boundary_.
Definition boundary.hpp:1233
Concept to identify template parameters that are derived from iganet::Spline_.
Definition bspline.hpp:3858
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:26
Definition core.hpp:73
deriv
Enumerator for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:76
std::ostream & operator<<(std::ostream &os, const MemoryDebugger< id > &obj)
Prints a memory debugger object.
Definition memory.hpp:145
init
Enumerator for specifying the initialization of B-spline coefficients.
Definition bspline.hpp:58
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
Signed short integer type used by IgANet's compact enumerations.
Definition core.hpp:76
STL namespace.
Serialization prototype.
Definition serialize.hpp:29