IgANet
IGAnets - Isogeometric Analysis Networks
Loading...
Searching...
No Matches
functionspace.hpp
Go to the documentation of this file.
1
15#pragma once
16
17#include <boost/preprocessor/seq/for_each.hpp>
18
23#include <iganet/utils/zip.hpp>
24
25namespace iganet {
26
27using namespace literals;
28using utils::operator+;
29
31enum class functionspace : short_t {
32 interior = 0,
33 boundary = 1
34};
35
37#define IGANET_FUNCTIONSPACE_DEFAULT_OPS(FunctionSpace) \
38 FunctionSpace() = default; \
39 FunctionSpace(FunctionSpace &&) = default; \
40 FunctionSpace(const FunctionSpace &) = default;
41
42namespace detail {
43
44// @brief Concept to identify template parameters that have a templated
45// find_knot_indices function
46template <typename T>
47concept HasTemplatedFindKnotIndices = requires(T t, typename T::eval_type x) {
48 { t.template find_knot_indices<functionspace::interior>(x) };
49};
50
51// @brief Concept to identify template parameters that have a templated
52// find_coeff_indices function
53template <typename T>
54concept HasTemplatedFindCoeffIndices = requires(T t, typename T::eval_type x) {
55 { t.template find_coeff_indices<functionspace::interior>(x) };
56};
57
60
61// Forward declaration
62template <typename, typename> class FunctionSpace;
63
68template <typename... Splines, typename... Boundaries>
69// requires (SplineType<Splines> && ...) && (BoundaryType<Boundaries> && ...)
70class FunctionSpace<std::tuple<Splines...>, std::tuple<Boundaries...>>
71 : public FunctionSpaceType,
74
75public:
77 using value_type = std::common_type_t<typename Splines::value_type...>;
78
80 using spline_type = std::tuple<Splines...>;
81
83 using eval_type = std::tuple<utils::TensorArray<Splines::parDim()>...>;
84
86 using boundary_type = std::tuple<Boundaries...>;
87
89 using boundary_eval_type = std::tuple<typename Boundaries::eval_type...>;
90
94 template <std::size_t index>
95 inline static constexpr short_t geoDim() noexcept {
96 static_assert(index < nspaces());
97 return std::tuple_element_t<index, spline_type>::geoDim();
98 }
99
103 template <std::size_t index>
104 inline static constexpr short_t parDim() noexcept {
105 static_assert(index < nspaces());
106 return std::tuple_element_t<index, spline_type>::parDim();
107 }
108
113 template <std::size_t index>
114 inline static constexpr const auto& degrees() noexcept {
115 static_assert(index < nspaces());
116 return std::tuple_element_t<index, spline_type>::degrees();
117 }
118
124 template <std::size_t index>
125 inline static constexpr short_t degree(short_t i) noexcept {
126 static_assert(index < nspaces());
127 return std::tuple_element_t<index, spline_type>::degree(i);
128 }
129
130protected:
133
136
137public:
139 FunctionSpace() = default;
140
142 FunctionSpace(const FunctionSpace &) = default;
143
146
153 const std::array<int64_t, Splines::parDim()> &...ncoeffs,
154 enum init init = init::greville,
156 : spline_(Splines(ncoeffs, init, options)...),
157 boundary_(Boundaries(ncoeffs, init::none, options)...) {
159 }
160
166 const std::array<std::vector<typename Splines::value_type>,
167 Splines::parDim()> &...kv,
168 enum init init = init::greville,
170 : spline_(Splines(kv, init, options)...),
171 boundary_(Boundaries(kv, init::none, options)...) {
172
173 static_assert((Splines::is_nonuniform() && ... && true),
174 "Constructor is only available for non-uniform splines");
176 }
177
180 explicit FunctionSpace(const std::tuple<Splines...> &spline)
181 : spline_(spline) {
183 }
184
187 explicit FunctionSpace(std::tuple<Splines...> &&spline) : spline_(spline) {
189 }
190
194 explicit FunctionSpace(const std::tuple<Splines...> &spline,
195 const std::tuple<Boundaries...> &boundary)
196 : spline_(spline), boundary_(boundary) {}
197
201 explicit FunctionSpace(std::tuple<Splines...> &&spline,
202 std::tuple<Boundaries...> &&boundary)
203 : spline_(spline), boundary_(boundary) {}
205
208 inline static constexpr std::size_t nspaces() noexcept {
209 return sizeof...(Splines);
210 }
211
214 inline static constexpr std::size_t nboundaries() noexcept {
215 return sizeof...(Boundaries);
216 }
217
220 inline constexpr const auto &spaces() const noexcept { return spline_; }
221
224 inline constexpr auto &spaces() noexcept { return spline_; }
225
228 inline constexpr const auto &boundaries() const noexcept { return boundary_; }
229
232 inline constexpr auto &boundaries() noexcept { return boundary_; }
233
237 template <std::size_t index> inline const auto &space() const noexcept {
238 static_assert(index < nspaces());
239 return std::get<index>(spline_);
240 }
241
245 template <std::size_t index> inline auto &space() noexcept {
246 static_assert(index < nspaces());
247 return std::get<index>(spline_);
248 }
249
253 template <std::size_t index> inline const auto &boundary() const noexcept {
254 static_assert(index < nboundaries());
255 return std::get<index>(boundary_);
256 }
257
262 template <std::size_t index> inline auto &boundary() noexcept {
263 static_assert(index < nboundaries());
264 return std::get<index>(boundary_);
265 }
266
269 inline FunctionSpace clone() const noexcept { return FunctionSpace(*this); }
270
274 template <std::size_t... index> inline auto clone() const noexcept {
275
276 static_assert(((index < nspaces()) && ... && true));
277
278 return FunctionSpace<
279 std::tuple<std::tuple_element_t<index, spline_type>...>,
280 std::tuple<std::tuple_element_t<index, boundary_type>...>>(
281 std::make_tuple(std::get<index>(spline_)...),
282 std::make_tuple(std::get<index>(boundary_)...));
283 }
284
285private:
288 template <std::size_t... Is>
289 inline torch::Tensor
290 spaces_as_tensor_(std::index_sequence<Is...>) const noexcept {
291 return torch::cat({std::get<Is>(spline_).as_tensor()...});
292 }
293
294public:
298 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
299 return spaces_as_tensor_(
300 std::make_index_sequence<FunctionSpace::nspaces()>{});
301 }
302
303private:
306 template <std::size_t... Is>
307 inline torch::Tensor
308 boundary_as_tensor_(std::index_sequence<Is...>) const noexcept {
309 return torch::cat({std::get<Is>(boundary_).as_tensor()...});
310 }
311
312public:
316 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
317 return boundary_as_tensor_(
318 std::make_index_sequence<FunctionSpace::nboundaries()>{});
319 }
320
327 virtual inline torch::Tensor as_tensor() const noexcept {
328 return spaces_as_tensor();
329 }
330
331private:
334 template <std::size_t... Is>
335 inline int64_t
336 spaces_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
337 return std::apply(
338 [](auto... v) { return (v + ...); },
339 std::make_tuple(std::get<Is>(spline_).as_tensor_size()...));
340 }
341
342public:
346 virtual inline int64_t spaces_as_tensor_size() const noexcept {
347 return spaces_as_tensor_size_(
348 std::make_index_sequence<FunctionSpace::nspaces()>{});
349 }
350
351private:
354 template <std::size_t... Is>
355 inline int64_t
356 boundary_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
357 return std::apply(
358 [](auto... v) { return (v + ...); },
359 std::make_tuple(std::get<Is>(boundary_).as_tensor_size()...));
360 }
361
362public:
366 virtual inline int64_t boundary_as_tensor_size() const noexcept {
367 return boundary_as_tensor_size_(
368 std::make_index_sequence<FunctionSpace::nboundaries()>{});
369 }
370
377 virtual inline int64_t as_tensor_size() const noexcept {
378 return spaces_as_tensor_size();
379 }
380
381private:
383 template <std::size_t... Is>
384 inline FunctionSpace &spaces_from_tensor_(std::index_sequence<Is...>,
385 const torch::Tensor &tensor) {
386
387 // Compute the partial sums of all function spaces
388 std::array<int64_t, sizeof...(Is)> partialSums{0};
389 auto partial_sums = [&partialSums,
390 this]<std::size_t... Js>(std::index_sequence<Js...>) {
391 ((std::get<Js + 1>(partialSums) =
392 std::get<Js>(partialSums) + std::get<Js>(spline_).as_tensor_size()),
393 ...);
394 };
395 partial_sums(std::make_index_sequence<FunctionSpace::nspaces() - 1>{});
396
397 // Call from_tensor for all function spaces
398 ((std::get<Is>(spline_).from_tensor(tensor.index(
399 {torch::indexing::Slice(partialSums[Is],
400 partialSums[Is] +
401 std::get<Is>(spline_).as_tensor_size()),
402 "..."}))),
403 ...);
404
405 return *this;
406 }
407
408public:
412 virtual inline FunctionSpace &
413 spaces_from_tensor(const torch::Tensor &tensor) {
414 return spaces_from_tensor_(
415 std::make_index_sequence<FunctionSpace::nspaces()>{}, tensor);
416 }
417
418private:
421 template <std::size_t... Is>
422 inline FunctionSpace &boundary_from_tensor_(std::index_sequence<Is...>,
423 const torch::Tensor &tensor) {
424 (std::get<Is>(boundary_).from_tensor(std::get<Is>(spline_).as_tensor()),
425 ...);
426
427 return *this;
428 }
429
430public:
435 virtual inline FunctionSpace &
436 boundary_from_tensor(const torch::Tensor &tensor) {
437 return boundary_from_tensor_(
438 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
439 }
440
441private:
443 template <std::size_t... Is>
444 inline FunctionSpace &
445 boundary_from_full_tensor_(std::index_sequence<Is...>,
446 const torch::Tensor &tensor) {
447 (std::get<Is>(boundary_).from_full_tensor(
448 std::get<Is>(spline_).as_tensor()),
449 ...);
450
451 return *this;
452 }
453
454public:
458 virtual inline FunctionSpace &
459 boundary_from_full_tensor(const torch::Tensor &tensor) {
460 return boundary_from_full_tensor_(
461 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
462 }
463
467 virtual inline FunctionSpace &from_tensor(const torch::Tensor &tensor) {
468 spaces_from_tensor_(std::make_index_sequence<FunctionSpace::nspaces()>{},
469 tensor);
470 boundary_from_full_tensor_(
471 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
472 return *this;
473 }
474
475private:
477 template <std::size_t... Is>
478 inline pugi::xml_node &to_xml_(std::index_sequence<Is...>,
479 pugi::xml_node &root, int id = 0,
480 const std::string &label = "") const {
481
482 (std::get<Is>(spline_).to_xml(root, id, label, Is), ...);
483 return root;
484 }
485
486public:
491 inline pugi::xml_document to_xml(int id = 0,
492 const std::string &label = "") const {
493 pugi::xml_document doc;
494 pugi::xml_node root = doc.append_child("xml");
495 to_xml(root, id, label);
496
497 return doc;
498 }
499
505 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
506 const std::string &label = "") const {
507 return to_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
508 id, label);
509 }
510
511private:
513 template <std::size_t... Is>
514 inline FunctionSpace &from_xml_(std::index_sequence<Is...>,
515 const pugi::xml_node &root, int id = 0,
516 const std::string &label = "") {
517
518 (std::get<Is>(spline_).from_xml(root, id, label, Is), ...);
519 return *this;
520 }
521
522public:
528 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
529 const std::string &label = "") {
530 return from_xml(doc.child("xml"), id, label);
531 }
532
538 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
539 const std::string &label = "") {
540 return from_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
541 id, label);
542 }
543
544private:
546 template <std::size_t... Is>
547 nlohmann::json to_json_(std::index_sequence<Is...>) const {
548 auto json_this = nlohmann::json::array();
549 auto json_boundary = nlohmann::json::array();
550 (json_this.push_back(std::get<Is>(spline_).to_json()), ...);
551 (json_boundary.push_back(std::get<Is>(boundary_).to_json()), ...);
552
553 auto json = nlohmann::json::array();
554 for (auto [t, b] : utils::zip(json_this, json_boundary)) {
555 auto json_inner = nlohmann::json::array();
556 json_inner.push_back(t);
557 json_inner.push_back(b);
558 json.push_back(json_inner);
559 }
560
561 return json;
562 }
563
564public:
567 nlohmann::json to_json() const override {
568 return to_json_(std::make_index_sequence<FunctionSpace::nspaces()>{});
569 }
570
576 template <typename SplinesOther, typename BoundariesOther>
577 bool
579 bool result(true);
580
581 if (!std::is_same_v<spline_type, typename std::remove_cvref_t<
582 decltype(other)>::spline_type> ||
583 !std::is_same_v<boundary_type, typename std::remove_cvref_t<
584 decltype(other)>::boundary_type>)
585 return false;
586
587 result *= (spaces() == other.spaces());
588 result *= (boundaries() == other.boundaries());
589
590 return result;
591 }
592
593private:
596 template <functionspace comp = functionspace::interior,
597 deriv deriv = deriv::func, bool memory_optimized = false,
598 std::size_t... Is, typename... Xi>
599 inline auto eval_(std::index_sequence<Is...>,
600 const std::tuple<Xi...> &xi) const {
601 if constexpr (comp == functionspace::interior)
602 return std::tuple(
603 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
604 std::get<Is>(xi))...);
605 else if constexpr (comp == functionspace::boundary)
606 return std::tuple(
607 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
608 std::get<Is>(xi))...);
609 }
610
611 template <functionspace comp = functionspace::interior,
612 deriv deriv = deriv::func, bool memory_optimized = false,
613 std::size_t... Is, typename... Xi, typename... Knot_Indices>
614 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
615 const std::tuple<Knot_Indices...> &knot_indices) const {
616 if constexpr (comp == functionspace::interior)
617 return std::tuple(
618 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
619 std::get<Is>(xi), std::get<Is>(knot_indices))...);
620 else if constexpr (comp == functionspace::boundary)
621 return std::tuple(
622 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
623 std::get<Is>(xi), std::get<Is>(knot_indices))...);
624 }
625
626 template <functionspace comp = functionspace::interior,
627 deriv deriv = deriv::func, bool memory_optimized = false,
628 std::size_t... Is, typename... Xi, typename... Knot_Indices,
629 typename... Coeff_Indices>
630 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
631 const std::tuple<Knot_Indices...> &knot_indices,
632 const std::tuple<Coeff_Indices...> &coeff_indices) const {
633 if constexpr (comp == functionspace::interior)
634 return std::tuple(
635 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
636 std::get<Is>(xi), std::get<Is>(knot_indices),
637 std::get<Is>(coeff_indices))...);
638 else if constexpr (comp == functionspace::boundary)
639 return std::tuple(
640 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
641 std::get<Is>(xi), std::get<Is>(knot_indices),
642 std::get<Is>(coeff_indices))...);
643 }
645
646public:
651 template <functionspace comp = functionspace::interior,
652 deriv deriv = deriv::func, bool memory_optimized = false,
653 typename... Xi>
654 inline auto eval(const std::tuple<Xi...> &xi) const {
655 static_assert(FunctionSpace::nspaces() == sizeof...(Xi),
656 "Size of Xi mismatches functionspace dimension");
657 return eval_<comp, deriv, memory_optimized>(
658 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
659 }
660
665 template <functionspace comp = functionspace::interior,
666 deriv deriv = deriv::func, bool memory_optimized = false,
667 typename... Xi, typename... Knot_Indices>
668 inline auto eval(const std::tuple<Xi...> &xi,
669 const std::tuple<Knot_Indices...> &knot_indices) const {
670 static_assert(
671 (FunctionSpace::nspaces() == sizeof...(Xi)) &&
672 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)),
673 "Sizes of Xi and Knot_Indices mismatch functionspace dimension");
674 return eval_<comp, deriv, memory_optimized>(
675 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
676 }
677
683 template <functionspace comp = functionspace::interior,
684 deriv deriv = deriv::func, bool memory_optimized = false,
685 typename... Xi, typename... Knot_Indices, typename... Coeff_Indices>
686 inline auto eval(const std::tuple<Xi...> &xi,
687 const std::tuple<Knot_Indices...> &knot_indices,
688 const std::tuple<Coeff_Indices...> &coeff_indices) const {
689 static_assert((FunctionSpace::nspaces() == sizeof...(Xi)) &&
690 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)) &&
691 (FunctionSpace::nspaces() == sizeof...(Coeff_Indices)),
692 "Sizes of Xi, Knot_Indices and Coeff_Indices mismatch "
693 "functionspace dimension");
694 return eval_<comp, deriv, memory_optimized>(
695 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices,
696 coeff_indices);
697 }
699
700private:
704 template <functionspace comp = functionspace::interior, std::size_t... Is,
705 typename... Basfunc, typename... Coeff_Indices, typename... Numeval,
706 typename... Sizes>
707 inline auto
708 eval_from_precomputed_(std::index_sequence<Is...>,
709 const std::tuple<Basfunc...> &basfunc,
710 const std::tuple<Coeff_Indices...> &coeff_indices,
711 const std::tuple<Numeval...> &numeval,
712 const std::tuple<Sizes...> &sizes) const {
713 if constexpr (comp == functionspace::interior)
714 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
715 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
716 std::get<Is>(numeval), std::get<Is>(sizes))...);
717 else if constexpr (comp == functionspace::boundary)
718 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
719 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
720 std::get<Is>(numeval), std::get<Is>(sizes))...);
721 }
722
723 template <functionspace comp = functionspace::interior, std::size_t... Is,
724 typename... Basfunc, typename... Coeff_Indices, typename... Xi>
725 inline auto
726 eval_from_precomputed_(std::index_sequence<Is...>,
727 const std::tuple<Basfunc...> &basfunc,
728 const std::tuple<Coeff_Indices...> &coeff_indices,
729 const std::tuple<Xi...> &xi) const {
730 if constexpr (comp == functionspace::interior)
731 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
732 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
733 std::get<Is>(xi)[0].numel(), std::get<Is>(xi)[0].sizes())...);
734 else if constexpr (comp == functionspace::boundary)
735 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
736 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
737 std::get<Is>(xi))...);
738 }
740
741public:
750 template <functionspace comp = functionspace::interior, typename... Basfunc,
751 typename... Coeff_Indices, typename... Numeval, typename... Sizes>
752 inline auto
753 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
754 const std::tuple<Coeff_Indices...> &coeff_indices,
755 const std::tuple<Numeval...> &numeval,
756 const std::tuple<Sizes...> &sizes) const {
757 return eval_from_precomputed_<comp>(
758 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
759 coeff_indices, numeval, sizes);
760 }
761
767 template <functionspace comp = functionspace::interior, typename... Basfunc,
768 typename... Coeff_Indices, typename... Xi>
769 inline auto
770 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
771 const std::tuple<Coeff_Indices...> &coeff_indices,
772 const std::tuple<Xi...> &xi) const {
773 return eval_from_precomputed_<comp>(
774 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
775 coeff_indices, xi);
776 }
778
779private:
782 template <functionspace comp = functionspace::interior, std::size_t... Is>
783 inline auto
784 find_knot_indices_(std::index_sequence<Is...>,
785 const utils::TensorArray<nspaces()> &xi) const {
786 if constexpr (comp == functionspace::interior)
787 return std::tuple(std::get<Is>(spline_).find_knot_indices(xi)...);
788 else if constexpr (comp == functionspace::boundary)
789 return std::tuple(std::get<Is>(boundary_).find_knot_indices(xi)...);
790 }
791
792 template <functionspace comp = functionspace::interior, std::size_t... Is,
793 typename... Xi>
794 inline auto find_knot_indices_(std::index_sequence<Is...>,
795 const std::tuple<Xi...> &xi) const {
796 if constexpr (comp == functionspace::interior)
797 return std::tuple(
798 std::get<Is>(spline_).find_knot_indices(std::get<Is>(xi))...);
799 else if constexpr (comp == functionspace::boundary)
800 return std::tuple(
801 std::get<Is>(boundary_).find_knot_indices(std::get<Is>(xi))...);
802 }
804
805public:
811 template <functionspace comp = functionspace::interior>
812 inline auto find_knot_indices(const utils::TensorArray<nspaces()> &xi) const {
813 return find_knot_indices_<comp>(
814 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
815 }
816
822 template <functionspace comp = functionspace::interior, typename... Xi>
823 inline auto find_knot_indices(const std::tuple<Xi...> &xi) const {
824 return find_knot_indices_<comp>(
825 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
826 }
828
829private:
833 template <functionspace comp = functionspace::interior,
834 deriv deriv = deriv::func, bool memory_optimized = false,
835 std::size_t... Is, typename... Xi>
836 inline auto eval_basfunc_(std::index_sequence<Is...>,
837 const std::tuple<Xi...> &xi) const {
838 if constexpr (comp == functionspace::interior)
839 return std::tuple(
840 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
841 std::get<Is>(xi))...);
842 else if constexpr (comp == functionspace::boundary)
843 return std::tuple(std::get<Is>(boundary_)
844 .template eval_basfunc<deriv, memory_optimized>(
845 std::get<Is>(xi))...);
846 }
847
848 template <functionspace comp = functionspace::interior,
849 deriv deriv = deriv::func, bool memory_optimized = false,
850 std::size_t... Is, typename... Xi, typename... Knot_Indices>
851 inline auto
852 eval_basfunc_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
853 const std::tuple<Knot_Indices...> &knot_indices) const {
854 if constexpr (comp == functionspace::interior)
855 return std::tuple(
856 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
857 std::get<Is>(xi), std::get<Is>(knot_indices))...);
858 else if constexpr (comp == functionspace::boundary)
859 return std::tuple(
860 std::get<Is>(boundary_)
861 .template eval_basfunc<deriv, memory_optimized>(
862 std::get<Is>(xi), std::get<Is>(knot_indices))...);
863 }
865
866public:
871 template <functionspace comp = functionspace::interior,
872 deriv deriv = deriv::func, bool memory_optimized = false,
873 typename... Xi>
874 inline auto eval_basfunc(const std::tuple<Xi...> &xi) const {
875 return eval_basfunc_<comp, deriv, memory_optimized>(
876 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
877 }
878
883 template <functionspace comp = functionspace::interior,
884 deriv deriv = deriv::func, bool memory_optimized = false,
885 typename... Xi, typename... Knot_Indices>
886 inline auto
887 eval_basfunc(const std::tuple<Xi...> &xi,
888 const std::tuple<Knot_Indices...> &knot_indices) const {
889 return eval_basfunc_<comp, deriv, memory_optimized>(
890 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
891 }
893
894private:
897 template <functionspace comp = functionspace::interior,
898 bool memory_optimized = false, std::size_t... Is,
899 typename... Knot_Indices>
900 inline auto
901 find_coeff_indices_(std::index_sequence<Is...>,
902 const std::tuple<Knot_Indices...> &knot_indices) const {
903 if constexpr (comp == functionspace::interior)
904 return std::tuple(
905 std::get<Is>(spline_).template find_coeff_indices<memory_optimized>(
906 std::get<Is>(knot_indices))...);
907 else if constexpr (comp == functionspace::boundary)
908 return std::tuple(
909 std::get<Is>(boundary_).template find_coeff_indices<memory_optimized>(
910 std::get<Is>(knot_indices))...);
911 }
912
913public:
918 template <functionspace comp = functionspace::interior,
919 bool memory_optimized = false, typename... Knot_Indices>
920 inline auto
921 find_coeff_indices(const std::tuple<Knot_Indices...> &knot_indices) const {
922 return find_coeff_indices_<comp, memory_optimized>(
923 std::make_index_sequence<FunctionSpace::nspaces()>{}, knot_indices);
924 }
925
926private:
929 template <std::size_t... Is, std::size_t... Js>
930 inline auto &uniform_refine_(std::index_sequence<Is...>,
931 std::index_sequence<Js...>, int numRefine = 1,
932 int dimRefine = -1) {
933 (std::get<Is>(spline_).uniform_refine(numRefine, dimRefine), ...);
934 (std::get<Js>(boundary_).uniform_refine(numRefine, dimRefine), ...);
935 return *this;
936 }
937
938public:
944 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
945 return uniform_refine_(
946 std::make_index_sequence<FunctionSpace::nspaces()>{},
947 std::make_index_sequence<FunctionSpace::nboundaries()>{}, numRefine,
948 dimRefine);
949 }
950
951private:
954 template <typename real_t, std::size_t... Is, std::size_t... Js>
955 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
956 Options<real_t> options) const {
957 return FunctionSpace<
958 typename Splines::template real_derived_self_type<real_t>...,
959 typename Boundaries::template real_derived_self_type<real_t>...>(
960 std::get<Is>(spline_).to(options)...,
961 std::get<Js>(boundary_).to(options)...);
962 }
963
964public:
970 template <typename real_t> inline auto to(Options<real_t> options) const {
971 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
972 std::make_index_sequence<FunctionSpace::nboundaries()>{},
973 options);
974 }
975
976private:
979 template <std::size_t... Is, std::size_t... Js>
980 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
981 torch::Device device) const {
982 return FunctionSpace(std::get<Is>(spline_).to(device)...,
983 std::get<Js>(boundary_).to(device)...);
984 }
985
986public:
991 inline auto to(torch::Device device) const {
992 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
993 std::make_index_sequence<FunctionSpace::nboundaries()>{},
994 device);
995 }
996
997private:
999 template <typename real_t, std::size_t... Is, std::size_t... Js>
1000 inline auto to_(std::index_sequence<Is...>,
1001 std::index_sequence<Js...>) const {
1002 return FunctionSpace<
1003 typename Splines::template real_derived_self_type<real_t>...,
1004 typename Boundaries::template real_derived_self_type<real_t>...>(
1005 std::get<Is>(spline_).template to<real_t>()...,
1006 std::get<Js>(boundary_).template to<real_t>()...);
1007 }
1008
1009public:
1013 template <typename real_t> inline auto to() const {
1014 return to_<real_t>(
1015 std::make_index_sequence<FunctionSpace::nspaces()>{},
1016 std::make_index_sequence<FunctionSpace::nboundaries()>{});
1017 }
1018
1019private:
1021 template <std::size_t... Is>
1022 inline auto scale_(std::index_sequence<Is...>, value_type s, int dim = -1) {
1023 (std::get<Is>(spline_).scale(s, dim), ...);
1025 return *this;
1026 }
1027
1028public:
1033 inline auto scale(value_type s, int dim = -1) {
1034 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, s, dim);
1035 }
1036
1037private:
1039 template <std::size_t N, std::size_t... Is>
1040 inline auto scale_(std::index_sequence<Is...>, std::array<value_type, N> v) {
1041 (std::get<Is>(spline_).scale(v), ...);
1042 (std::get<Is>(boundary_).from_full_tensor(
1043 std::get<Is>(spline_).as_tensor()),
1044 ...);
1045 return *this;
1046 }
1047
1048public:
1053 template <std::size_t N> inline auto scale(std::array<value_type, N> v) {
1054 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
1055 }
1056
1057private:
1059 template <std::size_t N, std::size_t... Is>
1060 inline auto translate_(std::index_sequence<Is...>,
1061 std::array<value_type, N> v) {
1062 (std::get<Is>(spline_).translate(v), ...);
1063 (std::get<Is>(boundary_).from_full_tensor(
1064 std::get<Is>(spline_).as_tensor()),
1065 ...);
1066 return *this;
1067 }
1068
1069public:
1074 template <std::size_t N> inline auto translate(std::array<value_type, N> v) {
1075 return translate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
1076 }
1077
1078private:
1080 template <std::size_t... Is>
1081 inline auto rotate_(std::index_sequence<Is...>, value_type angle) {
1082 (std::get<Is>(spline_).rotate(angle), ...);
1083 (std::get<Is>(boundary_).from_full_tensor(
1084 std::get<Is>(spline_).as_tensor()),
1085 ...);
1086 return *this;
1087 }
1088
1089public:
1093 inline auto rotate(value_type angle) {
1094 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
1095 }
1096
1097private:
1099 template <std::size_t... Is>
1100 inline auto rotate_(std::index_sequence<Is...>,
1101 std::array<value_type, 3> angle) {
1102 (std::get<Is>(spline_).rotate(angle), ...);
1103 (std::get<Is>(boundary_).from_full_tensor(
1104 std::get<Is>(spline_).as_tensor()),
1105 ...);
1106 return *this;
1107 }
1108
1109public:
1113 inline auto rotate(std::array<value_type, 3> angle) {
1114 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
1115 }
1116
1117private:
1119 template <std::size_t... Is>
1120 inline auto boundingBox_(std::index_sequence<Is...>) const {
1121 return std::tuple(std::get<Is>(spline_).boundingBox()...);
1122 }
1123
1124public:
1127 inline auto boundingBox() const {
1128 return boundingBox_(std::make_index_sequence<FunctionSpace::nspaces()>{});
1129 }
1130
1131private:
1134 template <std::size_t... Is>
1135 inline torch::serialize::OutputArchive &
1136 write_(std::index_sequence<Is...>, torch::serialize::OutputArchive &archive,
1137 const std::string &key = "functionspace") const {
1138 (std::get<Is>(spline_).write(
1139 archive, key + ".fspace[" + std::to_string(Is) + "].interior"),
1140 ...);
1141 (std::get<Is>(boundary_).write(
1142 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
1143 ...);
1144 return archive;
1145 }
1146
1147public:
1153 inline torch::serialize::OutputArchive &
1154 write(torch::serialize::OutputArchive &archive,
1155 const std::string &key = "functionspace") const {
1156 write_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
1157 return archive;
1158 }
1159
1160private:
1163 template <std::size_t... Is>
1164 inline torch::serialize::InputArchive &
1165 read_(std::index_sequence<Is...>, torch::serialize::InputArchive &archive,
1166 const std::string &key = "functionspace") {
1167 (std::get<Is>(spline_).read(archive, key + ".fspace[" + std::to_string(Is) +
1168 "].interior"),
1169 ...);
1170 (std::get<Is>(boundary_).read(
1171 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
1172 ...);
1173 return archive;
1174 }
1175
1176public:
1182 inline torch::serialize::InputArchive &
1183 read(torch::serialize::InputArchive &archive,
1184 const std::string &key = "functionspace") {
1185 read_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
1186 return archive;
1187 }
1188
1191 inline void pretty_print(std::ostream &os) const noexcept override {
1192
1193 auto pretty_print_ = [this,
1194 &os]<std::size_t... Is>(std::index_sequence<Is...>) {
1195 ((os << "\ninterior = ", std::get<Is>(spline_).pretty_print(os),
1196 os << "\nboundary = ", std::get<Is>(boundary_).pretty_print(os)),
1197 ...);
1198 };
1199
1200 pretty_print_(std::make_index_sequence<nspaces()>{});
1201 }
1202
1203 // clang-format off
1221 // clang-format on
1224 template <functionspace comp = functionspace::interior,
1225 bool memory_optimized = false>
1226 inline auto curl(const utils::TensorArray<nspaces()> &xi) const {
1227 return curl<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1228 }
1229
1234 template <functionspace comp = functionspace::interior,
1235 bool memory_optimized = false, typename... TensorArrays>
1236 inline auto curl(const utils::TensorArray<nspaces()> &xi,
1237 const std::tuple<TensorArrays...> &knot_indices) const {
1238 return curl<comp, memory_optimized>(xi, knot_indices,
1239 find_coeff_indices<comp>(knot_indices));
1240 }
1241
1247 template <functionspace comp = functionspace::interior,
1248 bool memory_optimized = false>
1249 inline auto curl(const utils::TensorArray1 &xi,
1250 const std::tuple<utils::TensorArray1> &knot_indices,
1251 const std::tuple<torch::Tensor> &coeff_indices) const {
1252
1253 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1254
1255 throw std::runtime_error("Unsupported parametric/geometric dimension");
1256
1258 }
1259
1260 template <functionspace comp = functionspace::interior,
1261 bool memory_optimized = false>
1262 inline auto
1264 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1265 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1266
1267 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1268 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1269 xi[0].sizes() == xi[1].sizes());
1270
1277 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1278 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1279 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1280 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1281 }
1282
1283 template <functionspace comp = functionspace::interior,
1284 bool memory_optimized = false>
1285 inline auto curl(const utils::TensorArray3 &xi,
1286 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1287 utils::TensorArray3> &knot_indices,
1288 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1289 &coeff_indices) const {
1290
1291 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1292 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1293 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1294 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1295
1300 *std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1301 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] -
1302 *std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1303 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1304 *std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1305 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] -
1306 *std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1307 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1308 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1309 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1310 *std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1311 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1312 }
1313
1319 template <functionspace comp = functionspace::interior,
1320 bool memory_optimized = false>
1321 inline auto
1323 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1325 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1326 torch::Tensor> &coeff_indices) const {
1327
1328 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1329 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1330 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1331 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1332 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1333 xi[2].sizes() == xi[3].sizes());
1334
1335 throw std::runtime_error("Unsupported parametric/geometric dimension");
1336
1338 }
1340
1360 template <functionspace comp = functionspace::interior,
1361 bool memory_optimized = false>
1362 inline auto div(const utils::TensorArray<nspaces()> &xi) const {
1363 return div<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1364 }
1365
1370 template <functionspace comp = functionspace::interior,
1371 bool memory_optimized = false, typename... TensorArrays>
1372 inline auto div(const utils::TensorArray<nspaces()> &xi,
1373 const std::tuple<TensorArrays...> &knot_indices) const {
1374 return div<comp, memory_optimized>(xi, knot_indices,
1375 find_coeff_indices<comp>(knot_indices));
1376 }
1377
1383 template <functionspace comp = functionspace::interior,
1384 bool memory_optimized = false>
1385 inline auto div(const utils::TensorArray1 &xi,
1386 const std::tuple<utils::TensorArray1> &knot_indices,
1387 const std::tuple<torch::Tensor> &coeff_indices) const {
1388
1389 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1390
1391 if constexpr (comp == functionspace::interior) {
1392 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1393 "div(.) for vector-valued spaces requires 1D variables");
1394
1396 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1397 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1398 }
1399 }
1400
1406 template <functionspace comp = functionspace::interior,
1407 bool memory_optimized = false>
1408 inline auto
1410 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1411 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1412
1413 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1414 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1415 xi[0].sizes() == xi[1].sizes());
1416
1417 if constexpr (comp == functionspace::interior) {
1418 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1419 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1420 "div(.) for vector-valued spaces requires 1D variables");
1421
1423 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1424 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1425 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1426 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1427 }
1428 }
1429
1435 template <functionspace comp = functionspace::interior,
1436 bool memory_optimized = false>
1437 inline auto div(const utils::TensorArray3 &xi,
1438 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1439 utils::TensorArray3> &knot_indices,
1440 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1441 &coeff_indices) const {
1442
1443 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1444 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1445 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1446 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1447
1448 if constexpr (comp == functionspace::interior) {
1449 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1450 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1451 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1452 "div(.) for vector-valued spaces requires 1D variables");
1453
1455 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1456 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1457 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1458 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1459 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1460 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1461 }
1462 }
1463
1469 template <functionspace comp = functionspace::interior,
1470 bool memory_optimized = false>
1471 inline auto
1473 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1475 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1476 torch::Tensor> &coeff_indices) const {
1477
1478 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1479 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1480 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1481 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1482 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1483 xi[2].sizes() == xi[3].sizes());
1484
1485 if constexpr (comp == functionspace::interior) {
1486 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1487 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1488 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1489 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1490 "div(.) for vector-valued spaces requires 1D variables");
1491
1493 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1494 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1495 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1496 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1497 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1498 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
1499 *std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1500 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1501 }
1502 }
1504
1522 template <functionspace comp = functionspace::interior,
1523 bool memory_optimized = false>
1524 inline auto grad(const utils::TensorArray<nspaces()> &xi) const {
1525 return grad<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1526 }
1527
1532 template <functionspace comp = functionspace::interior,
1533 bool memory_optimized = false, typename... TensorArrays>
1534 inline auto grad(const utils::TensorArray<nspaces()> &xi,
1535 const std::tuple<TensorArrays...> &knot_indices) const {
1536 return grad<comp, memory_optimized>(xi, knot_indices,
1537 find_coeff_indices<comp>(knot_indices));
1538 }
1539
1545 template <functionspace comp = functionspace::interior,
1546 bool memory_optimized = false>
1547 inline auto grad(const utils::TensorArray1 &xi,
1548 const std::tuple<utils::TensorArray1> &knot_indices,
1549 const std::tuple<torch::Tensor> &coeff_indices) const {
1550
1551 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1552
1553 if constexpr (comp == functionspace::interior) {
1554 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1555 "grad(.) for vector-valued spaces requires 1D variables");
1556
1558 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1559 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1560 }
1561 }
1562
1568 template <functionspace comp = functionspace::interior,
1569 bool memory_optimized = false>
1570 inline auto
1572 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1573 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1574
1575 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1576 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1577 xi[0].sizes() == xi[1].sizes());
1578
1579 if constexpr (comp == functionspace::interior) {
1580 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1581 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1582 "grad(.) for vector-valued spaces requires 1D variables");
1583
1585 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1586 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1587 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1588 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1589 }
1590 }
1591
1597 template <functionspace comp = functionspace::interior,
1598 bool memory_optimized = false>
1599 inline auto grad(const utils::TensorArray3 &xi,
1600 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1601 utils::TensorArray3> &knot_indices,
1602 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1603 &coeff_indices) const {
1604
1605 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1606 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1607 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1608 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1609
1610 if constexpr (comp == functionspace::interior) {
1611 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1612 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1613 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1614 "div(.) for vector-valued spaces requires 1D variables");
1615
1617 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1618 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1619 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1620 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1621 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1622 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1623 }
1624 }
1625
1631 template <functionspace comp = functionspace::interior,
1632 bool memory_optimized = false>
1633 inline auto
1635 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1637 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1638 torch::Tensor> &coeff_indices) const {
1639
1640 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1641 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1642 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1643 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1644 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1645 xi[2].sizes() == xi[3].sizes());
1646
1647 if constexpr (comp == functionspace::interior) {
1648 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1649 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1650 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1651 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1652 "grad(.) for vector-valued spaces requires 1D variables");
1653
1655 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1656 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1657 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1658 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1659 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1660 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1661 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1662 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1663 }
1664 }
1666
1667 // clang-format off
1700 // clang-format on
1703 template <functionspace comp = functionspace::interior,
1704 bool memory_optimized = false>
1705 inline auto hess(const utils::TensorArray<nspaces()> &xi) const {
1706 return hess<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1707 }
1708
1713 template <functionspace comp = functionspace::interior,
1714 bool memory_optimized = false, typename... TensorArrays>
1715 inline auto hess(const utils::TensorArray<nspaces()> &xi,
1716 const std::tuple<TensorArrays...> &knot_indices) const {
1717 return hess<comp, memory_optimized>(xi, knot_indices,
1718 find_coeff_indices<comp>(knot_indices));
1719 }
1720
1726 template <functionspace comp = functionspace::interior,
1727 bool memory_optimized = false>
1728 inline auto hess(const utils::TensorArray1 &xi,
1729 const std::tuple<utils::TensorArray1> &knot_indices,
1730 const std::tuple<torch::Tensor> &coeff_indices) const {
1731
1732 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1733
1734 if constexpr (comp == functionspace::interior) {
1735 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1736 "hess(.) for vector-valued spaces requires 1D variables");
1737
1739 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1740 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)));
1741 }
1742 }
1743
1749 template <functionspace comp = functionspace::interior,
1750 bool memory_optimized = false>
1751 inline auto
1753 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1754 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1755
1756 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1757 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1758 xi[0].sizes() == xi[1].sizes());
1759
1760 if constexpr (comp == functionspace::interior) {
1761 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1762 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1763 "hess(.) for vector-valued spaces requires 1D variables");
1764
1766 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1767 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1768 std::get<0>(spline_)
1769 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1770 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1771 std::get<0>(spline_)
1772 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1773 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1774 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1775 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1776
1777 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1778 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1779 std::get<1>(spline_)
1780 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1781 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1782 std::get<1>(spline_)
1783 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1784 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1785 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1786 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)));
1787 }
1788 }
1789
1795 template <functionspace comp = functionspace::interior,
1796 bool memory_optimized = false>
1797 inline auto hess(const utils::TensorArray3 &xi,
1798 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1799 utils::TensorArray3> &knot_indices,
1800 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1801 &coeff_indices) const {
1802
1803 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1804 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1805 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1806 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1807
1808 if constexpr (comp == functionspace::interior) {
1809 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1810 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1811 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1812 "hess(.) for vector-valued spaces requires 1D variables");
1813
1815 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1816 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1817 std::get<0>(spline_)
1818 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1819 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1820 std::get<0>(spline_)
1821 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1822 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1823 std::get<0>(spline_)
1824 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1825 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1826 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1827 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1828 std::get<0>(spline_)
1829 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1830 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1831 std::get<0>(spline_)
1832 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1833 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1834 std::get<0>(spline_)
1835 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1836 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1837 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1838 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1839
1840 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1841 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1842 std::get<1>(spline_)
1843 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1844 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1845 std::get<1>(spline_)
1846 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1847 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1848 std::get<1>(spline_)
1849 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1850 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1851 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1852 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1853 std::get<1>(spline_)
1854 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1855 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1856 std::get<1>(spline_)
1857 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1858 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1859 std::get<1>(spline_)
1860 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1861 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1862 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1863 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1864
1865 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1866 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1867 std::get<2>(spline_)
1868 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1869 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1870 std::get<2>(spline_)
1871 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1872 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1873 std::get<2>(spline_)
1874 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1875 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1876 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1877 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1878 std::get<2>(spline_)
1879 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1880 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1881 std::get<2>(spline_)
1882 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1883 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1884 std::get<2>(spline_)
1885 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1886 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1887 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1888 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)));
1889 }
1890 }
1891
1897 template <functionspace comp = functionspace::interior,
1898 bool memory_optimized = false>
1899 inline auto
1901 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1903 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1904 torch::Tensor> &coeff_indices) const {
1905
1906 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1907 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1908 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1909 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1910 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1911 xi[2].sizes() == xi[3].sizes());
1912
1913 if constexpr (comp == functionspace::interior) {
1914 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1915 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1916 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1917 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1918 "hess(.) for vector-valued spaces requires 1D variables");
1919
1921 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1922 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1923 std::get<0>(spline_)
1924 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1925 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1926 std::get<0>(spline_)
1927 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1928 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1929 std::get<0>(spline_)
1930 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1931 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1932 std::get<0>(spline_)
1933 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1934 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1935 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1936 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1937 std::get<0>(spline_)
1938 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1939 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1940 std::get<0>(spline_)
1941 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1942 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1943 std::get<0>(spline_)
1944 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1945 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1946 std::get<0>(spline_)
1947 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1948 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1949 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1950 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1951 std::get<0>(spline_)
1952 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1953 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1954 std::get<0>(spline_)
1955 .template eval<deriv::dt + deriv::dx, memory_optimized>(
1956 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1957 std::get<0>(spline_)
1958 .template eval<deriv::dt + deriv::dy, memory_optimized>(
1959 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1960 std::get<0>(spline_)
1961 .template eval<deriv::dt + deriv::dz, memory_optimized>(
1962 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1963 std::get<0>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1964 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1965
1966 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1967 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1968 std::get<1>(spline_)
1969 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1970 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1971 std::get<1>(spline_)
1972 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1973 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1974 std::get<1>(spline_)
1975 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1976 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1977 std::get<1>(spline_)
1978 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1979 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1980 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1981 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1982 std::get<1>(spline_)
1983 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1984 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1985 std::get<1>(spline_)
1986 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1987 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1988 std::get<1>(spline_)
1989 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1990 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1991 std::get<1>(spline_)
1992 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1993 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1994 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1995 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1996 std::get<1>(spline_)
1997 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1998 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1999 std::get<1>(spline_)
2000 .template eval<deriv::dt + deriv::dx, memory_optimized>(
2001 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
2002 std::get<1>(spline_)
2003 .template eval<deriv::dt + deriv::dy, memory_optimized>(
2004 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
2005 std::get<1>(spline_)
2006 .template eval<deriv::dt + deriv::dz, memory_optimized>(
2007 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
2008 std::get<1>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
2009 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
2010
2011 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2012 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2013 std::get<2>(spline_)
2014 .template eval<deriv::dx + deriv::dy, memory_optimized>(
2015 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2016 std::get<2>(spline_)
2017 .template eval<deriv::dx + deriv::dz, memory_optimized>(
2018 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2019 std::get<2>(spline_)
2020 .template eval<deriv::dx + deriv::dt, memory_optimized>(
2021 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2022 std::get<2>(spline_)
2023 .template eval<deriv::dy + deriv::dx, memory_optimized>(
2024 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2025 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2026 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2027 std::get<2>(spline_)
2028 .template eval<deriv::dy + deriv::dz, memory_optimized>(
2029 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2030 std::get<2>(spline_)
2031 .template eval<deriv::dy + deriv::dt, memory_optimized>(
2032 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2033 std::get<2>(spline_)
2034 .template eval<deriv::dz + deriv::dx, memory_optimized>(
2035 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2036 std::get<2>(spline_)
2037 .template eval<deriv::dz + deriv::dy, memory_optimized>(
2038 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2039 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2040 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2041 std::get<2>(spline_)
2042 .template eval<deriv::dz + deriv::dt, memory_optimized>(
2043 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2044 std::get<2>(spline_)
2045 .template eval<deriv::dt + deriv::dx, memory_optimized>(
2046 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2047 std::get<2>(spline_)
2048 .template eval<deriv::dt + deriv::dy, memory_optimized>(
2049 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2050 std::get<2>(spline_)
2051 .template eval<deriv::dt + deriv::dz, memory_optimized>(
2052 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2053 std::get<2>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
2054 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
2055
2056 std::get<3>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2057 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2058 std::get<3>(spline_)
2059 .template eval<deriv::dx + deriv::dy, memory_optimized>(
2060 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2061 std::get<3>(spline_)
2062 .template eval<deriv::dx + deriv::dz, memory_optimized>(
2063 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2064 std::get<3>(spline_)
2065 .template eval<deriv::dx + deriv::dt, memory_optimized>(
2066 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2067 std::get<3>(spline_)
2068 .template eval<deriv::dy + deriv::dx, memory_optimized>(
2069 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2070 std::get<3>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2071 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2072 std::get<3>(spline_)
2073 .template eval<deriv::dy + deriv::dz, memory_optimized>(
2074 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2075 std::get<3>(spline_)
2076 .template eval<deriv::dy + deriv::dt, memory_optimized>(
2077 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2078 std::get<3>(spline_)
2079 .template eval<deriv::dz + deriv::dx, memory_optimized>(
2080 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2081 std::get<3>(spline_)
2082 .template eval<deriv::dz + deriv::dy, memory_optimized>(
2083 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2084 std::get<3>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2085 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2086 std::get<3>(spline_)
2087 .template eval<deriv::dz + deriv::dt, memory_optimized>(
2088 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2089 std::get<3>(spline_)
2090 .template eval<deriv::dt + deriv::dx, memory_optimized>(
2091 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2092 std::get<3>(spline_)
2093 .template eval<deriv::dt + deriv::dy, memory_optimized>(
2094 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2095 std::get<3>(spline_)
2096 .template eval<deriv::dt + deriv::dz, memory_optimized>(
2097 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
2098 std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
2099 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)));
2100 }
2101 }
2103
2104 // clang-format off
2133 // clang-format on
2135 template <functionspace comp = functionspace::interior,
2136 bool memory_optimized = false>
2137 inline auto jac(const utils::TensorArray<nspaces()> &xi) const {
2138 return jac<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
2139 }
2140
2145 template <functionspace comp = functionspace::interior,
2146 bool memory_optimized = false, typename... TensorArrays>
2147 inline auto jac(const utils::TensorArray<nspaces()> &xi,
2148 const std::tuple<TensorArrays...> &knot_indices) const {
2149 return jac<comp, memory_optimized>(xi, knot_indices,
2150 find_coeff_indices<comp>(knot_indices));
2151 }
2152
2158 template <functionspace comp = functionspace::interior,
2159 bool memory_optimized = false>
2160 inline auto jac(const utils::TensorArray1 &xi,
2161 const std::tuple<utils::TensorArray1> &knot_indices,
2162 const std::tuple<torch::Tensor> &coeff_indices) const {
2163
2164 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
2165
2166 if constexpr (comp == functionspace::interior) {
2167 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
2168 "jac(.) for vector-valued spaces requires 1D variables");
2169
2171 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
2172 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
2173 }
2174 }
2175
2181 template <functionspace comp = functionspace::interior,
2182 bool memory_optimized = false>
2183 inline auto
2185 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
2186 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
2187
2188 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2189 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2190 xi[0].sizes() == xi[1].sizes());
2191
2192 if constexpr (comp == functionspace::interior) {
2193 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2194 std::tuple_element_t<1, spline_type>::geoDim() == 1,
2195 "jac(.) for vector-valued spaces requires 1D variables");
2196
2198 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
2199 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2200 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
2201 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2202
2203 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
2204 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2205 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
2206 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
2207 }
2208 }
2209
2215 template <functionspace comp = functionspace::interior,
2216 bool memory_optimized = false>
2217 inline auto jac(const utils::TensorArray3 &xi,
2218 const std::tuple<utils::TensorArray3, utils::TensorArray3,
2219 utils::TensorArray3> &knot_indices,
2220 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
2221 &coeff_indices) const {
2222
2223 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2224 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2225 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2226 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
2227
2228 if constexpr (comp == functionspace::interior) {
2229 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2230 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2231 std::tuple_element_t<2, spline_type>::geoDim() == 1,
2232 "jac(.) for vector-valued spaces requires 1D variables");
2233
2235 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
2236 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2237 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
2238 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2239 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
2240 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2241
2242 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
2243 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2244 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
2245 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2246 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
2247 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2248
2249 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
2250 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2251 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
2252 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2253 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
2254 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
2255 }
2256 }
2257
2263 template <functionspace comp = functionspace::interior,
2264 bool memory_optimized = false>
2265 inline auto
2267 const std::tuple<utils::TensorArray4, utils::TensorArray4,
2269 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
2270 torch::Tensor> &coeff_indices) const {
2271
2272 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2273 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2274 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2275 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
2276 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
2277 xi[2].sizes() == xi[3].sizes());
2278
2279 if constexpr (comp == functionspace::interior) {
2280 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2281 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2282 std::tuple_element_t<2, spline_type>::geoDim() == 1,
2283 "jac(.) for vector-valued spaces requires 1D variables");
2284
2286 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
2287 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2288 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
2289 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2290 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
2291 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2292 std::get<0>(spline_).template eval<deriv::dt, memory_optimized>(
2293 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2294
2295 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
2296 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2297 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
2298 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2299 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
2300 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2301 std::get<1>(spline_).template eval<deriv::dt, memory_optimized>(
2302 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2303
2304 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
2305 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2306 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
2307 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2308 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
2309 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2310 std::get<2>(spline_).template eval<deriv::dt, memory_optimized>(
2311 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2312
2313 std::get<3>(spline_).template eval<deriv::dx, memory_optimized>(
2314 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2315 std::get<3>(spline_).template eval<deriv::dy, memory_optimized>(
2316 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2317 std::get<3>(spline_).template eval<deriv::dz, memory_optimized>(
2318 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2319 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
2320 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2321 }
2322 }
2324
2325 // clang-format off
2342 // clang-format on
2345 template <functionspace comp = functionspace::interior,
2346 bool memory_optimized = false>
2347 inline auto lapl(const utils::TensorArray<nspaces()> &xi) const {
2348 return lapl<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
2349 }
2350
2355 template <functionspace comp = functionspace::interior,
2356 bool memory_optimized = false, typename... TensorArrays>
2357 inline auto lapl(const utils::TensorArray<nspaces()> &xi,
2358 const std::tuple<TensorArrays...> &knot_indices) const {
2359 return lapl<comp, memory_optimized>(xi, knot_indices,
2360 find_coeff_indices<comp>(knot_indices));
2361 }
2362
2368 template <functionspace comp = functionspace::interior,
2369 bool memory_optimized = false>
2370 inline auto lapl(const utils::TensorArray1 &xi,
2371 const std::tuple<utils::TensorArray1> &knot_indices,
2372 const std::tuple<torch::Tensor> &coeff_indices) const {
2373
2374 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
2375
2376 if constexpr (comp == functionspace::interior) {
2377 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
2378 "lapl(.) for vector-valued spaces requires 1D variables");
2379
2381 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2382 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
2383 }
2384 }
2385
2391 template <functionspace comp = functionspace::interior,
2392 bool memory_optimized = false>
2393 inline auto
2395 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
2396 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
2397
2398 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2399 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2400 xi[0].sizes() == xi[1].sizes());
2401
2402 if constexpr (comp == functionspace::interior) {
2403 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2404 std::tuple_element_t<1, spline_type>::geoDim() == 1,
2405 "lapl(.) for vector-valued spaces requires 1D variables");
2406
2408 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2409 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2410 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2411 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
2412 }
2413 }
2414
2420 template <functionspace comp = functionspace::interior,
2421 bool memory_optimized = false>
2422 inline auto lapl(const utils::TensorArray3 &xi,
2423 const std::tuple<utils::TensorArray3, utils::TensorArray3,
2424 utils::TensorArray3> &knot_indices,
2425 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
2426 &coeff_indices) const {
2427
2428 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2429 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2430 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2431 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
2432
2433 if constexpr (comp == functionspace::interior) {
2434 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2435 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2436 std::tuple_element_t<2, spline_type>::geoDim() == 1,
2437 "div(.) for vector-valued spaces requires 1D variables");
2438
2440 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2441 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2442 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2443 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2444 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2445 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
2446 }
2447 }
2448
2454 template <functionspace comp = functionspace::interior,
2455 bool memory_optimized = false>
2456 inline auto
2458 const std::tuple<utils::TensorArray4, utils::TensorArray4,
2460 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
2461 torch::Tensor> &coeff_indices) const {
2462
2463 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2464 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2465 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2466 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
2467 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
2468 xi[2].sizes() == xi[3].sizes());
2469
2470 if constexpr (comp == functionspace::interior) {
2471 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2472 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2473 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
2474 std::tuple_element_t<3, spline_type>::geoDim() == 1,
2475 "div(.) for vector-valued spaces requires 1D variables");
2476
2478 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2479 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2480 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2481 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2482 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2483 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
2484 *std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
2485 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2486 }
2487 }
2489
2490#define GENERATE_EXPR_MACRO(r, data, name) \
2491private: \
2492 template <functionspace comp = functionspace::interior, \
2493 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
2494 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2495 const std::tuple<Xi...> &xi) const { \
2496 if constexpr (comp == functionspace::interior) \
2497 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2498 std::get<Is>(xi))...); \
2499 else if constexpr (comp == functionspace::boundary) \
2500 return std::tuple( \
2501 std::get<Is>(boundary_).template name<memory_optimized>( \
2502 std::get<Is>(xi))...); \
2503 } \
2504 \
2505 template <functionspace comp = functionspace::interior, \
2506 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2507 typename... Knot_Indices> \
2508 inline auto BOOST_PP_CAT(name, _all_)( \
2509 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2510 const std::tuple<Knot_Indices...> &knot_indices) const { \
2511 if constexpr (comp == functionspace::interior) \
2512 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2513 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2514 else if constexpr (comp == functionspace::boundary) \
2515 return std::tuple( \
2516 std::get<Is>(boundary_).template name<memory_optimized>( \
2517 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2518 } \
2519 \
2520 template <functionspace comp = functionspace::interior, \
2521 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2522 typename... Knot_Indices, typename... Coeff_Indices> \
2523 inline auto BOOST_PP_CAT(name, _all_)( \
2524 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2525 const std::tuple<Knot_Indices...> &knot_indices, \
2526 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
2527 if constexpr (comp == functionspace::interior) \
2528 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2529 std::get<Is>(xi), std::get<Is>(knot_indices), \
2530 std::get<Is>(coeff_indices))...); \
2531 else if constexpr (comp == functionspace::boundary) \
2532 return std::tuple( \
2533 std::get<Is>(boundary_).template name<memory_optimized>( \
2534 std::get<Is>(xi), std::get<Is>(knot_indices), \
2535 std::get<Is>(coeff_indices))...); \
2536 } \
2537 \
2538 template <functionspace comp = functionspace::interior, \
2539 bool memory_optimized = false, std::size_t... Is, std::size_t N> \
2540 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
2541 const utils::TensorArray<N> &xi) const { \
2542 if constexpr (comp == functionspace::interior) \
2543 return name<comp, memory_optimized>( \
2544 xi, std::tuple(std::get<Is>(spline_).find_knot_indices(xi)...)); \
2545 else if constexpr (comp == functionspace::boundary) \
2546 return name<comp, memory_optimized>( \
2547 xi, std::tuple(std::get<Is>(boundary_).find_knot_indices(xi)...)); \
2548 } \
2549 \
2550 template <functionspace comp = functionspace::interior, \
2551 bool memory_optimized = false, std::size_t... Is, std::size_t N, \
2552 typename... Knot_Indices> \
2553 inline auto BOOST_PP_CAT(name, _)( \
2554 std::index_sequence<Is...>, const utils::TensorArray<N> &xi, \
2555 const std::tuple<Knot_Indices...> &knot_indices) const { \
2556 if constexpr (comp == functionspace::interior) \
2557 return name<comp, memory_optimized>( \
2558 xi, knot_indices, \
2559 std::tuple(std::get<Is>(spline_).find_coeff_indices( \
2560 std::get<Is>(knot_indices))...)); \
2561 else if constexpr (comp == functionspace::boundary) \
2562 return name<comp, memory_optimized>( \
2563 xi, knot_indices, \
2564 std::tuple(std::get<Is>(boundary_).find_coeff_indices( \
2565 std::get<Is>(knot_indices))...)); \
2566 } \
2567 \
2568public: \
2569 template <functionspace comp = functionspace::interior, \
2570 bool memory_optimized = false, typename... Args> \
2571 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2572 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2573 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2574 } \
2575 \
2576 template <functionspace comp = functionspace::interior, \
2577 bool memory_optimized = false> \
2578 inline auto name(const torch::Tensor &xi) const { \
2579 return name<comp, memory_optimized>(utils::TensorArray1({xi})); \
2580 } \
2581 \
2582 template <functionspace comp = functionspace::interior, \
2583 bool memory_optimized = false, std::size_t N> \
2584 inline auto name(const utils::TensorArray<N> &xi) const { \
2585 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2586 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi); \
2587 } \
2588 \
2589 template <functionspace comp = functionspace::interior, \
2590 bool memory_optimized = false, std::size_t N, \
2591 typename... Knot_Indices> \
2592 inline auto name(const utils::TensorArray<N> &xi, \
2593 const std::tuple<Knot_Indices...> &knot_indices) const { \
2594 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2595 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, \
2596 knot_indices); \
2597 }
2598
2601 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
2603#undef GENERATE_EXPR_MACRO
2604
2605#define GENERATE_IEXPR_MACRO(r, data, name) \
2606private: \
2607 template <functionspace comp = functionspace::interior, \
2608 bool memory_optimized = false, std::size_t... Is, \
2609 typename Geometry, typename... Xi> \
2610 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2611 const Geometry &G, \
2612 const std::tuple<Xi...> &xi) const { \
2613 if constexpr (comp == functionspace::interior) { \
2614 if constexpr (Geometry::nspaces() == 1) \
2615 return std::tuple( \
2616 std::get<Is>(spline_).template name<memory_optimized>( \
2617 G.space(), std::get<Is>(xi))...); \
2618 else if constexpr (Geometry::nspaces() == nspaces()) \
2619 return std::tuple( \
2620 std::get<Is>(spline_).template name<memory_optimized>( \
2621 G.template space<Is>(), std::get<Is>(xi))...); \
2622 } else if constexpr (comp == functionspace::boundary) { \
2623 if constexpr (Geometry::nboundaries() == 1) \
2624 return std::tuple( \
2625 std::get<Is>(boundary_).template name<memory_optimized>( \
2626 static_cast<typename Geometry::boundary_type::boundary_type>( \
2627 G.boundary().coeffs()), \
2628 std::get<Is>(xi))...); \
2629 else if constexpr (Geometry::nboundaries() == nboundaries()) \
2630 return std::tuple( \
2631 std::get<Is>(boundary_).template name<memory_optimized>( \
2632 G.template boundary<Is>().coeffs(), std::get<Is>(xi))...); \
2633 } \
2634 } \
2635 \
2636 template <functionspace comp = functionspace::interior, \
2637 bool memory_optimized = false, std::size_t... Is, \
2638 typename Geometry, typename... Xi, typename... Knot_Indices, \
2639 typename... Knot_Indices_G> \
2640 inline auto BOOST_PP_CAT(name, _all_)( \
2641 std::index_sequence<Is...>, const Geometry &G, \
2642 const std::tuple<Xi...> &xi, \
2643 const std::tuple<Knot_Indices...> &knot_indices, \
2644 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
2645 if constexpr (comp == functionspace::interior) { \
2646 if constexpr (Geometry::nspaces() == 1) \
2647 return std::tuple( \
2648 std::get<Is>(spline_).template name<memory_optimized>( \
2649 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2650 std::get<Is>(knot_indices_G))...); \
2651 else \
2652 return std::tuple( \
2653 std::get<Is>(spline_).template name<memory_optimized>( \
2654 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2655 std::get<Is>(knot_indices_G))...); \
2656 } else if constexpr (comp == functionspace::boundary) { \
2657 if constexpr (Geometry::nspaces() == 1) \
2658 return std::tuple( \
2659 std::get<Is>(boundary_).template name<memory_optimized>( \
2660 static_cast<typename Geometry::boundary_type::boundary_type>( \
2661 G.boundary().coeffs()), \
2662 std::get<Is>(xi), std::get<Is>(knot_indices), \
2663 std::get<Is>(knot_indices_G))...); \
2664 else \
2665 return std::tuple( \
2666 std::get<Is>(boundary_).template name<memory_optimized>( \
2667 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2668 std::get<Is>(knot_indices), std::get<Is>(knot_indices_G))...); \
2669 } \
2670 } \
2671 \
2672 template <functionspace comp = functionspace::interior, \
2673 bool memory_optimized = false, std::size_t... Is, \
2674 typename Geometry, typename... Xi, typename... Knot_Indices, \
2675 typename... Coeff_Indices, typename... Knot_Indices_G, \
2676 typename... Coeff_Indices_G> \
2677 inline auto BOOST_PP_CAT(name, _all_)( \
2678 std::index_sequence<Is...>, const Geometry &G, \
2679 const std::tuple<Xi...> &xi, \
2680 const std::tuple<Knot_Indices...> &knot_indices, \
2681 const std::tuple<Coeff_Indices...> &coeff_indices, \
2682 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
2683 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
2684 if constexpr (comp == functionspace::interior) { \
2685 if constexpr (Geometry::nspaces() == 1) \
2686 return std::tuple( \
2687 std::get<Is>(spline_).template name<memory_optimized>( \
2688 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2689 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2690 std::get<Is>(coeff_indices_G))...); \
2691 else \
2692 return std::tuple( \
2693 std::get<Is>(spline_).template name<memory_optimized>( \
2694 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2695 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2696 std::get<Is>(coeff_indices_G))...); \
2697 } else if constexpr (comp == functionspace::boundary) { \
2698 if constexpr (Geometry::nspaces() == 1) \
2699 return std::tuple( \
2700 std::get<Is>(boundary_).template name<memory_optimized>( \
2701 static_cast<typename Geometry::boundary_type::boundary_type>( \
2702 G.boundary().coeffs()), \
2703 std::get<Is>(xi), std::get<Is>(knot_indices), \
2704 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2705 std::get<Is>(coeff_indices_G))...); \
2706 else \
2707 return std::tuple( \
2708 std::get<Is>(boundary_).template name<memory_optimized>( \
2709 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2710 std::get<Is>(knot_indices), std::get<Is>(coeff_indices), \
2711 std::get<Is>(knot_indices_G), \
2712 std::get<Is>(coeff_indices_G))...); \
2713 } \
2714 } \
2715 \
2716public: \
2717 template <functionspace comp = functionspace::interior, \
2718 bool memory_optimized = false, typename... Args> \
2719 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2720 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2721 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2722 }
2723
2726 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
2728#undef GENERATE_IEXPR_MACRO
2729};
2730
2736template <typename... Splines>
2737inline std::ostream &operator<<(std::ostream &os,
2738 const FunctionSpace<Splines...> &obj) {
2739 obj.pretty_print(os);
2740 return os;
2741}
2742
2747template <typename Spline, typename Boundary>
2748// requires SplineType<Spline> && BoundaryType<Boundary>
2750 public utils::Serializable,
2751 private utils::FullQualifiedName {
2752
2753public:
2755 using value_type = Spline::value_type;
2756
2758 using spline_type = Spline;
2759
2761 using eval_type = utils::TensorArray<Spline::parDim()>;
2762
2765
2767 using boundary_eval_type = Boundary::eval_type;
2768
2772 template <std::size_t index=0>
2773 inline static constexpr short_t geoDim() noexcept {
2774 static_assert(index < nspaces());
2775 return spline_type::geoDim();
2776 }
2777
2781 template <std::size_t index=0>
2782 inline static constexpr short_t parDim() noexcept {
2783 static_assert(index < nspaces());
2784 return spline_type::parDim();
2785 }
2786
2791 template <std::size_t index=0>
2792 inline static constexpr const auto& degrees() noexcept {
2793 static_assert(index < nspaces());
2794 return spline_type::degrees();
2795 }
2796
2802 template <std::size_t index=0>
2803 inline static constexpr short_t degree(short_t i) noexcept {
2804 static_assert(index < nspaces());
2805 return spline_type::degree(i);
2806 }
2807
2808protected:
2811
2814
2815public:
2817 FunctionSpace() = default;
2818
2820 FunctionSpace(const FunctionSpace &) = default;
2821
2824
2831 const std::array<int64_t, Spline::parDim()> &ncoeffs,
2832 enum init init = init::greville,
2834 : spline_(ncoeffs, init, options),
2835 boundary_(ncoeffs, init::none, options) {
2836 boundary_.from_full_tensor(spline_.as_tensor());
2837 }
2838
2844 std::array<std::vector<value_type>, Spline::parDim()> kv,
2845 enum init init = init::greville,
2847 : spline_(kv, init, options), boundary_(kv, init::none, options) {
2848 static_assert(Spline::is_nonuniform(),
2849 "Constructor is only available for non-uniform splines");
2850 boundary_.from_full_tensor(spline_.as_tensor());
2851 }
2852
2855 explicit FunctionSpace(const Spline &spline)
2856 : spline_(spline),
2857 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2858 boundary_.from_full_tensor(spline_.as_tensor());
2859 }
2860
2863 explicit FunctionSpace(Spline &&spline)
2864 : spline_(spline),
2865 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2866 boundary_.from_full_tensor(spline_.as_tensor());
2867 }
2869
2872 inline static constexpr std::size_t nspaces() noexcept { return 1; }
2873
2876 inline static constexpr std::size_t nboundaries() noexcept { return 1; }
2877
2880 inline constexpr const auto &spaces() const noexcept { return spline_; }
2881
2884 inline constexpr auto &spaces() noexcept { return spline_; }
2885
2888 inline constexpr const auto &boundaries() const noexcept { return boundary_; }
2889
2892 inline constexpr auto &boundaries() noexcept { return boundary_; }
2893
2897 template <std::size_t index = 0>
2898 inline constexpr const spline_type &space() const noexcept {
2899 static_assert(index < nspaces());
2900 return spline_;
2901 }
2902
2906 template <std::size_t index = 0>
2907 inline constexpr spline_type &space() noexcept {
2908 static_assert(index < nspaces());
2909 return spline_;
2910 }
2911
2915 template <std::size_t index = 0>
2916 inline constexpr const boundary_type &boundary() const noexcept {
2917 static_assert(index < nboundaries());
2918 return boundary_;
2919 }
2920
2925 template <std::size_t index = 0>
2926 inline constexpr boundary_type &boundary() noexcept {
2927 static_assert(index < nboundaries());
2928 return boundary_;
2929 }
2930
2933 inline constexpr FunctionSpace clone() const noexcept {
2934 return FunctionSpace(*this);
2935 }
2936
2940 template <std::size_t... index> inline constexpr auto clone() const noexcept {
2941
2942 static_assert(((index < nspaces()) && ... && true));
2943
2944 if constexpr (sizeof...(index) == 1)
2945 return FunctionSpace(*this);
2946 else
2947 return FunctionSpace<
2948 std::tuple<std::tuple_element_t<index, std::tuple<spline_type>>...>,
2949 std::tuple<
2950 std::tuple_element_t<index, std::tuple<boundary_type>>...>>(
2951 std::get<index>(std::make_tuple(spline_))...,
2952 std::get<index>(std::make_tuple(boundary_))...);
2953 }
2954
2957 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
2958 return spline_.as_tensor();
2959 }
2960
2963 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
2964 return boundary_.as_tensor();
2965 }
2966
2973 virtual inline torch::Tensor as_tensor() const noexcept {
2974 return spaces_as_tensor();
2975 }
2976
2980 virtual inline int64_t spaces_as_tensor_size() const noexcept {
2981 return spline_.as_tensor_size();
2982 }
2983
2987 virtual inline int64_t boundary_as_tensor_size() const noexcept {
2988 return boundary_.as_tensor_size();
2989 }
2990
2997 virtual inline int64_t as_tensor_size() const noexcept {
2998 return spaces_as_tensor_size();
2999 }
3000
3004 virtual inline FunctionSpace &
3005 spaces_from_tensor(const torch::Tensor &coeffs) noexcept {
3006 spline_.from_tensor(coeffs);
3007 return *this;
3008 }
3009
3014 virtual inline FunctionSpace &
3015 boundary_from_tensor(const torch::Tensor &coeffs) noexcept {
3016 boundary_.from_tensor(coeffs);
3017 return *this;
3018 }
3019
3023 virtual inline FunctionSpace &
3024 boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept {
3025 boundary_.from_full_tensor(coeffs);
3026 return *this;
3027 }
3028
3032 inline FunctionSpace &from_tensor(const torch::Tensor &coeffs) noexcept {
3033 spline_.from_tensor(coeffs);
3034 boundary_.from_full_tensor(coeffs);
3035 return *this;
3036 }
3037
3042 inline pugi::xml_document to_xml(int id = 0,
3043 const std::string &label = "") const {
3044 pugi::xml_document doc;
3045 pugi::xml_node root = doc.append_child("xml");
3046 to_xml(root, id, label);
3047
3048 return doc;
3049 }
3050
3056 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
3057 const std::string &label = "") const {
3058 return spline_.to_xml(root, id, label);
3059 }
3060
3066 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
3067 const std::string &label = "") {
3068 return from_xml(doc.child("xml"), id, label);
3069 }
3070
3076 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
3077 const std::string &label = "") {
3078 spline_.from_xml(root, id, label);
3079 return *this;
3080 }
3081
3084 nlohmann::json to_json() const override {
3085 auto json = nlohmann::json::array();
3086 json.push_back(spline_.to_json());
3087 json.push_back(boundary_.to_json());
3088 return json;
3089 }
3090
3096 template <typename SplinesOther, typename BoundariesOther>
3097 bool
3099 bool result(true);
3100
3101 if (!std::is_same_v<spline_type, typename std::remove_cvref_t<
3102 decltype(other)>::spline_type> ||
3103 !std::is_same_v<boundary_type, typename std::remove_cvref_t<
3104 decltype(other)>::boundary_type>)
3105 return false;
3106
3107 result *= (spaces() == other.spaces());
3108 result *= (boundaries() == other.boundaries());
3109
3110 return result;
3111 }
3112
3117 const std::function<std::array<typename Spline::value_type,
3118 Spline::geoDim()>(
3119 const std::array<typename Spline::value_type, Spline::parDim()> &)>
3120 mapping) {
3121 spline_.transform(mapping);
3122 return *this;
3123 }
3124
3125private:
3128 template <functionspace comp = functionspace::interior,
3129 deriv deriv = deriv::func, bool memory_optimized = false,
3130 std::size_t... Is, typename... Xi>
3131 inline auto eval_(std::index_sequence<Is...>,
3132 const std::tuple<Xi...> &xi) const {
3133 if constexpr (comp == functionspace::interior)
3134 return std::tuple(
3135 spline_.template eval<deriv, memory_optimized>(std::get<Is>(xi))...);
3136 else if constexpr (comp == functionspace::boundary)
3137 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
3138 std::get<Is>(xi))...);
3139 }
3140
3141 template <functionspace comp = functionspace::interior,
3142 deriv deriv = deriv::func, bool memory_optimized = false,
3143 std::size_t... Is, typename... Xi, typename... Knot_Indices>
3144 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
3145 const std::tuple<Knot_Indices...> &knot_indices) const {
3146 if constexpr (comp == functionspace::interior)
3147 return std::tuple(spline_.template eval<deriv, memory_optimized>(
3148 std::get<Is>(xi), std::get<Is>(knot_indices))...);
3149 else if constexpr (comp == functionspace::boundary)
3150 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
3151 std::get<Is>(xi), std::get<Is>(knot_indices))...);
3152 }
3153
3154 template <functionspace comp = functionspace::interior,
3155 deriv deriv = deriv::func, bool memory_optimized = false,
3156 std::size_t... Is, typename... Xi, typename... Knot_Indices,
3157 typename... Coeff_Indices>
3158 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
3159 const std::tuple<Knot_Indices...> &knot_indices,
3160 const std::tuple<Coeff_Indices...> &coeff_indices) const {
3161 if constexpr (comp == functionspace::interior)
3162 return std::tuple(spline_.template eval<deriv, memory_optimized>(
3163 std::get<Is>(xi), std::get<Is>(knot_indices),
3164 std::get<Is>(coeff_indices))...);
3165 else if constexpr (comp == functionspace::boundary)
3166 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
3167 std::get<Is>(xi), std::get<Is>(knot_indices),
3168 std::get<Is>(coeff_indices))...);
3169 }
3171
3172public:
3177 template <functionspace comp = functionspace::interior,
3178 deriv deriv = deriv::func, bool memory_optimized = false,
3179 typename Arg, typename... Args>
3180 inline auto eval(const Arg &arg, const Args &...args) const {
3181 if constexpr (comp == functionspace::interior)
3182 if constexpr (utils::is_tuple_v<Arg>)
3183 return eval_<comp, deriv, memory_optimized>(
3184 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
3185 else
3186 return spline_.template eval<deriv, memory_optimized>(arg, args...);
3187 else if constexpr (comp == functionspace::boundary) {
3188 if constexpr (utils::is_tuple_of_tuples_v<Arg>)
3189 return eval_<comp, deriv, memory_optimized>(
3190 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
3191 else
3192 return boundary_.template eval<deriv, memory_optimized>(arg, args...);
3193 }
3194 }
3195
3202 template <functionspace comp = functionspace::interior, typename... Args>
3203 inline auto eval_from_precomputed(const Args &...args) const {
3204 if constexpr (comp == functionspace::interior)
3205 return spline_.eval_from_precomputed(args...);
3206 else if constexpr (comp == functionspace::boundary)
3207 return boundary_.eval_from_precomputed(args...);
3208 }
3209
3210private:
3212 template <functionspace comp = functionspace::interior, std::size_t... Is,
3213 typename Xi>
3214 inline auto find_knot_indices_(std::index_sequence<Is...>,
3215 const Xi &xi) const {
3216 if constexpr (comp == functionspace::interior)
3217 return std::tuple(spline_.find_knot_indices(std::get<Is>(xi))...);
3218 else
3219 return std::tuple(boundary_.find_knot_indices(std::get<Is>(xi))...);
3220 }
3221
3222public:
3228 template <functionspace comp = functionspace::interior, typename Xi>
3229 inline auto find_knot_indices(const Xi &xi) const {
3230 if constexpr (comp == functionspace::interior)
3231 if constexpr (utils::is_tuple_v<Xi>)
3232 return find_knot_indices_<comp>(
3233 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
3234 else
3235 return spline_.find_knot_indices(xi);
3236 else if constexpr (comp == functionspace::boundary) {
3237 if constexpr (utils::is_tuple_of_tuples_v<Xi>)
3238 return find_knot_indices_<comp>(
3239 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
3240 else
3241 return boundary_.find_knot_indices(xi);
3242 }
3243 }
3244
3249 template <functionspace comp = functionspace::interior,
3250 deriv deriv = deriv::func, bool memory_optimized = false,
3251 typename... Args>
3252 inline auto eval_basfunc(const Args &...args) const {
3253 if constexpr (comp == functionspace::interior)
3254 return spline_.template eval_basfunc<deriv, memory_optimized>(args...);
3255 else if constexpr (comp == functionspace::boundary)
3256 return boundary_.template eval_basfunc<deriv, memory_optimized>(args...);
3257 }
3258
3259private:
3262 template <functionspace comp = functionspace::interior,
3263 bool memory_optimized = false, std::size_t... Is,
3264 typename Knot_Indices>
3265 inline auto find_coeff_indices_(std::index_sequence<Is...>,
3266 const Knot_Indices &knot_indices) const {
3267 if constexpr (comp == functionspace::interior)
3268 return std::tuple(spline_.template find_coeff_indices<memory_optimized>(
3269 std::get<Is>(knot_indices))...);
3270 else
3271 return std::tuple(boundary_.template find_coeff_indices<memory_optimized>(
3272 std::get<Is>(knot_indices))...);
3273 }
3274
3275public:
3280 template <functionspace comp = functionspace::interior,
3281 bool memory_optimized = false, typename Knot_Indices>
3282 inline auto find_coeff_indices(const Knot_Indices &knot_indices) const {
3283 if constexpr (comp == functionspace::interior)
3284 if constexpr (utils::is_tuple_v<Knot_Indices>)
3285 return find_coeff_indices_<comp, memory_optimized>(
3286 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
3287 knot_indices);
3288 else
3289 return spline_.template find_coeff_indices<memory_optimized>(
3290 knot_indices);
3291 else if constexpr (comp == functionspace::boundary) {
3292 if constexpr (utils::is_tuple_of_tuples_v<Knot_Indices>)
3293 return find_coeff_indices_<comp, memory_optimized>(
3294 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
3295 knot_indices);
3296 else
3297 return boundary_.template find_coeff_indices<memory_optimized>(
3298 knot_indices);
3299 }
3300 }
3301
3307 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
3308 spline_.uniform_refine(numRefine, dimRefine);
3309 boundary_.uniform_refine(numRefine, dimRefine);
3310 return *this;
3311 }
3312
3318 template <typename real_t> inline auto to(Options<real_t> options) const {
3319 return FunctionSpace<
3320 typename spline_type::template real_derived_self_type<real_t>,
3321 typename boundary_type::template real_derived_self_type<real_t>>(
3322 spline_.to(options), boundary_.to(options));
3323 }
3324
3329 inline auto to(torch::Device device) const {
3330 return FunctionSpace(spline_.to(device), boundary_.to(device));
3331 }
3332
3336 template <typename real_t> inline auto to() const {
3337 return FunctionSpace<
3338 typename spline_type::template real_derived_self_type<real_t>,
3339 typename boundary_type::template real_derived_self_type<real_t>>(
3340 spline_.template to<real_t>(), boundary_.template to<real_t>());
3341 }
3342
3347 inline auto scale(value_type s, int dim = -1) {
3348 spline_.scale(s, dim);
3349 boundary_.from_full_tensor(spline_.as_tensor());
3350 return *this;
3351 }
3352
3357 template <std::size_t N> inline auto scale(std::array<value_type, N> v) {
3358 spline_.scale(v);
3359 boundary_.from_full_tensor(spline_.as_tensor());
3360 return *this;
3361 }
3362
3367 template <std::size_t N> inline auto translate(std::array<value_type, N> v) {
3368 spline_.translate(v);
3369 boundary_.from_full_tensor(spline_.as_tensor());
3370 return *this;
3371 }
3372
3376 inline auto rotate(value_type angle) {
3377 spline_.rotate(angle);
3378 boundary_.from_full_tensor(spline_.as_tensor());
3379 return *this;
3380 }
3381
3385 inline auto rotate(std::array<value_type, 3> angle) {
3386 spline_.rotate(angle);
3387 boundary_.from_full_tensor(spline_.as_tensor());
3388 return *this;
3389 }
3390
3396 inline torch::serialize::OutputArchive &
3397 write(torch::serialize::OutputArchive &archive,
3398 const std::string &key = "functionspace") const {
3399 spline_.write(archive, key);
3400 boundary_.write(archive, key);
3401 return archive;
3402 }
3403
3409 inline torch::serialize::InputArchive &
3410 read(torch::serialize::InputArchive &archive,
3411 const std::string &key = "functionspace") {
3412 spline_.read(archive, key);
3413 boundary_.read(archive, key);
3414 return archive;
3415 }
3416
3419 inline void pretty_print(std::ostream &os) const noexcept override {
3420 os << name() << "(\nspline = ";
3421 spline_.pretty_print(os);
3422 os << "\nboundary = ";
3423 boundary_.pretty_print(os);
3424 os << "\n)";
3425 }
3426
3427#define GENERATE_EXPR_MACRO(r, data, name) \
3428private: \
3429 template <functionspace comp = functionspace::interior, \
3430 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
3431 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
3432 const std::tuple<Xi...> &xi) const { \
3433 if constexpr (comp == functionspace::interior) \
3434 return std::tuple( \
3435 spline_.template name<memory_optimized>(std::get<Is>(xi))...); \
3436 else if constexpr (comp == functionspace::boundary) \
3437 return std::tuple( \
3438 boundary_.template name<memory_optimized>(std::get<Is>(xi))...); \
3439 } \
3440 \
3441 template <functionspace comp = functionspace::interior, \
3442 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
3443 typename... Knot_Indices> \
3444 inline auto BOOST_PP_CAT(name, _all_)( \
3445 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
3446 const std::tuple<Knot_Indices...> &knot_indices) const { \
3447 if constexpr (comp == functionspace::interior) \
3448 return std::tuple(spline_.template name<memory_optimized>( \
3449 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
3450 else if constexpr (comp == functionspace::boundary) \
3451 return std::tuple(boundary_.template name<memory_optimized>( \
3452 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
3453 } \
3454 \
3455 template <functionspace comp = functionspace::interior, \
3456 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
3457 typename... Knot_Indices, typename... Coeff_Indices> \
3458 inline auto BOOST_PP_CAT(name, _all_)( \
3459 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
3460 const std::tuple<Knot_Indices...> &knot_indices, \
3461 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
3462 if constexpr (comp == functionspace::interior) \
3463 return std::tuple(spline_.template name<memory_optimized>( \
3464 std::get<Is>(xi), std::get<Is>(knot_indices), \
3465 std::get<Is>(coeff_indices))...); \
3466 else if constexpr (comp == functionspace::boundary) \
3467 return std::tuple(boundary_.template name<memory_optimized>( \
3468 std::get<Is>(xi), std::get<Is>(knot_indices), \
3469 std::get<Is>(coeff_indices))...); \
3470 } \
3471 \
3472public: \
3473 template <functionspace comp = functionspace::interior, \
3474 bool memory_optimized = false, typename Arg, typename... Args> \
3475 inline auto name(const Arg &arg, const Args &...args) const { \
3476 if constexpr (comp == functionspace::interior) \
3477 if constexpr (utils::is_tuple_v<Arg>) \
3478 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3479 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
3480 else \
3481 return spline_.template name<memory_optimized>(arg, args...); \
3482 else if constexpr (comp == functionspace::boundary) { \
3483 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
3484 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3485 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
3486 else \
3487 return boundary_.template name<memory_optimized>(arg, args...); \
3488 } \
3489 }
3490
3493 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
3495#undef GENERATE_EXPR_MACRO
3496
3497#define GENERATE_IEXPR_MACRO(r, data, name) \
3498private: \
3499 template <functionspace comp = functionspace::interior, \
3500 bool memory_optimized = false, std::size_t... Is, \
3501 typename Geometry, typename... Xi> \
3502 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
3503 const Geometry &G, \
3504 const std::tuple<Xi...> &xi) const { \
3505 if constexpr (comp == functionspace::interior) \
3506 return std::tuple(spline_.template name<memory_optimized>( \
3507 G.space(), std::get<Is>(xi))...); \
3508 else if constexpr (comp == functionspace::boundary) \
3509 return std::tuple(boundary_.template name<memory_optimized>( \
3510 static_cast<typename Geometry::boundary_type::boundary_type>( \
3511 G.boundary().coeffs()), \
3512 std::get<Is>(xi))...); \
3513 } \
3514 \
3515 template <functionspace comp = functionspace::interior, \
3516 bool memory_optimized = false, std::size_t... Is, \
3517 typename Geometry, typename... Xi, typename... Knot_Indices, \
3518 typename... Knot_Indices_G> \
3519 inline auto BOOST_PP_CAT(name, _all_)( \
3520 std::index_sequence<Is...>, const Geometry &G, \
3521 const std::tuple<Xi...> &xi, \
3522 const std::tuple<Knot_Indices...> &knot_indices, \
3523 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
3524 if constexpr (comp == functionspace::interior) \
3525 return std::tuple(spline_.template name<memory_optimized>( \
3526 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
3527 std::get<Is>(knot_indices_G))...); \
3528 else if constexpr (comp == functionspace::boundary) \
3529 return std::tuple(boundary_.template name<memory_optimized>( \
3530 static_cast<typename Geometry::boundary_type::boundary_type>( \
3531 G.boundary().coeffs()), \
3532 std::get<Is>(xi), std::get<Is>(knot_indices), \
3533 std::get<Is>(knot_indices_G))...); \
3534 } \
3535 \
3536 template <functionspace comp = functionspace::interior, \
3537 bool memory_optimized = false, std::size_t... Is, \
3538 typename Geometry, typename... Xi, typename... Knot_Indices, \
3539 typename... Coeff_Indices, typename... Knot_Indices_G, \
3540 typename... Coeff_Indices_G> \
3541 inline auto BOOST_PP_CAT(name, _all_)( \
3542 std::index_sequence<Is...>, const Geometry &G, \
3543 const std::tuple<Xi...> &xi, \
3544 const std::tuple<Knot_Indices...> &knot_indices, \
3545 const std::tuple<Coeff_Indices...> &coeff_indices, \
3546 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
3547 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
3548 if constexpr (comp == functionspace::interior) \
3549 return std::tuple(spline_.template name<memory_optimized>( \
3550 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
3551 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3552 std::get<Is>(coeff_indices_G))...); \
3553 else if constexpr (comp == functionspace::boundary) \
3554 return std::tuple(boundary_.template name<memory_optimized>( \
3555 static_cast<typename Geometry::boundary_type::boundary_type>( \
3556 G.boundary().coeffs()), \
3557 std::get<Is>(xi), std::get<Is>(knot_indices), \
3558 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3559 std::get<Is>(coeff_indices_G))...); \
3560 } \
3561 \
3562public: \
3563 template <functionspace comp = functionspace::interior, \
3564 bool memory_optimized = false, typename Geometry, typename Arg, \
3565 typename... Args> \
3566 inline auto name(const Geometry &G, const Arg &arg, const Args &...args) \
3567 const { \
3568 if constexpr (comp == functionspace::interior) { \
3569 if constexpr (utils::is_tuple_v<Arg>) \
3570 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3571 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3572 args...); \
3573 else \
3574 return spline_.template name<memory_optimized>(G.space(), arg, \
3575 args...); \
3576 } else if constexpr (comp == functionspace::boundary) { \
3577 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
3578 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3579 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3580 args...); \
3581 else \
3582 return boundary_.template name<memory_optimized>( \
3583 static_cast<typename Geometry::boundary_type::boundary_type>( \
3584 G.boundary().coeffs()), \
3585 arg, args...); \
3586 } \
3587 }
3588
3591 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
3593#undef GENERATE_IEXPR_MACRO
3594};
3595
3597template <typename... Args> struct FunctionSpace_trait;
3598
3600template <typename Spline> struct FunctionSpace_trait<Spline> {
3602};
3603
3605template <typename Spline, typename Boundary>
3609
3611template <typename... Splines>
3612struct FunctionSpace_trait<std::tuple<Splines...>> {
3615};
3616
3618template <typename... Splines, typename... Boundaries>
3619struct FunctionSpace_trait<std::tuple<Splines...>, std::tuple<Boundaries...>> {
3621 utils::tuple_cat_t<Boundaries...>>;
3622};
3623
3627template <typename Spline, typename Boundary>
3631
3635template <typename... Splines, typename... Boundaries>
3636struct FunctionSpace_trait<std::tuple<FunctionSpace<Splines, Boundaries>...>> {
3638 utils::tuple_cat_t<Boundaries...>>::type;
3639};
3640
3641} // namespace detail
3642
3645template <typename T>
3646concept FunctionSpaceType = std::is_base_of_v<detail::FunctionSpaceType, T>;
3647
3649template <typename... Args>
3651
3659template <typename Splines, typename Boundaries>
3660inline std::ostream &operator<<(std::ostream &os,
3662 obj.pretty_print(os);
3663 return os;
3664}
3665
3683template <typename Spline> using S = FunctionSpace<Spline>;
3684
3686template <typename Spline, short_t = Spline::parDim()> class TH;
3687
3697template <typename Spline>
3698class TH<Spline, 1>
3699 : public FunctionSpace<
3700 std::tuple<typename Spline::template derived_self_type<
3701 typename Spline::value_type, Spline::geoDim(),
3702 Spline::degree(0) + 1>,
3703 typename Spline::template derived_self_type<
3704 typename Spline::value_type, Spline::geoDim(),
3705 Spline::degree(0)>>> {
3706public:
3708 using Base = FunctionSpace<std::tuple<
3709 typename Spline::template derived_self_type<
3710 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3711 typename Spline::template derived_self_type<
3712 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3713
3719 explicit TH(const std::array<int64_t, 1> &ncoeffs,
3720 enum init init = init::greville,
3723 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {
3724 static_assert(Spline::is_nonuniform(),
3725 "TH function space requires non-uniform splines");
3726 Base::template space<0>().reduce_continuity();
3727 }
3728
3733 explicit TH(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3734 enum init init = init::greville,
3737 : Base({{kv[0].front + kv[0] + kv[0].back(), kv[1]}}, kv, init, options) {
3738 static_assert(Spline::is_nonuniform(),
3739 "TH function space requires non-uniform splines");
3740 Base::template space<0>().reduce_continuity();
3741 }
3743
3746};
3747
3759template <typename Spline>
3760class TH<Spline, 2>
3761 : public FunctionSpace<
3762 std::tuple<typename Spline::template derived_self_type<
3763 typename Spline::value_type, Spline::geoDim(),
3764 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3765 typename Spline::template derived_self_type<
3766 typename Spline::value_type, Spline::geoDim(),
3767 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3768 typename Spline::template derived_self_type<
3769 typename Spline::value_type, Spline::geoDim(),
3770 Spline::degree(0), Spline::degree(1)>>> {
3771public:
3774 std::tuple<typename Spline::template derived_self_type<
3775 typename Spline::value_type, Spline::geoDim(),
3776 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3777 typename Spline::template derived_self_type<
3778 typename Spline::value_type, Spline::geoDim(),
3779 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3780 typename Spline::template derived_self_type<
3781 typename Spline::value_type, Spline::geoDim(),
3782 Spline::degree(0), Spline::degree(1)>>>;
3783
3789 explicit TH(const std::array<int64_t, 2> &ncoeffs,
3790 enum init init = init::greville,
3793 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
3794 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
3795 static_assert(Spline::is_nonuniform(),
3796 "TH function space requires non-uniform splines");
3797 Base::template space<0>().reduce_continuity();
3798 Base::template space<1>().reduce_continuity();
3799 }
3800
3805 explicit TH(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3806 enum init init = init::greville,
3809 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3810 kv[1].front() + kv[1] + kv[1].back()}},
3811 {{kv[0].front() + kv[0] + kv[0].back(),
3812 kv[1].front() + kv[1] + kv[1].back()}},
3813 kv, init, options) {
3814 static_assert(Spline::is_nonuniform(),
3815 "TH function space requires non-uniform splines");
3816 Base::template space<0>().reduce_continuity();
3817 Base::template space<1>().reduce_continuity();
3818 }
3820
3823};
3824
3837template <typename Spline>
3838class TH<Spline, 3>
3839 : public FunctionSpace<std::tuple<
3840 typename Spline::template derived_self_type<
3841 typename Spline::value_type, Spline::geoDim(),
3842 Spline::degree(0) + 1, Spline::degree(1) + 1,
3843 Spline::degree(2) + 1>,
3844 typename Spline::template derived_self_type<
3845 typename Spline::value_type, Spline::geoDim(),
3846 Spline::degree(0) + 1, Spline::degree(1) + 1,
3847 Spline::degree(2) + 1>,
3848 typename Spline::template derived_self_type<
3849 typename Spline::value_type, Spline::geoDim(),
3850 Spline::degree(0) + 1, Spline::degree(1) + 1,
3851 Spline::degree(2) + 1>,
3852 typename Spline::template derived_self_type<
3853 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3854 Spline::degree(1), Spline::degree(2)>>> {
3855public:
3857 using Base = FunctionSpace<std::tuple<
3858 typename Spline::template derived_self_type<
3859 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3860 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3861 typename Spline::template derived_self_type<
3862 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3863 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3864 typename Spline::template derived_self_type<
3865 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3866 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3867 typename Spline::template derived_self_type<
3868 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3869 Spline::degree(1), Spline::degree(2)>>>;
3870
3876 explicit TH(const std::array<int64_t, 3> &ncoeffs,
3877 enum init init = init::greville,
3880 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3881 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3882 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
3883 options) {
3884 static_assert(Spline::is_nonuniform(),
3885 "TH function space requires non-uniform splines");
3886 Base::template space<0>().reduce_continuity();
3887 Base::template space<1>().reduce_continuity();
3888 Base::template space<2>().reduce_continuity();
3889 }
3890
3895 explicit TH(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3896 enum init init = init::greville,
3899 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3900 kv[1].front() + kv[1] + kv[1].back(),
3901 kv[2].front() + kv[2] + kv[2].back()}},
3902 {{kv[0].front() + kv[0] + kv[0].back(),
3903 kv[1].front() + kv[1] + kv[1].back(),
3904 kv[2].front() + kv[2] + kv[2].back()}},
3905 {{kv[0].front() + kv[0] + kv[0].back(),
3906 kv[1].front() + kv[1] + kv[1].back(),
3907 kv[2].front() + kv[2] + kv[2].back()}},
3908 kv, init, options) {
3909 static_assert(Spline::is_nonuniform(),
3910 "TH function space requires non-uniform splines");
3911 Base::template space<0>().reduce_continuity();
3912 Base::template space<1>().reduce_continuity();
3913 Base::template space<2>().reduce_continuity();
3914 }
3916
3919};
3920
3934template <typename Spline>
3935class TH<Spline, 4>
3936 : public FunctionSpace<std::tuple<
3937 typename Spline::template derived_self_type<
3938 typename Spline::value_type, Spline::geoDim(),
3939 Spline::degree(0) + 1, Spline::degree(1) + 1,
3940 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3941 typename Spline::template derived_self_type<
3942 typename Spline::value_type, Spline::geoDim(),
3943 Spline::degree(0) + 1, Spline::degree(1) + 1,
3944 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3945 typename Spline::template derived_self_type<
3946 typename Spline::value_type, Spline::geoDim(),
3947 Spline::degree(0) + 1, Spline::degree(1) + 1,
3948 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3949 typename Spline::template derived_self_type<
3950 typename Spline::value_type, Spline::geoDim(),
3951 Spline::degree(0) + 1, Spline::degree(1) + 1,
3952 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3953 typename Spline::template derived_self_type<
3954 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3955 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3956public:
3958 using Base = FunctionSpace<std::tuple<
3959 typename Spline::template derived_self_type<
3960 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3961 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3962 typename Spline::template derived_self_type<
3963 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3964 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3965 typename Spline::template derived_self_type<
3966 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3967 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3968 typename Spline::template derived_self_type<
3969 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3970 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3971 typename Spline::template derived_self_type<
3972 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3973 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3974
3980 explicit TH(const std::array<int64_t, 4> &ncoeffs,
3981 enum init init = init::greville,
3984 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3985 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3986 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3987 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
3988 init, options) {
3989 static_assert(Spline::is_nonuniform(),
3990 "TH function space requires non-uniform splines");
3991 Base::template space<0>().reduce_continuity();
3992 Base::template space<1>().reduce_continuity();
3993 Base::template space<2>().reduce_continuity();
3994 Base::template space<3>().reduce_continuity();
3995 }
3996
4001 explicit TH(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
4002 enum init init = init::greville,
4005 : Base({{kv[0].front() + kv[0] + kv[0].back(),
4006 kv[1].front() + kv[1] + kv[1].back(),
4007 kv[2].front() + kv[2] + kv[2].back(),
4008 kv[3].front() + kv[3] + kv[3].back()}},
4009 {{kv[0].front() + kv[0] + kv[0].back(),
4010 kv[1].front() + kv[1] + kv[1].back(),
4011 kv[2].front() + kv[2] + kv[2].back(),
4012 kv[3].front() + kv[3] + kv[3].back()}},
4013 {{kv[0].front() + kv[0] + kv[0].back(),
4014 kv[1].front() + kv[1] + kv[1].back(),
4015 kv[2].front() + kv[2] + kv[2].back(),
4016 kv[3].front() + kv[3] + kv[3].back()}},
4017 {{kv[0].front() + kv[0] + kv[0].back(),
4018 kv[1].front() + kv[1] + kv[1].back(),
4019 kv[2].front() + kv[2] + kv[2].back(),
4020 kv[3].front() + kv[3] + kv[3].back()}},
4021 kv, init, options) {
4022 static_assert(Spline::is_nonuniform(),
4023 "TH function space requires non-uniform splines");
4024 Base::template space<0>().reduce_continuity();
4025 Base::template space<1>().reduce_continuity();
4026 Base::template space<2>().reduce_continuity();
4027 Base::template space<3>().reduce_continuity();
4028 }
4030
4033};
4034
4036template <typename Spline, short_t = Spline::parDim()> class NE;
4037
4047template <typename Spline>
4048class NE<Spline, 1>
4049 : public FunctionSpace<
4050 std::tuple<typename Spline::template derived_self_type<
4051 typename Spline::value_type, Spline::geoDim(),
4052 Spline::degree(0) + 1>,
4053 typename Spline::template derived_self_type<
4054 typename Spline::value_type, Spline::geoDim(),
4055 Spline::degree(0)>>> {
4056public:
4058 using Base = FunctionSpace<std::tuple<
4059 typename Spline::template derived_self_type<
4060 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
4061 typename Spline::template derived_self_type<
4062 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
4063
4069 explicit NE(const std::array<int64_t, 1> &ncoeffs,
4070 enum init init = init::greville,
4073 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
4074
4079 explicit NE(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
4080 enum init init = init::greville,
4083 : Base(kv, kv, init, options) {
4084 static_assert(Spline::is_nonuniform(),
4085 "Constructor only available for non-uniform splines");
4086 }
4088
4091};
4092
4103template <typename Spline>
4104class NE<Spline, 2>
4105 : public FunctionSpace<
4106 std::tuple<typename Spline::template derived_self_type<
4107 typename Spline::value_type, Spline::geoDim(),
4108 Spline::degree(0) + 1, Spline::degree(1) + 1>,
4109 typename Spline::template derived_self_type<
4110 typename Spline::value_type, Spline::geoDim(),
4111 Spline::degree(0) + 1, Spline::degree(1) + 1>,
4112 typename Spline::template derived_self_type<
4113 typename Spline::value_type, Spline::geoDim(),
4114 Spline::degree(0), Spline::degree(1)>>> {
4115public:
4118 std::tuple<typename Spline::template derived_self_type<
4119 typename Spline::value_type, Spline::geoDim(),
4120 Spline::degree(0) + 1, Spline::degree(1) + 1>,
4121 typename Spline::template derived_self_type<
4122 typename Spline::value_type, Spline::geoDim(),
4123 Spline::degree(0) + 1, Spline::degree(1) + 1>,
4124 typename Spline::template derived_self_type<
4125 typename Spline::value_type, Spline::geoDim(),
4126 Spline::degree(0), Spline::degree(1)>>>;
4127
4133 explicit NE(const std::array<int64_t, 2> &ncoeffs,
4134 enum init init = init::greville,
4137 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
4138 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
4139 static_assert(Spline::is_nonuniform(),
4140 "NE function space requires non-uniform splines");
4141 Base::template space<0>().reduce_continuity(1, 1);
4142 Base::template space<1>().reduce_continuity(1, 0);
4143 }
4144
4149 explicit NE(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
4150 enum init init = init::greville,
4153 : Base(kv, kv, kv, init, options) {
4154 static_assert(Spline::is_nonuniform(),
4155 "NE function space requires non-uniform splines");
4156 Base::template space<0>().reduce_continuity(1, 1);
4157 Base::template space<1>().reduce_continuity(1, 0);
4158 }
4160
4163};
4164
4177template <typename Spline>
4178class NE<Spline, 3>
4179 : public FunctionSpace<std::tuple<
4180 typename Spline::template derived_self_type<
4181 typename Spline::value_type, Spline::geoDim(),
4182 Spline::degree(0) + 1, Spline::degree(1) + 1,
4183 Spline::degree(2) + 1>,
4184 typename Spline::template derived_self_type<
4185 typename Spline::value_type, Spline::geoDim(),
4186 Spline::degree(0) + 1, Spline::degree(1) + 1,
4187 Spline::degree(2) + 1>,
4188 typename Spline::template derived_self_type<
4189 typename Spline::value_type, Spline::geoDim(),
4190 Spline::degree(0) + 1, Spline::degree(1) + 1,
4191 Spline::degree(2) + 1>,
4192 typename Spline::template derived_self_type<
4193 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4194 Spline::degree(1), Spline::degree(2)>>> {
4195public:
4197 using Base = FunctionSpace<std::tuple<
4198 typename Spline::template derived_self_type<
4199 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4200 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4201 typename Spline::template derived_self_type<
4202 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4203 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4204 typename Spline::template derived_self_type<
4205 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4206 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4207 typename Spline::template derived_self_type<
4208 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4209 Spline::degree(1), Spline::degree(2)>>>;
4210
4216 explicit NE(const std::array<int64_t, 3> &ncoeffs,
4217 enum init init = init::greville,
4220 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
4221 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
4222 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
4223 options) {
4224 static_assert(Spline::is_nonuniform(),
4225 "NE function space requires non-uniform splines");
4226 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
4227 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
4228 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
4229 }
4230
4235 explicit NE(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4236 enum init init = init::greville,
4239 : Base(kv, kv, kv, kv, init, options) {
4240 static_assert(Spline::is_nonuniform(),
4241 "NE function space requires non-uniform splines");
4242 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
4243 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
4244 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
4245 }
4247
4250};
4251
4265template <typename Spline>
4266class NE<Spline, 4>
4267 : public FunctionSpace<std::tuple<
4268 typename Spline::template derived_self_type<
4269 typename Spline::value_type, Spline::geoDim(),
4270 Spline::degree(0) + 1, Spline::degree(1) + 1,
4271 Spline::degree(2) + 1, Spline::degree(3) + 1>,
4272 typename Spline::template derived_self_type<
4273 typename Spline::value_type, Spline::geoDim(),
4274 Spline::degree(0) + 1, Spline::degree(1) + 1,
4275 Spline::degree(2) + 1, Spline::degree(3) + 1>,
4276 typename Spline::template derived_self_type<
4277 typename Spline::value_type, Spline::geoDim(),
4278 Spline::degree(0) + 1, Spline::degree(1) + 1,
4279 Spline::degree(2) + 1, Spline::degree(3) + 1>,
4280 typename Spline::template derived_self_type<
4281 typename Spline::value_type, Spline::geoDim(),
4282 Spline::degree(0) + 1, Spline::degree(1) + 1,
4283 Spline::degree(2) + 1, Spline::degree(3) + 1>,
4284 typename Spline::template derived_self_type<
4285 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4286 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
4287public:
4289 using Base = FunctionSpace<std::tuple<
4290 typename Spline::template derived_self_type<
4291 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4292 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
4293 typename Spline::template derived_self_type<
4294 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4295 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
4296 typename Spline::template derived_self_type<
4297 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4298 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
4299 typename Spline::template derived_self_type<
4300 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4301 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
4302 typename Spline::template derived_self_type<
4303 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4304 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
4305
4311 explicit NE(const std::array<int64_t, 4> &ncoeffs,
4312 enum init init = init::greville,
4315 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
4316 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
4317 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
4318 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
4319 init, options) {
4320 static_assert(Spline::is_nonuniform(),
4321 "NE function space requires non-uniform splines");
4322 Base::template space<0>()
4323 .reduce_continuity(1, 1)
4324 .reduce_continuity(1, 2)
4325 .reduce_continuity(1, 3);
4326 Base::template space<1>()
4327 .reduce_continuity(1, 0)
4328 .reduce_continuity(1, 2)
4329 .reduce_continuity(1, 3);
4330 Base::template space<2>()
4331 .reduce_continuity(1, 0)
4332 .reduce_continuity(1, 1)
4333 .reduce_continuity(1, 3);
4334 Base::template space<3>()
4335 .reduce_continuity(1, 0)
4336 .reduce_continuity(1, 1)
4337 .reduce_continuity(1, 2);
4338 }
4339
4344 explicit NE(const std::array<std::vector<typename Spline::value_type>,
4345 Spline::parDim()> &kv,
4346 enum init init = init::greville,
4349 : Base(kv, kv, kv, kv, kv, init, options) {
4350 static_assert(Spline::is_nonuniform(),
4351 "NE function space requires non-uniform splines");
4352 Base::template space<0>()
4353 .reduce_continuity(1, 1)
4354 .reduce_continuity(1, 2)
4355 .reduce_continuity(1, 3);
4356 Base::template space<1>()
4357 .reduce_continuity(1, 0)
4358 .reduce_continuity(1, 2)
4359 .reduce_continuity(1, 3);
4360 Base::template space<2>()
4361 .reduce_continuity(1, 0)
4362 .reduce_continuity(1, 1)
4363 .reduce_continuity(1, 3);
4364 Base::template space<3>()
4365 .reduce_continuity(1, 0)
4366 .reduce_continuity(1, 1)
4367 .reduce_continuity(1, 2);
4368 }
4370
4373};
4374
4376template <typename Spline, short_t = Spline::parDim()> class RT;
4377
4387template <typename Spline>
4388class RT<Spline, 1>
4389 : public FunctionSpace<
4390 std::tuple<typename Spline::template derived_self_type<
4391 typename Spline::value_type, Spline::geoDim(),
4392 Spline::degree(0) + 1>,
4393 typename Spline::template derived_self_type<
4394 typename Spline::value_type, Spline::geoDim(),
4395 Spline::degree(0)>>> {
4396public:
4398 using Base = FunctionSpace<std::tuple<
4399 typename Spline::template derived_self_type<
4400 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
4401 typename Spline::template derived_self_type<
4402 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
4403
4409 explicit RT(const std::array<int64_t, 1> &ncoeffs,
4410 enum init init = init::greville,
4413 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
4414
4419 explicit RT(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
4420 enum init init = init::greville,
4423 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}}, kv, init,
4424 options) {
4425 static_assert(Spline::is_nonuniform(),
4426 "Constructor only available for non-uniform splines");
4427 }
4429
4432};
4433
4445template <typename Spline>
4446class RT<Spline, 2>
4447 : public FunctionSpace<
4448 std::tuple<typename Spline::template derived_self_type<
4449 typename Spline::value_type, Spline::geoDim(),
4450 Spline::degree(0) + 1, Spline::degree(1)>,
4451 typename Spline::template derived_self_type<
4452 typename Spline::value_type, Spline::geoDim(),
4453 Spline::degree(0), Spline::degree(1) + 1>,
4454 typename Spline::template derived_self_type<
4455 typename Spline::value_type, Spline::geoDim(),
4456 Spline::degree(0), Spline::degree(1)>>> {
4457public:
4459 std::tuple<typename Spline::template derived_self_type<
4460 typename Spline::value_type, Spline::geoDim(),
4461 Spline::degree(0) + 1, Spline::degree(1)>,
4462 typename Spline::template derived_self_type<
4463 typename Spline::value_type, Spline::geoDim(),
4464 Spline::degree(0), Spline::degree(1) + 1>,
4465 typename Spline::template derived_self_type<
4466 typename Spline::value_type, Spline::geoDim(),
4467 Spline::degree(0), Spline::degree(1)>>>;
4468
4474 explicit RT(const std::array<int64_t, 2> &ncoeffs,
4475 enum init init = init::greville,
4478 : Base(ncoeffs + utils::to_array(1_i64, 0_i64),
4479 ncoeffs + utils::to_array(0_i64, 1_i64), ncoeffs, init, options) {}
4480
4485 explicit RT(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
4486 enum init init = init::greville,
4489 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}},
4490 {{kv[0], kv[1].front() + kv[1] + kv[1].back()}}, kv, init,
4491 options) {
4492 static_assert(Spline::is_nonuniform(),
4493 "Constructor only available for non-uniform splines");
4494 }
4496
4499};
4500
4512template <typename Spline>
4513class RT<Spline, 3>
4514 : public FunctionSpace<std::tuple<
4515 typename Spline::template derived_self_type<
4516 typename Spline::value_type, Spline::geoDim(),
4517 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2)>,
4518 typename Spline::template derived_self_type<
4519 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4520 Spline::degree(1) + 1, Spline::degree(2)>,
4521 typename Spline::template derived_self_type<
4522 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4523 Spline::degree(1), Spline::degree(2) + 1>,
4524 typename Spline::template derived_self_type<
4525 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4526 Spline::degree(1), Spline::degree(2)>>> {
4527public:
4529 using Base = FunctionSpace<std::tuple<
4530 typename Spline::template derived_self_type<
4531 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4532 Spline::degree(1), Spline::degree(2)>,
4533 typename Spline::template derived_self_type<
4534 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4535 Spline::degree(1) + 1, Spline::degree(2)>,
4536 typename Spline::template derived_self_type<
4537 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4538 Spline::degree(1), Spline::degree(2) + 1>,
4539 typename Spline::template derived_self_type<
4540 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4541 Spline::degree(1), Spline::degree(2)>>>;
4542
4548 explicit RT(const std::array<int64_t, 3> &ncoeffs,
4549 enum init init = init::greville,
4552 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
4553 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
4554 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), ncoeffs, init,
4555 options) {}
4556
4561 explicit RT(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4562 enum init init = init::greville,
4565 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
4566 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
4567 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, kv, init,
4568 options) {
4569 static_assert(Spline::is_nonuniform(),
4570 "Constructor only available for non-uniform splines");
4571 }
4573
4576};
4577
4591template <typename Spline>
4592class RT<Spline, 4>
4593 : public FunctionSpace<std::tuple<
4594 typename Spline::template derived_self_type<
4595 typename Spline::value_type, Spline::geoDim(),
4596 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2),
4597 Spline::degree(3)>,
4598 typename Spline::template derived_self_type<
4599 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4600 Spline::degree(1) + 1, Spline::degree(2), Spline::degree(3)>,
4601 typename Spline::template derived_self_type<
4602 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4603 Spline::degree(1), Spline::degree(2) + 1, Spline::degree(3)>,
4604 typename Spline::template derived_self_type<
4605 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4606 Spline::degree(1), Spline::degree(2), Spline::degree(3) + 1>,
4607 typename Spline::template derived_self_type<
4608 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4609 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
4610public:
4612 using Base = FunctionSpace<std::tuple<
4613 typename Spline::template derived_self_type<
4614 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4615 Spline::degree(1), Spline::degree(2), Spline::degree(3)>,
4616 typename Spline::template derived_self_type<
4617 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4618 Spline::degree(1) + 1, Spline::degree(2), Spline::degree(3)>,
4619 typename Spline::template derived_self_type<
4620 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4621 Spline::degree(1), Spline::degree(2) + 1, Spline::degree(3)>,
4622 typename Spline::template derived_self_type<
4623 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4624 Spline::degree(1), Spline::degree(2), Spline::degree(3) + 1>,
4625 typename Spline::template derived_self_type<
4626 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4627 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
4628
4634 explicit RT(const std::array<int64_t, 4> &ncoeffs,
4635 enum init init = init::greville,
4638 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64, 0_i64),
4639 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64, 0_i64),
4640 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64, 0_i64),
4641 ncoeffs + utils::to_array(0_i64, 0_i64, 0_i64, 1_i64), ncoeffs,
4642 init, options) {}
4643
4648 explicit RT(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
4649 enum init init = init::greville,
4652 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2], kv[3]}},
4653 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2], kv[3]}},
4654 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back(), kv[3]}},
4655 {{kv[0], kv[1], kv[2], kv[3].front() + kv[3] + kv[3].back()}}, kv,
4656 init, options) {
4657 static_assert(Spline::is_nonuniform(),
4658 "Constructor only available for non-uniform splines");
4659 }
4661
4664};
4665
4667template <typename Spline, short_t = Spline::parDim()> class Hcurl;
4668
4680template <typename Spline>
4681class Hcurl<Spline, 3>
4682 : public FunctionSpace<std::tuple<
4683 typename Spline::template derived_self_type<
4684 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4685 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4686 typename Spline::template derived_self_type<
4687 typename Spline::value_type, Spline::geoDim(),
4688 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2) + 1>,
4689 typename Spline::template derived_self_type<
4690 typename Spline::value_type, Spline::geoDim(),
4691 Spline::degree(0) + 1, Spline::degree(1) + 1,
4692 Spline::degree(2)>>> {
4693
4694public:
4696 using Base = FunctionSpace<std::tuple<
4697 typename Spline::template derived_self_type<
4698 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4699 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4700 typename Spline::template derived_self_type<
4701 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4702 Spline::degree(1), Spline::degree(2) + 1>,
4703 typename Spline::template derived_self_type<
4704 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4705 Spline::degree(1) + 1, Spline::degree(2)>>>;
4706
4712 explicit Hcurl(const std::array<int64_t, 3> &ncoeffs,
4713 enum init init = init::greville,
4716 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
4717 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
4718 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), init, options) {}
4719
4724 explicit Hcurl(
4725 const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4726 enum init init = init::greville,
4729 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
4730 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
4731 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, init,
4732 options) {
4733 static_assert(Spline::is_nonuniform(),
4734 "Constructor only available for non-uniform splines");
4735 }
4738};
4739
4741template <typename Spline, short_t = Spline::parDim()> class NE_RT_DG;
4742
4758template <typename Spline>
4759class NE_RT_DG<Spline, 2>
4760 : public FunctionSpace<std::tuple<
4761 // Vector potential field \f$ H^1(\Omega) \f$
4762 typename Spline::template derived_self_type<
4763 typename Spline::value_type, Spline::geoDim(),
4764 Spline::degree(0) + 1, Spline::degree(1) + 1>,
4765 // Velocity field \f$ \mathbf{H}(\mathbf{curl}, \Omega) \f$
4766 typename Spline::template derived_self_type<
4767 typename Spline::value_type, Spline::geoDim(),
4768 Spline::degree(0) + 1, Spline::degree(1)>,
4769 typename Spline::template derived_self_type<
4770 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4771 Spline::degree(1) + 1>,
4772 // Pressure field \f$ L^2(\Omega) \f$
4773 typename Spline::template derived_self_type<
4774 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4775 Spline::degree(1)>>> {
4776
4777public:
4779 using Base = FunctionSpace<std::tuple<
4780 // Vector potential field \f$ H^1(\Omega) \f$
4781 typename Spline::template derived_self_type<
4782 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4783 Spline::degree(1) + 1>,
4784 // Velocity field \f$ \mathbf{H}(\mathbf{curl}, \Omega) \f$
4785 typename Spline::template derived_self_type<
4786 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4787 Spline::degree(1)>,
4788 typename Spline::template derived_self_type<
4789 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4790 Spline::degree(1) + 1>,
4791 // Pressure field \f$ L^2(\Omega) \f$
4792 typename Spline::template derived_self_type<
4793 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4794 Spline::degree(1)>>>;
4795
4801 explicit NE_RT_DG(const std::array<int64_t, 2> &ncoeffs,
4802 enum init init = init::greville,
4805 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
4806 ncoeffs + utils::to_array(1_i64, 0_i64),
4807 ncoeffs + utils::to_array(0_i64, 1_i64), ncoeffs, init, options) {}
4808
4813 explicit NE_RT_DG(
4814 const std::array<std::vector<typename Spline::value_type>, 2> &kv,
4815 enum init init = init::greville,
4818 : Base({{kv[0].front() + kv[0] + kv[0].back(),
4819 kv[1].front() + kv[1] + kv[1].back()}},
4820 {{kv[0].front() + kv[0] + kv[0].back(), kv[1]}},
4821 {{kv[0], kv[1].front() + kv[1] + kv[1].back()}}, {{kv[0], kv[1]}},
4822 init, options) {
4823 static_assert(Spline::is_nonuniform(),
4824 "Constructor only available for non-uniform splines");
4825 }
4828};
4829
4846template <typename Spline>
4847class NE_RT_DG<Spline, 3>
4848 : public FunctionSpace<std::tuple<
4849 // Vector potential field \f$ H^1(\Omega) \f$
4850 typename Spline::template derived_self_type<
4851 typename Spline::value_type, Spline::geoDim(),
4852 Spline::degree(0) + 1, Spline::degree(1) + 1,
4853 Spline::degree(2) + 1>,
4854 // Velocity field \f$ \mathbf{H}(\mathbf{curl}, \Omega) \f$
4855 typename Spline::template derived_self_type<
4856 typename Spline::value_type, Spline::geoDim(),
4857 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2)>,
4858 typename Spline::template derived_self_type<
4859 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4860 Spline::degree(1) + 1, Spline::degree(2)>,
4861 typename Spline::template derived_self_type<
4862 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4863 Spline::degree(1), Spline::degree(2) + 1>,
4864 // Pressure field \f$ L^2(\Omega) \f$
4865 typename Spline::template derived_self_type<
4866 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4867 Spline::degree(1), Spline::degree(2)>>> {
4868
4869public:
4871 using Base = FunctionSpace<std::tuple<
4872 // Vector potential field \f$ H^1(\Omega) \f$
4873 typename Spline::template derived_self_type<
4874 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4875 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4876 // Velocity field \f$ \mathbf{H}(\mathbf{curl}, \Omega) \f$
4877 typename Spline::template derived_self_type<
4878 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4879 Spline::degree(1), Spline::degree(2)>,
4880 typename Spline::template derived_self_type<
4881 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4882 Spline::degree(1) + 1, Spline::degree(2)>,
4883 typename Spline::template derived_self_type<
4884 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4885 Spline::degree(1), Spline::degree(2) + 1>,
4886 // Pressure field \f$ L^2(\Omega) \f$
4887 typename Spline::template derived_self_type<
4888 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4889 Spline::degree(1), Spline::degree(2)>>>;
4890
4896 explicit NE_RT_DG(const std::array<int64_t, 3> &ncoeffs,
4897 enum init init = init::greville,
4900 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
4901 ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
4902 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
4903 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), ncoeffs, init,
4904 options) {}
4905
4910 explicit NE_RT_DG(
4911 const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4912 enum init init = init::greville,
4915 : Base({{kv[0].front() + kv[0] + kv[0].back(),
4916 kv[1].front() + kv[1] + kv[1].back(),
4917 kv[2].front() + kv[2] + kv[2].back()}},
4918 {{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
4919 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
4920 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}},
4921 {{kv[0], kv[1], kv[2]}}, init, options) {
4922 static_assert(Spline::is_nonuniform(),
4923 "Constructor only available for non-uniform splines");
4924 }
4927};
4928
4929#undef IGANET_FUNCTIONSPACE_DEFAULT_OPS
4930
4931} // namespace iganet
Boundary treatment.
#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 (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
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
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
auto to(Options< real_t > options) const
Returns a copy of the boundary object with settings from options.
Definition boundary.hpp:2129
auto & from_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor.
Definition boundary.hpp:1316
torch::Tensor as_tensor() const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1261
auto & uniform_refine(int numRefine=1, int dim=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition boundary.hpp:1586
int64_t as_tensor_size() const
Returns the size of the single tensor representation of all spline objects.
Definition boundary.hpp:1282
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
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)+1, Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1), Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)> > > Base
Base type.
Definition functionspace.hpp:4705
Hcurl(const std::array< int64_t, 3 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4712
Hcurl(const std::array< std::vector< typename Spline::value_type >, 3 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the Hcurl operation.
Definition functionspace.hpp:4724
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)> > > Base
Base type.
Definition functionspace.hpp:4062
NE(const std::array< int64_t, 1 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4069
NE(const std::array< std::vector< typename Spline::value_type >, 1 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the NE operation.
Definition functionspace.hpp:4079
NE(const std::array< int64_t, 2 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4133
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)> > > Base
Base type.
Definition functionspace.hpp:4126
NE(const std::array< std::vector< typename Spline::value_type >, 2 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the NE operation.
Definition functionspace.hpp:4149
NE(const std::array< int64_t, 3 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4216
NE(const std::array< std::vector< typename Spline::value_type >, 3 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the NE operation.
Definition functionspace.hpp:4235
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)> > > Base
Base type.
Definition functionspace.hpp:4209
NE(const std::array< int64_t, 4 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4311
NE(const std::array< std::vector< typename Spline::value_type >, Spline::parDim()> &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the NE operation.
Definition functionspace.hpp:4344
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1, Spline::degree(3)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1, Spline::degree(3)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1, Spline::degree(3)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1, Spline::degree(3)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2), Spline::degree(3)> > > Base
Base type.
Definition functionspace.hpp:4304
NE_RT_DG(const std::array< int64_t, 2 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4801
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)> > > Base
Base type.
Definition functionspace.hpp:4794
NE_RT_DG(const std::array< std::vector< typename Spline::value_type >, 2 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the NE_RT_DG operation.
Definition functionspace.hpp:4813
NE_RT_DG(const std::array< std::vector< typename Spline::value_type >, 3 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the NE_RT_DG operation.
Definition functionspace.hpp:4910
NE_RT_DG(const std::array< int64_t, 3 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4896
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1), Spline::degree(2)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)+1, Spline::degree(2)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)> > > Base
Base type.
Definition functionspace.hpp:4889
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:47
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)> > > Base
Base type.
Definition functionspace.hpp:4402
RT(const std::array< int64_t, 1 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4409
RT(const std::array< std::vector< typename Spline::value_type >, 1 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the RT operation.
Definition functionspace.hpp:4419
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)> > > Base
Definition functionspace.hpp:4467
RT(const std::array< int64_t, 2 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4474
RT(const std::array< std::vector< typename Spline::value_type >, 2 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the RT operation.
Definition functionspace.hpp:4485
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1), Spline::degree(2)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)+1, Spline::degree(2)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)> > > Base
Base type.
Definition functionspace.hpp:4541
RT(const std::array< int64_t, 3 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4548
RT(const std::array< std::vector< typename Spline::value_type >, 3 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the RT operation.
Definition functionspace.hpp:4561
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, 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(1)+1, 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(2)+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), Spline::degree(3)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2), Spline::degree(3)> > > Base
Base type.
Definition functionspace.hpp:4627
RT(const std::array< int64_t, 4 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4634
RT(const std::array< std::vector< typename Spline::value_type >, 4 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the RT operation.
Definition functionspace.hpp:4648
TH(const std::array< int64_t, 1 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:3719
TH(const std::array< std::vector< typename Spline::value_type >, 1 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the TH operation.
Definition functionspace.hpp:3733
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)> > > Base
Base type.
Definition functionspace.hpp:3712
TH(const std::array< std::vector< typename Spline::value_type >, 2 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the TH operation.
Definition functionspace.hpp:3805
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)> > > Base
Base type.
Definition functionspace.hpp:3782
TH(const std::array< int64_t, 2 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:3789
TH(const std::array< int64_t, 3 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:3876
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)> > > Base
Base type.
Definition functionspace.hpp:3869
TH(const std::array< std::vector< typename Spline::value_type >, 3 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the TH operation.
Definition functionspace.hpp:3895
TH(const std::array< std::vector< typename Spline::value_type >, 4 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Provides the TH operation.
Definition functionspace.hpp:4001
TH(const std::array< int64_t, 4 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:3980
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1, Spline::degree(3)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1, Spline::degree(3)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1, Spline::degree(3)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1, Spline::degree(3)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2), Spline::degree(3)> > > Base
Base type.
Definition functionspace.hpp:3973
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:1013
auto find_knot_indices(const utils::TensorArray< nspaces()> &xi) const
Returns the knot indices of knot spans containing xi
Definition functionspace.hpp:812
auto eval_basfunc_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the values of the spline objects' basis functions in the points xi
Definition functionspace.hpp:836
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 functionspace.hpp:753
virtual int64_t boundary_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:366
auto hess(const utils::TensorArray< nspaces()> &xi) const
Returns a block-tensor with the Hessian of the function space object in the points xi with respect to...
Definition functionspace.hpp:1705
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:567
auto jac(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Provides the jac operation.
Definition functionspace.hpp:2160
static constexpr short_t geoDim() noexcept
Returns the geometric dimensions of the index-th space.
Definition functionspace.hpp:95
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:991
auto rotate_(std::index_sequence< Is... >, std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:1100
torch::serialize::InputArchive & read(torch::serialize::InputArchive &archive, const std::string &key="functionspace")
Loads the function space object from a torch::serialize::InputArchive object.
Definition functionspace.hpp:1183
int64_t boundary_as_tensor_size_(std::index_sequence< Is... >) const noexcept
Returns the size of the single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:356
auto & boundary() noexcept
Returns a non-constant reference to the index-th boundary object.
Definition functionspace.hpp:262
auto boundingBox() const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:1127
FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:269
auto div(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Provides the div operation.
Definition functionspace.hpp:1372
auto curl(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Provides the curl operation.
Definition functionspace.hpp:1249
static constexpr std::size_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:214
auto to_(std::index_sequence< Is... >, std::index_sequence< Js... >, Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:955
auto jac(const utils::TensorArray3 &xi, const std::tuple< utils::TensorArray3, utils::TensorArray3, utils::TensorArray3 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the jac operation.
Definition functionspace.hpp:2217
auto jac(const utils::TensorArray< nspaces()> &xi) const
Returns a block-tensor with the Jacobian of the function space object in the points xi with respect t...
Definition functionspace.hpp:2137
static constexpr const auto & degrees() noexcept
Returns a constant reference to the array of degrees of the index-th space.
Definition functionspace.hpp:114
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:298
torch::Tensor boundary_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:308
auto & space() noexcept
Returns a non-constant reference to the index-th space.
Definition functionspace.hpp:245
auto & uniform_refine_(std::index_sequence< Is... >, std::index_sequence< Js... >, int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:930
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:1074
std::tuple< Boundaries... > boundary_type
Boundary type.
Definition functionspace.hpp:86
FunctionSpace(std::tuple< Splines... > &&spline, std::tuple< Boundaries... > &&boundary)
Provides the FunctionSpace operation.
Definition functionspace.hpp:201
std::common_type_t< typename Splines::value_type... > value_type
Value type.
Definition functionspace.hpp:77
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 spline objects from precomputed basis function.
Definition functionspace.hpp:726
virtual FunctionSpace & from_tensor(const torch::Tensor &tensor)
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:467
auto clone() const noexcept
Returns a clone of a subset of the function space.
Definition functionspace.hpp:274
auto div(const utils::TensorArray< nspaces()> &xi) const
Returns a block-tensor with the divergence of the function space object with respect to the parametri...
Definition functionspace.hpp:1362
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:1093
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:944
FunctionSpace & from_xml(const pugi::xml_node &root, int id=0, const std::string &label="")
Updates the function space object from XML node.
Definition functionspace.hpp:538
FunctionSpace & boundary_from_tensor_(std::index_sequence< Is... >, const torch::Tensor &tensor)
Sets the tuple of boundaries from a single-tensor representation of the boundaries only.
Definition functionspace.hpp:422
auto eval_basfunc(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects' basis functions in the points xi
Definition functionspace.hpp:874
auto hess(const utils::TensorArray4 &xi, const std::tuple< utils::TensorArray4, utils::TensorArray4, utils::TensorArray4, utils::TensorArray4 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the hess operation.
Definition functionspace.hpp:1900
virtual FunctionSpace & boundary_from_tensor(const torch::Tensor &tensor)
Sets the tuple of boundaries from a single-tensor representation of the boundaries only.
Definition functionspace.hpp:436
auto eval_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi, const std::tuple< Knot_Indices... > &knot_indices, const std::tuple< Coeff_Indices... > &coeff_indices) const
Returns the values of the spline objects in the points xi
Definition functionspace.hpp:630
auto curl(const utils::TensorArray< nspaces()> &xi) const
Returns a block-tensor with the curl of the function space object with respect to the parametric vari...
Definition functionspace.hpp:1226
auto lapl(const utils::TensorArray2 &xi, const std::tuple< utils::TensorArray2, utils::TensorArray2 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the lapl operation.
Definition functionspace.hpp:2394
FunctionSpace & boundary_from_full_tensor_(std::index_sequence< Is... >, const torch::Tensor &tensor)
Sets the tuple of boundaries from a single-tensor representation.
Definition functionspace.hpp:445
auto find_coeff_indices(const std::tuple< Knot_Indices... > &knot_indices) const
Returns the indices of the spline objects' coefficients corresponding to the knot indices indices.
Definition functionspace.hpp:921
auto scale_(std::index_sequence< Is... >, value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:1022
auto eval_basfunc_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi, const std::tuple< Knot_Indices... > &knot_indices) const
Returns the values of the spline objects' basis functions in the points xi
Definition functionspace.hpp:852
auto boundingBox_(std::index_sequence< Is... >) const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:1120
std::tuple< typename Boundaries::eval_type... > boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:89
auto grad(const utils::TensorArray2 &xi, const std::tuple< utils::TensorArray2, utils::TensorArray2 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the grad operation.
Definition functionspace.hpp:1571
auto eval(const std::tuple< Xi... > &xi, const std::tuple< Knot_Indices... > &knot_indices, const std::tuple< Coeff_Indices... > &coeff_indices) const
Provides the eval operation.
Definition functionspace.hpp:686
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:1053
auto lapl(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Provides the lapl operation.
Definition functionspace.hpp:2370
auto eval(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects in the points xi
Definition functionspace.hpp:654
auto curl(const utils::TensorArray4 &xi, const std::tuple< utils::TensorArray4, utils::TensorArray4, utils::TensorArray4, utils::TensorArray4 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the curl operation.
Definition functionspace.hpp:1322
auto lapl(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Provides the lapl operation.
Definition functionspace.hpp:2357
auto hess(const utils::TensorArray2 &xi, const std::tuple< utils::TensorArray2, utils::TensorArray2 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the hess operation.
Definition functionspace.hpp:1752
auto div(const utils::TensorArray3 &xi, const std::tuple< utils::TensorArray3, utils::TensorArray3, utils::TensorArray3 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the div operation.
Definition functionspace.hpp:1437
FunctionSpace(const std::array< std::vector< typename Splines::value_type >, Splines::parDim()> &...kv, enum init init=init::greville, Options< value_type > options=iganet::Options< value_type >{})
Provides the FunctionSpace operation.
Definition functionspace.hpp:165
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:970
FunctionSpace(std::tuple< Splines... > &&spline)
Provides the FunctionSpace operation.
Definition functionspace.hpp:187
auto grad(const utils::TensorArray< nspaces()> &xi) const
Returns a block-tensor with the gradient of the function space object in the points xi with respect t...
Definition functionspace.hpp:1524
int64_t spaces_as_tensor_size_(std::index_sequence< Is... >) const noexcept
Returns the size of the single-tensor representation of the tuple of function spaces.
Definition functionspace.hpp:336
auto to_(std::index_sequence< Is... >, std::index_sequence< Js... >, torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:980
std::tuple< utils::TensorArray< Splines::parDim()>... > eval_type
Spline evaluation type.
Definition functionspace.hpp:83
auto hess(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Provides the hess operation.
Definition functionspace.hpp:1715
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 spline objects from precomputed basis function.
Definition functionspace.hpp:708
auto to_(std::index_sequence< Is... >, std::index_sequence< Js... >) const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:1000
nlohmann::json to_json_(std::index_sequence< Is... >) const
Serialization to JSON.
Definition functionspace.hpp:547
auto eval_basfunc(const std::tuple< Xi... > &xi, const std::tuple< Knot_Indices... > &knot_indices) const
Provides the eval_basfunc operation.
Definition functionspace.hpp:887
virtual int64_t spaces_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the tuple of function spaces.
Definition functionspace.hpp:346
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:1113
auto div(const utils::TensorArray2 &xi, const std::tuple< utils::TensorArray2, utils::TensorArray2 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the div operation.
Definition functionspace.hpp:1409
auto find_coeff_indices_(std::index_sequence< Is... >, const std::tuple< Knot_Indices... > &knot_indices) const
Returns the indices of the spline objects' coefficients corresponding to the knot indices indices.
Definition functionspace.hpp:901
constexpr auto & boundaries() noexcept
Returns a non-constant reference to the tuple of boundary object.
Definition functionspace.hpp:232
auto lapl(const utils::TensorArray3 &xi, const std::tuple< utils::TensorArray3, utils::TensorArray3, utils::TensorArray3 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the lapl operation.
Definition functionspace.hpp:2422
const auto & boundary() const noexcept
Returns a constant reference to the index-th boundary object.
Definition functionspace.hpp:253
FunctionSpace(const std::array< int64_t, Splines::parDim()> &...ncoeffs, enum init init=init::greville, Options< value_type > options=iganet::Options< value_type >{})
Constructor.
Definition functionspace.hpp:152
auto jac(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Provides the jac operation.
Definition functionspace.hpp:2147
auto curl(const utils::TensorArray2 &xi, const std::tuple< utils::TensorArray2, utils::TensorArray2 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor > &coeff_indices) const
Definition functionspace.hpp:1263
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:327
auto jac(const utils::TensorArray2 &xi, const std::tuple< utils::TensorArray2, utils::TensorArray2 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the jac operation.
Definition functionspace.hpp:2184
boundary_type boundary_
Boundaries.
Definition functionspace.hpp:135
auto div(const utils::TensorArray4 &xi, const std::tuple< utils::TensorArray4, utils::TensorArray4, utils::TensorArray4, utils::TensorArray4 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the div operation.
Definition functionspace.hpp:1472
constexpr const auto & boundaries() const noexcept
Returns a constant reference to the tuple of boundary object.
Definition functionspace.hpp:228
auto hess(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Provides the hess operation.
Definition functionspace.hpp:1728
constexpr const auto & spaces() const noexcept
Returns a constant reference to the tuple of function spaces.
Definition functionspace.hpp:220
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the function space object.
Definition functionspace.hpp:1191
const auto & space() const noexcept
Returns a constant reference to the index-th function space.
Definition functionspace.hpp:237
auto jac(const utils::TensorArray4 &xi, const std::tuple< utils::TensorArray4, utils::TensorArray4, utils::TensorArray4, utils::TensorArray4 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the jac operation.
Definition functionspace.hpp:2266
FunctionSpace & from_xml(const pugi::xml_document &doc, int id=0, const std::string &label="")
Updates the function space object from XML object.
Definition functionspace.hpp:528
pugi::xml_node & to_xml_(std::index_sequence< Is... >, pugi::xml_node &root, int id=0, const std::string &label="") const
Returns the function space object as XML node.
Definition functionspace.hpp:478
static constexpr short_t degree(short_t i) noexcept
Returns a constant reference to the degree in the. -th dimension of the index-th space.
Definition functionspace.hpp:125
torch::serialize::OutputArchive & write(torch::serialize::OutputArchive &archive, const std::string &key="functionspace") const
Writes the function space object into a torch::serialize::OutputArchive object.
Definition functionspace.hpp:1154
auto eval_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi, const std::tuple< Knot_Indices... > &knot_indices) const
Returns the values of the spline objects in the points xi
Definition functionspace.hpp:614
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Provides the find_knot_indices operation.
Definition functionspace.hpp:823
auto grad(const utils::TensorArray4 &xi, const std::tuple< utils::TensorArray4, utils::TensorArray4, utils::TensorArray4, utils::TensorArray4 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the grad operation.
Definition functionspace.hpp:1634
FunctionSpace & spaces_from_tensor_(std::index_sequence< Is... >, const torch::Tensor &tensor)
Sets the tuple of spaces from a single-tensor representation.
Definition functionspace.hpp:384
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:1033
auto find_knot_indices_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the knot indices of knot spans containing xi
Definition functionspace.hpp:794
bool operator==(const FunctionSpace< SplinesOther, BoundariesOther > &other) const
Returns true if both function space objects are the same.
Definition functionspace.hpp:578
auto eval(const std::tuple< Xi... > &xi, const std::tuple< Knot_Indices... > &knot_indices) const
Provides the eval operation.
Definition functionspace.hpp:668
auto div(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Provides the div operation.
Definition functionspace.hpp:1385
FunctionSpace(const std::tuple< Splines... > &spline)
Provides the FunctionSpace operation.
Definition functionspace.hpp:180
torch::serialize::InputArchive & read_(std::index_sequence< Is... >, torch::serialize::InputArchive &archive, const std::string &key="functionspace")
Loads the function space object from a torch::serialize::InputArchive object.
Definition functionspace.hpp:1165
pugi::xml_node & to_xml(pugi::xml_node &root, int id=0, const std::string &label="") const
Returns the function space object as XML node.
Definition functionspace.hpp:505
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &tensor)
Sets the tuple of boundaries from a single-tensor representation.
Definition functionspace.hpp:459
torch::Tensor spaces_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:290
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &tensor)
Sets the tuple of spaces from a single-tensor representation.
Definition functionspace.hpp:413
auto curl(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Provides the curl operation.
Definition functionspace.hpp:1236
static constexpr short_t parDim() noexcept
Returns the parametric dimensions of the index-th space.
Definition functionspace.hpp:104
auto scale_(std::index_sequence< Is... >, std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:1040
auto hess(const utils::TensorArray3 &xi, const std::tuple< utils::TensorArray3, utils::TensorArray3, utils::TensorArray3 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the hess operation.
Definition functionspace.hpp:1797
auto lapl(const utils::TensorArray< nspaces()> &xi) const
Returns a block-tensor with the Laplacian of the function space object in the points xi with respect ...
Definition functionspace.hpp:2347
auto curl(const utils::TensorArray3 &xi, const std::tuple< utils::TensorArray3, utils::TensorArray3, utils::TensorArray3 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Definition functionspace.hpp:1285
constexpr auto & spaces() noexcept
Returns a non-constant reference to the tuple of function spaces.
Definition functionspace.hpp:224
auto translate_(std::index_sequence< Is... >, std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:1060
auto find_knot_indices_(std::index_sequence< Is... >, const utils::TensorArray< nspaces()> &xi) const
Returns the knot indices of knot spans containing xi
Definition functionspace.hpp:784
auto eval_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the values of the spline objects in the points xi
Definition functionspace.hpp:599
std::tuple< Splines... > spline_type
Spline type.
Definition functionspace.hpp:80
auto lapl(const utils::TensorArray4 &xi, const std::tuple< utils::TensorArray4, utils::TensorArray4, utils::TensorArray4, utils::TensorArray4 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the lapl operation.
Definition functionspace.hpp:2457
FunctionSpace(const std::tuple< Splines... > &spline, const std::tuple< Boundaries... > &boundary)
Provides the FunctionSpace operation.
Definition functionspace.hpp:194
auto grad(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Provides the grad operation.
Definition functionspace.hpp:1547
auto rotate_(std::index_sequence< Is... >, value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:1081
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:316
auto grad(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Provides the grad operation.
Definition functionspace.hpp:1534
torch::serialize::OutputArchive & write_(std::index_sequence< Is... >, torch::serialize::OutputArchive &archive, const std::string &key="functionspace") const
Writes the function space object into a torch::serialize::OutputArchive object.
Definition functionspace.hpp:1136
auto grad(const utils::TensorArray3 &xi, const std::tuple< utils::TensorArray3, utils::TensorArray3, utils::TensorArray3 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Provides the grad operation.
Definition functionspace.hpp:1599
static constexpr std::size_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:208
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 functionspace.hpp:770
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:377
pugi::xml_document to_xml(int id=0, const std::string &label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:491
FunctionSpace & from_xml_(std::index_sequence< Is... >, const pugi::xml_node &root, int id=0, const std::string &label="")
Updates the function space object from XML object.
Definition functionspace.hpp:514
Function space.
Definition functionspace.hpp:2751
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:3307
auto find_coeff_indices(const Knot_Indices &knot_indices) const
Returns the indices of the spline objects' coefficients corresponding to the knot indices indices.
Definition functionspace.hpp:3282
FunctionSpace(const Spline &spline)
Provides the FunctionSpace operation.
Definition functionspace.hpp:2855
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:3357
FunctionSpace(const std::array< int64_t, Spline::parDim()> &ncoeffs, enum init init=init::greville, Options< value_type > options=iganet::Options< value_type >{})
Constructor.
Definition functionspace.hpp:2830
auto eval_basfunc(const Args &...args) const
Returns the values of the spline objects' basis functions in the points xi.
Definition functionspace.hpp:3252
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:2997
bool operator==(const FunctionSpace< SplinesOther, BoundariesOther > &other) const
Returns true if both function space objects are the same.
Definition functionspace.hpp:3098
auto find_coeff_indices_(std::index_sequence< Is... >, const Knot_Indices &knot_indices) const
Returns the indices of the spline objects' coefficients corresponding to the knot indices indices.
Definition functionspace.hpp:3265
constexpr const boundary_type & boundary() const noexcept
Returns a constant reference to the index-th boundary object.
Definition functionspace.hpp:2916
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the space.
Definition functionspace.hpp:2957
pugi::xml_document to_xml(int id=0, const std::string &label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:3042
FunctionSpace()=default
Default constructor.
torch::serialize::InputArchive & read(torch::serialize::InputArchive &archive, const std::string &key="functionspace")
Loads the function space object from a torch::serialize::InputArchive object.
Definition functionspace.hpp:3410
virtual int64_t boundary_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the boundary.
Definition functionspace.hpp:2987
static constexpr short_t geoDim() noexcept
Returns the geometric dimensions of the index-th space.
Definition functionspace.hpp:2773
FunctionSpace & transform(const std::function< std::array< typename Spline::value_type, Spline::geoDim()>(const std::array< typename Spline::value_type, Spline::parDim()> &)> mapping)
Transforms the coefficients based on the given mapping.
Definition functionspace.hpp:3116
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the boundary.
Definition functionspace.hpp:2963
constexpr boundary_type & boundary() noexcept
Returns a non-constant reference to the index-th boundary object.
Definition functionspace.hpp:2926
static constexpr short_t parDim() noexcept
Returns the parametric dimensions of the index-th space.
Definition functionspace.hpp:2782
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:3347
Spline spline_type
Spline type.
Definition functionspace.hpp:2758
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the function space object.
Definition functionspace.hpp:3419
pugi::xml_node & to_xml(pugi::xml_node &root, int id=0, const std::string &label="") const
Returns the function space object as XML node.
Definition functionspace.hpp:3056
virtual int64_t spaces_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the space.
Definition functionspace.hpp:2980
FunctionSpace & from_xml(const pugi::xml_document &doc, int id=0, const std::string &label="")
Updates the function space object from XML object.
Definition functionspace.hpp:3066
auto find_knot_indices(const Xi &xi) const
Returns the knot indices of knot spans containing xi.
Definition functionspace.hpp:3229
auto eval_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the values of the spline object in the points xi
Definition functionspace.hpp:3131
torch::serialize::OutputArchive & write(torch::serialize::OutputArchive &archive, const std::string &key="functionspace") const
Writes the function space object into a torch::serialize::OutputArchive object.
Definition functionspace.hpp:3397
FunctionSpace(Spline &&spline)
Provides the FunctionSpace operation.
Definition functionspace.hpp:2863
Boundary::eval_type boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:2767
constexpr spline_type & space() noexcept
Returns a non-constant reference to the index-th function space.
Definition functionspace.hpp:2907
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:3329
auto eval(const Arg &arg, const Args &...args) const
Returns the values of the spline object in the points xi.
Definition functionspace.hpp:3180
auto eval_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi, const std::tuple< Knot_Indices... > &knot_indices, const std::tuple< Coeff_Indices... > &coeff_indices) const
Returns the values of the spline object in the points xi
Definition functionspace.hpp:3158
constexpr auto & spaces() noexcept
Returns a non-constant reference to the tuple of function spaces.
Definition functionspace.hpp:2884
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:3385
static constexpr std::size_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:2872
constexpr FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:2933
auto find_knot_indices_(std::index_sequence< Is... >, const Xi &xi) const
Returns the knot indices of knot spans containing xi.
Definition functionspace.hpp:3214
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:3376
static constexpr std::size_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:2876
static constexpr const auto & degrees() noexcept
Returns a constant reference to the array of degrees of the index-th space.
Definition functionspace.hpp:2792
constexpr const auto & spaces() const noexcept
Returns a constant reference to the tuple of function spaces.
Definition functionspace.hpp:2880
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:3367
static constexpr short_t degree(short_t i) noexcept
Returns a constant reference to the degree in the. -th dimension of the index-th space.
Definition functionspace.hpp:2803
FunctionSpace & from_xml(const pugi::xml_node &root, int id=0, const std::string &label="")
Updates the function space object from XML node.
Definition functionspace.hpp:3076
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:3318
auto eval_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi, const std::tuple< Knot_Indices... > &knot_indices) const
Returns the values of the spline object in the points xi
Definition functionspace.hpp:3144
virtual FunctionSpace & boundary_from_tensor(const torch::Tensor &coeffs) noexcept
Sets the boundary from a single-tensor representation of the boundary only.
Definition functionspace.hpp:3015
constexpr auto & boundaries() noexcept
Returns a non-constant reference to the tuple of boundary object.
Definition functionspace.hpp:2892
FunctionSpace(FunctionSpace &&)=default
Move constructor.
boundary_type boundary_
Boundary.
Definition functionspace.hpp:2813
Boundary boundary_type
Boundary type.
Definition functionspace.hpp:2764
utils::TensorArray< Spline::parDim()> eval_type
Spline evaluation type.
Definition functionspace.hpp:2761
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &coeffs) noexcept
Sets the space from a single-tensor representation.
Definition functionspace.hpp:3005
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept
Sets the boundary from a single-tensor representation.
Definition functionspace.hpp:3024
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:2973
constexpr const auto & boundaries() const noexcept
Returns a constant reference to the tuple of boundary object.
Definition functionspace.hpp:2888
FunctionSpace(const FunctionSpace &)=default
Copy constructor.
spline_type spline_
Spline.
Definition functionspace.hpp:2810
Spline::value_type value_type
Value type.
Definition functionspace.hpp:2755
auto eval_from_precomputed(const Args &...args) const
Returns the value of the spline object from precomputed basis function.
Definition functionspace.hpp:3203
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:3084
FunctionSpace & from_tensor(const torch::Tensor &coeffs) noexcept
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:3032
FunctionSpace(std::array< std::vector< value_type >, Spline::parDim()> kv, enum init init=init::greville, Options< value_type > options=iganet::Options< value_type >{})
Provides the FunctionSpace operation.
Definition functionspace.hpp:2843
constexpr const spline_type & space() const noexcept
Returns a constant reference to the index-th function space.
Definition functionspace.hpp:2898
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:3336
constexpr auto clone() const noexcept
Returns a subset of the tuple of function spaces.
Definition functionspace.hpp:2940
Full qualified name descriptor.
Definition fqn.hpp:22
virtual const std::string & name() const noexcept
Returns the full qualified name of the object.
Definition fqn.hpp:28
Concept to identify template parameters that are derived from iganet::details::FunctionSpaceType.
Definition functionspace.hpp:3646
Definition functionspace.hpp:54
Definition functionspace.hpp:47
Container utility functions.
#define IGANET_FUNCTIONSPACE_DEFAULT_OPS(FunctionSpace)
Macro: Implements the default methods of a function space.
Definition functionspace.hpp:37
FunctionSpace_trait< Spline, Boundary >::type type
Definition functionspace.hpp:3629
FunctionSpace_trait< utils::tuple_cat_t< Splines... >, utils::tuple_cat_t< Boundaries... > >::type type
Definition functionspace.hpp:3638
std::ostream & operator<<(std::ostream &os, const FunctionSpace< Splines... > &obj)
Print (as string) a function space object.
Definition functionspace.hpp:2737
Forward declaration.
Definition functionspace.hpp:3597
TensorArray< 4 > TensorArray4
Definition tensorarray.hpp:32
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:26
auto zip(T &&...seqs)
Provides the zip operation.
Definition zip.hpp:135
TensorArray< 3 > TensorArray3
Definition tensorarray.hpp:31
TensorArray< 1 > TensorArray1
Definition tensorarray.hpp:29
tuple_cat< Tuples... >::type tuple_cat_t
Alias for tuple_cat::type.
Definition tuple.hpp:73
TensorArray< 2 > TensorArray2
Definition tensorarray.hpp:30
Forward declaration of BlockTensor.
Definition blocktensor.hpp:47
Definition core.hpp:73
deriv
Enumerator for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:76
BoundaryCommon< BoundaryCore< Spline, Spline::parDim()> > Boundary
Boundary.
Definition boundary.hpp:2171
detail::FunctionSpace_trait< Args... >::type FunctionSpace
Function space alias.
Definition functionspace.hpp:3650
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
FunctionSpace< Spline > S
Spline function space .
Definition functionspace.hpp:3683
functionspace
Enumerator for the function space component.
Definition functionspace.hpp:31
@ none
Definition boundary.hpp:38
short int short_t
Signed short integer type used by IgANet's compact enumerations.
Definition core.hpp:76
H(curl) function space.
Definition functionspace.hpp:4667
Nedelec like function space.
Definition functionspace.hpp:4036
Nedelec-Raviart-Thomas-$P$ triple function space.
Definition functionspace.hpp:4741
Raviart-Thomas like function space.
Definition functionspace.hpp:4376
Taylor-Hood like function space.
Definition functionspace.hpp:3686
STL namespace.
Serialization prototype.
Definition serialize.hpp:29
Tuple utility functions.
Zip utility function.