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 <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
42 template <typename Spline, short_t> requires SplineType<Spline> class BoundaryCore;
43
49 template <typename Spline>
50 requires SplineType<Spline>
51class BoundaryCore<Spline, /* parDim */ 1> : public utils::Serializable,
53
55 template <typename BoundaryCore> friend class BoundaryCommon;
56
57protected:
59 using spline_type = Spline;
60
63 typename Spline::template derived_self_type<typename Spline::value_type,
64 Spline::geoDim()>;
65
68 template <typename real_t>
70 typename Spline::template derived_self_type<real_t, Spline::geoDim()>;
71
73 std::tuple<boundary_spline_type, boundary_spline_type> bdr_;
74
75public:
77 using boundary_type = decltype(bdr_);
78
80 using eval_type = std::tuple<torch::Tensor, torch::Tensor>;
81
85 : bdr_({boundary_spline_type(options), boundary_spline_type(options)}) {}
86
88 BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
89
91 BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
92
94 BoundaryCore(const BoundaryCore &other, bool clone)
95 : bdr_(clone ? std::apply(
96 [](const auto &...bspline) {
97 return std::make_tuple(bspline.clone()...);
98 },
99 other.coeffs())
100 : other.coeffs()) {}
101
103 BoundaryCore(const std::array<int64_t, 1> &, enum init init = init::zeros,
106 : bdr_({boundary_spline_type(std::array<int64_t, 0>{}, init, options),
107 boundary_spline_type(std::array<int64_t, 0>{}, init, options)}) {}
108
110 BoundaryCore(const std::array<std::vector<typename Spline::value_type>, 1> &,
111 enum init init = init::zeros,
114 : bdr_({boundary_spline_type(std::array<int64_t, 0>{}, init, options),
115 boundary_spline_type(std::array<int64_t, 0>{}, init, options)}) {}
116
123 inline auto &from_full_tensor(const torch::Tensor &tensor) {
124
125 if (tensor.dim() > 1) {
126 auto tensor_view = tensor.view({Spline::geoDim(), -1, tensor.size(-1)});
127
128 side<west>().from_tensor(tensor_view.index({torch::indexing::Slice(), 0})
129 .reshape({-1, tensor.size(-1)}));
130 side<east>().from_tensor(tensor_view.index({torch::indexing::Slice(), -1})
131 .reshape({-1, tensor.size(-1)}));
132 } else {
133 auto tensor_view = tensor.view({Spline::geoDim(), -1});
134
135 side<west>().from_tensor(
136 tensor_view.index({torch::indexing::Slice(), 0}).flatten());
137 side<east>().from_tensor(
138 tensor_view.index({torch::indexing::Slice(), -1}).flatten());
139 }
140 return *this;
141 }
142
144 inline static constexpr short_t nsides() { return side::east; }
145
147 template <short_t s> inline constexpr auto &side() const {
148 static_assert(s > none && s <= nsides());
149 return std::get<s - 1>(bdr_);
150 }
151
153 template <short_t s> inline constexpr auto &side() {
154 static_assert(s > none && s <= nsides());
155 return std::get<s - 1>(bdr_);
156 }
157
160 inline constexpr auto &coeffs() const { return bdr_; }
161
164 inline constexpr auto &coeffs() { return bdr_; }
165
167 inline int64_t ncumcoeffs() const {
168 int64_t s = 0;
169 s += side<west>().ncumcoeffs();
170 s += side<east>().ncumcoeffs();
171
172 return s;
173 }
174
176 inline virtual void
177 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
178 os << name() << "(\n"
179 << "west = " << side<west>() << "\n"
180 << "east = " << side<east>() << "\n)";
181 }
182
184 inline nlohmann::json to_json() const override {
185 nlohmann::json json;
186 json["west"] = side<west>().to_json();
187 json["east"] = side<east>().to_json();
188
189 return json;
190 }
191
193 inline BoundaryCore &from_json(const nlohmann::json &json) {
194 side<west>().from_json(json["west"]);
195 side<east>().from_json(json["east"]);
196
197 return *this;
198 }
199
201 inline eval_type greville() const {
202 return eval_type{side<west>().greville(), side<east>().greville()};
203 }
204};
205
213 template <typename Spline>
214 requires SplineType<Spline>
215class BoundaryCore<Spline, /* parDim */ 2> : public utils::Serializable,
217
219 template <typename BoundaryCore> friend class BoundaryCommon;
220
221protected:
223 using spline_type = Spline;
224
226 using boundary_spline_type = std::tuple<
227 typename Spline::template derived_self_type<
228 typename Spline::value_type, Spline::geoDim(), Spline::degree(1)>,
229 typename Spline::template derived_self_type<
230 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>;
231
234 template <typename real_t>
236 std::tuple<typename Spline::template derived_self_type<
237 real_t, Spline::geoDim(), Spline::degree(1)>,
238 typename Spline::template derived_self_type<
239 real_t, Spline::geoDim(), Spline::degree(0)>>;
240
242 std::tuple<typename std::tuple_element_t<0, boundary_spline_type>,
243 typename std::tuple_element_t<0, boundary_spline_type>,
244 typename std::tuple_element_t<1, boundary_spline_type>,
245 typename std::tuple_element_t<1, boundary_spline_type>>
247
248public:
250 using boundary_type = decltype(bdr_);
251
253 using eval_type = std::tuple<utils::TensorArray<1>, utils::TensorArray<1>,
255
259 : bdr_({std::tuple_element_t<0, boundary_spline_type>(options),
260 std::tuple_element_t<0, boundary_spline_type>(options),
261 std::tuple_element_t<1, boundary_spline_type>(options),
262 std::tuple_element_t<1, boundary_spline_type>(options)}) {}
263
265 BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
266
268 BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
269
271 BoundaryCore(const BoundaryCore &other, bool clone)
272 : bdr_(clone ? std::apply(
273 [](const auto &...bspline) {
274 return std::make_tuple(bspline.clone()...);
275 },
276 other.coeffs())
277 : other.coeffs()) {}
278
280 BoundaryCore(const std::array<int64_t, 2> &ncoeffs,
281 enum init init = init::zeros,
284 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
285 std::array<int64_t, 1>({ncoeffs[1]}), init, options),
286 std::tuple_element_t<0, boundary_spline_type>(
287 std::array<int64_t, 1>({ncoeffs[1]}), init, options),
288 std::tuple_element_t<1, boundary_spline_type>(
289 std::array<int64_t, 1>({ncoeffs[0]}), init, options),
290 std::tuple_element_t<1, boundary_spline_type>(
291 std::array<int64_t, 1>({ncoeffs[0]}), init, options)}) {}
292
295 const std::array<std::vector<typename Spline::value_type>, 2> &kv,
296 enum init init = init::zeros,
299 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
300 std::array<std::vector<typename Spline::value_type>, 1>(
301 {kv[1]}),
302 init, options),
303 std::tuple_element_t<0, boundary_spline_type>(
304 std::array<std::vector<typename Spline::value_type>, 1>(
305 {kv[1]}),
306 init, options),
307 std::tuple_element_t<1, boundary_spline_type>(
308 std::array<std::vector<typename Spline::value_type>, 1>(
309 {kv[0]}),
310 init, options),
311 std::tuple_element_t<1, boundary_spline_type>(
312 std::array<std::vector<typename Spline::value_type>, 1>(
313 {kv[0]}),
314 init, options)}) {}
315
322 inline auto &from_full_tensor(const torch::Tensor &tensor) {
323
324 if (tensor.dim() > 1) {
325 auto tensor_view =
326 tensor.view({-1, side<west>().ncoeffs(0), side<south>().ncoeffs(0),
327 tensor.size(-1)});
328
329 side<west>().from_tensor(
330 tensor_view
331 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0})
332 .reshape({-1, tensor.size(-1)}));
333 side<east>().from_tensor(
334 tensor_view
335 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1})
336 .reshape({-1, tensor.size(-1)}));
337 side<south>().from_tensor(
338 tensor_view
339 .index({torch::indexing::Slice(), 0, torch::indexing::Slice()})
340 .reshape({-1, tensor.size(-1)}));
341 side<north>().from_tensor(
342 tensor_view
343 .index({torch::indexing::Slice(), -1, torch::indexing::Slice()})
344 .reshape({-1, tensor.size(-1)}));
345 } else {
346 auto tensor_view =
347 tensor.view({-1, side<west>().ncoeffs(0), side<south>().ncoeffs(0)});
348
349 side<west>().from_tensor(
350 tensor_view
351 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0})
352 .flatten());
353 side<east>().from_tensor(
354 tensor_view
355 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1})
356 .flatten());
357 side<south>().from_tensor(
358 tensor_view
359 .index({torch::indexing::Slice(), 0, torch::indexing::Slice()})
360 .flatten());
361 side<north>().from_tensor(
362 tensor_view
363 .index({torch::indexing::Slice(), -1, torch::indexing::Slice()})
364 .flatten());
365 }
366 return *this;
367 }
368
370 inline static constexpr short_t nsides() { return side::north; }
371
373 template <short_t s> inline constexpr auto &side() const {
374 static_assert(s > none && s <= nsides());
375 return std::get<s - 1>(bdr_);
376 }
377
379 template <short_t s> inline constexpr auto &side() {
380 static_assert(s > none && s <= nsides());
381 return std::get<s - 1>(bdr_);
382 }
383
386 inline constexpr auto &coeffs() const { return bdr_; }
387
390 inline constexpr auto &coeffs() { return bdr_; }
391
393 inline int64_t ncumcoeffs() const {
394 int64_t s = 0;
395 s += side<west>().ncumcoeffs();
396 s += side<east>().ncumcoeffs();
397 s += side<south>().ncumcoeffs();
398 s += side<north>().ncumcoeffs();
399
400 return s;
401 }
402
404 inline virtual void
405 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
406 os << name() << "(\n"
407 << "west = " << side<west>() << "\n"
408 << "east = " << side<east>() << "\n"
409 << "south = " << side<south>() << "\n"
410 << "north = " << side<north>() << "\n)";
411 }
412
414 inline nlohmann::json to_json() const override {
415 nlohmann::json json;
416 json["west"] = side<west>().to_json();
417 json["east"] = side<east>().to_json();
418 json["south"] = side<south>().to_json();
419 json["north"] = side<north>().to_json();
420
421 return json;
422 }
423
425 inline BoundaryCore &from_json(const nlohmann::json &json) {
426 side<west>().from_json(json["west"]);
427 side<east>().from_json(json["east"]);
428 side<south>().from_json(json["south"]);
429 side<north>().from_json(json["north"]);
430
431 return *this;
432 }
433
435 inline eval_type greville() const {
436 return eval_type{side<west>().greville(), side<east>().greville(),
437 side<south>().greville(), side<north>().greville()};
438 }
439};
440
450 template <typename Spline>
451 requires SplineType<Spline>
452class BoundaryCore<Spline, /* parDim */ 3> : public utils::Serializable,
454
456 template <typename BoundaryCore> friend class BoundaryCommon;
457
458protected:
460 using spline_type = Spline;
461
464 std::tuple<typename Spline::template derived_self_type<
465 typename Spline::value_type, Spline::geoDim(),
466 Spline::degree(1), Spline::degree(2)>,
467 typename Spline::template derived_self_type<
468 typename Spline::value_type, Spline::geoDim(),
469 Spline::degree(0), Spline::degree(2)>,
470 typename Spline::template derived_self_type<
471 typename Spline::value_type, Spline::geoDim(),
472 Spline::degree(0), Spline::degree(1)>>;
473
476 template <typename real_t>
478 typename Spline::template derived_self_type<
479 real_t, Spline::geoDim(), Spline::degree(1), Spline::degree(2)>,
480 typename Spline::template derived_self_type<
481 real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(2)>,
482 typename Spline::template derived_self_type<
483 real_t, Spline::geoDim(), Spline::degree(0), Spline::degree(1)>>;
484
486 std::tuple<typename std::tuple_element_t<0, boundary_spline_type>,
487 typename std::tuple_element_t<0, boundary_spline_type>,
488 typename std::tuple_element_t<1, boundary_spline_type>,
489 typename std::tuple_element_t<1, boundary_spline_type>,
490 typename std::tuple_element_t<2, boundary_spline_type>,
491 typename std::tuple_element_t<2, boundary_spline_type>>
493
494public:
496 using boundary_type = decltype(bdr_);
497
499 using eval_type = std::tuple<utils::TensorArray<2>, utils::TensorArray<2>,
502
506 : bdr_({std::tuple_element_t<0, boundary_spline_type>(options),
507 std::tuple_element_t<0, boundary_spline_type>(options),
508 std::tuple_element_t<1, boundary_spline_type>(options),
509 std::tuple_element_t<1, boundary_spline_type>(options),
510 std::tuple_element_t<2, boundary_spline_type>(options),
511 std::tuple_element_t<2, boundary_spline_type>(options)}) {}
512
514 BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
515
517 BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
518
520 BoundaryCore(const BoundaryCore &other, bool clone)
521 : bdr_(clone ? std::apply(
522 [](const auto &...bspline) {
523 return std::make_tuple(bspline.clone()...);
524 },
525 other.coeffs())
526 : other.coeffs()) {}
527
529 BoundaryCore(const std::array<int64_t, 3> &ncoeffs,
530 enum init init = init::zeros,
533 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
534 std::array<int64_t, 2>({ncoeffs[1], ncoeffs[2]}), init,
535 options),
536 std::tuple_element_t<0, boundary_spline_type>(
537 std::array<int64_t, 2>({ncoeffs[1], ncoeffs[2]}), init,
538 options),
539 std::tuple_element_t<1, boundary_spline_type>(
540 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[2]}), init,
541 options),
542 std::tuple_element_t<1, boundary_spline_type>(
543 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[2]}), init,
544 options),
545 std::tuple_element_t<2, boundary_spline_type>(
546 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[1]}), init,
547 options),
548 std::tuple_element_t<2, boundary_spline_type>(
549 std::array<int64_t, 2>({ncoeffs[0], ncoeffs[1]}), init,
550 options)}) {}
551
554 const std::array<std::vector<typename Spline::value_type>, 3> &kv,
555 enum init init = init::zeros,
558 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
559 std::array<std::vector<typename Spline::value_type>, 2>(
560 {kv[1], kv[2]}),
561 init, options),
562 std::tuple_element_t<0, boundary_spline_type>(
563 std::array<std::vector<typename Spline::value_type>, 2>(
564 {kv[1], kv[2]}),
565 init, options),
566 std::tuple_element_t<1, boundary_spline_type>(
567 std::array<std::vector<typename Spline::value_type>, 2>(
568 {kv[0], kv[2]}),
569 init, options),
570 std::tuple_element_t<1, boundary_spline_type>(
571 std::array<std::vector<typename Spline::value_type>, 2>(
572 {kv[0], kv[2]}),
573 init, options),
574 std::tuple_element_t<2, boundary_spline_type>(
575 std::array<std::vector<typename Spline::value_type>, 2>(
576 {kv[0], kv[1]}),
577 init, options),
578 std::tuple_element_t<2, boundary_spline_type>(
579 std::array<std::vector<typename Spline::value_type>, 2>(
580 {kv[0], kv[1]}),
581 init, options)}) {}
582
589 inline auto &from_full_tensor(const torch::Tensor &tensor) {
590
591 if (tensor.dim() > 1) {
592 auto tensor_view =
593 tensor.view({-1, side<west>().ncoeffs(1), side<west>().ncoeffs(0),
594 side<south>().ncoeffs(0), tensor.size(-1)});
595
596 side<west>().from_tensor(
597 tensor_view
598 .index({torch::indexing::Slice(), torch::indexing::Slice(),
599 torch::indexing::Slice(), 0})
600 .reshape({-1, tensor.size(-1)}));
601 side<east>().from_tensor(
602 tensor_view
603 .index({torch::indexing::Slice(), torch::indexing::Slice(),
604 torch::indexing::Slice(), -1})
605 .reshape({-1, tensor.size(-1)}));
606 side<south>().from_tensor(
607 tensor_view
608 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
609 torch::indexing::Slice()})
610 .reshape({-1, tensor.size(-1)}));
611 side<north>().from_tensor(
612 tensor_view
613 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
614 torch::indexing::Slice()})
615 .reshape({-1, tensor.size(-1)}));
616 side<front>().from_tensor(
617 tensor_view
618 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
619 torch::indexing::Slice()})
620 .reshape({-1, tensor.size(-1)}));
621 side<back>().from_tensor(
622 tensor_view
623 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
624 torch::indexing::Slice()})
625 .reshape({-1, tensor.size(-1)}));
626 } else {
627 auto tensor_view =
628 tensor.view({-1, side<west>().ncoeffs(1), side<west>().ncoeffs(0),
629 side<south>().ncoeffs(0)});
630
631 side<west>().from_tensor(
632 tensor_view
633 .index({torch::indexing::Slice(), torch::indexing::Slice(),
634 torch::indexing::Slice(), 0})
635 .flatten());
636 side<east>().from_tensor(
637 tensor_view
638 .index({torch::indexing::Slice(), torch::indexing::Slice(),
639 torch::indexing::Slice(), -1})
640 .flatten());
641
642 side<south>().from_tensor(
643 tensor_view
644 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
645 torch::indexing::Slice()})
646 .flatten());
647 side<north>().from_tensor(
648 tensor_view
649 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
650 torch::indexing::Slice()})
651 .flatten());
652
653 side<front>().from_tensor(
654 tensor_view
655 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
656 torch::indexing::Slice()})
657 .flatten());
658 side<back>().from_tensor(
659 tensor_view
660 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
661 torch::indexing::Slice()})
662 .flatten());
663 }
664 return *this;
665 }
666
668 inline static constexpr short_t nsides() { return side::back; }
669
671 template <short_t s> inline constexpr auto &side() const {
672 static_assert(s > none && s <= nsides());
673 return std::get<s - 1>(bdr_);
674 }
675
677 template <short_t s> inline constexpr auto &side() {
678 static_assert(s > none && s <= nsides());
679 return std::get<s - 1>(bdr_);
680 }
681
684 inline constexpr auto &coeffs() const { return bdr_; }
685
688 inline constexpr auto &coeffs() { return bdr_; }
689
691 inline int64_t ncumcoeffs() const {
692 int64_t s = 0;
693 s += side<west>().ncumcoeffs();
694 s += side<east>().ncumcoeffs();
695 s += side<south>().ncumcoeffs();
696 s += side<north>().ncumcoeffs();
697 s += side<front>().ncumcoeffs();
698 s += side<back>().ncumcoeffs();
699
700 return s;
701 }
702
704 inline virtual void
705 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
706 os << name() << "(\n"
707 << "west = " << side<west>() << "\n"
708 << "east = " << side<east>() << "\n"
709 << "south = " << side<south>() << "\n"
710 << "north = " << side<north>() << "\n"
711 << "front = " << side<front>() << "\n"
712 << "back = " << side<back>() << "\n)";
713 }
714
716 inline nlohmann::json to_json() const override {
717 nlohmann::json json;
718 json["west"] = side<west>().to_json();
719 json["east"] = side<east>().to_json();
720 json["south"] = side<south>().to_json();
721 json["north"] = side<north>().to_json();
722 json["front"] = side<front>().to_json();
723 json["back"] = side<back>().to_json();
724
725 return json;
726 }
727
729 inline BoundaryCore &from_json(const nlohmann::json &json) {
730 side<west>().from_json(json["west"]);
731 side<east>().from_json(json["east"]);
732 side<south>().from_json(json["south"]);
733 side<north>().from_json(json["north"]);
734 side<front>().from_json(json["front"]);
735 side<back>().from_json(json["back"]);
736
737 return *this;
738 }
739
741 inline eval_type greville() const {
742 return eval_type{side<west>().greville(), side<east>().greville(),
743 side<south>().greville(), side<north>().greville(),
744 side<front>().greville(), side<back>().greville()};
745 }
746};
747
759 template <typename Spline>
760 requires SplineType<Spline>
761class BoundaryCore<Spline, /* parDim */ 4> : public utils::Serializable,
763
765 template <typename BoundaryCore> friend class BoundaryCommon;
766
767protected:
769 using spline_type = Spline;
770
773 std::tuple<typename Spline::template derived_self_type<
774 typename Spline::value_type, Spline::geoDim(),
775 Spline::degree(1), Spline::degree(2), Spline::degree(3)>,
776 typename Spline::template derived_self_type<
777 typename Spline::value_type, Spline::geoDim(),
778 Spline::degree(0), Spline::degree(2), Spline::degree(3)>,
779 typename Spline::template derived_self_type<
780 typename Spline::value_type, Spline::geoDim(),
781 Spline::degree(0), Spline::degree(1), Spline::degree(3)>,
782 typename Spline::template derived_self_type<
783 typename Spline::value_type, Spline::geoDim(),
784 Spline::degree(0), Spline::degree(1), Spline::degree(2)>>;
785
788 template <typename real_t>
790 std::tuple<typename Spline::template derived_self_type<
791 real_t, Spline::geoDim(), Spline::degree(1),
792 Spline::degree(2), Spline::degree(3)>,
793 typename Spline::template derived_self_type<
794 real_t, Spline::geoDim(), Spline::degree(0),
795 Spline::degree(2), Spline::degree(3)>,
796 typename Spline::template derived_self_type<
797 real_t, Spline::geoDim(), Spline::degree(0),
798 Spline::degree(1), Spline::degree(3)>,
799 typename Spline::template derived_self_type<
800 real_t, Spline::geoDim(), Spline::degree(0),
801 Spline::degree(1), Spline::degree(2)>>;
802
804 std::tuple<typename std::tuple_element_t<0, boundary_spline_type>,
805 typename std::tuple_element_t<0, boundary_spline_type>,
806 typename std::tuple_element_t<1, boundary_spline_type>,
807 typename std::tuple_element_t<1, boundary_spline_type>,
808 typename std::tuple_element_t<2, boundary_spline_type>,
809 typename std::tuple_element_t<2, boundary_spline_type>,
810 typename std::tuple_element_t<3, boundary_spline_type>,
811 typename std::tuple_element_t<3, boundary_spline_type>>
813
814public:
816 using boundary_type = decltype(bdr_);
817
819 using eval_type = std::tuple<utils::TensorArray<3>, utils::TensorArray<3>,
823
827 : bdr_({std::tuple_element_t<0, boundary_spline_type>(options),
828 std::tuple_element_t<0, boundary_spline_type>(options),
829 std::tuple_element_t<1, boundary_spline_type>(options),
830 std::tuple_element_t<1, boundary_spline_type>(options),
831 std::tuple_element_t<2, boundary_spline_type>(options),
832 std::tuple_element_t<2, boundary_spline_type>(options),
833 std::tuple_element_t<3, boundary_spline_type>(options),
834 std::tuple_element_t<3, boundary_spline_type>(options)}) {}
835
837 BoundaryCore(const boundary_type &bdr_) : bdr_(bdr_) {}
838
840 BoundaryCore(boundary_type &&bdr_) : bdr_(bdr_) {}
841
843 BoundaryCore(const BoundaryCore &other, bool clone)
844 : bdr_(clone ? std::apply(
845 [](const auto &...bspline) {
846 return std::make_tuple(bspline.clone()...);
847 },
848 other.coeffs())
849 : other.coeffs()) {}
850
852 BoundaryCore(const std::array<int64_t, 4> &ncoeffs,
853 enum init init = init::zeros,
856 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
857 std::array<int64_t, 3>({ncoeffs[1], ncoeffs[2], ncoeffs[3]}),
858 init, options),
859 std::tuple_element_t<0, boundary_spline_type>(
860 std::array<int64_t, 3>({ncoeffs[1], ncoeffs[2], ncoeffs[3]}),
861 init, options),
862 std::tuple_element_t<1, boundary_spline_type>(
863 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[2], ncoeffs[3]}),
864 init, options),
865 std::tuple_element_t<1, boundary_spline_type>(
866 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[2], ncoeffs[3]}),
867 init, options),
868 std::tuple_element_t<2, boundary_spline_type>(
869 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[3]}),
870 init, options),
871 std::tuple_element_t<2, boundary_spline_type>(
872 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[3]}),
873 init, options),
874 std::tuple_element_t<3, boundary_spline_type>(
875 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[2]}),
876 init, options),
877 std::tuple_element_t<3, boundary_spline_type>(
878 std::array<int64_t, 3>({ncoeffs[0], ncoeffs[1], ncoeffs[2]}),
879 init, options)}) {}
880
883 const std::array<std::vector<typename Spline::value_type>, 4> &kv,
884 enum init init = init::zeros,
887 : bdr_({std::tuple_element_t<0, boundary_spline_type>(
888 std::array<std::vector<typename Spline::value_type>, 3>(
889 {kv[1], kv[2], kv[3]}),
890 init, options),
891 std::tuple_element_t<0, boundary_spline_type>(
892 std::array<std::vector<typename Spline::value_type>, 3>(
893 {kv[1], kv[2], kv[3]}),
894 init, options),
895 std::tuple_element_t<1, boundary_spline_type>(
896 std::array<std::vector<typename Spline::value_type>, 3>(
897 {kv[0], kv[2], kv[3]}),
898 init, options),
899 std::tuple_element_t<1, boundary_spline_type>(
900 std::array<std::vector<typename Spline::value_type>, 3>(
901 {kv[0], kv[2], kv[3]}),
902 init, options),
903 std::tuple_element_t<2, boundary_spline_type>(
904 std::array<std::vector<typename Spline::value_type>, 3>(
905 {kv[0], kv[1], kv[3]}),
906 init, options),
907 std::tuple_element_t<2, boundary_spline_type>(
908 std::array<std::vector<typename Spline::value_type>, 3>(
909 {kv[0], kv[1], kv[3]}),
910 init, options),
911 std::tuple_element_t<3, boundary_spline_type>(
912 std::array<std::vector<typename Spline::value_type>, 3>(
913 {kv[0], kv[1], kv[2]}),
914 init, options),
915 std::tuple_element_t<3, boundary_spline_type>(
916 std::array<std::vector<typename Spline::value_type>, 3>(
917 {kv[0], kv[1], kv[2]}),
918 init, options)}) {}
919
926 inline auto &from_full_tensor(const torch::Tensor &tensor) {
927
928 if (tensor.dim() > 1) {
929 auto tensor_view = tensor.view(
930 {-1, side<west>().ncoeffs(2), side<west>().ncoeffs(1),
931 side<west>().ncoeffs(0), side<south>().ncoeffs(0), tensor.size(-1)});
932
933 side<west>().from_tensor(
934 tensor_view
935 .index({torch::indexing::Slice(), torch::indexing::Slice(),
936 torch::indexing::Slice(), torch::indexing::Slice(), 0})
937 .reshape({-1, tensor.size(-1)}));
938 side<east>().from_tensor(
939 tensor_view
940 .index({torch::indexing::Slice(), torch::indexing::Slice(),
941 torch::indexing::Slice(), torch::indexing::Slice(), -1})
942 .reshape({-1, tensor.size(-1)}));
943 side<south>().from_tensor(
944 tensor_view
945 .index({torch::indexing::Slice(), torch::indexing::Slice(),
946 torch::indexing::Slice(), 0, torch::indexing::Slice()})
947 .reshape({-1, tensor.size(-1)}));
948 side<north>().from_tensor(
949 tensor_view
950 .index({torch::indexing::Slice(), torch::indexing::Slice(),
951 torch::indexing::Slice(), -1, torch::indexing::Slice()})
952 .reshape({-1, tensor.size(-1)}));
953 side<front>().from_tensor(
954 tensor_view
955 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
956 torch::indexing::Slice(), torch::indexing::Slice()})
957 .reshape({-1, tensor.size(-1)}));
958 side<back>().from_tensor(
959 tensor_view
960 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
961 torch::indexing::Slice(), torch::indexing::Slice()})
962 .reshape({-1, tensor.size(-1)}));
963 side<stime>().from_tensor(
964 tensor_view
965 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
966 torch::indexing::Slice(), torch::indexing::Slice()})
967 .reshape({-1, tensor.size(-1)}));
968 side<etime>().from_tensor(
969 tensor_view
970 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
971 torch::indexing::Slice(), torch::indexing::Slice()})
972 .reshape({-1, tensor.size(-1)}));
973 } else {
974 auto tensor_view =
975 tensor.view({-1, side<west>().ncoeffs(2), side<west>().ncoeffs(1),
976 side<west>().ncoeffs(0), side<south>().ncoeffs(0)});
977
978 side<west>().from_tensor(
979 tensor_view
980 .index({torch::indexing::Slice(), torch::indexing::Slice(),
981 torch::indexing::Slice(), torch::indexing::Slice(), 0})
982 .flatten());
983 side<east>().from_tensor(
984 tensor_view
985 .index({torch::indexing::Slice(), torch::indexing::Slice(),
986 torch::indexing::Slice(), torch::indexing::Slice(), -1})
987 .flatten());
988
989 side<south>().from_tensor(
990 tensor_view
991 .index({torch::indexing::Slice(), torch::indexing::Slice(),
992 torch::indexing::Slice(), 0, torch::indexing::Slice()})
993 .flatten());
994 side<north>().from_tensor(
995 tensor_view
996 .index({torch::indexing::Slice(), torch::indexing::Slice(),
997 torch::indexing::Slice(), -1, torch::indexing::Slice()})
998 .flatten());
999
1000 side<front>().from_tensor(
1001 tensor_view
1002 .index({torch::indexing::Slice(), torch::indexing::Slice(), 0,
1003 torch::indexing::Slice(), torch::indexing::Slice()})
1004 .flatten());
1005 side<back>().from_tensor(
1006 tensor_view
1007 .index({torch::indexing::Slice(), torch::indexing::Slice(), -1,
1008 torch::indexing::Slice(), torch::indexing::Slice()})
1009 .flatten());
1010
1011 side<stime>().from_tensor(
1012 tensor_view
1013 .index({torch::indexing::Slice(), 0, torch::indexing::Slice(),
1014 torch::indexing::Slice(), torch::indexing::Slice()})
1015 .flatten());
1016 side<etime>().from_tensor(
1017 tensor_view
1018 .index({torch::indexing::Slice(), -1, torch::indexing::Slice(),
1019 torch::indexing::Slice(), torch::indexing::Slice()})
1020 .flatten());
1021 }
1022 return *this;
1023 }
1024
1026 inline static constexpr short_t nsides() { return side::etime; }
1027
1029 template <short_t s> inline constexpr auto &side() const {
1030 static_assert(s > none && s <= nsides());
1031 return std::get<s - 1>(bdr_);
1032 }
1033
1035 template <short_t s> inline constexpr auto &side() {
1036 static_assert(s > none && s <= nsides());
1037 return std::get<s - 1>(bdr_);
1038 }
1039
1042 inline constexpr auto &coeffs() const { return bdr_; }
1043
1046 inline constexpr auto &coeffs() { return bdr_; }
1047
1049 inline int64_t ncumcoeffs() const {
1050 int64_t s = 0;
1051 s += side<west>().ncumcoeffs();
1052 s += side<east>().ncumcoeffs();
1053 s += side<south>().ncumcoeffs();
1054 s += side<north>().ncumcoeffs();
1055 s += side<front>().ncumcoeffs();
1056 s += side<back>().ncumcoeffs();
1057 s += side<stime>().ncumcoeffs();
1058 s += side<etime>().ncumcoeffs();
1059
1060 return s;
1061 }
1062
1064 inline virtual void
1065 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
1066 os << name() << "(\n"
1067 << "west = " << side<west>() << "\n"
1068 << "east = " << side<east>() << "\n"
1069 << "south = " << side<south>() << "\n"
1070 << "north = " << side<north>() << "\n"
1071 << "front = " << side<front>() << "\n"
1072 << "back = " << side<back>() << "\n"
1073 << "stime = " << side<stime>() << "\n"
1074 << "etime = " << side<etime>() << "\n)";
1075 }
1076
1078 inline nlohmann::json to_json() const override {
1079 nlohmann::json json;
1080 json["west"] = side<west>().to_json();
1081 json["east"] = side<east>().to_json();
1082 json["south"] = side<south>().to_json();
1083 json["north"] = side<north>().to_json();
1084 json["front"] = side<front>().to_json();
1085 json["back"] = side<back>().to_json();
1086 json["stime"] = side<stime>().to_json();
1087 json["etime"] = side<etime>().to_json();
1088
1089 return json;
1090 }
1091
1093 inline BoundaryCore &from_json(const nlohmann::json &json) {
1094 side<west>().from_json(json["west"]);
1095 side<east>().from_json(json["east"]);
1096 side<south>().from_json(json["south"]);
1097 side<north>().from_json(json["north"]);
1098 side<front>().from_json(json["front"]);
1099 side<back>().from_json(json["back"]);
1100 side<stime>().from_json(json["stime"]);
1101 side<etime>().from_json(json["etime"]);
1102
1103 return *this;
1104 }
1105
1107 inline eval_type greville() const {
1108 return eval_type{side<west>().greville(), side<east>().greville(),
1109 side<south>().greville(), side<north>().greville(),
1110 side<front>().greville(), side<back>().greville(),
1111 side<stime>().greville(), side<etime>().greville()};
1112 }
1113};
1114
1116 class Boundary_ {};
1117
1119 template<typename T>
1120 concept BoundaryType = std::is_base_of_v<Boundary_, T>;
1121
1123template <typename BoundaryCore>
1124class BoundaryCommon : public Boundary_, public BoundaryCore {
1125public:
1127 using BoundaryCore::BoundaryCore;
1128
1130 BoundaryCommon clone() const { return BoundaryCommon(*this); }
1131
1132private:
1137 template <std::size_t... Is>
1138 inline torch::Tensor as_tensor_(std::index_sequence<Is...>) const {
1139 return torch::cat({std::get<Is>(BoundaryCore::bdr_).as_tensor()...});
1140 }
1141
1142public:
1147 inline torch::Tensor as_tensor() const {
1148 return as_tensor_(std::make_index_sequence<BoundaryCore::nsides()>{});
1149 }
1150
1151private:
1156 template <std::size_t... Is>
1157 inline int64_t as_tensor_size_(std::index_sequence<Is...>) const {
1158 return std::apply(
1159 [](auto... size) { return (size + ...); },
1160 std::make_tuple(std::get<Is>(BoundaryCore::bdr_).as_tensor_size()...));
1161 }
1162
1163public:
1166 //
1168 inline int64_t as_tensor_size() const {
1169 return as_tensor_size_(std::make_index_sequence<BoundaryCore::nsides()>{});
1170 }
1171
1172private:
1179 template <std::size_t... Is>
1180 inline auto &from_tensor_(std::index_sequence<Is...>,
1181 const torch::Tensor &tensor) {
1182
1183 std::size_t start(0);
1184 auto end = [&start](std::size_t inc) { return start += inc; };
1185
1186 (std::get<Is>(BoundaryCore::bdr_)
1187 .from_tensor(tensor.index({torch::indexing::Slice(
1188 start, end(std::get<Is>(BoundaryCore::bdr_).ncumcoeffs() *
1189 std::get<Is>(BoundaryCore::bdr_).geoDim()))})),
1190 ...);
1191
1192 return *this;
1193 }
1194
1195public:
1202 inline auto &from_tensor(const torch::Tensor &tensor) {
1203 return from_tensor_(std::make_index_sequence<BoundaryCore::nsides()>{},
1204 tensor);
1205 }
1206
1207private:
1210 template <deriv deriv = deriv::func, bool memory_optimized = false,
1211 size_t... Is, typename... Xi>
1212 inline auto eval_(std::index_sequence<Is...>,
1213 const std::tuple<Xi...> &xi) const {
1214 return std::tuple(
1215 std::get<Is>(BoundaryCore::bdr_)
1216 .template eval<deriv, memory_optimized>(std::get<Is>(xi))...);
1217 }
1218
1219 template <deriv deriv = deriv::func, bool memory_optimized = false,
1220 size_t... Is, typename... Xi, typename... Indices>
1221 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
1222 const std::tuple<Indices...> &indices) const {
1223 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1224 .template eval<deriv, memory_optimized>(
1225 std::get<Is>(xi), std::get<Is>(indices))...);
1226 }
1227
1228 template <deriv deriv = deriv::func, bool memory_optimized = false,
1229 size_t... Is, typename... Xi, typename... Indices,
1230 typename... Coeff_Indices>
1231 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
1232 const std::tuple<Indices...> &indices,
1233 const std::tuple<Coeff_Indices...> &coeff_indices) const {
1234 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1235 .template eval<deriv, memory_optimized>(
1236 std::get<Is>(xi), std::get<Is>(indices),
1237 std::get<Is>(coeff_indices))...);
1238 }
1240
1241public:
1244 template <deriv deriv = deriv::func, bool memory_optimized = false,
1245 typename... Xi>
1246 inline auto eval(const std::tuple<Xi...> &xi) const {
1247 return eval_<deriv, memory_optimized>(
1248 std::make_index_sequence<BoundaryCore::nsides()>{}, xi);
1249 }
1250
1251 template <deriv deriv = deriv::func, bool memory_optimized = false,
1252 typename... Xi, typename... Indices>
1253 inline auto eval(const std::tuple<Xi...> &xi,
1254 const std::tuple<Indices...> &indices) const {
1255 static_assert(sizeof...(Xi) == sizeof...(Indices));
1256 return eval_<deriv, memory_optimized>(
1257 std::make_index_sequence<BoundaryCore::nsides()>{}, xi, indices);
1258 }
1259
1260 template <deriv deriv = deriv::func, bool memory_optimized = false,
1261 typename... Xi, typename... Indices, typename... Coeff_Indices>
1262 inline auto eval(const std::tuple<Xi...> &xi,
1263 const std::tuple<Indices...> &indices,
1264 const std::tuple<Coeff_Indices...> &coeff_indices) const {
1265 static_assert(sizeof...(Xi) == sizeof...(Indices) &&
1266 sizeof...(Xi) == sizeof...(Coeff_Indices));
1267 return eval_<deriv, memory_optimized>(
1268 std::make_index_sequence<BoundaryCore::nsides()>{}, xi, indices,
1269 coeff_indices);
1270 }
1272
1273private:
1276 template <size_t... Is, typename... Basfunc, typename... Coeff_Indices,
1277 typename... Numeval, typename... Sizes>
1278 inline auto
1279 eval_from_precomputed_(std::index_sequence<Is...>,
1280 const std::tuple<Basfunc...> &basfunc,
1281 const std::tuple<Coeff_Indices...> &coeff_indices,
1282 const std::tuple<Numeval...> &numeval,
1283 const std::tuple<Sizes...> &sizes) const {
1284 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1285 .eval_from_precomputed(std::get<Is>(basfunc),
1286 std::get<Is>(coeff_indices),
1287 std::get<Is>(numeval),
1288 std::get<Is>(sizes))...);
1289 }
1290
1291 template <size_t... Is, typename... Basfunc, typename... Coeff_Indices,
1292 typename... Xi>
1293 inline auto
1294 eval_from_precomputed_(std::index_sequence<Is...>,
1295 const std::tuple<Basfunc...> &basfunc,
1296 const std::tuple<Coeff_Indices...> &coeff_indices,
1297 const std::tuple<Xi...> &xi) const {
1298 return std::tuple(
1299 std::get<Is>(BoundaryCore::bdr_)
1301 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
1302 std::get<Is>(xi)[0].numel(), std::get<Is>(xi)[0].sizes())...);
1303 }
1305
1306public:
1309 template <typename... Basfunc, typename... Coeff_Indices, typename... Numeval,
1310 typename... Sizes>
1311 inline auto
1312 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
1313 const std::tuple<Coeff_Indices...> &coeff_indices,
1314 const std::tuple<Numeval...> &numeval,
1315 const std::tuple<Sizes...> &sizes) const {
1316 static_assert(sizeof...(Basfunc) == sizeof...(Coeff_Indices) &&
1317 sizeof...(Basfunc) == sizeof...(Numeval) &&
1318 sizeof...(Basfunc) == sizeof...(Sizes));
1320 std::make_index_sequence<BoundaryCore::nsides()>{}, basfunc,
1321 coeff_indices, numeval, sizes);
1322 }
1323
1324 template <typename... Basfunc, typename... Coeff_Indices, typename... Xi>
1325 inline auto
1326 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
1327 const std::tuple<Coeff_Indices...> &coeff_indices,
1328 const std::tuple<Xi...> &xi) const {
1329 static_assert(sizeof...(Basfunc) == sizeof...(Coeff_Indices) &&
1330 sizeof...(Basfunc) == sizeof...(Xi));
1332 std::make_index_sequence<BoundaryCore::nsides()>{}, basfunc,
1333 coeff_indices, xi);
1334 }
1336
1337private:
1340 template <size_t... Is, typename... Xi>
1341 inline auto find_knot_indices_(std::index_sequence<Is...>,
1342 const std::tuple<Xi...> &xi) const {
1343 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1344 .find_knot_indices(std::get<Is>(xi))...);
1345 }
1346
1347public:
1349 template <typename... Xi>
1350 inline auto find_knot_indices(const std::tuple<Xi...> &xi) const {
1351 return find_knot_indices_(
1352 std::make_index_sequence<BoundaryCore::nsides()>{}, xi);
1353 }
1354
1355private:
1359 template <deriv deriv = deriv::func, bool memory_optimized = false,
1360 size_t... Is, typename... Xi>
1361 inline auto eval_basfunc_(std::index_sequence<Is...>,
1362 const std::tuple<Xi...> &xi) const {
1363 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1364 .template eval_basfunc<deriv, memory_optimized>(
1365 std::get<Is>(xi))...);
1366 }
1367
1368 template <deriv deriv = deriv::func, bool memory_optimized = false,
1369 size_t... Is, typename... Xi, typename... Indices>
1370 inline auto eval_basfunc_(std::index_sequence<Is...>,
1371 const std::tuple<Xi...> &xi,
1372 const std::tuple<Indices...> &indices) const {
1373 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1374 .template eval_basfunc<deriv, memory_optimized>(
1375 std::get<Is>(xi), std::get<Is>(indices))...);
1376 }
1378
1379public:
1382 template <deriv deriv = deriv::func, bool memory_optimized = false,
1383 typename... Xi>
1384 inline auto eval_basfunc(const std::tuple<Xi...> &xi) const {
1385 return eval_basfunc_<deriv, memory_optimized>(
1386 std::make_index_sequence<BoundaryCore::nsides()>{}, xi);
1387 }
1388
1389 template <deriv deriv = deriv::func, bool memory_optimized = false,
1390 typename... Xi, typename... Indices>
1391 inline auto eval_basfunc(const std::tuple<Xi...> &xi,
1392 const std::tuple<Indices...> &indices) const {
1393 static_assert(sizeof...(Xi) == sizeof...(Indices));
1394 return eval_basfunc_<deriv, memory_optimized>(
1395 std::make_index_sequence<BoundaryCore::nsides()>{}, xi, indices);
1396 }
1398
1399private:
1402 template <bool memory_optimized = false, size_t... Is, typename... Indices>
1403 inline auto find_coeff_indices_(std::index_sequence<Is...>,
1404 const std::tuple<Indices...> &indices) const {
1405 return std::tuple(std::get<Is>(BoundaryCore::bdr_)
1406 .template find_coeff_indices<memory_optimized>(
1407 std::get<Is>(indices))...);
1408 }
1409
1410public:
1413 template <bool memory_optimized = false, typename... Indices>
1414 inline auto find_coeff_indices(const std::tuple<Indices...> &indices) const {
1415 return find_coeff_indices_<memory_optimized>(
1416 std::make_index_sequence<BoundaryCore::nsides()>{}, indices);
1417 }
1418
1419private:
1422 template <size_t... Is>
1423 inline auto &uniform_refine_(std::index_sequence<Is...>, int numRefine = 1,
1424 int dim = -1) {
1425 (std::get<Is>(BoundaryCore::bdr_).uniform_refine(numRefine, dim), ...);
1426 return *this;
1427 }
1428
1429public:
1432 inline auto &uniform_refine(int numRefine = 1, int dim = -1) {
1433 if (dim == -1) {
1434 if constexpr (BoundaryCore::spline_type::parDim() > 1)
1435 uniform_refine_(std::make_index_sequence<BoundaryCore::nsides()>{},
1436 numRefine, dim);
1437 } else if (dim == 0) {
1438 if constexpr (BoundaryCore::nsides() == 2) {
1439 // We do not refine the boundary of a curve
1440 } else if constexpr (BoundaryCore::nsides() == 4) {
1441 std::get<side::south - 1>(BoundaryCore::bdr_)
1442 .uniform_refine(numRefine, 0);
1443 std::get<side::north - 1>(BoundaryCore::bdr_)
1444 .uniform_refine(numRefine, 0);
1445 } else if constexpr (BoundaryCore::nsides() == 6) {
1446 std::get<side::south - 1>(BoundaryCore::bdr_)
1447 .uniform_refine(numRefine, 0);
1448 std::get<side::north - 1>(BoundaryCore::bdr_)
1449 .uniform_refine(numRefine, 0);
1450 std::get<side::front - 1>(BoundaryCore::bdr_)
1451 .uniform_refine(numRefine, 0);
1452 std::get<side::back - 1>(BoundaryCore::bdr_)
1453 .uniform_refine(numRefine, 0);
1454 } else if constexpr (BoundaryCore::nsides() == 8) {
1455 std::get<side::south - 1>(BoundaryCore::bdr_)
1456 .uniform_refine(numRefine, 0);
1457 std::get<side::north - 1>(BoundaryCore::bdr_)
1458 .uniform_refine(numRefine, 0);
1459 std::get<side::front - 1>(BoundaryCore::bdr_)
1460 .uniform_refine(numRefine, 0);
1461 std::get<side::back - 1>(BoundaryCore::bdr_)
1462 .uniform_refine(numRefine, 0);
1463 std::get<side::stime - 1>(BoundaryCore::bdr_)
1464 .uniform_refine(numRefine, 0);
1465 std::get<side::etime - 1>(BoundaryCore::bdr_)
1466 .uniform_refine(numRefine, 0);
1467 } else
1468 throw std::runtime_error("Invalid dimension");
1469 } else if (dim == 1) {
1470 if constexpr (BoundaryCore::nsides() == 4) {
1471 std::get<side::east - 1>(BoundaryCore::bdr_)
1472 .uniform_refine(numRefine, 0);
1473 std::get<side::west - 1>(BoundaryCore::bdr_)
1474 .uniform_refine(numRefine, 0);
1475 } else if constexpr (BoundaryCore::nsides() == 6) {
1476 std::get<side::east - 1>(BoundaryCore::bdr_)
1477 .uniform_refine(numRefine, 0);
1478 std::get<side::west - 1>(BoundaryCore::bdr_)
1479 .uniform_refine(numRefine, 0);
1480 std::get<side::front - 1>(BoundaryCore::bdr_)
1481 .uniform_refine(numRefine, 1);
1482 std::get<side::back - 1>(BoundaryCore::bdr_)
1483 .uniform_refine(numRefine, 1);
1484
1485 } else if constexpr (BoundaryCore::nsides() == 8) {
1486 std::get<side::east - 1>(BoundaryCore::bdr_)
1487 .uniform_refine(numRefine, 0);
1488 std::get<side::west - 1>(BoundaryCore::bdr_)
1489 .uniform_refine(numRefine, 0);
1490 std::get<side::front - 1>(BoundaryCore::bdr_)
1491 .uniform_refine(numRefine, 1);
1492 std::get<side::back - 1>(BoundaryCore::bdr_)
1493 .uniform_refine(numRefine, 1);
1494 std::get<side::stime - 1>(BoundaryCore::bdr_)
1495 .uniform_refine(numRefine, 1);
1496 std::get<side::etime - 1>(BoundaryCore::bdr_)
1497 .uniform_refine(numRefine, 1);
1498 } else
1499 throw std::runtime_error("Invalid dimension");
1500 } else if (dim == 2) {
1501 if constexpr (BoundaryCore::nsides() == 6) {
1502 std::get<side::east - 1>(BoundaryCore::bdr_)
1503 .uniform_refine(numRefine, 1);
1504 std::get<side::west - 1>(BoundaryCore::bdr_)
1505 .uniform_refine(numRefine, 1);
1506 std::get<side::north - 1>(BoundaryCore::bdr_)
1507 .uniform_refine(numRefine, 1);
1508 std::get<side::south - 1>(BoundaryCore::bdr_)
1509 .uniform_refine(numRefine, 1);
1510 } else if constexpr (BoundaryCore::nsides() == 8) {
1511 std::get<side::west - 1>(BoundaryCore::bdr_)
1512 .uniform_refine(numRefine, 1);
1513 std::get<side::east - 1>(BoundaryCore::bdr_)
1514 .uniform_refine(numRefine, 1);
1515 std::get<side::south - 1>(BoundaryCore::bdr_)
1516 .uniform_refine(numRefine, 1);
1517 std::get<side::north - 1>(BoundaryCore::bdr_)
1518 .uniform_refine(numRefine, 1);
1519 std::get<side::stime - 1>(BoundaryCore::bdr_)
1520 .uniform_refine(numRefine, 2);
1521 std::get<side::etime - 1>(BoundaryCore::bdr_)
1522 .uniform_refine(numRefine, 2);
1523 } else
1524 throw std::runtime_error("Invalid dimension");
1525 } else if (dim == 3) {
1526 if constexpr (BoundaryCore::nsides() == 8) {
1527 std::get<side::west - 1>(BoundaryCore::bdr_)
1528 .uniform_refine(numRefine, 2);
1529 std::get<side::east - 1>(BoundaryCore::bdr_)
1530 .uniform_refine(numRefine, 2);
1531 std::get<side::south - 1>(BoundaryCore::bdr_)
1532 .uniform_refine(numRefine, 2);
1533 std::get<side::north - 1>(BoundaryCore::bdr_)
1534 .uniform_refine(numRefine, 2);
1535 std::get<side::front - 1>(BoundaryCore::bdr_)
1536 .uniform_refine(numRefine, 2);
1537 std::get<side::back - 1>(BoundaryCore::bdr_)
1538 .uniform_refine(numRefine, 2);
1539 } else
1540 throw std::runtime_error("Invalid dimension");
1541 } else
1542 throw std::runtime_error("Invalid dimension");
1543 return *this;
1544 }
1545
1546private:
1549 template <size_t... Is>
1550 inline torch::serialize::OutputArchive &
1551 write_(std::index_sequence<Is...>, torch::serialize::OutputArchive &archive,
1552 const std::string &key = "boundary") const {
1553 (std::get<Is>(BoundaryCore::bdr_)
1554 .write(archive, key + ".bdr[" + std::to_string(Is) + "]"),
1555 ...);
1556 return archive;
1557 }
1558
1559public:
1561 inline void save(const std::string &filename,
1562 const std::string &key = "boundary") const {
1563 torch::serialize::OutputArchive archive;
1564 write(archive, key).save_to(filename);
1565 }
1566
1569 inline torch::serialize::OutputArchive &
1570 write(torch::serialize::OutputArchive &archive,
1571 const std::string &key = "boundary") const {
1572 write_(std::make_index_sequence<BoundaryCore::nsides()>{}, archive, key);
1573 return archive;
1574 }
1575
1576private:
1579 template <size_t... Is>
1580 inline torch::serialize::InputArchive &
1581 read_(std::index_sequence<Is...>, torch::serialize::InputArchive &archive,
1582 const std::string &key = "boundary") {
1583 (std::get<Is>(BoundaryCore::bdr_)
1584 .read(archive, key + ".bdr[" + std::to_string(Is) + "]"),
1585 ...);
1586 return archive;
1587 }
1588
1589public:
1591 inline void load(const std::string &filename,
1592 const std::string &key = "boundary") {
1593 torch::serialize::InputArchive archive;
1594 archive.load_from(filename);
1595 read(archive, key);
1596 }
1597
1600 inline torch::serialize::InputArchive &
1601 read(torch::serialize::InputArchive &archive,
1602 const std::string &key = "boundary") {
1603 read_(std::make_index_sequence<BoundaryCore::nsides()>{}, archive, key);
1604 return archive;
1605 }
1606
1608 inline pugi::xml_document to_xml(int id = 0, std::string label = "",
1609 int index = -1) const {
1610 pugi::xml_document doc;
1611 pugi::xml_node root = doc.append_child("xml");
1612 to_xml(root, id, label, index);
1613
1614 return doc;
1615 }
1616
1618 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
1619 std::string label = "", int index = -1) const {
1620 // add Boundary node
1621 pugi::xml_node bdr = root.append_child("Boundary");
1622
1623 if (id >= 0)
1624 bdr.append_attribute("id") = id;
1625
1626 if (index >= 0)
1627 bdr.append_attribute("index") = index;
1628
1629 if (!label.empty())
1630 bdr.append_attribute("label") = label.c_str();
1631
1632 int index_ = 0;
1633 std::apply(
1634 [&bdr, &index_](const auto &...bspline) {
1635 (bspline.to_xml(bdr, -1, "", index_++), ...);
1636 },
1637 BoundaryCore::bdr_);
1638
1639 return root;
1640 }
1641
1643 inline BoundaryCommon &from_xml(const pugi::xml_document &doc, int id = 0,
1644 std::string label = "", int index = -1) {
1645 return from_xml(doc.child("xml"), id, label, index);
1646 }
1647
1649 inline BoundaryCommon &from_xml(const pugi::xml_node &root, int id = 0,
1650 std::string label = "", int index = -1) {
1651
1652 // Loop through all boundary nodes
1653 for (pugi::xml_node bdr : root.children("Boundary")) {
1654
1655 // Check for "Boundary" with given id, index, label
1656 if ((id >= 0 ? bdr.attribute("id").as_int() == id : true) &&
1657 (index >= 0 ? bdr.attribute("index").as_int() == index : true) &&
1658 (!label.empty() ? bdr.attribute("label").value() == label : true)) {
1659
1660 int index_ = 0;
1661 std::apply(
1662 [&bdr, &index_](auto &...bspline) {
1663 (bspline.from_xml(bdr, -1, "", index_++), ...);
1664 },
1665 BoundaryCore::bdr_);
1666
1667 return *this;
1668 } else
1669 continue; // try next "Boundary"
1670 }
1671
1672 throw std::runtime_error("XML object does not provide geometry with given "
1673 "id, index, and/or label");
1674 return *this;
1675 }
1676
1677private:
1680 template <typename BoundaryCore_, size_t... Is>
1681 inline bool isequal_(std::index_sequence<Is...>,
1682 const BoundaryCommon<BoundaryCore_> &other) const {
1683 return (
1684 (std::get<Is>(BoundaryCore::bdr_) == std::get<Is>(other.coeffs())) &&
1685 ...);
1686 }
1687
1688public:
1690 template <typename BoundaryCore_>
1691 inline bool operator==(const BoundaryCommon<BoundaryCore_> &other) const {
1692 return isequal_(std::make_index_sequence<BoundaryCore::nsides()>{}, other);
1693 }
1694
1696 template <typename BoundaryCore_>
1697 inline bool operator!=(const BoundaryCommon<BoundaryCore_> &other) const {
1698 return !(
1699 *this ==
1700 other); // Do not change this to (*this != other) is it does not work
1701 }
1702
1703private:
1706 template <typename BoundaryCore_, size_t... Is>
1707 inline bool
1708 isclose_(std::index_sequence<Is...>,
1709 const BoundaryCommon<BoundaryCore_> &other,
1710 typename BoundaryCore::spline_type::value_type rtol,
1711 typename BoundaryCore::spline_type::value_type atol) const {
1712 return ((std::get<Is>(BoundaryCore::bdr_)
1713 .isclose(std::get<Is>(other.coeffs()))) &&
1714 ...);
1715 }
1716
1717public:
1720 template <typename BoundaryCore_>
1721 inline bool
1723 typename BoundaryCore::spline_type::value_type rtol =
1724 typename BoundaryCore::spline_type::value_type{1e-5},
1725 typename BoundaryCore::spline_type::value_type atol =
1726 typename BoundaryCore::spline_type::value_type{1e-8}) const {
1727 return isclose_(std::make_index_sequence<BoundaryCore::nsides()>{}, other,
1728 rtol, atol);
1729 }
1730
1731#define GENERATE_EXPR_MACRO(r, data, name) \
1732private: \
1733 template <bool memory_optimized = false, size_t... Is, typename... Xi> \
1734 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
1735 const std::tuple<Xi...> &xi) const { \
1736 return std::tuple( \
1737 std::get<Is>(BoundaryCore::bdr_) \
1738 .template name<memory_optimized>(std::get<Is>(xi))...); \
1739 } \
1740 \
1741 template <bool memory_optimized = false, size_t... Is, typename... Xi, \
1742 typename... Indices> \
1743 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
1744 const std::tuple<Xi...> &xi, \
1745 const std::tuple<Indices...> &indices) \
1746 const { \
1747 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1748 .template name<memory_optimized>( \
1749 std::get<Is>(xi), std::get<Is>(indices))...); \
1750 } \
1751 \
1752 template <bool memory_optimized = false, size_t... Is, typename... Xi, \
1753 typename... Indices, typename... Coeff_Indices> \
1754 inline auto BOOST_PP_CAT(name, _)( \
1755 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
1756 const std::tuple<Indices...> &indices, \
1757 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
1758 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1759 .template name<memory_optimized>( \
1760 std::get<Is>(xi), std::get<Is>(indices), \
1761 std::get<Is>(coeff_indices))...); \
1762 } \
1763 \
1764public: \
1765 template <bool memory_optimized = false, typename... Args> \
1766 inline auto name(const Args &...args) const { \
1767 return BOOST_PP_CAT(name, _)<memory_optimized>( \
1768 std::make_index_sequence<BoundaryCore::nsides()>{}, args...); \
1769 }
1770
1773 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
1775#undef GENERATE_EXPR_MACRO
1776
1777#define GENERATE_IEXPR_MACRO(r, data, name) \
1778private: \
1779 template <bool memory_optimized = false, size_t... Is, typename... Geometry, \
1780 typename... Xi> \
1781 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
1782 const std::tuple<Geometry...> &G, \
1783 const std::tuple<Xi...> &xi) const { \
1784 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1785 .template name<memory_optimized>( \
1786 std::get<Is>(G), std::get<Is>(xi))...); \
1787 } \
1788 \
1789 template <bool memory_optimized = false, size_t... Is, typename... Geometry, \
1790 typename... Xi, typename... Indices> \
1791 inline auto BOOST_PP_CAT(name, _)( \
1792 std::index_sequence<Is...>, const std::tuple<Geometry...> &G, \
1793 const std::tuple<Xi...> &xi, const std::tuple<Indices...> &indices) \
1794 const { \
1795 return std::tuple( \
1796 std::get<Is>(BoundaryCore::bdr_) \
1797 .template name<memory_optimized>( \
1798 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(indices))...); \
1799 } \
1800 \
1801 template <bool memory_optimized = false, size_t... Is, typename... Geometry, \
1802 typename... Xi, typename... Indices, typename... Coeff_Indices> \
1803 inline auto BOOST_PP_CAT(name, _)( \
1804 std::index_sequence<Is...>, const std::tuple<Geometry...> &G, \
1805 const std::tuple<Xi...> &xi, const std::tuple<Indices...> &indices, \
1806 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
1807 return std::tuple(std::get<Is>(BoundaryCore::bdr_) \
1808 .template name<memory_optimized>( \
1809 std::get<Is>(G), std::get<Is>(xi), \
1810 std::get<Is>(indices), \
1811 std::get<Is>(coeff_indices))...); \
1812 } \
1813 \
1814public: \
1815 template <bool memory_optimized = false, typename... Args> \
1816 inline auto name(const Args &...args) const { \
1817 return BOOST_PP_CAT(name, _)<memory_optimized>( \
1818 std::make_index_sequence<BoundaryCore::nsides()>{}, args...); \
1819 }
1820
1823 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
1825#undef GENERATE_IEXPR_MACRO
1826
1828 auto device() const noexcept {
1829 return std::apply(
1830 [](const auto &...bspline) {
1831 return std::make_tuple(bspline.device()...);
1832 },
1833 BoundaryCore::bdr_);
1834 }
1835
1837 auto device_index() const noexcept {
1838 return std::apply(
1839 [](const auto &...bspline) {
1840 return std::make_tuple(bspline.device_index()...);
1841 },
1842 BoundaryCore::bdr_);
1843 }
1844
1846 auto dtype() const noexcept {
1847 return std::apply(
1848 [](const auto &...bspline) {
1849 return std::make_tuple(bspline.dtype()...);
1850 },
1851 BoundaryCore::bdr_);
1852 }
1853
1855 auto layout() const noexcept {
1856 return std::apply(
1857 [](const auto &...bspline) {
1858 return std::make_tuple(bspline.layout()...);
1859 },
1860 BoundaryCore::bdr_);
1861 }
1862
1864 auto requires_grad() const noexcept {
1865 return std::apply(
1866 [](const auto &...bspline) {
1867 return std::make_tuple(bspline.requires_grad()...);
1868 },
1869 BoundaryCore::bdr_);
1870 }
1871
1873 auto pinned_memory() const noexcept {
1874 return std::apply(
1875 [](const auto &...bspline) {
1876 return std::make_tuple(bspline.pinned_memory()...);
1877 },
1878 BoundaryCore::bdr_);
1879 }
1880
1882 auto is_sparse() const noexcept {
1883 return std::apply(
1884 [](const auto &...bspline) {
1885 return std::make_tuple(bspline.is_sparse()...);
1886 },
1887 BoundaryCore::bdr_);
1888 }
1889
1891 auto is_uniform() const noexcept {
1892 return std::apply(
1893 [](const auto &...bspline) {
1894 return std::make_tuple(bspline.is_uniform()...);
1895 },
1896 BoundaryCore::bdr_);
1897 }
1898
1900 auto is_nonuniform() const noexcept {
1901 return std::apply(
1902 [](const auto &...bspline) {
1903 return std::make_tuple(bspline.is_nonuniform()...);
1904 },
1905 BoundaryCore::bdr_);
1906 }
1907
1910 std::apply(
1911 [requires_grad](const auto &...bspline) {
1912 (bspline.set_requires_grad(requires_grad), ...);
1913 },
1914 BoundaryCore::bdr_);
1915
1916 return *this;
1917 }
1918
1920 template <typename real_t> inline auto to(Options<real_t> options) const {
1921 using boundary_type = BoundaryCommon<iganet::BoundaryCore<
1922 decltype(typename BoundaryCore::spline_type{}.to(options)),
1923 BoundaryCore::spline_type::parDim()>>;
1924
1925 return boundary_type(std::apply(
1926 [&options](const auto &...bspline) {
1927 return std::make_tuple(bspline.to(options)...);
1928 },
1929 BoundaryCore::bdr_));
1930 }
1931
1933 inline auto to(torch::Device device) const {
1934 return BoundaryCommon(std::apply(
1935 [&device](const auto &...bspline) {
1936 return std::make_tuple(bspline.to(device)...);
1937 },
1938 BoundaryCore::bdr_));
1939 }
1940
1942 template <typename real_t> inline auto to() const {
1943 using boundary_type = BoundaryCommon<iganet::BoundaryCore<
1944 decltype(typename BoundaryCore::spline_type{}.template to<real_t>()),
1945 BoundaryCore::spline_type::parDim()>>;
1946
1947 return boundary_type(std::apply(
1948 [](const auto &...bspline) {
1949 return std::make_tuple(bspline.template to<real_t>()...);
1950 },
1951 BoundaryCore::bdr_));
1952 }
1953};
1954
1956 template <typename Spline>
1957 requires SplineType<Spline>
1958using Boundary = BoundaryCommon<BoundaryCore<Spline, Spline::parDim()>>;
1959
1961 template <typename Spline>
1962 requires SplineType<Spline>
1963inline std::ostream &operator<<(std::ostream &os, const Boundary<Spline> &obj) {
1964 obj.pretty_print(os);
1965 return os;
1966}
1967
1968} // namespace iganet
#define GENERATE_IEXPR_MACRO(r, data, name)
Auto-generated functions.
Definition boundary.hpp:1777
#define GENERATE_EXPR_MACRO(r, data, name)
Definition boundary.hpp:1731
Multivariate B-splines.
#define GENERATE_EXPR_SEQ
Sequence of expression (parametric coordinates)
Definition bspline.hpp:41
#define GENERATE_IEXPR_SEQ
Sequence of expression (physical coordinates)
Definition bspline.hpp:47
Boundary base class
Definition boundary.hpp:1116
Boundary (common high-level functionality)
Definition boundary.hpp:1124
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition boundary.hpp:1350
auto to(torch::Device device) const
Returns a copy of the boundary object with settings from device.
Definition boundary.hpp:1933
auto dtype() const noexcept
Returns the dtype property of all splines.
Definition boundary.hpp:1846
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:1312
auto pinned_memory() const noexcept
Returns the pinned_memory property of all splines.
Definition boundary.hpp:1873
bool isequal_(std::index_sequence< Is... >, const BoundaryCommon< BoundaryCore_ > &other) const
Returns true if both boundary spline objects are the same.
Definition boundary.hpp:1681
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:1384
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:1601
auto eval(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects in the points xi
Definition boundary.hpp:1246
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:1279
auto to() const
Returns a copy of the boundary object with real_t type.
Definition boundary.hpp:1942
bool isclose_(std::index_sequence< Is... >, const BoundaryCommon< BoundaryCore_ > &other, typename BoundaryCore::spline_type::value_type rtol, typename BoundaryCore::spline_type::value_type atol) const
Returns true if both boundary spline objects are close up to the given tolerances.
Definition boundary.hpp:1708
auto to(Options< real_t > options) const
Returns a copy of the boundary object with settings from options.
Definition boundary.hpp:1920
auto device_index() const noexcept
Returns the device_index property of all splines.
Definition boundary.hpp:1837
auto is_uniform() const noexcept
Returns true if the B-spline is uniform of all splines.
Definition boundary.hpp:1891
BoundaryCommon & from_xml(const pugi::xml_document &doc, int id=0, std::string label="", int index=-1)
Updates the boundary object from XML object.
Definition boundary.hpp:1643
torch::Tensor as_tensor_(std::index_sequence< Is... >) const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1138
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:1157
auto eval_basfunc_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the values of the boundary spline spline object's basis functions in the points xi
Definition boundary.hpp:1361
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:1341
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:1423
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:1551
pugi::xml_document to_xml(int id=0, std::string label="", int index=-1) const
Returns the boundary object as XML object.
Definition boundary.hpp:1608
auto is_nonuniform() const noexcept
Returns true if the B-spline is non-uniform if all splines.
Definition boundary.hpp:1900
BoundaryCommon & from_xml(const pugi::xml_node &root, int id=0, std::string label="", int index=-1)
Updates the boundary object from XML node.
Definition boundary.hpp:1649
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:1231
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:1414
auto requires_grad() const noexcept
Returns the requires_grad property of all splines.
Definition boundary.hpp:1864
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:1253
BoundaryCommon clone() const
Returns a clone of the boundary object.
Definition boundary.hpp:1130
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:1391
auto & from_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor.
Definition boundary.hpp:1202
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:1180
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:1262
void load(const std::string &filename, const std::string &key="boundary")
Loads the boundary spline object from file.
Definition boundary.hpp:1591
torch::Tensor as_tensor() const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1147
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 spline object's basis functions in the points xi
Definition boundary.hpp:1370
BoundaryCommon & set_requires_grad(bool requires_grad)
Sets the boundary object's requires_grad property.
Definition boundary.hpp:1909
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:1212
pugi::xml_node & to_xml(pugi::xml_node &root, int id=0, std::string label="", int index=-1) const
Returns the boundary object as XML node.
Definition boundary.hpp:1618
bool isclose(const BoundaryCommon< BoundaryCore_ > &other, typename BoundaryCore::spline_type::value_type rtol=typename BoundaryCore::spline_type::value_type{1e-5}, typename 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:1722
auto & uniform_refine(int numRefine=1, int dim=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition boundary.hpp:1432
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:1294
int64_t as_tensor_size() const
Returns the size of the single tensor representation of all spline objects.
Definition boundary.hpp:1168
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:1326
bool operator==(const BoundaryCommon< BoundaryCore_ > &other) const
Returns true if both boundary objects are the same.
Definition boundary.hpp:1691
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:1403
auto layout() const noexcept
Returns the layout property of all splines.
Definition boundary.hpp:1855
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:1570
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:1581
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:1221
void save(const std::string &filename, const std::string &key="boundary") const
Saves the boundary spline to file.
Definition boundary.hpp:1561
auto device() const noexcept
Auto-generated functions.
Definition boundary.hpp:1828
bool operator!=(const BoundaryCommon< BoundaryCore_ > &other) const
Returns true if both boundary objects are different.
Definition boundary.hpp:1697
auto is_sparse() const noexcept
Returns if the layout is sparse of all splines.
Definition boundary.hpp:1882
constexpr auto & side() const
Returns constant reference to side-th Spline.
Definition boundary.hpp:147
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:103
std::tuple< boundary_spline_type, boundary_spline_type > bdr_
Tuple of splines.
Definition boundary.hpp:73
std::tuple< torch::Tensor, torch::Tensor > eval_type
Evaluation type.
Definition boundary.hpp:80
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:94
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:88
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:110
constexpr auto & coeffs() const
Returns a constant reference to the array of coefficients for all boundary segments.
Definition boundary.hpp:160
typename 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:70
constexpr auto & coeffs()
Returns a non-constant reference to the array of coefficients for all boundary segments.
Definition boundary.hpp:164
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:144
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:83
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:167
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:193
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:91
constexpr auto & side()
Returns non-constant reference to side-th Spline.
Definition boundary.hpp:153
typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim()> boundary_spline_type
Boundary spline type.
Definition boundary.hpp:64
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:177
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:184
Spline spline_type
Spline type.
Definition boundary.hpp:59
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:77
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:201
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:123
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:230
constexpr auto & side()
Returns non-constant reference to the s-th side's spline.
Definition boundary.hpp:379
std::tuple< utils::TensorArray< 1 >, utils::TensorArray< 1 >, utils::TensorArray< 1 >, utils::TensorArray< 1 > > eval_type
Evaluation type.
Definition boundary.hpp:254
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:370
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:435
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:271
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:414
constexpr auto & coeffs()
Returns a non-constant reference to the array of coefficients for all boundary segments.
Definition boundary.hpp:390
constexpr auto & coeffs() const
Returns a constant reference to the array of coefficients for all boundary segments.
Definition boundary.hpp:386
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:425
Spline spline_type
Spline type.
Definition boundary.hpp:223
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:322
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:405
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:250
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:257
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:265
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:239
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:280
constexpr auto & side() const
Returns constant reference to the s-th side's spline.
Definition boundary.hpp:373
std::tuple< typename std::tuple_element_t< 0, boundary_spline_type >, typename std::tuple_element_t< 0, boundary_spline_type >, typename std::tuple_element_t< 1, boundary_spline_type >, typename std::tuple_element_t< 1, boundary_spline_type > > bdr_
Tuple of splines.
Definition boundary.hpp:246
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:393
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:294
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:268
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:729
constexpr auto & side() const
Returns constant reference to side-th spline.
Definition boundary.hpp:671
constexpr auto & coeffs() const
Returns a constant reference to the array of coefficients for all boundary segments.
Definition boundary.hpp:684
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:553
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:514
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:496
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:520
Spline spline_type
Spline type.
Definition boundary.hpp:460
std::tuple< typename std::tuple_element_t< 0, boundary_spline_type >, typename std::tuple_element_t< 0, boundary_spline_type >, typename std::tuple_element_t< 1, boundary_spline_type >, typename std::tuple_element_t< 1, boundary_spline_type >, typename std::tuple_element_t< 2, boundary_spline_type >, typename std::tuple_element_t< 2, boundary_spline_type > > bdr_
Tuple of splines.
Definition boundary.hpp:492
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:472
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:705
constexpr auto & coeffs()
Returns a non-constant reference to the array of coefficients for all boundary segments.
Definition boundary.hpp:688
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:517
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:504
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:529
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:691
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:589
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:483
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:716
constexpr auto & side()
Returns non-constant reference to side-th spline.
Definition boundary.hpp:677
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:501
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:668
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:741
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:852
constexpr auto & side()
Returns non-constant reference to side-th spline.
Definition boundary.hpp:1035
BoundaryCore & from_json(const nlohmann::json &json)
Updates the boundary object from JSON object.
Definition boundary.hpp:1093
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:926
eval_type greville() const
Returns the Greville abscissae.
Definition boundary.hpp:1107
int64_t ncumcoeffs() const
Returns the total number of coefficients.
Definition boundary.hpp:1049
std::tuple< typename std::tuple_element_t< 0, boundary_spline_type >, typename std::tuple_element_t< 0, boundary_spline_type >, typename std::tuple_element_t< 1, boundary_spline_type >, typename std::tuple_element_t< 1, boundary_spline_type >, typename std::tuple_element_t< 2, boundary_spline_type >, typename std::tuple_element_t< 2, boundary_spline_type >, typename std::tuple_element_t< 3, boundary_spline_type >, typename std::tuple_element_t< 3, boundary_spline_type > > bdr_
Tuple of splines.
Definition boundary.hpp:812
BoundaryCore(boundary_type &&bdr_)
Move constructor.
Definition boundary.hpp:840
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the Boundary object.
Definition boundary.hpp:1065
static constexpr short_t nsides()
Returns the number of sides.
Definition boundary.hpp:1026
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:822
BoundaryCore(const BoundaryCore &other, bool clone)
Copy/clone constructor.
Definition boundary.hpp:843
constexpr auto & coeffs()
Returns a non-constant reference to the array of coefficients for all boundary segments.
Definition boundary.hpp:1046
Spline spline_type
Spline type.
Definition boundary.hpp:769
BoundaryCore(const boundary_type &bdr_)
Copy constructor.
Definition boundary.hpp:837
constexpr auto & side() const
Returns constant reference to side-th spline.
Definition boundary.hpp:1029
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:882
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:784
nlohmann::json to_json() const override
Returns the boundary object as JSON object.
Definition boundary.hpp:1078
BoundaryCore(Options< typename Spline::value_type > options=Options< typename Spline::value_type >{})
Default constructor.
Definition boundary.hpp:825
decltype(bdr_) boundary_type
Boundary type.
Definition boundary.hpp:816
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:801
constexpr auto & coeffs() const
Returns a constant reference to the array of coefficients for all boundary segments.
Definition boundary.hpp:1042
BoundaryCore.
Definition boundary.hpp:42
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:107
Full qualified name descriptor.
Definition fqn.hpp:26
Concept to identify template parameters that are derived from iganet::Boundary_.
Definition boundary.hpp:1120
Concept to identify template parameters that are derived from iganet::Spline_.
Definition bspline.hpp:3259
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:28
Definition boundary.hpp:22
deriv
Enumerator for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:74
struct iganet::@0 Log
Logger.
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
std::ostream & operator<<(std::ostream &os, const Boundary< Spline > &obj)
Print (as string) a Boundary object.
Definition boundary.hpp:1963
STL namespace.
Serialization prototype.
Definition serialize.hpp:31