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
19#include <bspline.hpp>
20#include <utils/container.hpp>
21#include <utils/type_traits.hpp>
22#include <utils/zip.hpp>
23
24namespace iganet {
25
26using namespace literals;
27using utils::operator+;
28
30enum class functionspace : short_t {
31 interior = 0,
32 boundary = 1
33};
34
36#define IGANET_FUNCTIONSPACE_DEFAULT_OPS(FunctionSpace) \
37 FunctionSpace() = default; \
38 FunctionSpace(FunctionSpace &&) = default; \
39 FunctionSpace(const FunctionSpace &) = default;
40
41namespace detail {
42
43// Forward declaration
44template <typename, typename> class FunctionSpace;
45
50template <typename... Splines, typename... Boundaries>
51class FunctionSpace<std::tuple<Splines...>, std::tuple<Boundaries...>>
53
54 static_assert(is_SplineType_v<Splines...>,
55 "Splines must be valid SplineTypes");
56 static_assert(is_BoundaryType_v<Boundaries...>,
57 "Boundaries must be valid BoundaryTypes");
58
59public:
61 using value_type = std::common_type_t<typename Splines::value_type...>;
62
64 using spline_type = std::tuple<Splines...>;
65
67 using eval_type = std::tuple<utils::TensorArray<Splines::parDim()>...>;
68
70 using boundary_type = std::tuple<Boundaries...>;
71
73 using boundary_eval_type = std::tuple<typename Boundaries::eval_type...>;
74
75protected:
78
81
82public:
84 FunctionSpace() = default;
85
87 FunctionSpace(const FunctionSpace &) = default;
88
91
94 FunctionSpace(const std::array<int64_t, Splines::parDim()> &...ncoeffs,
97 : spline_({ncoeffs, init, options}...),
98 boundary_({ncoeffs, init::none, options}...) {
100 }
101
102 FunctionSpace(const std::array<std::vector<typename Splines::value_type>,
103 Splines::parDim()> &...kv,
104 enum init init = init::greville,
106 : spline_({kv, init, options}...),
107 boundary_({kv, init::none, options}...) {
108
109 static_assert((Splines::is_nonuniform() && ... && true),
110 "Constructor is only available for non-uniform splines");
112 }
113
114 explicit FunctionSpace(const std::tuple<Splines...> &spline)
115 : spline_(spline) {
117 }
118
119 explicit FunctionSpace(std::tuple<Splines...> &&spline)
120 : spline_(spline) {
122 }
123
124 explicit FunctionSpace(const std::tuple<Splines...> &spline,
125 const std::tuple<Boundaries...> &boundary)
127 }
128
129 explicit FunctionSpace(std::tuple<Splines...> &&spline,
130 std::tuple<Boundaries...> &&boundary)
132 }
134
136 inline static constexpr short_t nspaces() noexcept {
137 return sizeof...(Splines);
138 }
139
141 inline static constexpr short_t nboundaries() noexcept {
142 return sizeof...(Boundaries);
143 }
144
146 template <short_t s> inline const auto &space() const noexcept {
147 static_assert(s >= 0 && s < nspaces());
148 return std::get<s>(spline_);
149 }
150
152 template <short_t s> inline auto &space() noexcept {
153 static_assert(s >= 0 && s < nspaces());
154 return std::get<s>(spline_);
155 }
156
158 template <short_t s> inline const auto &boundary() const noexcept {
159 static_assert(s >= 0 && s < nboundaries());
160 return std::get<s>(boundary_);
161 }
162
165 template <short_t s> inline auto &boundary() noexcept {
166 static_assert(s >= 0 && s < nboundaries());
167 return std::get<s>(boundary_);
168 }
169
171 inline FunctionSpace clone() const noexcept { return FunctionSpace(*this); }
172
174 template <short_t... s> inline auto clone() const noexcept {
175
176 static_assert(((s >= 0 && s < nspaces()) && ... && true));
177
179 std::tuple<std::tuple_element_t<s, boundary_type>...>>(
180 std::make_tuple(std::get<s>(spline_)...), std::make_tuple(std::get<s>(boundary_)...));
181 }
182
183private:
186 template <std::size_t... Is>
187 inline torch::Tensor
188 spaces_as_tensor_(std::index_sequence<Is...>) const noexcept {
189 return torch::cat({std::get<Is>(spline_).as_tensor()...});
190 }
191
192public:
195 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
196 return spaces_as_tensor_(
197 std::make_index_sequence<FunctionSpace::nspaces()>{});
198 }
199
200private:
203 template <std::size_t... Is>
204 inline torch::Tensor
205 boundary_as_tensor_(std::index_sequence<Is...>) const noexcept {
206 return torch::cat({std::get<Is>(boundary_).as_tensor()...});
207 }
208
209public:
212 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
213 return boundary_as_tensor_(
214 std::make_index_sequence<FunctionSpace::nboundaries()>{});
215 }
216
222 virtual inline torch::Tensor as_tensor() const noexcept {
223 return spaces_as_tensor();
224 }
225
226private:
229 template <std::size_t... Is>
230 inline int64_t
231 spaces_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
232 return std::apply(
233 [](auto... v) { return (v + ...); },
234 std::make_tuple(std::get<Is>(spline_).as_tensor_size()...));
235 }
236
237public:
241 return spaces_as_tensor_size_(
242 std::make_index_sequence<FunctionSpace::nspaces()>{});
243 }
244
245private:
248 template <std::size_t... Is>
249 inline int64_t
250 boundary_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
251 return std::apply(
252 [](auto... v) { return (v + ...); },
253 std::make_tuple(std::get<Is>(boundary_).as_tensor_size()...));
254 }
255
256public:
260 return boundary_as_tensor_size_(
261 std::make_index_sequence<FunctionSpace::nboundaries()>{});
262 }
263
270 return spaces_as_tensor_size();
271 }
272
273private:
275 template <std::size_t... Is>
276 inline FunctionSpace &spaces_from_tensor_(std::index_sequence<Is...>,
277 const torch::Tensor &tensor) {
278
279 // Compute the partial sums of all function spaces
280 std::array<int64_t, sizeof...(Is)> partialSums{0};
281 auto partial_sums = [&partialSums,
282 this]<std::size_t... Js>(std::index_sequence<Js...>) {
283 ((std::get<Js + 1>(partialSums) =
284 std::get<Js>(partialSums) + std::get<Js>(spline_).as_tensor_size()),
285 ...);
286 };
287 partial_sums(std::make_index_sequence<FunctionSpace::nspaces() - 1>{});
288
289 // Call from_tensor for all function spaces
290 ((std::get<Is>(spline_).from_tensor(tensor.index(
291 {torch::indexing::Slice(partialSums[Is],
292 partialSums[Is] +
293 std::get<Is>(spline_).as_tensor_size()),
294 "..."}))),
295 ...);
296
297 return *this;
298 }
299
300public:
302 virtual inline FunctionSpace &
303 spaces_from_tensor(const torch::Tensor &tensor) {
304 return spaces_from_tensor_(
305 std::make_index_sequence<FunctionSpace::nspaces()>{}, tensor);
306 }
307
308private:
311 template <std::size_t... Is>
312 inline FunctionSpace &boundary_from_tensor_(std::index_sequence<Is...>,
313 const torch::Tensor &tensor) {
314 (std::get<Is>(boundary_).from_tensor(std::get<Is>(spline_).as_tensor()),
315 ...);
316
317 return *this;
318 }
319
320public:
323 virtual inline FunctionSpace &
324 boundary_from_tensor(const torch::Tensor &tensor) {
325 return boundary_from_tensor_(
326 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
327 }
328
329private:
331 template <std::size_t... Is>
332 inline FunctionSpace &
333 boundary_from_full_tensor_(std::index_sequence<Is...>,
334 const torch::Tensor &tensor) {
335 (std::get<Is>(boundary_).from_full_tensor(
336 std::get<Is>(spline_).as_tensor()),
337 ...);
338
339 return *this;
340 }
341
342public:
344 virtual inline FunctionSpace &
345 boundary_from_full_tensor(const torch::Tensor &tensor) {
346 return boundary_from_full_tensor_(
347 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
348 }
349
351 virtual inline FunctionSpace &from_tensor(const torch::Tensor &tensor) {
352 spaces_from_tensor_(std::make_index_sequence<FunctionSpace::nspaces()>{},
353 tensor);
354 boundary_from_full_tensor_(
355 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
356 return *this;
357 }
358
359private:
361 template <std::size_t... Is>
362 inline pugi::xml_node &to_xml_(std::index_sequence<Is...>,
363 pugi::xml_node &root, int id = 0,
364 std::string label = "") const {
365
366 (std::get<Is>(spline_).to_xml(root, id, label, Is), ...);
367 return root;
368 }
369
370public:
372 inline pugi::xml_document to_xml(int id = 0, std::string label = "") const {
373 pugi::xml_document doc;
374 pugi::xml_node root = doc.append_child("xml");
375 to_xml(root, id, label);
376
377 return doc;
378 }
379
381 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
382 std::string label = "") const {
383 return to_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
384 id, label);
385 }
386
387private:
389 template <std::size_t... Is>
390 inline FunctionSpace &from_xml_(std::index_sequence<Is...>,
391 const pugi::xml_node &root, int id = 0,
392 std::string label = "") {
393
394 (std::get<Is>(spline_).from_xml(root, id, label, Is), ...);
395 return *this;
396 }
397
398public:
400 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
401 std::string label = "") {
402 return from_xml(doc.child("xml"), id, label);
403 }
404
406 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
407 std::string label = "") {
408 return from_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
409 id, label);
410 }
411
412private:
414 template <std::size_t... Is>
415 nlohmann::json to_json_(std::index_sequence<Is...>) const {
416 auto json_this = nlohmann::json::array();
417 auto json_boundary = nlohmann::json::array();
418 (json_this.push_back(std::get<Is>(spline_).to_json()), ...);
419 (json_boundary.push_back(std::get<Is>(boundary_).to_json()), ...);
420
421 auto json = nlohmann::json::array();
422 for (auto [t, b] : utils::zip(json_this, json_boundary)) {
423 auto json_inner = nlohmann::json::array();
424 json_inner.push_back(t);
425 json_inner.push_back(b);
426 json.push_back(json_inner);
427 }
428
429 return json;
430 }
431
432public:
434 nlohmann::json to_json() const override {
435 return to_json_(std::make_index_sequence<FunctionSpace::nspaces()>{});
436 }
437
438private:
442 deriv deriv = deriv::func, bool memory_optimized = false,
443 std::size_t... Is, typename... Xi>
444 inline auto eval_(std::index_sequence<Is...>,
445 const std::tuple<Xi...> &xi) const {
446 if constexpr (comp == functionspace::interior)
447 return std::tuple(
448 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
449 std::get<Is>(xi))...);
450 else if constexpr (comp == functionspace::boundary)
451 return std::tuple(
452 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
453 std::get<Is>(xi))...);
454 }
455
457 deriv deriv = deriv::func, bool memory_optimized = false,
458 std::size_t... Is, typename... Xi, typename... Knot_Indices>
459 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
460 const std::tuple<Knot_Indices...> &knot_indices) const {
461 if constexpr (comp == functionspace::interior)
462 return std::tuple(
463 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
464 std::get<Is>(xi), std::get<Is>(knot_indices))...);
465 else if constexpr (comp == functionspace::boundary)
466 return std::tuple(
467 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
468 std::get<Is>(xi), std::get<Is>(knot_indices))...);
469 }
470
472 deriv deriv = deriv::func, bool memory_optimized = false,
473 std::size_t... Is, typename... Xi, typename... Knot_Indices,
474 typename... Coeff_Indices>
475 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
476 const std::tuple<Knot_Indices...> &knot_indices,
477 const std::tuple<Coeff_Indices...> &coeff_indices) const {
478 if constexpr (comp == functionspace::interior)
479 return std::tuple(
480 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
481 std::get<Is>(xi), std::get<Is>(knot_indices),
482 std::get<Is>(coeff_indices))...);
483 else if constexpr (comp == functionspace::boundary)
484 return std::tuple(
485 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
486 std::get<Is>(xi), std::get<Is>(knot_indices),
487 std::get<Is>(coeff_indices))...);
488 }
490
491public:
495 deriv deriv = deriv::func, bool memory_optimized = false,
496 typename... Xi>
497 inline auto eval(const std::tuple<Xi...> &xi) const {
498 static_assert(FunctionSpace::nspaces() == sizeof...(Xi),
499 "Size of Xi mismatches functionspace dimension");
501 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
502 }
503
505 deriv deriv = deriv::func, bool memory_optimized = false,
506 typename... Xi, typename... Knot_Indices>
507 inline auto eval(const std::tuple<Xi...> &xi,
508 const std::tuple<Knot_Indices...> &knot_indices) const {
509 static_assert(
510 (FunctionSpace::nspaces() == sizeof...(Xi)) &&
511 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)),
512 "Sizes of Xi and Knot_Indices mismatch functionspace dimension");
514 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
515 }
516
518 deriv deriv = deriv::func, bool memory_optimized = false,
519 typename... Xi, typename... Knot_Indices, typename... Coeff_Indices>
520 inline auto eval(const std::tuple<Xi...> &xi,
521 const std::tuple<Knot_Indices...> &knot_indices,
522 const std::tuple<Coeff_Indices...> &coeff_indices) const {
523 static_assert((FunctionSpace::nspaces() == sizeof...(Xi)) &&
524 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)) &&
525 (FunctionSpace::nspaces() == sizeof...(Coeff_Indices)),
526 "Sizes of Xi, Knot_Indices and Coeff_Indices mismatch "
527 "functionspace dimension");
529 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices,
531 }
533
534private:
538 template <functionspace comp = functionspace::interior, std::size_t... Is,
539 typename... Basfunc, typename... Coeff_Indices, typename... Numeval,
540 typename... Sizes>
541 inline auto
542 eval_from_precomputed_(std::index_sequence<Is...>,
543 const std::tuple<Basfunc...> &basfunc,
544 const std::tuple<Coeff_Indices...> &coeff_indices,
545 const std::tuple<Numeval...> &numeval,
546 const std::tuple<Sizes...> &sizes) const {
547 if constexpr (comp == functionspace::interior)
548 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
549 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
550 std::get<Is>(numeval), std::get<Is>(sizes))...);
551 else if constexpr (comp == functionspace::boundary)
552 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
553 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
554 std::get<Is>(numeval), std::get<Is>(sizes))...);
555 }
556
557 template <functionspace comp = functionspace::interior, std::size_t... Is,
558 typename... Basfunc, typename... Coeff_Indices, typename... Xi>
559 inline auto
560 eval_from_precomputed_(std::index_sequence<Is...>,
561 const std::tuple<Basfunc...> &basfunc,
562 const std::tuple<Coeff_Indices...> &coeff_indices,
563 const std::tuple<Xi...> &xi) const {
564 if constexpr (comp == functionspace::interior)
565 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
566 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
567 std::get<Is>(xi)[0].numel(), std::get<Is>(xi)[0].sizes())...);
568 else if constexpr (comp == functionspace::boundary)
569 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
570 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
571 std::get<Is>(xi))...);
572 }
574
575public:
579 template <functionspace comp = functionspace::interior, typename... Basfunc,
580 typename... Coeff_Indices, typename... Numeval, typename... Sizes>
581 inline auto
582 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
583 const std::tuple<Coeff_Indices...> &coeff_indices,
584 const std::tuple<Numeval...> &numeval,
585 const std::tuple<Sizes...> &sizes) const {
587 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
589 }
590
591 template <functionspace comp = functionspace::interior, typename... Basfunc,
592 typename... Coeff_Indices, typename... Xi>
593 inline auto
594 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
595 const std::tuple<Coeff_Indices...> &coeff_indices,
596 const std::tuple<Xi...> &xi) const {
598 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
600 }
602
603private:
606 template <functionspace comp = functionspace::interior, std::size_t... Is>
607 inline auto find_knot_indices_(std::index_sequence<Is...>,
608 const utils::TensorArray<nspaces()> &xi) const {
609 if constexpr (comp == functionspace::interior)
610 return std::tuple(
611 std::get<Is>(spline_).find_knot_indices(xi)...);
612 else if constexpr (comp == functionspace::boundary)
613 return std::tuple(
614 std::get<Is>(boundary_).find_knot_indices(xi)...);
615 }
616
617 template <functionspace comp = functionspace::interior, std::size_t... Is,
618 typename... Xi>
619 inline auto find_knot_indices_(std::index_sequence<Is...>,
620 const std::tuple<Xi...> &xi) const {
621 if constexpr (comp == functionspace::interior)
622 return std::tuple(
623 std::get<Is>(spline_).find_knot_indices(std::get<Is>(xi))...);
624 else if constexpr (comp == functionspace::boundary)
625 return std::tuple(
626 std::get<Is>(boundary_).find_knot_indices(std::get<Is>(xi))...);
627 }
629
630public:
633 template <functionspace comp = functionspace::interior>
634 inline auto find_knot_indices(const utils::TensorArray<nspaces()> &xi) const {
636 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
637 }
638
639 template <functionspace comp = functionspace::interior, typename... Xi>
640 inline auto find_knot_indices(const std::tuple<Xi...> &xi) const {
642 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
643 }
645
646private:
651 deriv deriv = deriv::func, bool memory_optimized = false,
652 std::size_t... Is, typename... Xi>
653 inline auto eval_basfunc_(std::index_sequence<Is...>,
654 const std::tuple<Xi...> &xi) const {
655 if constexpr (comp == functionspace::interior)
656 return std::tuple(
657 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
658 std::get<Is>(xi))...);
659 else if constexpr (comp == functionspace::boundary)
660 return std::tuple(std::get<Is>(boundary_)
662 std::get<Is>(xi))...);
663 }
664
666 deriv deriv = deriv::func, bool memory_optimized = false,
667 std::size_t... Is, typename... Xi, typename... Knot_Indices>
668 inline auto
669 eval_basfunc_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
670 const std::tuple<Knot_Indices...> &knot_indices) const {
671 if constexpr (comp == functionspace::interior)
672 return std::tuple(
673 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
674 std::get<Is>(xi), std::get<Is>(knot_indices))...);
675 else if constexpr (comp == functionspace::boundary)
676 return std::tuple(
677 std::get<Is>(boundary_)
679 std::get<Is>(xi), std::get<Is>(knot_indices))...);
680 }
682
683public:
687 deriv deriv = deriv::func, bool memory_optimized = false,
688 typename... Xi>
689 inline auto eval_basfunc(const std::tuple<Xi...> &xi) const {
691 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
692 }
693
695 deriv deriv = deriv::func, bool memory_optimized = false,
696 typename... Xi, typename... Knot_Indices>
697 inline auto
698 eval_basfunc(const std::tuple<Xi...> &xi,
699 const std::tuple<Knot_Indices...> &knot_indices) const {
701 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
702 }
704
705private:
709 bool memory_optimized = false, std::size_t... Is,
710 typename... Knot_Indices>
711 inline auto
712 find_coeff_indices_(std::index_sequence<Is...>,
713 const std::tuple<Knot_Indices...> &knot_indices) const {
714 if constexpr (comp == functionspace::interior)
715 return std::tuple(
716 std::get<Is>(spline_).template find_coeff_indices<memory_optimized>(
717 std::get<Is>(knot_indices))...);
718 else if constexpr (comp == functionspace::boundary)
719 return std::tuple(
720 std::get<Is>(boundary_).template find_coeff_indices<memory_optimized>(
721 std::get<Is>(knot_indices))...);
722 }
723
724public:
728 bool memory_optimized = false, typename... Knot_Indices>
729 inline auto
730 find_coeff_indices(const std::tuple<Knot_Indices...> &knot_indices) const {
732 std::make_index_sequence<FunctionSpace::nspaces()>{}, knot_indices);
733 }
734
735private:
738 template <std::size_t... Is, std::size_t... Js>
739 inline auto &uniform_refine_(std::index_sequence<Is...>,
740 std::index_sequence<Js...>, int numRefine = 1,
741 int dimRefine = -1) {
742 (std::get<Is>(spline_).uniform_refine(numRefine, dimRefine), ...);
743 (std::get<Js>(boundary_).uniform_refine(numRefine, dimRefine), ...);
744 return *this;
745 }
746
747public:
750 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
751 return uniform_refine_(
752 std::make_index_sequence<FunctionSpace::nspaces()>{},
753 std::make_index_sequence<FunctionSpace::nboundaries()>{}, numRefine,
754 dimRefine);
755 }
756
757private:
760 template <typename real_t, std::size_t... Is, std::size_t... Js>
761 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
762 Options<real_t> options) const {
763 return FunctionSpace<
764 typename Splines::template real_derived_self_type<real_t>...,
765 typename Boundaries::template real_derived_self_type<real_t>...>(
766 std::get<Is>(spline_).to(options)...,
767 std::get<Js>(boundary_).to(options)...);
768 }
769
770public:
773 template <typename real_t> inline auto to(Options<real_t> options) const {
774 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
775 std::make_index_sequence<FunctionSpace::nboundaries()>{},
776 options);
777 }
778
779private:
782 template <std::size_t... Is, std::size_t... Js>
783 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
784 torch::Device device) const {
785 return FunctionSpace(std::get<Is>(spline_).to(device)...,
786 std::get<Js>(boundary_).to(device)...);
787 }
788
789public:
792 inline auto to(torch::Device device) const {
793 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
794 std::make_index_sequence<FunctionSpace::nboundaries()>{},
795 device);
796 }
797
798private:
800 template <typename real_t, std::size_t... Is, std::size_t... Js>
801 inline auto to_(std::index_sequence<Is...>,
802 std::index_sequence<Js...>) const {
803 return FunctionSpace<
804 typename Splines::template real_derived_self_type<real_t>...,
805 typename Boundaries::template real_derived_self_type<real_t>...>(
806 std::get<Is>(spline_).template to<real_t>()...,
807 std::get<Js>(boundary_).template to<real_t>()...);
808 }
809
810public:
812 template <typename real_t> inline auto to() const {
813 return to_<real_t>(
814 std::make_index_sequence<FunctionSpace::nspaces()>{},
815 std::make_index_sequence<FunctionSpace::nboundaries()>{});
816 }
817
818private:
820 template <std::size_t... Is>
821 inline auto scale_(std::index_sequence<Is...>, value_type s, int dim = -1) {
822 (std::get<Is>(spline_).scale(s, dim), ...);
824 return *this;
825 }
826
827public:
829 inline auto scale(value_type s, int dim = -1) {
830 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, s, dim);
831 }
832
833private:
835 template <std::size_t N, std::size_t... Is>
836 inline auto scale_(std::index_sequence<Is...>, std::array<value_type, N> v) {
837 (std::get<Is>(spline_).scale(v), ...);
838 (std::get<Is>(boundary_).from_full_tensor(
839 std::get<Is>(spline_).as_tensor()),
840 ...);
841 return *this;
842 }
843
844public:
846 template <size_t N> inline auto scale(std::array<value_type, N> v) {
847 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
848 }
849
850private:
852 template <std::size_t N, std::size_t... Is>
853 inline auto translate_(std::index_sequence<Is...>,
854 std::array<value_type, N> v) {
855 (std::get<Is>(spline_).translate(v), ...);
856 (std::get<Is>(boundary_).from_full_tensor(
857 std::get<Is>(spline_).as_tensor()),
858 ...);
859 return *this;
860 }
861
862public:
864 template <size_t N> inline auto translate(std::array<value_type, N> v) {
865 return translate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
866 }
867
868private:
870 template <std::size_t... Is>
871 inline auto rotate_(std::index_sequence<Is...>, value_type angle) {
872 (std::get<Is>(spline_).rotate(angle), ...);
873 (std::get<Is>(boundary_).from_full_tensor(
874 std::get<Is>(spline_).as_tensor()),
875 ...);
876 return *this;
877 }
878
879public:
881 inline auto rotate(value_type angle) {
882 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
883 }
884
885private:
887 template <std::size_t... Is>
888 inline auto rotate_(std::index_sequence<Is...>,
889 std::array<value_type, 3> angle) {
890 (std::get<Is>(spline_).rotate(angle), ...);
891 (std::get<Is>(boundary_).from_full_tensor(
892 std::get<Is>(spline_).as_tensor()),
893 ...);
894 return *this;
895 }
896
897public:
899 inline auto rotate(std::array<value_type, 3> angle) {
900 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
901 }
902
903private:
905 template <std::size_t... Is>
906 inline auto boundingBox_(std::index_sequence<Is...>) const {
907 return std::tuple(std::get<Is>(spline_).boundingBox()...);
908 }
909
910public:
912 inline auto boundingBox() const {
913 return boundingBox_(std::make_index_sequence<FunctionSpace::nspaces()>{});
914 }
915
916private:
919 template <std::size_t... Is>
920 inline torch::serialize::OutputArchive &
921 write_(std::index_sequence<Is...>, torch::serialize::OutputArchive &archive,
922 const std::string &key = "functionspace") const {
923 (std::get<Is>(spline_).write(
924 archive, key + ".fspace[" + std::to_string(Is) + "].interior"),
925 ...);
926 (std::get<Is>(boundary_).write(
927 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
928 ...);
929 return archive;
930 }
931
932public:
935 inline torch::serialize::OutputArchive &
936 write(torch::serialize::OutputArchive &archive,
937 const std::string &key = "functionspace") const {
938 write_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
939 return archive;
940 }
941
942private:
945 template <std::size_t... Is>
946 inline torch::serialize::InputArchive &
947 read_(std::index_sequence<Is...>, torch::serialize::InputArchive &archive,
948 const std::string &key = "functionspace") {
949 (std::get<Is>(spline_).read(archive, key + ".fspace[" + std::to_string(Is) +
950 "].interior"),
951 ...);
952 (std::get<Is>(boundary_).read(
953 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
954 ...);
955 return archive;
956 }
957
958public:
961 inline torch::serialize::InputArchive &
962 read(torch::serialize::InputArchive &archive,
963 const std::string &key = "functionspace") {
964 read_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
965 return archive;
966 }
967
969 inline virtual void
970 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
971
972 auto pretty_print_ = [this,
973 &os]<std::size_t... Is>(std::index_sequence<Is...>) {
974 ((os << "\ninterior = ", std::get<Is>(spline_).pretty_print(os),
975 os << "\nboundary = ", std::get<Is>(boundary_).pretty_print(os)),
976 ...);
977 };
978
979 pretty_print_(std::make_index_sequence<nspaces()>{});
980 }
981
982 // clang-format off
1000 // clang-format off
1004 bool memory_optimized = false>
1005 inline auto curl(const utils::TensorArray<nspaces()> &xi) const {
1007 }
1008
1010 bool memory_optimized = false,
1011 typename... TensorArrays>
1012 inline auto curl(const utils::TensorArray<nspaces()> &xi,
1013 const std::tuple<TensorArrays...> &knot_indices) const {
1016 }
1017
1019 bool memory_optimized = false>
1020 inline auto curl(const utils::TensorArray1 &xi,
1021 const std::tuple<utils::TensorArray1> &knot_indices,
1022 const std::tuple<torch::Tensor> &coeff_indices) const {
1023
1024 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1025
1026 throw std::runtime_error("Unsupported parametric/geometric dimension");
1027
1029 }
1030
1032 bool memory_optimized = false>
1033 inline auto
1035 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1036 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1037
1038 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1039 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1040 xi[0].sizes() == xi[1].sizes());
1041
1048 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1049 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1050 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1051 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1052 }
1053
1055 bool memory_optimized = false>
1056 inline auto curl(const utils::TensorArray3 &xi,
1057 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1059 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1060 &coeff_indices) const {
1061
1062 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1063 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1064 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1065 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1066
1071 *std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1072 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] -
1073 *std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1074 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1075 *std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1076 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] -
1077 *std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1078 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1079 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1080 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1081 *std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1082 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1083 }
1084
1086 bool memory_optimized = false>
1087 inline auto
1089 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1091 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1092 torch::Tensor> &coeff_indices) const {
1093
1094 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1095 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1096 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1097 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1098 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1099 xi[2].sizes() == xi[3].sizes());
1100
1101 throw std::runtime_error("Unsupported parametric/geometric dimension");
1102
1104 }
1106
1132 bool memory_optimized = false>
1133 inline auto div(const utils::TensorArray<nspaces()> &xi) const {
1135 }
1136
1138 bool memory_optimized = false,
1139 typename... TensorArrays>
1140 inline auto div(const utils::TensorArray<nspaces()> &xi,
1141 const std::tuple<TensorArrays...> &knot_indices) const {
1144 }
1145
1147 bool memory_optimized = false>
1148 inline auto div(const utils::TensorArray1 &xi,
1149 const std::tuple<utils::TensorArray1> &knot_indices,
1150 const std::tuple<torch::Tensor> &coeff_indices) const {
1151
1152 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1153
1154 if constexpr (comp == functionspace::interior) {
1155 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1156 "div(.) for vector-valued spaces requires 1D variables");
1157
1159 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1160 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1161 }
1162 }
1163
1165 bool memory_optimized = false>
1166 inline auto
1168 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1169 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1170
1171 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1172 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1173 xi[0].sizes() == xi[1].sizes());
1174
1175 if constexpr (comp == functionspace::interior) {
1176 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1177 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1178 "div(.) for vector-valued spaces requires 1D variables");
1179
1181 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1182 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1183 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1184 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1185 }
1186 }
1187
1189 bool memory_optimized = false>
1190 inline auto div(const utils::TensorArray3 &xi,
1191 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1193 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1194 &coeff_indices) const {
1195
1196 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1197 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1198 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1199 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1200
1201 if constexpr (comp == functionspace::interior) {
1202 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1203 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1204 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1205 "div(.) for vector-valued spaces requires 1D variables");
1206
1208 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1209 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1210 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1211 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1212 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1213 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1214 }
1215 }
1216
1218 bool memory_optimized = false>
1219 inline auto
1221 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1223 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1224 torch::Tensor> &coeff_indices) const {
1225
1226 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1227 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1228 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1229 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1230 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1231 xi[2].sizes() == xi[3].sizes());
1232
1233 if constexpr (comp == functionspace::interior) {
1234 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1235 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1236 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1237 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1238 "div(.) for vector-valued spaces requires 1D variables");
1239
1241 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1242 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1243 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1244 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1245 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1246 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
1247 *std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1248 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1249 }
1250 }
1252
1271 bool memory_optimized = false>
1272 inline auto grad(const utils::TensorArray<nspaces()> &xi) const {
1274 }
1275
1277 bool memory_optimized = false,
1278 typename... TensorArrays>
1279 inline auto grad(const utils::TensorArray<nspaces()> &xi,
1280 const std::tuple<TensorArrays...> &knot_indices) const {
1283 }
1284
1286 bool memory_optimized = false>
1287 inline auto grad(const utils::TensorArray1 &xi,
1288 const std::tuple<utils::TensorArray1> &knot_indices,
1289 const std::tuple<torch::Tensor> &coeff_indices) const {
1290
1291 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1292
1293 if constexpr (comp == functionspace::interior) {
1294 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1295 "grad(.) for vector-valued spaces requires 1D variables");
1296
1298 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1299 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1300 }
1301 }
1302
1304 bool memory_optimized = false>
1305 inline auto
1307 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1308 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1309
1310 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1311 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1312 xi[0].sizes() == xi[1].sizes());
1313
1314 if constexpr (comp == functionspace::interior) {
1315 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1316 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1317 "grad(.) for vector-valued spaces requires 1D variables");
1318
1320 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1321 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1322 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1323 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1324 }
1325 }
1326
1328 bool memory_optimized = false>
1329 inline auto grad(const utils::TensorArray3 &xi,
1330 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1332 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1333 &coeff_indices) const {
1334
1335 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1336 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1337 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1338 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1339
1340 if constexpr (comp == functionspace::interior) {
1341 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1342 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1343 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1344 "div(.) for vector-valued spaces requires 1D variables");
1345
1347 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1348 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1349 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1350 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1351 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1352 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1353 }
1354 }
1355
1357 bool memory_optimized = false>
1358 inline auto
1360 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1362 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1363 torch::Tensor> &coeff_indices) const {
1364
1365 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1366 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1367 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1368 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1369 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1370 xi[2].sizes() == xi[3].sizes());
1371
1372 if constexpr (comp == functionspace::interior) {
1373 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1374 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1375 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1376 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1377 "grad(.) for vector-valued spaces requires 1D variables");
1378
1380 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1381 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1382 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1383 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1384 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1385 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1386 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1387 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1388 }
1389 }
1391
1392 // clang-format off
1425 // clang-format on
1429 bool memory_optimized = false>
1430 inline auto hess(const utils::TensorArray<nspaces()> &xi) const {
1432 }
1433
1435 bool memory_optimized = false,
1436 typename... TensorArrays>
1437 inline auto hess(const utils::TensorArray<nspaces()> &xi,
1438 const std::tuple<TensorArrays...> &knot_indices) const {
1441 }
1442
1444 bool memory_optimized = false>
1445 inline auto hess(const utils::TensorArray1 &xi,
1446 const std::tuple<utils::TensorArray1> &knot_indices,
1447 const std::tuple<torch::Tensor> &coeff_indices) const {
1448
1449 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1450
1451 if constexpr (comp == functionspace::interior) {
1452 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1453 "hess(.) for vector-valued spaces requires 1D variables");
1454
1456 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1457 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)));
1458 }
1459 }
1460
1462 bool memory_optimized = false>
1463 inline auto
1465 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1466 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1467
1468 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1469 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1470 xi[0].sizes() == xi[1].sizes());
1471
1472 if constexpr (comp == functionspace::interior) {
1473 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1474 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1475 "hess(.) for vector-valued spaces requires 1D variables");
1476
1478 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1479 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1480 std::get<0>(spline_)
1482 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1483 std::get<0>(spline_)
1485 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1486 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1487 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1488
1489 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1490 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1491 std::get<1>(spline_)
1493 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1494 std::get<1>(spline_)
1496 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1497 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1498 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)));
1499 }
1500 }
1501
1503 bool memory_optimized = false>
1504 inline auto hess(const utils::TensorArray3 &xi,
1505 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1507 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1508 &coeff_indices) const {
1509
1510 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1511 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1512 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1513 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1514
1515 if constexpr (comp == functionspace::interior) {
1516 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1517 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1518 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1519 "hess(.) for vector-valued spaces requires 1D variables");
1520
1522 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1523 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1524 std::get<0>(spline_)
1526 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1527 std::get<0>(spline_)
1529 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1530 std::get<0>(spline_)
1532 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1533 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1534 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1535 std::get<0>(spline_)
1537 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1538 std::get<0>(spline_)
1540 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1541 std::get<0>(spline_)
1543 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1544 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1545 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1546
1547 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1548 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1549 std::get<1>(spline_)
1551 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1552 std::get<1>(spline_)
1554 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1555 std::get<1>(spline_)
1557 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1558 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1559 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1560 std::get<1>(spline_)
1562 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1563 std::get<1>(spline_)
1565 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1566 std::get<1>(spline_)
1568 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1569 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1570 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1571
1572 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1573 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1574 std::get<2>(spline_)
1576 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1577 std::get<2>(spline_)
1579 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1580 std::get<2>(spline_)
1582 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1583 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1584 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1585 std::get<2>(spline_)
1587 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1588 std::get<2>(spline_)
1590 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1591 std::get<2>(spline_)
1593 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1594 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1595 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)));
1596 }
1597 }
1598
1600 bool memory_optimized = false>
1601 inline auto
1603 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1605 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1606 torch::Tensor> &coeff_indices) const {
1607
1608 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1609 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1610 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1611 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1612 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1613 xi[2].sizes() == xi[3].sizes());
1614
1615 if constexpr (comp == functionspace::interior) {
1616 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1617 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1618 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1619 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1620 "hess(.) for vector-valued spaces requires 1D variables");
1621
1623 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1624 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1625 std::get<0>(spline_)
1627 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1628 std::get<0>(spline_)
1630 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1631 std::get<0>(spline_)
1633 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1634 std::get<0>(spline_)
1636 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1637 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1638 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1639 std::get<0>(spline_)
1641 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1642 std::get<0>(spline_)
1644 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1645 std::get<0>(spline_)
1647 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1648 std::get<0>(spline_)
1650 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1651 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1652 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1653 std::get<0>(spline_)
1655 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1656 std::get<0>(spline_)
1658 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1659 std::get<0>(spline_)
1661 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1662 std::get<0>(spline_)
1664 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1665 std::get<0>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1666 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1667
1668 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1669 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1670 std::get<1>(spline_)
1672 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1673 std::get<1>(spline_)
1675 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1676 std::get<1>(spline_)
1678 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1679 std::get<1>(spline_)
1681 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1682 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1683 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1684 std::get<1>(spline_)
1686 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1687 std::get<1>(spline_)
1689 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1690 std::get<1>(spline_)
1692 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1693 std::get<1>(spline_)
1695 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1696 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1697 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1698 std::get<1>(spline_)
1700 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1701 std::get<1>(spline_)
1703 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1704 std::get<1>(spline_)
1706 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1707 std::get<1>(spline_)
1709 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1710 std::get<1>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1711 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1712
1713 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1714 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1715 std::get<2>(spline_)
1717 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1718 std::get<2>(spline_)
1720 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1721 std::get<2>(spline_)
1723 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1724 std::get<2>(spline_)
1726 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1727 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1728 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1729 std::get<2>(spline_)
1731 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1732 std::get<2>(spline_)
1734 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1735 std::get<2>(spline_)
1737 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1738 std::get<2>(spline_)
1740 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1741 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1742 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1743 std::get<2>(spline_)
1745 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1746 std::get<2>(spline_)
1748 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1749 std::get<2>(spline_)
1751 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1752 std::get<2>(spline_)
1754 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1755 std::get<2>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1756 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1757
1758 std::get<3>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1759 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1760 std::get<3>(spline_)
1762 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1763 std::get<3>(spline_)
1765 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1766 std::get<3>(spline_)
1768 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1769 std::get<3>(spline_)
1771 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1772 std::get<3>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1773 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1774 std::get<3>(spline_)
1776 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1777 std::get<3>(spline_)
1779 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1780 std::get<3>(spline_)
1782 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1783 std::get<3>(spline_)
1785 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1786 std::get<3>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1787 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1788 std::get<3>(spline_)
1790 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1791 std::get<3>(spline_)
1793 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1794 std::get<3>(spline_)
1796 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1797 std::get<3>(spline_)
1799 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1800 std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1801 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)));
1802 }
1803 }
1805
1806 // clang-format off
1840 // clang-format on
1843 bool memory_optimized = false>
1844 inline auto jac(const utils::TensorArray<nspaces()> &xi) const {
1846 }
1847
1849 bool memory_optimized = false,
1850 typename... TensorArrays>
1851 inline auto jac(const utils::TensorArray<nspaces()> &xi,
1852 const std::tuple<TensorArrays...> &knot_indices) const {
1855 }
1856
1858 bool memory_optimized = false>
1859 inline auto jac(const utils::TensorArray1 &xi,
1860 const std::tuple<utils::TensorArray1> &knot_indices,
1861 const std::tuple<torch::Tensor> &coeff_indices) const {
1862
1863 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1864
1865 if constexpr (comp == functionspace::interior) {
1866 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1867 "jac(.) for vector-valued spaces requires 1D variables");
1868
1870 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1871 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1872 }
1873 }
1874
1876 bool memory_optimized = false>
1877 inline auto
1879 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1880 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1881
1882 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1883 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1884 xi[0].sizes() == xi[1].sizes());
1885
1886 if constexpr (comp == functionspace::interior) {
1887 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1888 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1889 "jac(.) for vector-valued spaces requires 1D variables");
1890
1892 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1893 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1894 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1895 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1896
1897 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1898 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1899 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1900 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1901 }
1902 }
1903
1905 bool memory_optimized = false>
1906 inline auto jac(const utils::TensorArray3 &xi,
1907 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1909 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1910 &coeff_indices) const {
1911
1912 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1913 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1914 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1915 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1916
1917 if constexpr (comp == functionspace::interior) {
1918 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1919 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1920 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1921 "jac(.) for vector-valued spaces requires 1D variables");
1922
1924 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1925 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1926 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1927 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1928 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1929 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1930
1931 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1932 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1933 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1934 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1935 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1936 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1937
1938 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1939 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1940 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1941 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1942 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1943 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1944 }
1945 }
1946
1948 bool memory_optimized = false>
1949 inline auto
1951 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1953 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1954 torch::Tensor> &coeff_indices) const {
1955
1956 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1957 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1958 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1959 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1960 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1961 xi[2].sizes() == xi[3].sizes());
1962
1963 if constexpr (comp == functionspace::interior) {
1964 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1965 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1966 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1967 "jac(.) for vector-valued spaces requires 1D variables");
1968
1970 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1971 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1972 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1973 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1974 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1975 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1976 std::get<0>(spline_).template eval<deriv::dt, memory_optimized>(
1977 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1978
1979 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1980 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1981 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1982 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1983 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1984 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1985 std::get<1>(spline_).template eval<deriv::dt, memory_optimized>(
1986 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1987
1988 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1989 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1990 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1991 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1992 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1993 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1994 std::get<2>(spline_).template eval<deriv::dt, memory_optimized>(
1995 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1996
1997 std::get<3>(spline_).template eval<deriv::dx, memory_optimized>(
1998 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
1999 std::get<3>(spline_).template eval<deriv::dy, memory_optimized>(
2000 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2001 std::get<3>(spline_).template eval<deriv::dz, memory_optimized>(
2002 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2003 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
2004 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2005 }
2006 }
2008
2009 // clang-format off
2026 // clang-format on
2030 bool memory_optimized = false>
2031 inline auto lapl(const utils::TensorArray<nspaces()> &xi) const {
2033 }
2034
2036 bool memory_optimized = false,
2037 typename... TensorArrays>
2038 inline auto lapl(const utils::TensorArray<nspaces()> &xi,
2039 const std::tuple<TensorArrays...> &knot_indices) const {
2042 }
2043
2045 bool memory_optimized = false>
2046 inline auto lapl(const utils::TensorArray1 &xi,
2047 const std::tuple<utils::TensorArray1> &knot_indices,
2048 const std::tuple<torch::Tensor> &coeff_indices) const {
2049
2050 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
2051
2052 if constexpr (comp == functionspace::interior) {
2053 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
2054 "lapl(.) for vector-valued spaces requires 1D variables");
2055
2057 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2058 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
2059 }
2060 }
2061
2063 bool memory_optimized = false>
2064 inline auto
2066 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
2067 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
2068
2069 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2070 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2071 xi[0].sizes() == xi[1].sizes());
2072
2073 if constexpr (comp == functionspace::interior) {
2074 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2075 std::tuple_element_t<1, spline_type>::geoDim() == 1,
2076 "lapl(.) for vector-valued spaces requires 1D variables");
2077
2079 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2080 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2081 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2082 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
2083 }
2084 }
2085
2087 bool memory_optimized = false>
2088 inline auto lapl(const utils::TensorArray3 &xi,
2089 const std::tuple<utils::TensorArray3, utils::TensorArray3,
2091 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
2092 &coeff_indices) const {
2093
2094 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2095 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2096 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2097 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
2098
2099 if constexpr (comp == functionspace::interior) {
2100 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2101 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2102 std::tuple_element_t<2, spline_type>::geoDim() == 1,
2103 "div(.) for vector-valued spaces requires 1D variables");
2104
2106 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2107 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2108 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2109 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2110 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2111 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
2112 }
2113 }
2114
2116 bool memory_optimized = false>
2117 inline auto
2119 const std::tuple<utils::TensorArray4, utils::TensorArray4,
2121 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
2122 torch::Tensor> &coeff_indices) const {
2123
2124 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2125 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2126 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2127 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
2128 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
2129 xi[2].sizes() == xi[3].sizes());
2130
2131 if constexpr (comp == functionspace::interior) {
2132 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2133 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2134 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
2135 std::tuple_element_t<3, spline_type>::geoDim() == 1,
2136 "div(.) for vector-valued spaces requires 1D variables");
2137
2139 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2140 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2141 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2142 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2143 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2144 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
2145 *std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
2146 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2147 }
2148 }
2150
2151#define GENERATE_EXPR_MACRO(r, data, name) \
2152private: \
2153 template <functionspace comp = functionspace::interior, \
2154 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
2155 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2156 const std::tuple<Xi...> &xi) const { \
2157 if constexpr (comp == functionspace::interior) \
2158 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2159 std::get<Is>(xi))...); \
2160 else if constexpr (comp == functionspace::boundary) \
2161 return std::tuple( \
2162 std::get<Is>(boundary_).template name<memory_optimized>( \
2163 std::get<Is>(xi))...); \
2164 } \
2165 \
2166 template <functionspace comp = functionspace::interior, \
2167 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2168 typename... Knot_Indices> \
2169 inline auto BOOST_PP_CAT(name, _all_)( \
2170 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2171 const std::tuple<Knot_Indices...> &knot_indices) const { \
2172 if constexpr (comp == functionspace::interior) \
2173 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2174 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2175 else if constexpr (comp == functionspace::boundary) \
2176 return std::tuple( \
2177 std::get<Is>(boundary_).template name<memory_optimized>( \
2178 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2179 } \
2180 \
2181 template <functionspace comp = functionspace::interior, \
2182 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2183 typename... Knot_Indices, typename... Coeff_Indices> \
2184 inline auto BOOST_PP_CAT(name, _all_)( \
2185 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2186 const std::tuple<Knot_Indices...> &knot_indices, \
2187 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
2188 if constexpr (comp == functionspace::interior) \
2189 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2190 std::get<Is>(xi), std::get<Is>(knot_indices), \
2191 std::get<Is>(coeff_indices))...); \
2192 else if constexpr (comp == functionspace::boundary) \
2193 return std::tuple( \
2194 std::get<Is>(boundary_).template name<memory_optimized>( \
2195 std::get<Is>(xi), std::get<Is>(knot_indices), \
2196 std::get<Is>(coeff_indices))...); \
2197 } \
2198 \
2199 template <functionspace comp = functionspace::interior, \
2200 bool memory_optimized = false, std::size_t... Is, std::size_t N> \
2201 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
2202 const utils::TensorArray<N> &xi) const { \
2203 if constexpr (comp == functionspace::interior) \
2204 return name<comp, memory_optimized>( \
2205 xi, std::tuple(std::get<Is>(spline_).find_knot_indices(xi)...)); \
2206 else if constexpr (comp == functionspace::boundary) \
2207 return name<comp, memory_optimized>( \
2208 xi, std::tuple(std::get<Is>(boundary_).find_knot_indices(xi)...)); \
2209 } \
2210 \
2211 template <functionspace comp = functionspace::interior, \
2212 bool memory_optimized = false, std::size_t... Is, std::size_t N, \
2213 typename... Knot_Indices> \
2214 inline auto BOOST_PP_CAT(name, _)( \
2215 std::index_sequence<Is...>, const utils::TensorArray<N> &xi, \
2216 const std::tuple<Knot_Indices...> &knot_indices) const { \
2217 if constexpr (comp == functionspace::interior) \
2218 return name<comp, memory_optimized>( \
2219 xi, knot_indices, \
2220 std::tuple(std::get<Is>(spline_).find_coeff_indices( \
2221 std::get<Is>(knot_indices))...)); \
2222 else if constexpr (comp == functionspace::boundary) \
2223 return name<comp, memory_optimized>( \
2224 xi, knot_indices, \
2225 std::tuple(std::get<Is>(boundary_).find_coeff_indices( \
2226 std::get<Is>(knot_indices))...)); \
2227 } \
2228 \
2229public: \
2230 template <functionspace comp = functionspace::interior, \
2231 bool memory_optimized = false, typename... Args> \
2232 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2233 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2234 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2235 } \
2236 \
2237 template <functionspace comp = functionspace::interior, \
2238 bool memory_optimized = false> \
2239 inline auto name(const torch::Tensor &xi) const { \
2240 return name<comp, memory_optimized>(utils::TensorArray1({xi})); \
2241 } \
2242 \
2243 template <functionspace comp = functionspace::interior, \
2244 bool memory_optimized = false, std::size_t N> \
2245 inline auto name(const utils::TensorArray<N> &xi) const { \
2246 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2247 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi); \
2248 } \
2249 \
2250 template <functionspace comp = functionspace::interior, \
2251 bool memory_optimized = false, std::size_t N, \
2252 typename... Knot_Indices> \
2253 inline auto name(const utils::TensorArray<N> &xi, \
2254 const std::tuple<Knot_Indices...> &knot_indices) const { \
2255 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2256 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, \
2257 knot_indices); \
2258 }
2259
2264#undef GENERATE_EXPR_MACRO
2265
2266#define GENERATE_IEXPR_MACRO(r, data, name) \
2267private: \
2268 template <functionspace comp = functionspace::interior, \
2269 bool memory_optimized = false, std::size_t... Is, \
2270 typename Geometry, typename... Xi> \
2271 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2272 const Geometry &G, \
2273 const std::tuple<Xi...> &xi) const { \
2274 if constexpr (comp == functionspace::interior) { \
2275 if constexpr (Geometry::nspaces() == 1) \
2276 return std::tuple( \
2277 std::get<Is>(spline_).template name<memory_optimized>( \
2278 G.space(), std::get<Is>(xi))...); \
2279 else if constexpr (Geometry::nspaces() == nspaces()) \
2280 return std::tuple( \
2281 std::get<Is>(spline_).template name<memory_optimized>( \
2282 G.template space<Is>(), std::get<Is>(xi))...); \
2283 } else if constexpr (comp == functionspace::boundary) { \
2284 if constexpr (Geometry::nboundaries() == 1) \
2285 return std::tuple( \
2286 std::get<Is>(boundary_).template name<memory_optimized>( \
2287 static_cast<typename Geometry::boundary_type::boundary_type>( \
2288 G.boundary().coeffs()), \
2289 std::get<Is>(xi))...); \
2290 else if constexpr (Geometry::nboundaries() == nboundaries()) \
2291 return std::tuple( \
2292 std::get<Is>(boundary_).template name<memory_optimized>( \
2293 G.template boundary<Is>().coeffs(), std::get<Is>(xi))...); \
2294 } \
2295 } \
2296 \
2297 template <functionspace comp = functionspace::interior, \
2298 bool memory_optimized = false, std::size_t... Is, \
2299 typename Geometry, typename... Xi, typename... Knot_Indices, \
2300 typename... Knot_Indices_G> \
2301 inline auto BOOST_PP_CAT(name, _all_)( \
2302 std::index_sequence<Is...>, const Geometry &G, \
2303 const std::tuple<Xi...> &xi, \
2304 const std::tuple<Knot_Indices...> &knot_indices, \
2305 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
2306 if constexpr (comp == functionspace::interior) { \
2307 if constexpr (Geometry::nspaces() == 1) \
2308 return std::tuple( \
2309 std::get<Is>(spline_).template name<memory_optimized>( \
2310 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2311 std::get<Is>(knot_indices_G))...); \
2312 else \
2313 return std::tuple( \
2314 std::get<Is>(spline_).template name<memory_optimized>( \
2315 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2316 std::get<Is>(knot_indices_G))...); \
2317 } else if constexpr (comp == functionspace::boundary) { \
2318 if constexpr (Geometry::nspaces() == 1) \
2319 return std::tuple( \
2320 std::get<Is>(boundary_).template name<memory_optimized>( \
2321 static_cast<typename Geometry::boundary_type::boundary_type>( \
2322 G.boundary().coeffs()), \
2323 std::get<Is>(xi), std::get<Is>(knot_indices), \
2324 std::get<Is>(knot_indices_G))...); \
2325 else \
2326 return std::tuple( \
2327 std::get<Is>(boundary_).template name<memory_optimized>( \
2328 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2329 std::get<Is>(knot_indices), std::get<Is>(knot_indices_G))...); \
2330 } \
2331 } \
2332 \
2333 template <functionspace comp = functionspace::interior, \
2334 bool memory_optimized = false, std::size_t... Is, \
2335 typename Geometry, typename... Xi, typename... Knot_Indices, \
2336 typename... Coeff_Indices, typename... Knot_Indices_G, \
2337 typename... Coeff_Indices_G> \
2338 inline auto BOOST_PP_CAT(name, _all_)( \
2339 std::index_sequence<Is...>, const Geometry &G, \
2340 const std::tuple<Xi...> &xi, \
2341 const std::tuple<Knot_Indices...> &knot_indices, \
2342 const std::tuple<Coeff_Indices...> &coeff_indices, \
2343 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
2344 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
2345 if constexpr (comp == functionspace::interior) { \
2346 if constexpr (Geometry::nspaces() == 1) \
2347 return std::tuple( \
2348 std::get<Is>(spline_).template name<memory_optimized>( \
2349 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2350 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2351 std::get<Is>(coeff_indices_G))...); \
2352 else \
2353 return std::tuple( \
2354 std::get<Is>(spline_).template name<memory_optimized>( \
2355 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2356 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2357 std::get<Is>(coeff_indices_G))...); \
2358 } else if constexpr (comp == functionspace::boundary) { \
2359 if constexpr (Geometry::nspaces() == 1) \
2360 return std::tuple( \
2361 std::get<Is>(boundary_).template name<memory_optimized>( \
2362 static_cast<typename Geometry::boundary_type::boundary_type>( \
2363 G.boundary().coeffs()), \
2364 std::get<Is>(xi), std::get<Is>(knot_indices), \
2365 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2366 std::get<Is>(coeff_indices_G))...); \
2367 else \
2368 return std::tuple( \
2369 std::get<Is>(boundary_).template name<memory_optimized>( \
2370 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2371 std::get<Is>(knot_indices), std::get<Is>(coeff_indices), \
2372 std::get<Is>(knot_indices_G), \
2373 std::get<Is>(coeff_indices_G))...); \
2374 } \
2375 } \
2376 \
2377public: \
2378 template <functionspace comp = functionspace::interior, \
2379 bool memory_optimized = false, typename... Args> \
2380 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2381 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2382 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2383 }
2384
2389#undef GENERATE_IEXPR_MACRO
2390};
2391
2393template <typename... Splines>
2394inline std::ostream &operator<<(std::ostream &os,
2396 obj.pretty_print(os);
2397 return os;
2398}
2399
2404template <typename Spline, typename Boundary>
2406 private utils::FullQualifiedName {
2407
2408 static_assert(is_SplineType_v<Spline>, "Spline must be a valid SplineType");
2409 static_assert(is_BoundaryType_v<Boundary>,
2410 "Boundary must be a valid BoundaryType");
2411
2412public:
2414 using value_type = typename Spline::value_type;
2415
2417 using spline_type = Spline;
2418
2420 using eval_type = utils::TensorArray<Spline::parDim()>;
2421
2424
2426 using boundary_eval_type = typename Boundary::eval_type;
2427
2428protected:
2431
2434
2435public:
2437 FunctionSpace() = default;
2438
2440 FunctionSpace(const FunctionSpace &) = default;
2441
2444
2447 FunctionSpace(const std::array<int64_t, Spline::parDim()> &ncoeffs,
2448 enum init init = init::greville,
2450 : spline_(ncoeffs, init, options),
2451 boundary_(ncoeffs, init::none, options) {
2452 boundary_.from_full_tensor(spline_.as_tensor());
2453 }
2454
2455 FunctionSpace(std::array<std::vector<value_type>, Spline::parDim()> kv,
2456 enum init init = init::greville,
2458 : spline_(kv, init, options), boundary_(kv, init::none, options) {
2459 static_assert(Spline::is_nonuniform(),
2460 "Constructor is only available for non-uniform splines");
2461 boundary_.from_full_tensor(spline_.as_tensor());
2462 }
2463
2464 explicit FunctionSpace(const Spline &spline)
2465 : spline_(spline),
2466 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2467 boundary_.from_full_tensor(spline_.as_tensor());
2468 }
2469
2470 explicit FunctionSpace(Spline &&spline)
2471 : spline_(spline),
2472 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2473 boundary_.from_full_tensor(spline_.as_tensor());
2474 }
2476
2478 inline static constexpr short_t nspaces() noexcept { return 1; }
2479
2481 inline static constexpr short_t nboundaries() noexcept { return 1; }
2482
2484 template <short_t s = 0>
2485 inline constexpr const spline_type &space() const noexcept {
2486 static_assert(s >= 0 && s < nspaces());
2487 return spline_;
2488 }
2489
2491 template <short_t s = 0> inline constexpr spline_type &space() noexcept {
2492 static_assert(s >= 0 && s < nspaces());
2493 return spline_;
2494 }
2495
2497 template <short_t s = 0>
2498 inline constexpr const boundary_type &boundary() const noexcept {
2499 static_assert(s >= 0 && s < nboundaries());
2500 return boundary_;
2501 }
2502
2505 template <short_t s = 0> inline constexpr boundary_type &boundary() noexcept {
2506 static_assert(s >= 0 && s < nboundaries());
2507 return boundary_;
2508 }
2509
2511 inline constexpr FunctionSpace clone() const noexcept {
2512 return FunctionSpace(*this);
2513 }
2514
2516 template <short_t... s> inline constexpr auto clone() const noexcept {
2517
2518 static_assert(((s >= 0 && s < nspaces()) && ... && true));
2519
2520 if constexpr (sizeof...(s) == 1)
2521 return FunctionSpace(*this);
2522 else
2523 return FunctionSpace<
2524 std::tuple<std::tuple_element_t<s, std::tuple<spline_type>>...>,
2525 std::tuple<std::tuple_element_t<s, std::tuple<boundary_type>>...>>(
2526 std::get<s>(std::make_tuple(spline_))...,
2527 std::get<s>(std::make_tuple(boundary_))...);
2528 }
2529
2531 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
2532 return spline_.as_tensor();
2533 }
2534
2536 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
2537 return boundary_.as_tensor();
2538 }
2539
2545 virtual inline torch::Tensor as_tensor() const noexcept {
2546 return spaces_as_tensor();
2547 }
2548
2552 return spline_.as_tensor_size();
2553 }
2554
2558 return boundary_.as_tensor_size();
2559 }
2560
2567 return spaces_as_tensor_size();
2568 }
2569
2571 virtual inline FunctionSpace &
2572 spaces_from_tensor(const torch::Tensor &coeffs) noexcept {
2573 spline_.from_tensor(coeffs);
2574 return *this;
2575 }
2576
2579 virtual inline FunctionSpace &
2580 boundary_from_tensor(const torch::Tensor &coeffs) noexcept {
2581 boundary_.from_tensor(coeffs);
2582 return *this;
2583 }
2584
2586 virtual inline FunctionSpace &
2587 boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept {
2588 boundary_.from_full_tensor(coeffs);
2589 return *this;
2590 }
2591
2593 inline FunctionSpace &from_tensor(const torch::Tensor &coeffs) noexcept {
2594 spline_.from_tensor(coeffs);
2595 boundary_.from_full_tensor(coeffs);
2596 return *this;
2597 }
2598
2600 inline pugi::xml_document to_xml(int id = 0, std::string label = "") const {
2601 pugi::xml_document doc;
2602 pugi::xml_node root = doc.append_child("xml");
2603 to_xml(root, id, label);
2604
2605 return doc;
2606 }
2607
2609 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
2610 std::string label = "") const {
2611 return spline_.to_xml(root, id, label);
2612 }
2613
2615 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
2616 std::string label = "") {
2617 return from_xml(doc.child("xml"), id, label);
2618 }
2619
2621 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
2622 std::string label = "") {
2623 spline_.from_xml(root, id, label);
2624 return *this;
2625 }
2626
2628 nlohmann::json to_json() const override {
2629 auto json = nlohmann::json::array();
2630 json.push_back(spline_.to_json());
2631 json.push_back(boundary_.to_json());
2632 return json;
2633 }
2634
2637 const std::function<std::array<typename Spline::value_type,
2638 Spline::geoDim()>(
2639 const std::array<typename Spline::value_type, Spline::parDim()> &)>
2642 return *this;
2643 }
2644
2645private:
2649 deriv deriv = deriv::func, bool memory_optimized = false,
2650 std::size_t... Is, typename... Xi>
2651 inline auto eval_(std::index_sequence<Is...>,
2652 const std::tuple<Xi...> &xi) const {
2653 if constexpr (comp == functionspace::interior)
2654 return std::tuple(
2655 spline_.template eval<deriv, memory_optimized>(std::get<Is>(xi))...);
2656 else if constexpr (comp == functionspace::boundary)
2657 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2658 std::get<Is>(xi))...);
2659 }
2660
2662 deriv deriv = deriv::func, bool memory_optimized = false,
2663 std::size_t... Is, typename... Xi, typename... Knot_Indices>
2664 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
2665 const std::tuple<Knot_Indices...> &knot_indices) const {
2666 if constexpr (comp == functionspace::interior)
2667 return std::tuple(spline_.template eval<deriv, memory_optimized>(
2668 std::get<Is>(xi), std::get<Is>(knot_indices))...);
2669 else if constexpr (comp == functionspace::boundary)
2670 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2671 std::get<Is>(xi), std::get<Is>(knot_indices))...);
2672 }
2673
2675 deriv deriv = deriv::func, bool memory_optimized = false,
2676 std::size_t... Is, typename... Xi, typename... Knot_Indices,
2677 typename... Coeff_Indices>
2678 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
2679 const std::tuple<Knot_Indices...> &knot_indices,
2680 const std::tuple<Coeff_Indices...> &coeff_indices) const {
2681 if constexpr (comp == functionspace::interior)
2682 return std::tuple(spline_.template eval<deriv, memory_optimized>(
2683 std::get<Is>(xi), std::get<Is>(knot_indices),
2684 std::get<Is>(coeff_indices))...);
2685 else if constexpr (comp == functionspace::boundary)
2686 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2687 std::get<Is>(xi), std::get<Is>(knot_indices),
2688 std::get<Is>(coeff_indices))...);
2689 }
2691
2692public:
2695 deriv deriv = deriv::func, bool memory_optimized = false,
2696 typename Arg, typename... Args>
2697 inline auto eval(const Arg &arg, const Args &...args) const {
2698 if constexpr (comp == functionspace::interior)
2699 if constexpr (utils::is_tuple_v<Arg>)
2701 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
2702 else
2703 return spline_.template eval<deriv, memory_optimized>(arg, args...);
2704 else if constexpr (comp == functionspace::boundary) {
2705 if constexpr (utils::is_tuple_of_tuples_v<Arg>)
2707 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
2708 else
2709 return boundary_.template eval<deriv, memory_optimized>(arg, args...);
2710 }
2711 }
2712
2715 template <functionspace comp = functionspace::interior, typename... Args>
2716 inline auto eval_from_precomputed(const Args &...args) const {
2717 if constexpr (comp == functionspace::interior)
2718 return spline_.eval_from_precomputed(args...);
2719 else if constexpr (comp == functionspace::boundary)
2721 }
2722
2723private:
2725 template <functionspace comp = functionspace::interior, std::size_t... Is,
2726 typename Xi>
2727 inline auto find_knot_indices_(std::index_sequence<Is...>,
2728 const Xi &xi) const {
2729 if constexpr (comp == functionspace::interior)
2730 return std::tuple(spline_.find_knot_indices(std::get<Is>(xi))...);
2731 else
2732 return std::tuple(boundary_.find_knot_indices(std::get<Is>(xi))...);
2733 }
2734
2735public:
2737 template <functionspace comp = functionspace::interior, typename Xi>
2738 inline auto find_knot_indices(const Xi &xi) const {
2739 if constexpr (comp == functionspace::interior)
2740 if constexpr (utils::is_tuple_v<Xi>)
2742 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
2743 else
2744 return spline_.find_knot_indices(xi);
2745 else if constexpr (comp == functionspace::boundary) {
2746 if constexpr (utils::is_tuple_of_tuples_v<Xi>)
2748 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
2749 else
2751 }
2752 }
2753
2757 deriv deriv = deriv::func, bool memory_optimized = false,
2758 typename... Args>
2759 inline auto eval_basfunc(const Args &...args) const {
2760 if constexpr (comp == functionspace::interior)
2762 else if constexpr (comp == functionspace::boundary)
2764 }
2765
2766private:
2770 bool memory_optimized = false, std::size_t... Is,
2771 typename Knot_Indices>
2772 inline auto find_coeff_indices_(std::index_sequence<Is...>,
2773 const Knot_Indices &knot_indices) const {
2774 if constexpr (comp == functionspace::interior)
2775 return std::tuple(spline_.template find_coeff_indices<memory_optimized>(
2776 std::get<Is>(knot_indices))...);
2777 else
2778 return std::tuple(boundary_.template find_coeff_indices<memory_optimized>(
2779 std::get<Is>(knot_indices))...);
2780 }
2781
2782public:
2786 bool memory_optimized = false, typename Knot_Indices>
2788 if constexpr (comp == functionspace::interior)
2789 if constexpr (utils::is_tuple_v<Knot_Indices>)
2791 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
2792 knot_indices);
2793 else
2795 knot_indices);
2796 else if constexpr (comp == functionspace::boundary) {
2797 if constexpr (utils::is_tuple_of_tuples_v<Knot_Indices>)
2799 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
2800 knot_indices);
2801 else
2803 knot_indices);
2804 }
2805 }
2806
2809 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
2810 spline_.uniform_refine(numRefine, dimRefine);
2812 return *this;
2813 }
2814
2817 template <typename real_t> inline auto to(Options<real_t> options) const {
2818 return FunctionSpace<
2819 typename spline_type::template real_derived_self_type<real_t>,
2820 typename boundary_type::template real_derived_self_type<real_t>>(
2821 spline_.to(options), boundary_.to(options));
2822 }
2823
2826 inline auto to(torch::Device device) const {
2827 return FunctionSpace(spline_.to(device), boundary_.to(device));
2828 }
2829
2831 template <typename real_t> inline auto to() const {
2832 return FunctionSpace<
2833 typename spline_type::template real_derived_self_type<real_t>,
2834 typename boundary_type::template real_derived_self_type<real_t>>(
2835 spline_.template to<real_t>(), boundary_.template to<real_t>());
2836 }
2837
2839 inline auto scale(value_type s, int dim = -1) {
2840 spline_.scale(s, dim);
2841 boundary_.from_full_tensor(spline_.as_tensor());
2842 return *this;
2843 }
2844
2846 template <size_t N> inline auto scale(std::array<value_type, N> v) {
2847 spline_.scale(v);
2848 boundary_.from_full_tensor(spline_.as_tensor());
2849 return *this;
2850 }
2851
2853 template <size_t N> inline auto translate(std::array<value_type, N> v) {
2854 spline_.translate(v);
2855 boundary_.from_full_tensor(spline_.as_tensor());
2856 return *this;
2857 }
2858
2860 inline auto rotate(value_type angle) {
2861 spline_.rotate(angle);
2862 boundary_.from_full_tensor(spline_.as_tensor());
2863 return *this;
2864 }
2865
2867 inline auto rotate(std::array<value_type, 3> angle) {
2868 spline_.rotate(angle);
2869 boundary_.from_full_tensor(spline_.as_tensor());
2870 return *this;
2871 }
2872
2875 inline torch::serialize::OutputArchive &
2876 write(torch::serialize::OutputArchive &archive,
2877 const std::string &key = "functionspace") const {
2878 spline_.write(archive, key);
2880 return archive;
2881 }
2882
2885 inline torch::serialize::InputArchive &
2886 read(torch::serialize::InputArchive &archive,
2887 const std::string &key = "functionspace") {
2888 spline_.read(archive, key);
2890 return archive;
2891 }
2892
2894 inline virtual void
2895 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
2896 os << name() << "(\nspline = ";
2897 spline_.pretty_print(os);
2898 os << "\nboundary = ";
2899 boundary_.pretty_print(os);
2900 os << "\n)";
2901 }
2902
2903#define GENERATE_EXPR_MACRO(r, data, name) \
2904private: \
2905 template <functionspace comp = functionspace::interior, \
2906 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
2907 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2908 const std::tuple<Xi...> &xi) const { \
2909 if constexpr (comp == functionspace::interior) \
2910 return std::tuple( \
2911 spline_.template name<memory_optimized>(std::get<Is>(xi))...); \
2912 else if constexpr (comp == functionspace::boundary) \
2913 return std::tuple( \
2914 boundary_.template name<memory_optimized>(std::get<Is>(xi))...); \
2915 } \
2916 \
2917 template <functionspace comp = functionspace::interior, \
2918 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2919 typename... Knot_Indices> \
2920 inline auto BOOST_PP_CAT(name, _all_)( \
2921 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2922 const std::tuple<Knot_Indices...> &knot_indices) const { \
2923 if constexpr (comp == functionspace::interior) \
2924 return std::tuple(spline_.template name<memory_optimized>( \
2925 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2926 else if constexpr (comp == functionspace::boundary) \
2927 return std::tuple(boundary_.template name<memory_optimized>( \
2928 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2929 } \
2930 \
2931 template <functionspace comp = functionspace::interior, \
2932 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2933 typename... Knot_Indices, typename... Coeff_Indices> \
2934 inline auto BOOST_PP_CAT(name, _all_)( \
2935 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2936 const std::tuple<Knot_Indices...> &knot_indices, \
2937 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
2938 if constexpr (comp == functionspace::interior) \
2939 return std::tuple(spline_.template name<memory_optimized>( \
2940 std::get<Is>(xi), std::get<Is>(knot_indices), \
2941 std::get<Is>(coeff_indices))...); \
2942 else if constexpr (comp == functionspace::boundary) \
2943 return std::tuple(boundary_.template name<memory_optimized>( \
2944 std::get<Is>(xi), std::get<Is>(knot_indices), \
2945 std::get<Is>(coeff_indices))...); \
2946 } \
2947 \
2948public: \
2949 template <functionspace comp = functionspace::interior, \
2950 bool memory_optimized = false, typename Arg, typename... Args> \
2951 inline auto name(const Arg &arg, const Args &...args) const { \
2952 if constexpr (comp == functionspace::interior) \
2953 if constexpr (utils::is_tuple_v<Arg>) \
2954 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2955 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
2956 else \
2957 return spline_.template name<memory_optimized>(arg, args...); \
2958 else if constexpr (comp == functionspace::boundary) { \
2959 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
2960 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2961 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
2962 else \
2963 return boundary_.template name<memory_optimized>(arg, args...); \
2964 } \
2965 }
2966
2971#undef GENERATE_EXPR_MACRO
2972
2973#define GENERATE_IEXPR_MACRO(r, data, name) \
2974private: \
2975 template <functionspace comp = functionspace::interior, \
2976 bool memory_optimized = false, std::size_t... Is, \
2977 typename Geometry, typename... Xi> \
2978 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2979 const Geometry &G, \
2980 const std::tuple<Xi...> &xi) const { \
2981 if constexpr (comp == functionspace::interior) \
2982 return std::tuple(spline_.template name<memory_optimized>( \
2983 G.space(), std::get<Is>(xi))...); \
2984 else if constexpr (comp == functionspace::boundary) \
2985 return std::tuple(boundary_.template name<memory_optimized>( \
2986 static_cast<typename Geometry::boundary_type::boundary_type>( \
2987 G.boundary().coeffs()), \
2988 std::get<Is>(xi))...); \
2989 } \
2990 \
2991 template <functionspace comp = functionspace::interior, \
2992 bool memory_optimized = false, std::size_t... Is, \
2993 typename Geometry, typename... Xi, typename... Knot_Indices, \
2994 typename... Knot_Indices_G> \
2995 inline auto BOOST_PP_CAT(name, _all_)( \
2996 std::index_sequence<Is...>, const Geometry &G, \
2997 const std::tuple<Xi...> &xi, \
2998 const std::tuple<Knot_Indices...> &knot_indices, \
2999 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
3000 if constexpr (comp == functionspace::interior) \
3001 return std::tuple(spline_.template name<memory_optimized>( \
3002 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
3003 std::get<Is>(knot_indices_G))...); \
3004 else if constexpr (comp == functionspace::boundary) \
3005 return std::tuple(boundary_.template name<memory_optimized>( \
3006 static_cast<typename Geometry::boundary_type::boundary_type>( \
3007 G.boundary().coeffs()), \
3008 std::get<Is>(xi), std::get<Is>(knot_indices), \
3009 std::get<Is>(knot_indices_G))...); \
3010 } \
3011 \
3012 template <functionspace comp = functionspace::interior, \
3013 bool memory_optimized = false, std::size_t... Is, \
3014 typename Geometry, typename... Xi, typename... Knot_Indices, \
3015 typename... Coeff_Indices, typename... Knot_Indices_G, \
3016 typename... Coeff_Indices_G> \
3017 inline auto BOOST_PP_CAT(name, _all_)( \
3018 std::index_sequence<Is...>, const Geometry &G, \
3019 const std::tuple<Xi...> &xi, \
3020 const std::tuple<Knot_Indices...> &knot_indices, \
3021 const std::tuple<Coeff_Indices...> &coeff_indices, \
3022 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
3023 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
3024 if constexpr (comp == functionspace::interior) \
3025 return std::tuple(spline_.template name<memory_optimized>( \
3026 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
3027 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3028 std::get<Is>(coeff_indices_G))...); \
3029 else if constexpr (comp == functionspace::boundary) \
3030 return std::tuple(boundary_.template name<memory_optimized>( \
3031 static_cast<typename Geometry::boundary_type::boundary_type>( \
3032 G.boundary().coeffs()), \
3033 std::get<Is>(xi), std::get<Is>(knot_indices), \
3034 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3035 std::get<Is>(coeff_indices_G))...); \
3036 } \
3037 \
3038public: \
3039 template <functionspace comp = functionspace::interior, \
3040 bool memory_optimized = false, typename Geometry, typename Arg, \
3041 typename... Args> \
3042 inline auto name(const Geometry &G, const Arg &arg, const Args &...args) \
3043 const { \
3044 if constexpr (comp == functionspace::interior) { \
3045 if constexpr (utils::is_tuple_v<Arg>) \
3046 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3047 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3048 args...); \
3049 else \
3050 return spline_.template name<memory_optimized>(G.space(), arg, \
3051 args...); \
3052 } else if constexpr (comp == functionspace::boundary) { \
3053 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
3054 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3055 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3056 args...); \
3057 else \
3058 return boundary_.template name<memory_optimized>( \
3059 static_cast<typename Geometry::boundary_type::boundary_type>( \
3060 G.boundary().coeffs()), \
3061 arg, args...); \
3062 } \
3063 }
3064
3069#undef GENERATE_IEXPR_MACRO
3070};
3071
3073template <typename... Args> struct FunctionSpace_trait;
3074
3076template <typename Spline> struct FunctionSpace_trait<Spline> {
3078};
3079
3081template <typename Spline, typename Boundary>
3085
3087template <typename... Splines>
3092
3094template <typename... Splines, typename... Boundaries>
3095struct FunctionSpace_trait<std::tuple<Splines...>, std::tuple<Boundaries...>> {
3098};
3099
3101template <typename Spline, typename Boundary>
3105
3107template <typename... Splines, typename... Boundaries>
3108struct FunctionSpace_trait<std::tuple<FunctionSpace<Splines, Boundaries>...>> {
3109 using type =
3111 utils::tuple_cat_t<Boundaries...>>::type;
3112};
3113
3114} // namespace detail
3115
3117template <typename... Args>
3119
3121template <typename Splines, typename Boundaries>
3122inline std::ostream &operator<<(std::ostream &os,
3124 obj.pretty_print(os);
3125 return os;
3126}
3127
3145template <typename Spline> using S = FunctionSpace<Spline>;
3146
3148template <typename Spline, short_t = Spline::parDim()> class TH;
3149
3159template <typename Spline>
3160class TH<Spline, 1>
3161 : public FunctionSpace<
3162 std::tuple<typename Spline::template derived_self_type<
3163 typename Spline::value_type, Spline::geoDim(),
3164 Spline::degree(0) + 1>,
3165 typename Spline::template derived_self_type<
3166 typename Spline::value_type, Spline::geoDim(),
3167 Spline::degree(0)>>> {
3168public:
3170 using Base = FunctionSpace<std::tuple<
3171 typename Spline::template derived_self_type<
3172 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3173 typename Spline::template derived_self_type<
3174 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3175
3178 TH(const std::array<int64_t, 1> &ncoeffs, enum init init = init::greville,
3181 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {
3182 static_assert(Spline::is_nonuniform(),
3183 "TH function space requires non-uniform splines");
3184 Base::template space<0>().reduce_continuity();
3185 }
3186
3187 TH(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3188 enum init init = init::greville,
3191 : Base({{kv[0].front + kv[0] + kv[0].back(), kv[1]}}, kv, init, options) {
3192 static_assert(Spline::is_nonuniform(),
3193 "TH function space requires non-uniform splines");
3194 Base::template space<0>().reduce_continuity();
3195 }
3197
3199};
3200
3212template <typename Spline>
3213class TH<Spline, 2>
3214 : public FunctionSpace<
3215 std::tuple<typename Spline::template derived_self_type<
3216 typename Spline::value_type, Spline::geoDim(),
3217 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3218 typename Spline::template derived_self_type<
3219 typename Spline::value_type, Spline::geoDim(),
3220 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3221 typename Spline::template derived_self_type<
3222 typename Spline::value_type, Spline::geoDim(),
3223 Spline::degree(0), Spline::degree(1)>>> {
3224public:
3227 std::tuple<typename Spline::template derived_self_type<
3228 typename Spline::value_type, Spline::geoDim(),
3229 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3230 typename Spline::template derived_self_type<
3231 typename Spline::value_type, Spline::geoDim(),
3232 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3233 typename Spline::template derived_self_type<
3234 typename Spline::value_type, Spline::geoDim(),
3235 Spline::degree(0), Spline::degree(1)>>>;
3236
3239 TH(const std::array<int64_t, 2> &ncoeffs, enum init init = init::greville,
3242 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
3243 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
3244 static_assert(Spline::is_nonuniform(),
3245 "TH function space requires non-uniform splines");
3246 Base::template space<0>().reduce_continuity();
3247 Base::template space<1>().reduce_continuity();
3248 }
3249
3250 TH(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3251 enum init init = init::greville,
3254 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3255 kv[1].front() + kv[1] + kv[1].back()}},
3256 {{kv[0].front() + kv[0] + kv[0].back(),
3257 kv[1].front() + kv[1] + kv[1].back()}},
3258 kv, init, options) {
3259 static_assert(Spline::is_nonuniform(),
3260 "TH function space requires non-uniform splines");
3261 Base::template space<0>().reduce_continuity();
3262 Base::template space<1>().reduce_continuity();
3263 }
3265
3267};
3268
3281template <typename Spline>
3282class TH<Spline, 3>
3283 : public FunctionSpace<std::tuple<
3284 typename Spline::template derived_self_type<
3285 typename Spline::value_type, Spline::geoDim(),
3286 Spline::degree(0) + 1, Spline::degree(1) + 1,
3287 Spline::degree(2) + 1>,
3288 typename Spline::template derived_self_type<
3289 typename Spline::value_type, Spline::geoDim(),
3290 Spline::degree(0) + 1, Spline::degree(1) + 1,
3291 Spline::degree(2) + 1>,
3292 typename Spline::template derived_self_type<
3293 typename Spline::value_type, Spline::geoDim(),
3294 Spline::degree(0) + 1, Spline::degree(1) + 1,
3295 Spline::degree(2) + 1>,
3296 typename Spline::template derived_self_type<
3297 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3298 Spline::degree(1), Spline::degree(2)>>> {
3299public:
3301 using Base = FunctionSpace<std::tuple<
3302 typename Spline::template derived_self_type<
3303 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3304 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3305 typename Spline::template derived_self_type<
3306 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3307 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3308 typename Spline::template derived_self_type<
3309 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3310 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3311 typename Spline::template derived_self_type<
3312 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3313 Spline::degree(1), Spline::degree(2)>>>;
3314
3317 TH(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
3320 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3321 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3322 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
3323 options) {
3324 static_assert(Spline::is_nonuniform(),
3325 "TH function space requires non-uniform splines");
3326 Base::template space<0>().reduce_continuity();
3327 Base::template space<1>().reduce_continuity();
3328 Base::template space<2>().reduce_continuity();
3329 }
3330
3331 TH(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3332 enum init init = init::greville,
3335 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3336 kv[1].front() + kv[1] + kv[1].back(),
3337 kv[2].front() + kv[2] + kv[2].back()}},
3338 {{kv[0].front() + kv[0] + kv[0].back(),
3339 kv[1].front() + kv[1] + kv[1].back(),
3340 kv[2].front() + kv[2] + kv[2].back()}},
3341 {{kv[0].front() + kv[0] + kv[0].back(),
3342 kv[1].front() + kv[1] + kv[1].back(),
3343 kv[2].front() + kv[2] + kv[2].back()}},
3344 kv, init, options) {
3345 static_assert(Spline::is_nonuniform(),
3346 "TH function space requires non-uniform splines");
3347 Base::template space<0>().reduce_continuity();
3348 Base::template space<1>().reduce_continuity();
3349 Base::template space<2>().reduce_continuity();
3350 }
3352
3354};
3355
3369template <typename Spline>
3370class TH<Spline, 4>
3371 : public FunctionSpace<std::tuple<
3372 typename Spline::template derived_self_type<
3373 typename Spline::value_type, Spline::geoDim(),
3374 Spline::degree(0) + 1, Spline::degree(1) + 1,
3375 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3376 typename Spline::template derived_self_type<
3377 typename Spline::value_type, Spline::geoDim(),
3378 Spline::degree(0) + 1, Spline::degree(1) + 1,
3379 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3380 typename Spline::template derived_self_type<
3381 typename Spline::value_type, Spline::geoDim(),
3382 Spline::degree(0) + 1, Spline::degree(1) + 1,
3383 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3384 typename Spline::template derived_self_type<
3385 typename Spline::value_type, Spline::geoDim(),
3386 Spline::degree(0) + 1, Spline::degree(1) + 1,
3387 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3388 typename Spline::template derived_self_type<
3389 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3390 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3391public:
3393 using Base = FunctionSpace<std::tuple<
3394 typename Spline::template derived_self_type<
3395 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3396 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3397 typename Spline::template derived_self_type<
3398 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3399 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3400 typename Spline::template derived_self_type<
3401 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3402 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3403 typename Spline::template derived_self_type<
3404 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3405 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3406 typename Spline::template derived_self_type<
3407 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3408 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3409
3412 TH(const std::array<int64_t, 4> &ncoeffs, enum init init = init::greville,
3415 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3416 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3417 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3418 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
3419 init, options) {
3420 static_assert(Spline::is_nonuniform(),
3421 "TH function space requires non-uniform splines");
3422 Base::template space<0>().reduce_continuity();
3423 Base::template space<1>().reduce_continuity();
3424 Base::template space<2>().reduce_continuity();
3425 Base::template space<3>().reduce_continuity();
3426 }
3427
3428 TH(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
3429 enum init init = init::greville,
3432 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3433 kv[1].front() + kv[1] + kv[1].back(),
3434 kv[2].front() + kv[2] + kv[2].back(),
3435 kv[3].front() + kv[3] + kv[3].back()}},
3436 {{kv[0].front() + kv[0] + kv[0].back(),
3437 kv[1].front() + kv[1] + kv[1].back(),
3438 kv[2].front() + kv[2] + kv[2].back(),
3439 kv[3].front() + kv[3] + kv[3].back()}},
3440 {{kv[0].front() + kv[0] + kv[0].back(),
3441 kv[1].front() + kv[1] + kv[1].back(),
3442 kv[2].front() + kv[2] + kv[2].back(),
3443 kv[3].front() + kv[3] + kv[3].back()}},
3444 {{kv[0].front() + kv[0] + kv[0].back(),
3445 kv[1].front() + kv[1] + kv[1].back(),
3446 kv[2].front() + kv[2] + kv[2].back(),
3447 kv[3].front() + kv[3] + kv[3].back()}},
3448 kv, init, options) {
3449 static_assert(Spline::is_nonuniform(),
3450 "TH function space requires non-uniform splines");
3451 Base::template space<0>().reduce_continuity();
3452 Base::template space<1>().reduce_continuity();
3453 Base::template space<2>().reduce_continuity();
3454 Base::template space<3>().reduce_continuity();
3455 }
3457
3459};
3460
3462
3464template <typename Spline, short_t = Spline::parDim()> class NE;
3465
3475template <typename Spline>
3476class NE<Spline, 1>
3477 : public FunctionSpace<
3478 std::tuple<typename Spline::template derived_self_type<
3479 typename Spline::value_type, Spline::geoDim(),
3480 Spline::degree(0) + 1>,
3481 typename Spline::template derived_self_type<
3482 typename Spline::value_type, Spline::geoDim(),
3483 Spline::degree(0)>>> {
3484public:
3486 using Base = FunctionSpace<std::tuple<
3487 typename Spline::template derived_self_type<
3488 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3489 typename Spline::template derived_self_type<
3490 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3491
3494 NE(const std::array<int64_t, 1> &ncoeffs, enum init init = init::greville,
3497 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
3498
3499 NE(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3500 enum init init = init::greville,
3503 : Base(kv, kv, init, options) {
3504 static_assert(Spline::is_nonuniform(),
3505 "Constructor only available for non-uniform splines");
3506 }
3508
3510};
3511
3522template <typename Spline>
3523class NE<Spline, 2>
3524 : public FunctionSpace<
3525 std::tuple<typename Spline::template derived_self_type<
3526 typename Spline::value_type, Spline::geoDim(),
3527 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3528 typename Spline::template derived_self_type<
3529 typename Spline::value_type, Spline::geoDim(),
3530 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3531 typename Spline::template derived_self_type<
3532 typename Spline::value_type, Spline::geoDim(),
3533 Spline::degree(0), Spline::degree(1)>>> {
3534public:
3537 std::tuple<typename Spline::template derived_self_type<
3538 typename Spline::value_type, Spline::geoDim(),
3539 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3540 typename Spline::template derived_self_type<
3541 typename Spline::value_type, Spline::geoDim(),
3542 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3543 typename Spline::template derived_self_type<
3544 typename Spline::value_type, Spline::geoDim(),
3545 Spline::degree(0), Spline::degree(1)>>>;
3546
3549 NE(const std::array<int64_t, 2> &ncoeffs, enum init init = init::greville,
3552 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
3553 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
3554 static_assert(Spline::is_nonuniform(),
3555 "NE function space requires non-uniform splines");
3556 Base::template space<0>().reduce_continuity(1, 1);
3557 Base::template space<1>().reduce_continuity(1, 0);
3558 }
3559
3560 NE(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3561 enum init init = init::greville,
3564 : Base(kv, kv, kv, init, options) {
3565 static_assert(Spline::is_nonuniform(),
3566 "NE function space requires non-uniform splines");
3567 Base::template space<0>().reduce_continuity(1, 1);
3568 Base::template space<1>().reduce_continuity(1, 0);
3569 }
3571
3573};
3574
3587template <typename Spline>
3588class NE<Spline, 3>
3589 : public FunctionSpace<std::tuple<
3590 typename Spline::template derived_self_type<
3591 typename Spline::value_type, Spline::geoDim(),
3592 Spline::degree(0) + 1, Spline::degree(1) + 1,
3593 Spline::degree(2) + 1>,
3594 typename Spline::template derived_self_type<
3595 typename Spline::value_type, Spline::geoDim(),
3596 Spline::degree(0) + 1, Spline::degree(1) + 1,
3597 Spline::degree(2) + 1>,
3598 typename Spline::template derived_self_type<
3599 typename Spline::value_type, Spline::geoDim(),
3600 Spline::degree(0) + 1, Spline::degree(1) + 1,
3601 Spline::degree(2) + 1>,
3602 typename Spline::template derived_self_type<
3603 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3604 Spline::degree(1), Spline::degree(2)>>> {
3605public:
3607 using Base = FunctionSpace<std::tuple<
3608 typename Spline::template derived_self_type<
3609 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3610 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3611 typename Spline::template derived_self_type<
3612 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3613 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3614 typename Spline::template derived_self_type<
3615 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3616 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3617 typename Spline::template derived_self_type<
3618 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3619 Spline::degree(1), Spline::degree(2)>>>;
3620
3623 NE(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
3626 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3627 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3628 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
3629 options) {
3630 static_assert(Spline::is_nonuniform(),
3631 "NE function space requires non-uniform splines");
3632 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
3633 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
3634 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
3635 }
3636
3637 NE(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3638 enum init init = init::greville,
3641 : Base(kv, kv, kv, kv, init, options) {
3642 static_assert(Spline::is_nonuniform(),
3643 "NE function space requires non-uniform splines");
3644 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
3645 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
3646 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
3647 }
3649
3651};
3652
3666template <typename Spline>
3667class NE<Spline, 4>
3668 : public FunctionSpace<std::tuple<
3669 typename Spline::template derived_self_type<
3670 typename Spline::value_type, Spline::geoDim(),
3671 Spline::degree(0) + 1, Spline::degree(1) + 1,
3672 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3673 typename Spline::template derived_self_type<
3674 typename Spline::value_type, Spline::geoDim(),
3675 Spline::degree(0) + 1, Spline::degree(1) + 1,
3676 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3677 typename Spline::template derived_self_type<
3678 typename Spline::value_type, Spline::geoDim(),
3679 Spline::degree(0) + 1, Spline::degree(1) + 1,
3680 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3681 typename Spline::template derived_self_type<
3682 typename Spline::value_type, Spline::geoDim(),
3683 Spline::degree(0) + 1, Spline::degree(1) + 1,
3684 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3685 typename Spline::template derived_self_type<
3686 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3687 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3688public:
3690 using Base = FunctionSpace<std::tuple<
3691 typename Spline::template derived_self_type<
3692 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3693 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3694 typename Spline::template derived_self_type<
3695 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3696 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3697 typename Spline::template derived_self_type<
3698 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3699 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3700 typename Spline::template derived_self_type<
3701 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3702 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3703 typename Spline::template derived_self_type<
3704 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3705 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3706
3709 NE(const std::array<int64_t, 4> &ncoeffs, enum init init = init::greville,
3712 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3713 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3714 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3715 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
3716 init, options) {
3717 static_assert(Spline::is_nonuniform(),
3718 "NE function space requires non-uniform splines");
3719 Base::template space<0>()
3720 .reduce_continuity(1, 1)
3721 .reduce_continuity(1, 2)
3722 .reduce_continuity(1, 3);
3723 Base::template space<1>()
3724 .reduce_continuity(1, 0)
3725 .reduce_continuity(1, 2)
3726 .reduce_continuity(1, 3);
3727 Base::template space<2>()
3728 .reduce_continuity(1, 0)
3729 .reduce_continuity(1, 1)
3730 .reduce_continuity(1, 3);
3731 Base::template space<3>()
3732 .reduce_continuity(1, 0)
3733 .reduce_continuity(1, 1)
3734 .reduce_continuity(1, 2);
3735 }
3736
3737 NE(const std::array<std::vector<typename Spline::value_type>,
3738 Spline::parDim()> &kv,
3739 enum init init = init::greville,
3742 : Base(kv, kv, kv, kv, kv, init, options) {
3743 static_assert(Spline::is_nonuniform(),
3744 "NE function space requires non-uniform splines");
3745 Base::template space<0>()
3746 .reduce_continuity(1, 1)
3747 .reduce_continuity(1, 2)
3748 .reduce_continuity(1, 3);
3749 Base::template space<1>()
3750 .reduce_continuity(1, 0)
3751 .reduce_continuity(1, 2)
3752 .reduce_continuity(1, 3);
3753 Base::template space<2>()
3754 .reduce_continuity(1, 0)
3755 .reduce_continuity(1, 1)
3756 .reduce_continuity(1, 3);
3757 Base::template space<3>()
3758 .reduce_continuity(1, 0)
3759 .reduce_continuity(1, 1)
3760 .reduce_continuity(1, 2);
3761 }
3763
3765};
3766
3768
3770template <typename Spline, short_t = Spline::parDim()> class RT;
3771
3781template <typename Spline>
3782class RT<Spline, 1>
3783 : public FunctionSpace<
3784 std::tuple<typename Spline::template derived_self_type<
3785 typename Spline::value_type, Spline::geoDim(),
3786 Spline::degree(0) + 1>,
3787 typename Spline::template derived_self_type<
3788 typename Spline::value_type, Spline::geoDim(),
3789 Spline::degree(0)>>> {
3790public:
3792 using Base = FunctionSpace<std::tuple<
3793 typename Spline::template derived_self_type<
3794 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3795 typename Spline::template derived_self_type<
3796 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3797
3800 RT(const std::array<int64_t, 1> &ncoeffs, enum init init = init::greville,
3803 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
3804
3805 RT(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3806 enum init init = init::greville,
3809 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}}, kv, init,
3810 options) {
3811 static_assert(Spline::is_nonuniform(),
3812 "Constructor only available for non-uniform splines");
3813 }
3815
3817};
3818
3830template <typename Spline>
3831class RT<Spline, 2>
3832 : public FunctionSpace<
3833 std::tuple<typename Spline::template derived_self_type<
3834 typename Spline::value_type, Spline::geoDim(),
3835 Spline::degree(0) + 1, Spline::degree(1)>,
3836 typename Spline::template derived_self_type<
3837 typename Spline::value_type, Spline::geoDim(),
3838 Spline::degree(0), Spline::degree(1) + 1>,
3839 typename Spline::template derived_self_type<
3840 typename Spline::value_type, Spline::geoDim(),
3841 Spline::degree(0), Spline::degree(1)>>> {
3842public:
3844 std::tuple<typename Spline::template derived_self_type<
3845 typename Spline::value_type, Spline::geoDim(),
3846 Spline::degree(0) + 1, Spline::degree(1)>,
3847 typename Spline::template derived_self_type<
3848 typename Spline::value_type, Spline::geoDim(),
3849 Spline::degree(0), Spline::degree(1) + 1>,
3850 typename Spline::template derived_self_type<
3851 typename Spline::value_type, Spline::geoDim(),
3852 Spline::degree(0), Spline::degree(1)>>>;
3853
3856 RT(const std::array<int64_t, 2> &ncoeffs, enum init init = init::greville,
3859 : Base(ncoeffs + utils::to_array(1_i64, 0_i64),
3860 ncoeffs + utils::to_array(0_i64, 1_i64), ncoeffs, init, options) {}
3861
3862 RT(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3863 enum init init = init::greville,
3866 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}},
3867 {{kv[0], kv[1].front() + kv[1] + kv[1].back()}}, kv, init,
3868 options) {
3869 static_assert(Spline::is_nonuniform(),
3870 "Constructor only available for non-uniform splines");
3871 }
3873
3875};
3876
3888template <typename Spline>
3889class RT<Spline, 3>
3890 : public FunctionSpace<std::tuple<
3891 typename Spline::template derived_self_type<
3892 typename Spline::value_type, Spline::geoDim(),
3893 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2)>,
3894 typename Spline::template derived_self_type<
3895 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3896 Spline::degree(1) + 1, Spline::degree(2)>,
3897 typename Spline::template derived_self_type<
3898 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3899 Spline::degree(1), Spline::degree(2) + 1>,
3900 typename Spline::template derived_self_type<
3901 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3902 Spline::degree(1), Spline::degree(2)>>> {
3903public:
3905 using Base = FunctionSpace<std::tuple<
3906 typename Spline::template derived_self_type<
3907 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3908 Spline::degree(1), Spline::degree(2)>,
3909 typename Spline::template derived_self_type<
3910 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3911 Spline::degree(1) + 1, Spline::degree(2)>,
3912 typename Spline::template derived_self_type<
3913 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3914 Spline::degree(1), Spline::degree(2) + 1>,
3915 typename Spline::template derived_self_type<
3916 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3917 Spline::degree(1), Spline::degree(2)>>>;
3918
3921 RT(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
3924 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
3925 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
3926 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), ncoeffs, init,
3927 options) {}
3928
3929 RT(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3930 enum init init = init::greville,
3933 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
3934 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
3935 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, kv, init,
3936 options) {
3937 static_assert(Spline::is_nonuniform(),
3938 "Constructor only available for non-uniform splines");
3939 }
3941
3943};
3944
3958template <typename Spline>
3959class RT<Spline, 4>
3960 : public FunctionSpace<std::tuple<
3961 typename Spline::template derived_self_type<
3962 typename Spline::value_type, Spline::geoDim(),
3963 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2),
3964 Spline::degree(3)>,
3965 typename Spline::template derived_self_type<
3966 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3967 Spline::degree(1) + 1, Spline::degree(2), Spline::degree(3)>,
3968 typename Spline::template derived_self_type<
3969 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3970 Spline::degree(1), Spline::degree(2) + 1, Spline::degree(3)>,
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) + 1>,
3974 typename Spline::template derived_self_type<
3975 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3976 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3977public:
3979 using Base = FunctionSpace<std::tuple<
3980 typename Spline::template derived_self_type<
3981 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3982 Spline::degree(1), Spline::degree(2), Spline::degree(3)>,
3983 typename Spline::template derived_self_type<
3984 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3985 Spline::degree(1) + 1, Spline::degree(2), Spline::degree(3)>,
3986 typename Spline::template derived_self_type<
3987 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3988 Spline::degree(1), Spline::degree(2) + 1, Spline::degree(3)>,
3989 typename Spline::template derived_self_type<
3990 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3991 Spline::degree(1), Spline::degree(2), Spline::degree(3) + 1>,
3992 typename Spline::template derived_self_type<
3993 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3994 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3995
3998 RT(const std::array<int64_t, 4> &ncoeffs, enum init init = init::greville,
4001 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64, 0_i64),
4002 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64, 0_i64),
4003 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64, 0_i64),
4004 ncoeffs + utils::to_array(0_i64, 0_i64, 0_i64, 1_i64), ncoeffs,
4005 init, options) {}
4006
4007 RT(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
4008 enum init init = init::greville,
4011 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2], kv[3]}},
4012 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2], kv[3]}},
4013 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back(), kv[3]}},
4014 {{kv[0], kv[1], kv[2], kv[3].front() + kv[3] + kv[3].back()}}, kv,
4015 init, options) {
4016 static_assert(Spline::is_nonuniform(),
4017 "Constructor only available for non-uniform splines");
4018 }
4020
4022};
4023
4025
4027template <typename Spline, short_t = Spline::parDim()> class Hcurl;
4028
4040template <typename Spline>
4041class Hcurl<Spline, 3>
4042 : public FunctionSpace<std::tuple<
4043 typename Spline::template derived_self_type<
4044 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4045 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4046 typename Spline::template derived_self_type<
4047 typename Spline::value_type, Spline::geoDim(),
4048 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2) + 1>,
4049 typename Spline::template derived_self_type<
4050 typename Spline::value_type, Spline::geoDim(),
4051 Spline::degree(0) + 1, Spline::degree(1) + 1,
4052 Spline::degree(2)>>> {
4053
4054public:
4056 using Base = FunctionSpace<std::tuple<
4057 typename Spline::template derived_self_type<
4058 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4059 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4060 typename Spline::template derived_self_type<
4061 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4062 Spline::degree(1), Spline::degree(2) + 1>,
4063 typename Spline::template derived_self_type<
4064 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4065 Spline::degree(1) + 1, Spline::degree(2)>>>;
4066
4069 Hcurl(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
4072 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
4073 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
4074 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), init, options) {}
4075
4076 Hcurl(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4077 enum init init = init::greville,
4080 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
4081 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
4082 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, init,
4083 options) {
4084 static_assert(Spline::is_nonuniform(),
4085 "Constructor only available for non-uniform splines");
4086 }
4089};
4090
4092
4094#undef IGANET_FUNCTIONSPACE_DEFAULT_OPS
4095
4096} // namespace iganet
#define GENERATE_IEXPR_MACRO(r, data, name)
Auto-generated functions.
Definition boundary.hpp:1794
#define GENERATE_EXPR_MACRO(r, data, name)
Definition boundary.hpp:1748
Multivariate B-splines.
#define GENERATE_EXPR_SEQ
Sequence of expression (parametric coordinates)
Definition bspline.hpp:41
#define GENERATE_IEXPR_SEQ
Sequence of expression (physical coordinates)
Definition bspline.hpp:47
Boundary (common high-level functionality)
Definition boundary.hpp:1141
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition boundary.hpp:1367
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:1329
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:1618
auto to(Options< real_t > options) const
Returns a copy of the boundary object with settings from options.
Definition boundary.hpp:1937
auto & from_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor.
Definition boundary.hpp:1219
torch::Tensor as_tensor() const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1164
auto & uniform_refine(int numRefine=1, int dim=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition boundary.hpp:1449
int64_t as_tensor_size() const
Returns the size of the single tensor representation of all spline objects.
Definition boundary.hpp:1185
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:1587
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:4065
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:4069
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 >{})
Constructor.
Definition functionspace.hpp:4076
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:3490
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:3494
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 >{})
Constructor.
Definition functionspace.hpp:3499
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:3549
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:3545
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 >{})
Constructor.
Definition functionspace.hpp:3560
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:3623
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 >{})
Constructor.
Definition functionspace.hpp:3637
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:3619
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:3709
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 >{})
Constructor.
Definition functionspace.hpp:3737
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:3705
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:90
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:3796
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:3800
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 >{})
Constructor.
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)>, 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:3852
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:3856
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 >{})
Constructor.
Definition functionspace.hpp:3862
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:3917
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:3921
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 >{})
Constructor.
Definition functionspace.hpp:3929
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:3994
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:3998
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 >{})
Constructor.
Definition functionspace.hpp:4007
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:3178
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 >{})
Constructor.
Definition functionspace.hpp:3187
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:3174
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 >{})
Constructor.
Definition functionspace.hpp:3250
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:3235
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:3239
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:3317
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:3313
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 >{})
Constructor.
Definition functionspace.hpp:3331
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 >{})
Constructor.
Definition functionspace.hpp:3428
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:3412
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:3408
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:812
auto find_knot_indices(const utils::TensorArray< nspaces()> &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:634
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:653
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:582
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:259
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:1430
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:434
auto jac(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Returns a block-tensor with the Jacobian of the function space object in the points xi with respect t...
Definition functionspace.hpp:1859
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:792
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:888
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:962
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:250
pugi::xml_document to_xml(int id=0, std::string label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:372
auto & boundary() noexcept
Returns a non-constant reference to the -th boundary object.
Definition functionspace.hpp:165
auto boundingBox() const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:912
FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:171
auto div(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Returns a block-tensor with the divergence of the function space object with respect to the parametri...
Definition functionspace.hpp:1140
auto curl(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Returns a block-tensor with the curl of the function space object with respect to the parametric vari...
Definition functionspace.hpp:1020
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:761
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
Returns a block-tensor with the Jacobian of the function space object in the points xi with respect t...
Definition functionspace.hpp:1906
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:1844
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:195
torch::Tensor boundary_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:205
auto & space() noexcept
Returns a non-constant reference to the -th space.
Definition functionspace.hpp:152
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:739
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:864
std::tuple< Boundaries... > boundary_type
Boundary type.
Definition functionspace.hpp:70
FunctionSpace(std::tuple< Splines... > &&spline, std::tuple< Boundaries... > &&boundary)
Constructor.
Definition functionspace.hpp:129
std::common_type_t< typename Splines::value_type... > value_type
Value type.
Definition functionspace.hpp:61
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:560
virtual FunctionSpace & from_tensor(const torch::Tensor &tensor)
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:351
auto clone() const noexcept
Returns a clone of a subset of the function space.
Definition functionspace.hpp:174
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:1133
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:881
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:750
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:312
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:689
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
Returns a block-tensor with the Hessian of the function space object in the points xi with respect to...
Definition functionspace.hpp:1602
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:324
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:475
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:1005
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
Returns a block-tensor with the Laplacian of the function space object in the points xi with respect ...
Definition functionspace.hpp:2065
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:333
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:730
auto scale_(std::index_sequence< Is... >, value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:821
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:669
pugi::xml_node & to_xml_(std::index_sequence< Is... >, pugi::xml_node &root, int id=0, std::string label="") const
Returns the function space object as XML node.
Definition functionspace.hpp:362
auto boundingBox_(std::index_sequence< Is... >) const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:906
std::tuple< typename Boundaries::eval_type... > boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:73
FunctionSpace & from_xml(const pugi::xml_node &root, int id=0, std::string label="")
Updates the function space object from XML node.
Definition functionspace.hpp:406
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
Returns a block-tensor with the gradient of the function space object in the points xi with respect t...
Definition functionspace.hpp:1306
auto eval(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:520
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:846
auto lapl(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Returns a block-tensor with the Laplacian of the function space object in the points xi with respect ...
Definition functionspace.hpp:2046
auto eval(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects in the points xi
Definition functionspace.hpp:497
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
Returns a block-tensor with the curl of the function space object with respect to the parametric vari...
Definition functionspace.hpp:1088
auto lapl(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Returns a block-tensor with the Laplacian of the function space object in the points xi with respect ...
Definition functionspace.hpp:2038
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
Returns a block-tensor with the Hessian of the function space object in the points xi with respect to...
Definition functionspace.hpp:1464
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
Returns a block-tensor with the divergence of the function space object with respect to the parametri...
Definition functionspace.hpp:1190
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 >{})
Constructor.
Definition functionspace.hpp:102
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:773
FunctionSpace(std::tuple< Splines... > &&spline)
Constructor.
Definition functionspace.hpp:119
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:1272
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:231
static constexpr short_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:141
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:783
std::tuple< utils::TensorArray< Splines::parDim()>... > eval_type
Spline evaluation type.
Definition functionspace.hpp:67
auto hess(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Returns a block-tensor with the Hessian of the function space object in the points xi with respect to...
Definition functionspace.hpp:1437
static constexpr short_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:136
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:542
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:801
nlohmann::json to_json_(std::index_sequence< Is... >) const
Serialization to JSON.
Definition functionspace.hpp:415
auto eval_basfunc(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:698
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:240
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:899
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
Returns a block-tensor with the divergence of the function space object with respect to the parametri...
Definition functionspace.hpp:1167
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:712
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
Returns a block-tensor with the Laplacian of the function space object in the points xi with respect ...
Definition functionspace.hpp:2088
const auto & boundary() const noexcept
Returns a constant reference to the -th boundary object.
Definition functionspace.hpp:158
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:94
pugi::xml_node & to_xml(pugi::xml_node &root, int id=0, std::string label="") const
Returns the function space object as XML node.
Definition functionspace.hpp:381
auto jac(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Returns a block-tensor with the Jacobian of the function space object in the points xi with respect t...
Definition functionspace.hpp:1851
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:1034
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:222
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
Returns a block-tensor with the Jacobian of the function space object in the points xi with respect t...
Definition functionspace.hpp:1878
boundary_type boundary_
Boundaries.
Definition functionspace.hpp:80
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
Returns a block-tensor with the divergence of the function space object with respect to the parametri...
Definition functionspace.hpp:1220
auto hess(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Returns a block-tensor with the Hessian of the function space object in the points xi with respect to...
Definition functionspace.hpp:1445
const auto & space() const noexcept
Returns a constant reference to the -th function space.
Definition functionspace.hpp:146
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
Returns a block-tensor with the Jacobian of the function space object in the points xi with respect t...
Definition functionspace.hpp:1950
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:936
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:459
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:640
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
Returns a block-tensor with the gradient of the function space object in the points xi with respect t...
Definition functionspace.hpp:1359
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:276
FunctionSpace & from_xml_(std::index_sequence< Is... >, const pugi::xml_node &root, int id=0, std::string label="")
Updates the function space object from XML object.
Definition functionspace.hpp:390
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:829
auto find_knot_indices_(std::index_sequence< Is... >, const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:619
auto eval(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:507
auto div(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Returns a block-tensor with the divergence of the function space object with respect to the parametri...
Definition functionspace.hpp:1148
FunctionSpace(const std::tuple< Splines... > &spline)
Constructor.
Definition functionspace.hpp:114
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:947
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &tensor)
Sets the tuple of boundaries from a single-tensor representation.
Definition functionspace.hpp:345
torch::Tensor spaces_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:188
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &tensor)
Sets the tuple of spaces from a single-tensor representation.
Definition functionspace.hpp:303
auto curl(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Returns a block-tensor with the curl of the function space object with respect to the parametric vari...
Definition functionspace.hpp:1012
FunctionSpace & from_xml(const pugi::xml_document &doc, int id=0, std::string label="")
Updates the function space object from XML object.
Definition functionspace.hpp:400
auto scale_(std::index_sequence< Is... >, std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:836
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
Returns a block-tensor with the Hessian of the function space object in the points xi with respect to...
Definition functionspace.hpp:1504
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:2031
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:1056
auto translate_(std::index_sequence< Is... >, std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:853
auto find_knot_indices_(std::index_sequence< Is... >, const utils::TensorArray< nspaces()> &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:607
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:444
std::tuple< Splines... > spline_type
Spline type.
Definition functionspace.hpp:64
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
Returns a block-tensor with the Laplacian of the function space object in the points xi with respect ...
Definition functionspace.hpp:2118
FunctionSpace(const std::tuple< Splines... > &spline, const std::tuple< Boundaries... > &boundary)
Constructor.
Definition functionspace.hpp:124
auto grad(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Returns a block-tensor with the gradient of the function space object in the points xi with respect t...
Definition functionspace.hpp:1287
auto rotate_(std::index_sequence< Is... >, value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:871
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:212
auto grad(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Returns a block-tensor with the gradient of the function space object in the points xi with respect t...
Definition functionspace.hpp:1279
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:921
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
Returns a block-tensor with the gradient of the function space object in the points xi with respect t...
Definition functionspace.hpp:1329
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the function space object.
Definition functionspace.hpp:970
auto eval_from_precomputed(const std::tuple< Basfunc... > &basfunc, const std::tuple< Coeff_Indices... > &coeff_indices, const std::tuple< Xi... > &xi) const
Returns the value of the spline objects from precomputed basis function.
Definition functionspace.hpp:594
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:269
Function space.
Definition functionspace.hpp:2406
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:2809
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:2787
FunctionSpace(const Spline &spline)
Constructor.
Definition functionspace.hpp:2464
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:2846
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:2447
auto eval_basfunc(const Args &...args) const
Returns the values of the spline objects' basis functions in the points xi
Definition functionspace.hpp:2759
static constexpr short_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:2478
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:2566
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:2772
constexpr const boundary_type & boundary() const noexcept
Returns a constant reference to the -th boundary object.
Definition functionspace.hpp:2498
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the space.
Definition functionspace.hpp:2531
typename Boundary::eval_type boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:2426
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:2886
virtual int64_t boundary_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the boundary.
Definition functionspace.hpp:2557
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the boundary.
Definition functionspace.hpp:2536
constexpr boundary_type & boundary() noexcept
Returns a non-constant reference to the -th boundary object object.
Definition functionspace.hpp:2505
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:2839
Spline spline_type
Spline type.
Definition functionspace.hpp:2417
virtual int64_t spaces_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the space.
Definition functionspace.hpp:2551
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the function space object.
Definition functionspace.hpp:2895
auto find_knot_indices(const Xi &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:2738
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:2651
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:2876
FunctionSpace(Spline &&spline)
Constructor.
Definition functionspace.hpp:2470
constexpr spline_type & space() noexcept
Returns a non-constant reference to the -th function space.
Definition functionspace.hpp:2491
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:2826
FunctionSpace & from_xml(const pugi::xml_document &doc, int id=0, std::string label="")
Updates the function space object from XML object.
Definition functionspace.hpp:2615
auto eval(const Arg &arg, const Args &...args) const
Returns the values of the spline object in the points xi
Definition functionspace.hpp:2697
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:2678
FunctionSpace & from_xml(const pugi::xml_node &root, int id=0, std::string label="")
Updates the function space object from XML node.
Definition functionspace.hpp:2621
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:2867
pugi::xml_node & to_xml(pugi::xml_node &root, int id=0, std::string label="") const
Returns the function space object as XML node.
Definition functionspace.hpp:2609
constexpr FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:2511
auto find_knot_indices_(std::index_sequence< Is... >, const Xi &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:2727
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:2860
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:2853
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:2817
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:2664
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:2580
pugi::xml_document to_xml(int id=0, std::string label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:2600
FunctionSpace(FunctionSpace &&)=default
Move constructor.
typename Spline::value_type value_type
Value type.
Definition functionspace.hpp:2414
boundary_type boundary_
Boundary.
Definition functionspace.hpp:2433
utils::TensorArray< Spline::parDim()> eval_type
Spline evaluation type.
Definition functionspace.hpp:2420
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &coeffs) noexcept
Sets the space from a single-tensor representation.
Definition functionspace.hpp:2572
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept
Sets the boundary from a single-tensor representation.
Definition functionspace.hpp:2587
FunctionSpace & transform(const std::function< std::array< typename Spline::value_type, Spline::geoDim()>(const std::array< typename Spline::value_type, Spline::parDim()> &)> transformation)
Transforms the coefficients based on the given mapping.
Definition functionspace.hpp:2636
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:2545
FunctionSpace(const FunctionSpace &)=default
Copy constructor.
spline_type spline_
Spline.
Definition functionspace.hpp:2430
static constexpr short_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:2481
auto eval_from_precomputed(const Args &...args) const
Returns the value of the spline object from precomputed basis function.
Definition functionspace.hpp:2716
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:2628
FunctionSpace & from_tensor(const torch::Tensor &coeffs) noexcept
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:2593
FunctionSpace(std::array< std::vector< value_type >, Spline::parDim()> kv, enum init init=init::greville, Options< value_type > options=iganet::Options< value_type >{})
Constructor.
Definition functionspace.hpp:2455
constexpr const spline_type & space() const noexcept
Returns a constant reference to the -th function space.
Definition functionspace.hpp:2485
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:2831
constexpr auto clone() const noexcept
Returns a subset of the tuple of function spaces.
Definition functionspace.hpp:2516
Full qualified name descriptor.
Definition fqn.hpp:26
virtual const std::string & name() const noexcept
Returns the full qualified name of the object.
Definition fqn.hpp:31
Container utility functions.
#define IGANET_FUNCTIONSPACE_DEFAULT_OPS(FunctionSpace)
Macro: Implements the default methods of a function space.
Definition functionspace.hpp:36
typename FunctionSpace_trait< utils::tuple_cat_t< Splines... >, utils::tuple_cat_t< Boundaries... > >::type type
Definition functionspace.hpp:3111
typename FunctionSpace_trait< Spline, Boundary >::type type
Definition functionspace.hpp:3103
std::ostream & operator<<(std::ostream &os, const FunctionSpace< Splines... > &obj)
Print (as string) a function space object.
Definition functionspace.hpp:2394
Forward declaration.
Definition functionspace.hpp:3073
TensorArray< 4 > TensorArray4
Definition tensorarray.hpp:34
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:28
auto zip(T &&...seqs)
Definition zip.hpp:97
TensorArray< 3 > TensorArray3
Definition tensorarray.hpp:33
typename tuple_cat< Tuples... >::type tuple_cat_t
Alias for tuple_cat::type.
Definition type_traits.hpp:72
TensorArray< 1 > TensorArray1
Definition tensorarray.hpp:31
TensorArray< 2 > TensorArray2
Definition tensorarray.hpp:32
Forward declaration of BlockTensor.
Definition blocktensor.hpp:46
Definition boundary.hpp:22
deriv
Enumerator for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:74
BoundaryCommon< BoundaryCore< Spline, Spline::parDim()> > Boundary
Boundary.
Definition boundary.hpp:1974
constexpr bool is_SplineType_v
Alias to the value of is_SplineType.
Definition bspline.hpp:3243
std::ostream & operator<<(std::ostream &os, const Boundary< Spline > &obj)
Print (as string) a Boundary object.
Definition boundary.hpp:1978
struct iganet::@0 Log
Logger.
init
Enumerator for specifying the initialization of B-spline coefficients.
Definition bspline.hpp:55
FunctionSpace< Spline > S
Spline function space .
Definition functionspace.hpp:3145
functionspace
Enumerator for the function space component.
Definition functionspace.hpp:30
constexpr bool is_BoundaryType_v
Alias to the value of is_BoundaryType.
Definition boundary.hpp:1137
@ none
Definition boundary.hpp:38
short int short_t
Definition core.hpp:74
typename detail::FunctionSpace_trait< Args... >::type FunctionSpace
Function space alias.
Definition functionspace.hpp:3118
IGANET_FUNCTIONSPACE_TUPLE_WRAPPER(RT);.
Definition functionspace.hpp:4027
IGANET_FUNCTIONSPACE_TUPLE_WRAPPER(TH);.
Definition functionspace.hpp:3464
IGANET_FUNCTIONSPACE_TUPLE_WRAPPER(NE);.
Definition functionspace.hpp:3770
Taylor-Hood like function space.
Definition functionspace.hpp:3148
STL namespace.
Serialization prototype.
Definition serialize.hpp:31
Type traits.
Zip utility function.