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
45
46// Forward declaration
47 template <typename Spline, typename Boundary>
48 //requires SplineType<Spline> && BoundaryType<Boundary>
49 class FunctionSpace;
50
55 template <typename... Splines, typename... Boundaries>
56 //requires (SplineType<Splines> && ...) && (BoundaryType<Boundaries> && ...)
57class FunctionSpace<std::tuple<Splines...>, std::tuple<Boundaries...>>
59
60public:
62 using value_type = std::common_type_t<typename Splines::value_type...>;
63
65 using spline_type = std::tuple<Splines...>;
66
68 using eval_type = std::tuple<utils::TensorArray<Splines::parDim()>...>;
69
71 using boundary_type = std::tuple<Boundaries...>;
72
74 using boundary_eval_type = std::tuple<typename Boundaries::eval_type...>;
75
76protected:
79
82
83public:
85 FunctionSpace() = default;
86
88 FunctionSpace(const FunctionSpace &) = default;
89
92
95 FunctionSpace(const std::array<int64_t, Splines::parDim()> &...ncoeffs,
98 : spline_({ncoeffs, init, options}...),
99 boundary_({ncoeffs, init::none, options}...) {
101 }
102
103 FunctionSpace(const std::array<std::vector<typename Splines::value_type>,
104 Splines::parDim()> &...kv,
105 enum init init = init::greville,
107 : spline_({kv, init, options}...),
108 boundary_({kv, init::none, options}...) {
109
110 static_assert((Splines::is_nonuniform() && ... && true),
111 "Constructor is only available for non-uniform splines");
113 }
114
115 explicit FunctionSpace(const std::tuple<Splines...> &spline)
116 : spline_(spline) {
118 }
119
120 explicit FunctionSpace(std::tuple<Splines...> &&spline)
121 : spline_(spline) {
123 }
124
125 explicit FunctionSpace(const std::tuple<Splines...> &spline,
126 const std::tuple<Boundaries...> &boundary)
127 : spline_(spline), boundary_(boundary) {
128 }
129
130 explicit FunctionSpace(std::tuple<Splines...> &&spline,
131 std::tuple<Boundaries...> &&boundary)
132 : spline_(spline), boundary_(boundary) {
133 }
135
137 inline static constexpr short_t nspaces() noexcept {
138 return sizeof...(Splines);
139 }
140
142 inline static constexpr short_t nboundaries() noexcept {
143 return sizeof...(Boundaries);
144 }
145
147 template <short_t s> inline const auto &space() const noexcept {
148 static_assert(s >= 0 && s < nspaces());
149 return std::get<s>(spline_);
150 }
151
153 template <short_t s> inline auto &space() noexcept {
154 static_assert(s >= 0 && s < nspaces());
155 return std::get<s>(spline_);
156 }
157
159 template <short_t s> inline const auto &boundary() const noexcept {
160 static_assert(s >= 0 && s < nboundaries());
161 return std::get<s>(boundary_);
162 }
163
166 template <short_t s> inline auto &boundary() noexcept {
167 static_assert(s >= 0 && s < nboundaries());
168 return std::get<s>(boundary_);
169 }
170
172 inline FunctionSpace clone() const noexcept { return FunctionSpace(*this); }
173
175 template <short_t... s> inline auto clone() const noexcept {
176
177 static_assert(((s >= 0 && s < nspaces()) && ... && true));
178
180 std::tuple<std::tuple_element_t<s, boundary_type>...>>(
181 std::make_tuple(std::get<s>(spline_)...), std::make_tuple(std::get<s>(boundary_)...));
182 }
183
184private:
187 template <std::size_t... Is>
188 inline torch::Tensor
189 spaces_as_tensor_(std::index_sequence<Is...>) const noexcept {
190 return torch::cat({std::get<Is>(spline_).as_tensor()...});
191 }
192
193public:
196 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
197 return spaces_as_tensor_(
198 std::make_index_sequence<FunctionSpace::nspaces()>{});
199 }
200
201private:
204 template <std::size_t... Is>
205 inline torch::Tensor
206 boundary_as_tensor_(std::index_sequence<Is...>) const noexcept {
207 return torch::cat({std::get<Is>(boundary_).as_tensor()...});
208 }
209
210public:
213 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
214 return boundary_as_tensor_(
215 std::make_index_sequence<FunctionSpace::nboundaries()>{});
216 }
217
223 virtual inline torch::Tensor as_tensor() const noexcept {
224 return spaces_as_tensor();
225 }
226
227private:
230 template <std::size_t... Is>
231 inline int64_t
232 spaces_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
233 return std::apply(
234 [](auto... v) { return (v + ...); },
235 std::make_tuple(std::get<Is>(spline_).as_tensor_size()...));
236 }
237
238public:
241 virtual inline int64_t spaces_as_tensor_size() const noexcept {
242 return spaces_as_tensor_size_(
243 std::make_index_sequence<FunctionSpace::nspaces()>{});
244 }
245
246private:
249 template <std::size_t... Is>
250 inline int64_t
251 boundary_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
252 return std::apply(
253 [](auto... v) { return (v + ...); },
254 std::make_tuple(std::get<Is>(boundary_).as_tensor_size()...));
255 }
256
257public:
260 virtual inline int64_t boundary_as_tensor_size() const noexcept {
261 return boundary_as_tensor_size_(
262 std::make_index_sequence<FunctionSpace::nboundaries()>{});
263 }
264
270 virtual inline int64_t as_tensor_size() const noexcept {
271 return spaces_as_tensor_size();
272 }
273
274private:
276 template <std::size_t... Is>
277 inline FunctionSpace &spaces_from_tensor_(std::index_sequence<Is...>,
278 const torch::Tensor &tensor) {
279
280 // Compute the partial sums of all function spaces
281 std::array<int64_t, sizeof...(Is)> partialSums{0};
282 auto partial_sums = [&partialSums,
283 this]<std::size_t... Js>(std::index_sequence<Js...>) {
284 ((std::get<Js + 1>(partialSums) =
285 std::get<Js>(partialSums) + std::get<Js>(spline_).as_tensor_size()),
286 ...);
287 };
288 partial_sums(std::make_index_sequence<FunctionSpace::nspaces() - 1>{});
289
290 // Call from_tensor for all function spaces
291 ((std::get<Is>(spline_).from_tensor(tensor.index(
292 {torch::indexing::Slice(partialSums[Is],
293 partialSums[Is] +
294 std::get<Is>(spline_).as_tensor_size()),
295 "..."}))),
296 ...);
297
298 return *this;
299 }
300
301public:
303 virtual inline FunctionSpace &
304 spaces_from_tensor(const torch::Tensor &tensor) {
305 return spaces_from_tensor_(
306 std::make_index_sequence<FunctionSpace::nspaces()>{}, tensor);
307 }
308
309private:
312 template <std::size_t... Is>
313 inline FunctionSpace &boundary_from_tensor_(std::index_sequence<Is...>,
314 const torch::Tensor &tensor) {
315 (std::get<Is>(boundary_).from_tensor(std::get<Is>(spline_).as_tensor()),
316 ...);
317
318 return *this;
319 }
320
321public:
324 virtual inline FunctionSpace &
325 boundary_from_tensor(const torch::Tensor &tensor) {
326 return boundary_from_tensor_(
327 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
328 }
329
330private:
332 template <std::size_t... Is>
333 inline FunctionSpace &
334 boundary_from_full_tensor_(std::index_sequence<Is...>,
335 const torch::Tensor &tensor) {
336 (std::get<Is>(boundary_).from_full_tensor(
337 std::get<Is>(spline_).as_tensor()),
338 ...);
339
340 return *this;
341 }
342
343public:
345 virtual inline FunctionSpace &
346 boundary_from_full_tensor(const torch::Tensor &tensor) {
347 return boundary_from_full_tensor_(
348 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
349 }
350
352 virtual inline FunctionSpace &from_tensor(const torch::Tensor &tensor) {
353 spaces_from_tensor_(std::make_index_sequence<FunctionSpace::nspaces()>{},
354 tensor);
355 boundary_from_full_tensor_(
356 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
357 return *this;
358 }
359
360private:
362 template <std::size_t... Is>
363 inline pugi::xml_node &to_xml_(std::index_sequence<Is...>,
364 pugi::xml_node &root, int id = 0,
365 std::string label = "") const {
366
367 (std::get<Is>(spline_).to_xml(root, id, label, Is), ...);
368 return root;
369 }
370
371public:
373 inline pugi::xml_document to_xml(int id = 0, std::string label = "") const {
374 pugi::xml_document doc;
375 pugi::xml_node root = doc.append_child("xml");
376 to_xml(root, id, label);
377
378 return doc;
379 }
380
382 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
383 std::string label = "") const {
384 return to_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
385 id, label);
386 }
387
388private:
390 template <std::size_t... Is>
391 inline FunctionSpace &from_xml_(std::index_sequence<Is...>,
392 const pugi::xml_node &root, int id = 0,
393 std::string label = "") {
394
395 (std::get<Is>(spline_).from_xml(root, id, label, Is), ...);
396 return *this;
397 }
398
399public:
401 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
402 std::string label = "") {
403 return from_xml(doc.child("xml"), id, label);
404 }
405
407 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
408 std::string label = "") {
409 return from_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
410 id, label);
411 }
412
413private:
415 template <std::size_t... Is>
416 nlohmann::json to_json_(std::index_sequence<Is...>) const {
417 auto json_this = nlohmann::json::array();
418 auto json_boundary = nlohmann::json::array();
419 (json_this.push_back(std::get<Is>(spline_).to_json()), ...);
420 (json_boundary.push_back(std::get<Is>(boundary_).to_json()), ...);
421
422 auto json = nlohmann::json::array();
423 for (auto [t, b] : utils::zip(json_this, json_boundary)) {
424 auto json_inner = nlohmann::json::array();
425 json_inner.push_back(t);
426 json_inner.push_back(b);
427 json.push_back(json_inner);
428 }
429
430 return json;
431 }
432
433public:
435 nlohmann::json to_json() const override {
436 return to_json_(std::make_index_sequence<FunctionSpace::nspaces()>{});
437 }
438
439private:
442 template <functionspace comp = functionspace::interior,
443 deriv deriv = deriv::func, bool memory_optimized = false,
444 std::size_t... Is, typename... Xi>
445 inline auto eval_(std::index_sequence<Is...>,
446 const std::tuple<Xi...> &xi) const {
447 if constexpr (comp == functionspace::interior)
448 return std::tuple(
449 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
450 std::get<Is>(xi))...);
451 else if constexpr (comp == functionspace::boundary)
452 return std::tuple(
453 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
454 std::get<Is>(xi))...);
455 }
456
457 template <functionspace comp = functionspace::interior,
458 deriv deriv = deriv::func, bool memory_optimized = false,
459 std::size_t... Is, typename... Xi, typename... Knot_Indices>
460 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
461 const std::tuple<Knot_Indices...> &knot_indices) const {
462 if constexpr (comp == functionspace::interior)
463 return std::tuple(
464 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
465 std::get<Is>(xi), std::get<Is>(knot_indices))...);
466 else if constexpr (comp == functionspace::boundary)
467 return std::tuple(
468 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
469 std::get<Is>(xi), std::get<Is>(knot_indices))...);
470 }
471
472 template <functionspace comp = functionspace::interior,
473 deriv deriv = deriv::func, bool memory_optimized = false,
474 std::size_t... Is, typename... Xi, typename... Knot_Indices,
475 typename... Coeff_Indices>
476 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
477 const std::tuple<Knot_Indices...> &knot_indices,
478 const std::tuple<Coeff_Indices...> &coeff_indices) const {
479 if constexpr (comp == functionspace::interior)
480 return std::tuple(
481 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
482 std::get<Is>(xi), std::get<Is>(knot_indices),
483 std::get<Is>(coeff_indices))...);
484 else if constexpr (comp == functionspace::boundary)
485 return std::tuple(
486 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
487 std::get<Is>(xi), std::get<Is>(knot_indices),
488 std::get<Is>(coeff_indices))...);
489 }
491
492public:
495 template <functionspace comp = functionspace::interior,
496 deriv deriv = deriv::func, bool memory_optimized = false,
497 typename... Xi>
498 inline auto eval(const std::tuple<Xi...> &xi) const {
499 static_assert(FunctionSpace::nspaces() == sizeof...(Xi),
500 "Size of Xi mismatches functionspace dimension");
501 return eval_<comp, deriv, memory_optimized>(
502 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
503 }
504
505 template <functionspace comp = functionspace::interior,
506 deriv deriv = deriv::func, bool memory_optimized = false,
507 typename... Xi, typename... Knot_Indices>
508 inline auto eval(const std::tuple<Xi...> &xi,
509 const std::tuple<Knot_Indices...> &knot_indices) const {
510 static_assert(
511 (FunctionSpace::nspaces() == sizeof...(Xi)) &&
512 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)),
513 "Sizes of Xi and Knot_Indices mismatch functionspace dimension");
514 return eval_<comp, deriv, memory_optimized>(
515 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
516 }
517
518 template <functionspace comp = functionspace::interior,
519 deriv deriv = deriv::func, bool memory_optimized = false,
520 typename... Xi, typename... Knot_Indices, typename... Coeff_Indices>
521 inline auto eval(const std::tuple<Xi...> &xi,
522 const std::tuple<Knot_Indices...> &knot_indices,
523 const std::tuple<Coeff_Indices...> &coeff_indices) const {
524 static_assert((FunctionSpace::nspaces() == sizeof...(Xi)) &&
525 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)) &&
526 (FunctionSpace::nspaces() == sizeof...(Coeff_Indices)),
527 "Sizes of Xi, Knot_Indices and Coeff_Indices mismatch "
528 "functionspace dimension");
529 return eval_<comp, deriv, memory_optimized>(
530 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices,
531 coeff_indices);
532 }
534
535private:
539 template <functionspace comp = functionspace::interior, std::size_t... Is,
540 typename... Basfunc, typename... Coeff_Indices, typename... Numeval,
541 typename... Sizes>
542 inline auto
543 eval_from_precomputed_(std::index_sequence<Is...>,
544 const std::tuple<Basfunc...> &basfunc,
545 const std::tuple<Coeff_Indices...> &coeff_indices,
546 const std::tuple<Numeval...> &numeval,
547 const std::tuple<Sizes...> &sizes) const {
548 if constexpr (comp == functionspace::interior)
549 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
550 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
551 std::get<Is>(numeval), std::get<Is>(sizes))...);
552 else if constexpr (comp == functionspace::boundary)
553 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
554 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
555 std::get<Is>(numeval), std::get<Is>(sizes))...);
556 }
557
558 template <functionspace comp = functionspace::interior, std::size_t... Is,
559 typename... Basfunc, typename... Coeff_Indices, typename... Xi>
560 inline auto
561 eval_from_precomputed_(std::index_sequence<Is...>,
562 const std::tuple<Basfunc...> &basfunc,
563 const std::tuple<Coeff_Indices...> &coeff_indices,
564 const std::tuple<Xi...> &xi) const {
565 if constexpr (comp == functionspace::interior)
566 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
567 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
568 std::get<Is>(xi)[0].numel(), std::get<Is>(xi)[0].sizes())...);
569 else if constexpr (comp == functionspace::boundary)
570 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
571 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
572 std::get<Is>(xi))...);
573 }
575
576public:
580 template <functionspace comp = functionspace::interior, typename... Basfunc,
581 typename... Coeff_Indices, typename... Numeval, typename... Sizes>
582 inline auto
583 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
584 const std::tuple<Coeff_Indices...> &coeff_indices,
585 const std::tuple<Numeval...> &numeval,
586 const std::tuple<Sizes...> &sizes) const {
587 return eval_from_precomputed_<comp>(
588 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
589 coeff_indices, numeval, sizes);
590 }
591
592 template <functionspace comp = functionspace::interior, typename... Basfunc,
593 typename... Coeff_Indices, typename... Xi>
594 inline auto
595 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
596 const std::tuple<Coeff_Indices...> &coeff_indices,
597 const std::tuple<Xi...> &xi) const {
598 return eval_from_precomputed_<comp>(
599 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
600 coeff_indices, xi);
601 }
603
604private:
607 template <functionspace comp = functionspace::interior, std::size_t... Is>
608 inline auto find_knot_indices_(std::index_sequence<Is...>,
609 const utils::TensorArray<nspaces()> &xi) const {
610 if constexpr (comp == functionspace::interior)
611 return std::tuple(
612 std::get<Is>(spline_).find_knot_indices(xi)...);
613 else if constexpr (comp == functionspace::boundary)
614 return std::tuple(
615 std::get<Is>(boundary_).find_knot_indices(xi)...);
616 }
617
618 template <functionspace comp = functionspace::interior, std::size_t... Is,
619 typename... Xi>
620 inline auto find_knot_indices_(std::index_sequence<Is...>,
621 const std::tuple<Xi...> &xi) const {
622 if constexpr (comp == functionspace::interior)
623 return std::tuple(
624 std::get<Is>(spline_).find_knot_indices(std::get<Is>(xi))...);
625 else if constexpr (comp == functionspace::boundary)
626 return std::tuple(
627 std::get<Is>(boundary_).find_knot_indices(std::get<Is>(xi))...);
628 }
630
631public:
634 template <functionspace comp = functionspace::interior>
635 inline auto find_knot_indices(const utils::TensorArray<nspaces()> &xi) const {
636 return find_knot_indices_<comp>(
637 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
638 }
639
640 template <functionspace comp = functionspace::interior, typename... Xi>
641 inline auto find_knot_indices(const std::tuple<Xi...> &xi) const {
642 return find_knot_indices_<comp>(
643 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
644 }
646
647private:
651 template <functionspace comp = functionspace::interior,
652 deriv deriv = deriv::func, bool memory_optimized = false,
653 std::size_t... Is, typename... Xi>
654 inline auto eval_basfunc_(std::index_sequence<Is...>,
655 const std::tuple<Xi...> &xi) const {
656 if constexpr (comp == functionspace::interior)
657 return std::tuple(
658 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
659 std::get<Is>(xi))...);
660 else if constexpr (comp == functionspace::boundary)
661 return std::tuple(std::get<Is>(boundary_)
662 .template eval_basfunc<deriv, memory_optimized>(
663 std::get<Is>(xi))...);
664 }
665
666 template <functionspace comp = functionspace::interior,
667 deriv deriv = deriv::func, bool memory_optimized = false,
668 std::size_t... Is, typename... Xi, typename... Knot_Indices>
669 inline auto
670 eval_basfunc_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
671 const std::tuple<Knot_Indices...> &knot_indices) const {
672 if constexpr (comp == functionspace::interior)
673 return std::tuple(
674 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
675 std::get<Is>(xi), std::get<Is>(knot_indices))...);
676 else if constexpr (comp == functionspace::boundary)
677 return std::tuple(
678 std::get<Is>(boundary_)
679 .template eval_basfunc<deriv, memory_optimized>(
680 std::get<Is>(xi), std::get<Is>(knot_indices))...);
681 }
683
684public:
687 template <functionspace comp = functionspace::interior,
688 deriv deriv = deriv::func, bool memory_optimized = false,
689 typename... Xi>
690 inline auto eval_basfunc(const std::tuple<Xi...> &xi) const {
691 return eval_basfunc_<comp, deriv, memory_optimized>(
692 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
693 }
694
695 template <functionspace comp = functionspace::interior,
696 deriv deriv = deriv::func, bool memory_optimized = false,
697 typename... Xi, typename... Knot_Indices>
698 inline auto
699 eval_basfunc(const std::tuple<Xi...> &xi,
700 const std::tuple<Knot_Indices...> &knot_indices) const {
701 return eval_basfunc_<comp, deriv, memory_optimized>(
702 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
703 }
705
706private:
709 template <functionspace comp = functionspace::interior,
710 bool memory_optimized = false, std::size_t... Is,
711 typename... Knot_Indices>
712 inline auto
713 find_coeff_indices_(std::index_sequence<Is...>,
714 const std::tuple<Knot_Indices...> &knot_indices) const {
715 if constexpr (comp == functionspace::interior)
716 return std::tuple(
717 std::get<Is>(spline_).template find_coeff_indices<memory_optimized>(
718 std::get<Is>(knot_indices))...);
719 else if constexpr (comp == functionspace::boundary)
720 return std::tuple(
721 std::get<Is>(boundary_).template find_coeff_indices<memory_optimized>(
722 std::get<Is>(knot_indices))...);
723 }
724
725public:
728 template <functionspace comp = functionspace::interior,
729 bool memory_optimized = false, typename... Knot_Indices>
730 inline auto
731 find_coeff_indices(const std::tuple<Knot_Indices...> &knot_indices) const {
732 return find_coeff_indices_<comp, memory_optimized>(
733 std::make_index_sequence<FunctionSpace::nspaces()>{}, knot_indices);
734 }
735
736private:
739 template <std::size_t... Is, std::size_t... Js>
740 inline auto &uniform_refine_(std::index_sequence<Is...>,
741 std::index_sequence<Js...>, int numRefine = 1,
742 int dimRefine = -1) {
743 (std::get<Is>(spline_).uniform_refine(numRefine, dimRefine), ...);
744 (std::get<Js>(boundary_).uniform_refine(numRefine, dimRefine), ...);
745 return *this;
746 }
747
748public:
751 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
752 return uniform_refine_(
753 std::make_index_sequence<FunctionSpace::nspaces()>{},
754 std::make_index_sequence<FunctionSpace::nboundaries()>{}, numRefine,
755 dimRefine);
756 }
757
758private:
761 template <typename real_t, std::size_t... Is, std::size_t... Js>
762 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
763 Options<real_t> options) const {
764 return FunctionSpace<
765 typename Splines::template real_derived_self_type<real_t>...,
766 typename Boundaries::template real_derived_self_type<real_t>...>(
767 std::get<Is>(spline_).to(options)...,
768 std::get<Js>(boundary_).to(options)...);
769 }
770
771public:
774 template <typename real_t> inline auto to(Options<real_t> options) const {
775 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
776 std::make_index_sequence<FunctionSpace::nboundaries()>{},
777 options);
778 }
779
780private:
783 template <std::size_t... Is, std::size_t... Js>
784 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
785 torch::Device device) const {
786 return FunctionSpace(std::get<Is>(spline_).to(device)...,
787 std::get<Js>(boundary_).to(device)...);
788 }
789
790public:
793 inline auto to(torch::Device device) const {
794 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
795 std::make_index_sequence<FunctionSpace::nboundaries()>{},
796 device);
797 }
798
799private:
801 template <typename real_t, std::size_t... Is, std::size_t... Js>
802 inline auto to_(std::index_sequence<Is...>,
803 std::index_sequence<Js...>) const {
804 return FunctionSpace<
805 typename Splines::template real_derived_self_type<real_t>...,
806 typename Boundaries::template real_derived_self_type<real_t>...>(
807 std::get<Is>(spline_).template to<real_t>()...,
808 std::get<Js>(boundary_).template to<real_t>()...);
809 }
810
811public:
813 template <typename real_t> inline auto to() const {
814 return to_<real_t>(
815 std::make_index_sequence<FunctionSpace::nspaces()>{},
816 std::make_index_sequence<FunctionSpace::nboundaries()>{});
817 }
818
819private:
821 template <std::size_t... Is>
822 inline auto scale_(std::index_sequence<Is...>, value_type s, int dim = -1) {
823 (std::get<Is>(spline_).scale(s, dim), ...);
825 return *this;
826 }
827
828public:
830 inline auto scale(value_type s, int dim = -1) {
831 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, s, dim);
832 }
833
834private:
836 template <std::size_t N, std::size_t... Is>
837 inline auto scale_(std::index_sequence<Is...>, std::array<value_type, N> v) {
838 (std::get<Is>(spline_).scale(v), ...);
839 (std::get<Is>(boundary_).from_full_tensor(
840 std::get<Is>(spline_).as_tensor()),
841 ...);
842 return *this;
843 }
844
845public:
847 template <size_t N> inline auto scale(std::array<value_type, N> v) {
848 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
849 }
850
851private:
853 template <std::size_t N, std::size_t... Is>
854 inline auto translate_(std::index_sequence<Is...>,
855 std::array<value_type, N> v) {
856 (std::get<Is>(spline_).translate(v), ...);
857 (std::get<Is>(boundary_).from_full_tensor(
858 std::get<Is>(spline_).as_tensor()),
859 ...);
860 return *this;
861 }
862
863public:
865 template <size_t N> inline auto translate(std::array<value_type, N> v) {
866 return translate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
867 }
868
869private:
871 template <std::size_t... Is>
872 inline auto rotate_(std::index_sequence<Is...>, value_type angle) {
873 (std::get<Is>(spline_).rotate(angle), ...);
874 (std::get<Is>(boundary_).from_full_tensor(
875 std::get<Is>(spline_).as_tensor()),
876 ...);
877 return *this;
878 }
879
880public:
882 inline auto rotate(value_type angle) {
883 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
884 }
885
886private:
888 template <std::size_t... Is>
889 inline auto rotate_(std::index_sequence<Is...>,
890 std::array<value_type, 3> angle) {
891 (std::get<Is>(spline_).rotate(angle), ...);
892 (std::get<Is>(boundary_).from_full_tensor(
893 std::get<Is>(spline_).as_tensor()),
894 ...);
895 return *this;
896 }
897
898public:
900 inline auto rotate(std::array<value_type, 3> angle) {
901 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
902 }
903
904private:
906 template <std::size_t... Is>
907 inline auto boundingBox_(std::index_sequence<Is...>) const {
908 return std::tuple(std::get<Is>(spline_).boundingBox()...);
909 }
910
911public:
913 inline auto boundingBox() const {
914 return boundingBox_(std::make_index_sequence<FunctionSpace::nspaces()>{});
915 }
916
917private:
920 template <std::size_t... Is>
921 inline torch::serialize::OutputArchive &
922 write_(std::index_sequence<Is...>, torch::serialize::OutputArchive &archive,
923 const std::string &key = "functionspace") const {
924 (std::get<Is>(spline_).write(
925 archive, key + ".fspace[" + std::to_string(Is) + "].interior"),
926 ...);
927 (std::get<Is>(boundary_).write(
928 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
929 ...);
930 return archive;
931 }
932
933public:
936 inline torch::serialize::OutputArchive &
937 write(torch::serialize::OutputArchive &archive,
938 const std::string &key = "functionspace") const {
939 write_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
940 return archive;
941 }
942
943private:
946 template <std::size_t... Is>
947 inline torch::serialize::InputArchive &
948 read_(std::index_sequence<Is...>, torch::serialize::InputArchive &archive,
949 const std::string &key = "functionspace") {
950 (std::get<Is>(spline_).read(archive, key + ".fspace[" + std::to_string(Is) +
951 "].interior"),
952 ...);
953 (std::get<Is>(boundary_).read(
954 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
955 ...);
956 return archive;
957 }
958
959public:
962 inline torch::serialize::InputArchive &
963 read(torch::serialize::InputArchive &archive,
964 const std::string &key = "functionspace") {
965 read_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
966 return archive;
967 }
968
970 inline virtual void
971 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
972
973 auto pretty_print_ = [this,
974 &os]<std::size_t... Is>(std::index_sequence<Is...>) {
975 ((os << "\ninterior = ", std::get<Is>(spline_).pretty_print(os),
976 os << "\nboundary = ", std::get<Is>(boundary_).pretty_print(os)),
977 ...);
978 };
979
980 pretty_print_(std::make_index_sequence<nspaces()>{});
981 }
982
983 // clang-format off
1001 // clang-format off
1004 template <functionspace comp = functionspace::interior,
1005 bool memory_optimized = false>
1006 inline auto curl(const utils::TensorArray<nspaces()> &xi) const {
1007 return curl<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1008 }
1009
1010 template <functionspace comp = functionspace::interior,
1011 bool memory_optimized = false,
1012 typename... TensorArrays>
1013 inline auto curl(const utils::TensorArray<nspaces()> &xi,
1014 const std::tuple<TensorArrays...> &knot_indices) const {
1015 return curl<comp, memory_optimized>(xi, knot_indices,
1016 find_coeff_indices<comp>(knot_indices));
1017 }
1018
1019 template <functionspace comp = functionspace::interior,
1020 bool memory_optimized = false>
1021 inline auto curl(const utils::TensorArray1 &xi,
1022 const std::tuple<utils::TensorArray1> &knot_indices,
1023 const std::tuple<torch::Tensor> &coeff_indices) const {
1024
1025 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1026
1027 throw std::runtime_error("Unsupported parametric/geometric dimension");
1028
1030 }
1031
1032 template <functionspace comp = functionspace::interior,
1033 bool memory_optimized = false>
1034 inline auto
1036 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1037 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1038
1039 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1040 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1041 xi[0].sizes() == xi[1].sizes());
1042
1049 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1050 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1051 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1052 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1053 }
1054
1055 template <functionspace comp = functionspace::interior,
1056 bool memory_optimized = false>
1057 inline auto curl(const utils::TensorArray3 &xi,
1058 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1059 utils::TensorArray3> &knot_indices,
1060 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1061 &coeff_indices) const {
1062
1063 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1064 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1065 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1066 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1067
1072 *std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1073 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] -
1074 *std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1075 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1076 *std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1077 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] -
1078 *std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1079 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1080 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1081 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1082 *std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1083 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1084 }
1085
1086 template <functionspace comp = functionspace::interior,
1087 bool memory_optimized = false>
1088 inline auto
1090 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1092 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1093 torch::Tensor> &coeff_indices) const {
1094
1095 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1096 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1097 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1098 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1099 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1100 xi[2].sizes() == xi[3].sizes());
1101
1102 throw std::runtime_error("Unsupported parametric/geometric dimension");
1103
1105 }
1107
1132 template <functionspace comp = functionspace::interior,
1133 bool memory_optimized = false>
1134 inline auto div(const utils::TensorArray<nspaces()> &xi) const {
1135 return div<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1136 }
1137
1138 template <functionspace comp = functionspace::interior,
1139 bool memory_optimized = false,
1140 typename... TensorArrays>
1141 inline auto div(const utils::TensorArray<nspaces()> &xi,
1142 const std::tuple<TensorArrays...> &knot_indices) const {
1143 return div<comp, memory_optimized>(xi, knot_indices,
1144 find_coeff_indices<comp>(knot_indices));
1145 }
1146
1147 template <functionspace comp = functionspace::interior,
1148 bool memory_optimized = false>
1149 inline auto div(const utils::TensorArray1 &xi,
1150 const std::tuple<utils::TensorArray1> &knot_indices,
1151 const std::tuple<torch::Tensor> &coeff_indices) const {
1152
1153 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1154
1155 if constexpr (comp == functionspace::interior) {
1156 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1157 "div(.) for vector-valued spaces requires 1D variables");
1158
1160 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1161 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1162 }
1163 }
1164
1165 template <functionspace comp = functionspace::interior,
1166 bool memory_optimized = false>
1167 inline auto
1169 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1170 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1171
1172 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1173 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1174 xi[0].sizes() == xi[1].sizes());
1175
1176 if constexpr (comp == functionspace::interior) {
1177 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1178 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1179 "div(.) for vector-valued spaces requires 1D variables");
1180
1182 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1183 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1184 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1185 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1186 }
1187 }
1188
1189 template <functionspace comp = functionspace::interior,
1190 bool memory_optimized = false>
1191 inline auto div(const utils::TensorArray3 &xi,
1192 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1193 utils::TensorArray3> &knot_indices,
1194 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1195 &coeff_indices) const {
1196
1197 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1198 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1199 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1200 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1201
1202 if constexpr (comp == functionspace::interior) {
1203 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1204 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1205 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1206 "div(.) for vector-valued spaces requires 1D variables");
1207
1209 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1210 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1211 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1212 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1213 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1214 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1215 }
1216 }
1217
1218 template <functionspace comp = functionspace::interior,
1219 bool memory_optimized = false>
1220 inline auto
1222 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1224 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1225 torch::Tensor> &coeff_indices) const {
1226
1227 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1228 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1229 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1230 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1231 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1232 xi[2].sizes() == xi[3].sizes());
1233
1234 if constexpr (comp == functionspace::interior) {
1235 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1236 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1237 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1238 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1239 "div(.) for vector-valued spaces requires 1D variables");
1240
1242 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1243 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1244 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1245 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1246 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1247 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
1248 *std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1249 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1250 }
1251 }
1253
1271 template <functionspace comp = functionspace::interior,
1272 bool memory_optimized = false>
1273 inline auto grad(const utils::TensorArray<nspaces()> &xi) const {
1274 return grad<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1275 }
1276
1277 template <functionspace comp = functionspace::interior,
1278 bool memory_optimized = false,
1279 typename... TensorArrays>
1280 inline auto grad(const utils::TensorArray<nspaces()> &xi,
1281 const std::tuple<TensorArrays...> &knot_indices) const {
1282 return grad<comp, memory_optimized>(xi, knot_indices,
1283 find_coeff_indices<comp>(knot_indices));
1284 }
1285
1286 template <functionspace comp = functionspace::interior,
1287 bool memory_optimized = false>
1288 inline auto grad(const utils::TensorArray1 &xi,
1289 const std::tuple<utils::TensorArray1> &knot_indices,
1290 const std::tuple<torch::Tensor> &coeff_indices) const {
1291
1292 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1293
1294 if constexpr (comp == functionspace::interior) {
1295 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1296 "grad(.) for vector-valued spaces requires 1D variables");
1297
1299 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1300 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1301 }
1302 }
1303
1304 template <functionspace comp = functionspace::interior,
1305 bool memory_optimized = false>
1306 inline auto
1308 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1309 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1310
1311 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1312 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1313 xi[0].sizes() == xi[1].sizes());
1314
1315 if constexpr (comp == functionspace::interior) {
1316 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1317 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1318 "grad(.) for vector-valued spaces requires 1D variables");
1319
1321 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1322 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1323 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1324 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1325 }
1326 }
1327
1328 template <functionspace comp = functionspace::interior,
1329 bool memory_optimized = false>
1330 inline auto grad(const utils::TensorArray3 &xi,
1331 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1332 utils::TensorArray3> &knot_indices,
1333 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1334 &coeff_indices) const {
1335
1336 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1337 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1338 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1339 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1340
1341 if constexpr (comp == functionspace::interior) {
1342 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1343 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1344 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1345 "div(.) for vector-valued spaces requires 1D variables");
1346
1348 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1349 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1350 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1351 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1352 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1353 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1354 }
1355 }
1356
1357 template <functionspace comp = functionspace::interior,
1358 bool memory_optimized = false>
1359 inline auto
1361 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1363 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1364 torch::Tensor> &coeff_indices) const {
1365
1366 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1367 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1368 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1369 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1370 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1371 xi[2].sizes() == xi[3].sizes());
1372
1373 if constexpr (comp == functionspace::interior) {
1374 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1375 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1376 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1377 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1378 "grad(.) for vector-valued spaces requires 1D variables");
1379
1381 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1382 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1383 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1384 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1385 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1386 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1387 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1388 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1389 }
1390 }
1392
1393 // clang-format off
1426 // clang-format on
1429 template <functionspace comp = functionspace::interior,
1430 bool memory_optimized = false>
1431 inline auto hess(const utils::TensorArray<nspaces()> &xi) const {
1432 return hess<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1433 }
1434
1435 template <functionspace comp = functionspace::interior,
1436 bool memory_optimized = false,
1437 typename... TensorArrays>
1438 inline auto hess(const utils::TensorArray<nspaces()> &xi,
1439 const std::tuple<TensorArrays...> &knot_indices) const {
1440 return hess<comp, memory_optimized>(xi, knot_indices,
1441 find_coeff_indices<comp>(knot_indices));
1442 }
1443
1444 template <functionspace comp = functionspace::interior,
1445 bool memory_optimized = false>
1446 inline auto hess(const utils::TensorArray1 &xi,
1447 const std::tuple<utils::TensorArray1> &knot_indices,
1448 const std::tuple<torch::Tensor> &coeff_indices) const {
1449
1450 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1451
1452 if constexpr (comp == functionspace::interior) {
1453 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1454 "hess(.) for vector-valued spaces requires 1D variables");
1455
1457 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1458 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)));
1459 }
1460 }
1461
1462 template <functionspace comp = functionspace::interior,
1463 bool memory_optimized = false>
1464 inline auto
1466 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1467 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1468
1469 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1470 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1471 xi[0].sizes() == xi[1].sizes());
1472
1473 if constexpr (comp == functionspace::interior) {
1474 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1475 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1476 "hess(.) for vector-valued spaces requires 1D variables");
1477
1479 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1480 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1481 std::get<0>(spline_)
1482 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1483 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1484 std::get<0>(spline_)
1485 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1486 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1487 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1488 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1489
1490 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1491 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1492 std::get<1>(spline_)
1493 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1494 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1495 std::get<1>(spline_)
1496 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1497 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1498 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1499 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)));
1500 }
1501 }
1502
1503 template <functionspace comp = functionspace::interior,
1504 bool memory_optimized = false>
1505 inline auto hess(const utils::TensorArray3 &xi,
1506 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1507 utils::TensorArray3> &knot_indices,
1508 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1509 &coeff_indices) const {
1510
1511 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1512 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1513 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1514 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1515
1516 if constexpr (comp == functionspace::interior) {
1517 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1518 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1519 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1520 "hess(.) for vector-valued spaces requires 1D variables");
1521
1523 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1524 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1525 std::get<0>(spline_)
1526 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1527 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1528 std::get<0>(spline_)
1529 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1530 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1531 std::get<0>(spline_)
1532 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1533 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1534 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1535 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1536 std::get<0>(spline_)
1537 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1538 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1539 std::get<0>(spline_)
1540 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1541 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1542 std::get<0>(spline_)
1543 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1544 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1545 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1546 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1547
1548 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1549 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1550 std::get<1>(spline_)
1551 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1552 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1553 std::get<1>(spline_)
1554 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1555 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1556 std::get<1>(spline_)
1557 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1558 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1559 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1560 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1561 std::get<1>(spline_)
1562 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1563 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1564 std::get<1>(spline_)
1565 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1566 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1567 std::get<1>(spline_)
1568 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1569 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1570 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1571 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1572
1573 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1574 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1575 std::get<2>(spline_)
1576 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1577 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1578 std::get<2>(spline_)
1579 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1580 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1581 std::get<2>(spline_)
1582 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1583 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1584 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1585 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1586 std::get<2>(spline_)
1587 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1588 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1589 std::get<2>(spline_)
1590 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1591 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1592 std::get<2>(spline_)
1593 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1594 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1595 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1596 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)));
1597 }
1598 }
1599
1600 template <functionspace comp = functionspace::interior,
1601 bool memory_optimized = false>
1602 inline auto
1604 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1606 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1607 torch::Tensor> &coeff_indices) const {
1608
1609 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1610 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1611 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1612 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1613 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1614 xi[2].sizes() == xi[3].sizes());
1615
1616 if constexpr (comp == functionspace::interior) {
1617 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1618 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1619 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1620 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1621 "hess(.) for vector-valued spaces requires 1D variables");
1622
1624 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1625 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1626 std::get<0>(spline_)
1627 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1628 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1629 std::get<0>(spline_)
1630 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1631 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1632 std::get<0>(spline_)
1633 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1634 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1635 std::get<0>(spline_)
1636 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1637 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1638 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1639 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1640 std::get<0>(spline_)
1641 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1642 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1643 std::get<0>(spline_)
1644 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1645 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1646 std::get<0>(spline_)
1647 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1648 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1649 std::get<0>(spline_)
1650 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1651 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1652 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1653 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1654 std::get<0>(spline_)
1655 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1656 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1657 std::get<0>(spline_)
1658 .template eval<deriv::dt + deriv::dx, memory_optimized>(
1659 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1660 std::get<0>(spline_)
1661 .template eval<deriv::dt + deriv::dy, memory_optimized>(
1662 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1663 std::get<0>(spline_)
1664 .template eval<deriv::dt + deriv::dz, memory_optimized>(
1665 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1666 std::get<0>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1667 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1668
1669 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1670 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1671 std::get<1>(spline_)
1672 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1673 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1674 std::get<1>(spline_)
1675 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1676 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1677 std::get<1>(spline_)
1678 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1679 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1680 std::get<1>(spline_)
1681 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1682 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1683 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1684 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1685 std::get<1>(spline_)
1686 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1687 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1688 std::get<1>(spline_)
1689 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1690 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1691 std::get<1>(spline_)
1692 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1693 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1694 std::get<1>(spline_)
1695 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1696 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1697 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1698 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1699 std::get<1>(spline_)
1700 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1701 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1702 std::get<1>(spline_)
1703 .template eval<deriv::dt + deriv::dx, memory_optimized>(
1704 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1705 std::get<1>(spline_)
1706 .template eval<deriv::dt + deriv::dy, memory_optimized>(
1707 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1708 std::get<1>(spline_)
1709 .template eval<deriv::dt + deriv::dz, memory_optimized>(
1710 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1711 std::get<1>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1712 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1713
1714 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1715 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1716 std::get<2>(spline_)
1717 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1718 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1719 std::get<2>(spline_)
1720 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1721 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1722 std::get<2>(spline_)
1723 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1724 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1725 std::get<2>(spline_)
1726 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1727 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1728 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1729 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1730 std::get<2>(spline_)
1731 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1732 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1733 std::get<2>(spline_)
1734 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1735 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1736 std::get<2>(spline_)
1737 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1738 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1739 std::get<2>(spline_)
1740 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1741 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1742 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1743 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1744 std::get<2>(spline_)
1745 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1746 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1747 std::get<2>(spline_)
1748 .template eval<deriv::dt + deriv::dx, memory_optimized>(
1749 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1750 std::get<2>(spline_)
1751 .template eval<deriv::dt + deriv::dy, memory_optimized>(
1752 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1753 std::get<2>(spline_)
1754 .template eval<deriv::dt + deriv::dz, memory_optimized>(
1755 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1756 std::get<2>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1757 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1758
1759 std::get<3>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1760 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1761 std::get<3>(spline_)
1762 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1763 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1764 std::get<3>(spline_)
1765 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1766 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1767 std::get<3>(spline_)
1768 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1769 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1770 std::get<3>(spline_)
1771 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1772 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1773 std::get<3>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1774 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1775 std::get<3>(spline_)
1776 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1777 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1778 std::get<3>(spline_)
1779 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1780 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1781 std::get<3>(spline_)
1782 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1783 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1784 std::get<3>(spline_)
1785 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1786 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1787 std::get<3>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1788 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1789 std::get<3>(spline_)
1790 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1791 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1792 std::get<3>(spline_)
1793 .template eval<deriv::dt + deriv::dx, memory_optimized>(
1794 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1795 std::get<3>(spline_)
1796 .template eval<deriv::dt + deriv::dy, memory_optimized>(
1797 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1798 std::get<3>(spline_)
1799 .template eval<deriv::dt + deriv::dz, memory_optimized>(
1800 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1801 std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1802 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)));
1803 }
1804 }
1806
1807 // clang-format off
1841 // clang-format on
1843 template <functionspace comp = functionspace::interior,
1844 bool memory_optimized = false>
1845 inline auto jac(const utils::TensorArray<nspaces()> &xi) const {
1846 return jac<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1847 }
1848
1849 template <functionspace comp = functionspace::interior,
1850 bool memory_optimized = false,
1851 typename... TensorArrays>
1852 inline auto jac(const utils::TensorArray<nspaces()> &xi,
1853 const std::tuple<TensorArrays...> &knot_indices) const {
1854 return jac<comp, memory_optimized>(xi, knot_indices,
1855 find_coeff_indices<comp>(knot_indices));
1856 }
1857
1858 template <functionspace comp = functionspace::interior,
1859 bool memory_optimized = false>
1860 inline auto jac(const utils::TensorArray1 &xi,
1861 const std::tuple<utils::TensorArray1> &knot_indices,
1862 const std::tuple<torch::Tensor> &coeff_indices) const {
1863
1864 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1865
1866 if constexpr (comp == functionspace::interior) {
1867 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1868 "jac(.) for vector-valued spaces requires 1D variables");
1869
1871 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1872 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1873 }
1874 }
1875
1876 template <functionspace comp = functionspace::interior,
1877 bool memory_optimized = false>
1878 inline auto
1880 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1881 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1882
1883 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1884 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1885 xi[0].sizes() == xi[1].sizes());
1886
1887 if constexpr (comp == functionspace::interior) {
1888 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1889 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1890 "jac(.) for vector-valued spaces requires 1D variables");
1891
1893 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1894 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1895 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1896 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1897
1898 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1899 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1900 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1901 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1902 }
1903 }
1904
1905 template <functionspace comp = functionspace::interior,
1906 bool memory_optimized = false>
1907 inline auto jac(const utils::TensorArray3 &xi,
1908 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1909 utils::TensorArray3> &knot_indices,
1910 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1911 &coeff_indices) const {
1912
1913 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1914 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1915 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1916 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1917
1918 if constexpr (comp == functionspace::interior) {
1919 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1920 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1921 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1922 "jac(.) for vector-valued spaces requires 1D variables");
1923
1925 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1926 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1927 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1928 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1929 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1930 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1931
1932 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1933 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1934 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1935 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1936 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1937 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1938
1939 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1940 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1941 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1942 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1943 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1944 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1945 }
1946 }
1947
1948 template <functionspace comp = functionspace::interior,
1949 bool memory_optimized = false>
1950 inline auto
1952 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1954 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1955 torch::Tensor> &coeff_indices) const {
1956
1957 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1958 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1959 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1960 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1961 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1962 xi[2].sizes() == xi[3].sizes());
1963
1964 if constexpr (comp == functionspace::interior) {
1965 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1966 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1967 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1968 "jac(.) for vector-valued spaces requires 1D variables");
1969
1971 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1972 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1973 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1974 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1975 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1976 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1977 std::get<0>(spline_).template eval<deriv::dt, memory_optimized>(
1978 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1979
1980 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1981 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1982 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1983 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1984 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1985 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1986 std::get<1>(spline_).template eval<deriv::dt, memory_optimized>(
1987 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1988
1989 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1990 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1991 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1992 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1993 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1994 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1995 std::get<2>(spline_).template eval<deriv::dt, memory_optimized>(
1996 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1997
1998 std::get<3>(spline_).template eval<deriv::dx, memory_optimized>(
1999 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2000 std::get<3>(spline_).template eval<deriv::dy, memory_optimized>(
2001 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2002 std::get<3>(spline_).template eval<deriv::dz, memory_optimized>(
2003 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2004 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
2005 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2006 }
2007 }
2009
2010 // clang-format off
2027 // clang-format on
2030 template <functionspace comp = functionspace::interior,
2031 bool memory_optimized = false>
2032 inline auto lapl(const utils::TensorArray<nspaces()> &xi) const {
2033 return lapl<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
2034 }
2035
2036 template <functionspace comp = functionspace::interior,
2037 bool memory_optimized = false,
2038 typename... TensorArrays>
2039 inline auto lapl(const utils::TensorArray<nspaces()> &xi,
2040 const std::tuple<TensorArrays...> &knot_indices) const {
2041 return lapl<comp, memory_optimized>(xi, knot_indices,
2042 find_coeff_indices<comp>(knot_indices));
2043 }
2044
2045 template <functionspace comp = functionspace::interior,
2046 bool memory_optimized = false>
2047 inline auto lapl(const utils::TensorArray1 &xi,
2048 const std::tuple<utils::TensorArray1> &knot_indices,
2049 const std::tuple<torch::Tensor> &coeff_indices) const {
2050
2051 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
2052
2053 if constexpr (comp == functionspace::interior) {
2054 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
2055 "lapl(.) for vector-valued spaces requires 1D variables");
2056
2058 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2059 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
2060 }
2061 }
2062
2063 template <functionspace comp = functionspace::interior,
2064 bool memory_optimized = false>
2065 inline auto
2067 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
2068 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
2069
2070 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2071 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2072 xi[0].sizes() == xi[1].sizes());
2073
2074 if constexpr (comp == functionspace::interior) {
2075 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2076 std::tuple_element_t<1, spline_type>::geoDim() == 1,
2077 "lapl(.) for vector-valued spaces requires 1D variables");
2078
2080 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2081 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2082 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2083 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
2084 }
2085 }
2086
2087 template <functionspace comp = functionspace::interior,
2088 bool memory_optimized = false>
2089 inline auto lapl(const utils::TensorArray3 &xi,
2090 const std::tuple<utils::TensorArray3, utils::TensorArray3,
2091 utils::TensorArray3> &knot_indices,
2092 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
2093 &coeff_indices) const {
2094
2095 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2096 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2097 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2098 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
2099
2100 if constexpr (comp == functionspace::interior) {
2101 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2102 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2103 std::tuple_element_t<2, spline_type>::geoDim() == 1,
2104 "div(.) for vector-valued spaces requires 1D variables");
2105
2107 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2108 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2109 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2110 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2111 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2112 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
2113 }
2114 }
2115
2116 template <functionspace comp = functionspace::interior,
2117 bool memory_optimized = false>
2118 inline auto
2120 const std::tuple<utils::TensorArray4, utils::TensorArray4,
2122 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
2123 torch::Tensor> &coeff_indices) const {
2124
2125 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2126 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2127 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2128 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
2129 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
2130 xi[2].sizes() == xi[3].sizes());
2131
2132 if constexpr (comp == functionspace::interior) {
2133 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2134 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2135 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
2136 std::tuple_element_t<3, spline_type>::geoDim() == 1,
2137 "div(.) for vector-valued spaces requires 1D variables");
2138
2140 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2141 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2142 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2143 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2144 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2145 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
2146 *std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
2147 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2148 }
2149 }
2151
2152#define GENERATE_EXPR_MACRO(r, data, name) \
2153private: \
2154 template <functionspace comp = functionspace::interior, \
2155 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
2156 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2157 const std::tuple<Xi...> &xi) const { \
2158 if constexpr (comp == functionspace::interior) \
2159 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2160 std::get<Is>(xi))...); \
2161 else if constexpr (comp == functionspace::boundary) \
2162 return std::tuple( \
2163 std::get<Is>(boundary_).template name<memory_optimized>( \
2164 std::get<Is>(xi))...); \
2165 } \
2166 \
2167 template <functionspace comp = functionspace::interior, \
2168 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2169 typename... Knot_Indices> \
2170 inline auto BOOST_PP_CAT(name, _all_)( \
2171 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2172 const std::tuple<Knot_Indices...> &knot_indices) const { \
2173 if constexpr (comp == functionspace::interior) \
2174 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2175 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2176 else if constexpr (comp == functionspace::boundary) \
2177 return std::tuple( \
2178 std::get<Is>(boundary_).template name<memory_optimized>( \
2179 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2180 } \
2181 \
2182 template <functionspace comp = functionspace::interior, \
2183 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2184 typename... Knot_Indices, typename... Coeff_Indices> \
2185 inline auto BOOST_PP_CAT(name, _all_)( \
2186 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2187 const std::tuple<Knot_Indices...> &knot_indices, \
2188 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
2189 if constexpr (comp == functionspace::interior) \
2190 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2191 std::get<Is>(xi), std::get<Is>(knot_indices), \
2192 std::get<Is>(coeff_indices))...); \
2193 else if constexpr (comp == functionspace::boundary) \
2194 return std::tuple( \
2195 std::get<Is>(boundary_).template name<memory_optimized>( \
2196 std::get<Is>(xi), std::get<Is>(knot_indices), \
2197 std::get<Is>(coeff_indices))...); \
2198 } \
2199 \
2200 template <functionspace comp = functionspace::interior, \
2201 bool memory_optimized = false, std::size_t... Is, std::size_t N> \
2202 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
2203 const utils::TensorArray<N> &xi) const { \
2204 if constexpr (comp == functionspace::interior) \
2205 return name<comp, memory_optimized>( \
2206 xi, std::tuple(std::get<Is>(spline_).find_knot_indices(xi)...)); \
2207 else if constexpr (comp == functionspace::boundary) \
2208 return name<comp, memory_optimized>( \
2209 xi, std::tuple(std::get<Is>(boundary_).find_knot_indices(xi)...)); \
2210 } \
2211 \
2212 template <functionspace comp = functionspace::interior, \
2213 bool memory_optimized = false, std::size_t... Is, std::size_t N, \
2214 typename... Knot_Indices> \
2215 inline auto BOOST_PP_CAT(name, _)( \
2216 std::index_sequence<Is...>, const utils::TensorArray<N> &xi, \
2217 const std::tuple<Knot_Indices...> &knot_indices) const { \
2218 if constexpr (comp == functionspace::interior) \
2219 return name<comp, memory_optimized>( \
2220 xi, knot_indices, \
2221 std::tuple(std::get<Is>(spline_).find_coeff_indices( \
2222 std::get<Is>(knot_indices))...)); \
2223 else if constexpr (comp == functionspace::boundary) \
2224 return name<comp, memory_optimized>( \
2225 xi, knot_indices, \
2226 std::tuple(std::get<Is>(boundary_).find_coeff_indices( \
2227 std::get<Is>(knot_indices))...)); \
2228 } \
2229 \
2230public: \
2231 template <functionspace comp = functionspace::interior, \
2232 bool memory_optimized = false, typename... Args> \
2233 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2234 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2235 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2236 } \
2237 \
2238 template <functionspace comp = functionspace::interior, \
2239 bool memory_optimized = false> \
2240 inline auto name(const torch::Tensor &xi) const { \
2241 return name<comp, memory_optimized>(utils::TensorArray1({xi})); \
2242 } \
2243 \
2244 template <functionspace comp = functionspace::interior, \
2245 bool memory_optimized = false, std::size_t N> \
2246 inline auto name(const utils::TensorArray<N> &xi) const { \
2247 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2248 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi); \
2249 } \
2250 \
2251 template <functionspace comp = functionspace::interior, \
2252 bool memory_optimized = false, std::size_t N, \
2253 typename... Knot_Indices> \
2254 inline auto name(const utils::TensorArray<N> &xi, \
2255 const std::tuple<Knot_Indices...> &knot_indices) const { \
2256 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2257 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, \
2258 knot_indices); \
2259 }
2260
2263 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
2265#undef GENERATE_EXPR_MACRO
2266
2267#define GENERATE_IEXPR_MACRO(r, data, name) \
2268private: \
2269 template <functionspace comp = functionspace::interior, \
2270 bool memory_optimized = false, std::size_t... Is, \
2271 typename Geometry, typename... Xi> \
2272 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2273 const Geometry &G, \
2274 const std::tuple<Xi...> &xi) const { \
2275 if constexpr (comp == functionspace::interior) { \
2276 if constexpr (Geometry::nspaces() == 1) \
2277 return std::tuple( \
2278 std::get<Is>(spline_).template name<memory_optimized>( \
2279 G.space(), std::get<Is>(xi))...); \
2280 else if constexpr (Geometry::nspaces() == nspaces()) \
2281 return std::tuple( \
2282 std::get<Is>(spline_).template name<memory_optimized>( \
2283 G.template space<Is>(), std::get<Is>(xi))...); \
2284 } else if constexpr (comp == functionspace::boundary) { \
2285 if constexpr (Geometry::nboundaries() == 1) \
2286 return std::tuple( \
2287 std::get<Is>(boundary_).template name<memory_optimized>( \
2288 static_cast<typename Geometry::boundary_type::boundary_type>( \
2289 G.boundary().coeffs()), \
2290 std::get<Is>(xi))...); \
2291 else if constexpr (Geometry::nboundaries() == nboundaries()) \
2292 return std::tuple( \
2293 std::get<Is>(boundary_).template name<memory_optimized>( \
2294 G.template boundary<Is>().coeffs(), std::get<Is>(xi))...); \
2295 } \
2296 } \
2297 \
2298 template <functionspace comp = functionspace::interior, \
2299 bool memory_optimized = false, std::size_t... Is, \
2300 typename Geometry, typename... Xi, typename... Knot_Indices, \
2301 typename... Knot_Indices_G> \
2302 inline auto BOOST_PP_CAT(name, _all_)( \
2303 std::index_sequence<Is...>, const Geometry &G, \
2304 const std::tuple<Xi...> &xi, \
2305 const std::tuple<Knot_Indices...> &knot_indices, \
2306 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
2307 if constexpr (comp == functionspace::interior) { \
2308 if constexpr (Geometry::nspaces() == 1) \
2309 return std::tuple( \
2310 std::get<Is>(spline_).template name<memory_optimized>( \
2311 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2312 std::get<Is>(knot_indices_G))...); \
2313 else \
2314 return std::tuple( \
2315 std::get<Is>(spline_).template name<memory_optimized>( \
2316 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2317 std::get<Is>(knot_indices_G))...); \
2318 } else if constexpr (comp == functionspace::boundary) { \
2319 if constexpr (Geometry::nspaces() == 1) \
2320 return std::tuple( \
2321 std::get<Is>(boundary_).template name<memory_optimized>( \
2322 static_cast<typename Geometry::boundary_type::boundary_type>( \
2323 G.boundary().coeffs()), \
2324 std::get<Is>(xi), std::get<Is>(knot_indices), \
2325 std::get<Is>(knot_indices_G))...); \
2326 else \
2327 return std::tuple( \
2328 std::get<Is>(boundary_).template name<memory_optimized>( \
2329 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2330 std::get<Is>(knot_indices), std::get<Is>(knot_indices_G))...); \
2331 } \
2332 } \
2333 \
2334 template <functionspace comp = functionspace::interior, \
2335 bool memory_optimized = false, std::size_t... Is, \
2336 typename Geometry, typename... Xi, typename... Knot_Indices, \
2337 typename... Coeff_Indices, typename... Knot_Indices_G, \
2338 typename... Coeff_Indices_G> \
2339 inline auto BOOST_PP_CAT(name, _all_)( \
2340 std::index_sequence<Is...>, const Geometry &G, \
2341 const std::tuple<Xi...> &xi, \
2342 const std::tuple<Knot_Indices...> &knot_indices, \
2343 const std::tuple<Coeff_Indices...> &coeff_indices, \
2344 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
2345 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
2346 if constexpr (comp == functionspace::interior) { \
2347 if constexpr (Geometry::nspaces() == 1) \
2348 return std::tuple( \
2349 std::get<Is>(spline_).template name<memory_optimized>( \
2350 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2351 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2352 std::get<Is>(coeff_indices_G))...); \
2353 else \
2354 return std::tuple( \
2355 std::get<Is>(spline_).template name<memory_optimized>( \
2356 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2357 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2358 std::get<Is>(coeff_indices_G))...); \
2359 } else if constexpr (comp == functionspace::boundary) { \
2360 if constexpr (Geometry::nspaces() == 1) \
2361 return std::tuple( \
2362 std::get<Is>(boundary_).template name<memory_optimized>( \
2363 static_cast<typename Geometry::boundary_type::boundary_type>( \
2364 G.boundary().coeffs()), \
2365 std::get<Is>(xi), std::get<Is>(knot_indices), \
2366 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2367 std::get<Is>(coeff_indices_G))...); \
2368 else \
2369 return std::tuple( \
2370 std::get<Is>(boundary_).template name<memory_optimized>( \
2371 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2372 std::get<Is>(knot_indices), std::get<Is>(coeff_indices), \
2373 std::get<Is>(knot_indices_G), \
2374 std::get<Is>(coeff_indices_G))...); \
2375 } \
2376 } \
2377 \
2378public: \
2379 template <functionspace comp = functionspace::interior, \
2380 bool memory_optimized = false, typename... Args> \
2381 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2382 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2383 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2384 }
2385
2388 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
2390#undef GENERATE_IEXPR_MACRO
2391};
2392
2394template <typename... Splines>
2395inline std::ostream &operator<<(std::ostream &os,
2396 const FunctionSpace<Splines...> &obj) {
2397 obj.pretty_print(os);
2398 return os;
2399}
2400
2405 template <typename Spline, typename Boundary>
2406 //requires SplineType<Spline> && BoundaryType<Boundary>
2408 public utils::Serializable,
2409 private utils::FullQualifiedName {
2410
2411public:
2413 using value_type = typename Spline::value_type;
2414
2416 using spline_type = Spline;
2417
2419 using eval_type = utils::TensorArray<Spline::parDim()>;
2420
2423
2425 using boundary_eval_type = typename Boundary::eval_type;
2426
2427protected:
2430
2433
2434public:
2436 FunctionSpace() = default;
2437
2439 FunctionSpace(const FunctionSpace &) = default;
2440
2443
2446 FunctionSpace(const std::array<int64_t, Spline::parDim()> &ncoeffs,
2447 enum init init = init::greville,
2449 : spline_(ncoeffs, init, options),
2450 boundary_(ncoeffs, init::none, options) {
2451 boundary_.from_full_tensor(spline_.as_tensor());
2452 }
2453
2454 FunctionSpace(std::array<std::vector<value_type>, Spline::parDim()> kv,
2455 enum init init = init::greville,
2457 : spline_(kv, init, options), boundary_(kv, init::none, options) {
2458 static_assert(Spline::is_nonuniform(),
2459 "Constructor is only available for non-uniform splines");
2460 boundary_.from_full_tensor(spline_.as_tensor());
2461 }
2462
2463 explicit FunctionSpace(const Spline &spline)
2464 : spline_(spline),
2465 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2466 boundary_.from_full_tensor(spline_.as_tensor());
2467 }
2468
2469 explicit FunctionSpace(Spline &&spline)
2470 : spline_(spline),
2471 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2472 boundary_.from_full_tensor(spline_.as_tensor());
2473 }
2475
2477 inline static constexpr short_t nspaces() noexcept { return 1; }
2478
2480 inline static constexpr short_t nboundaries() noexcept { return 1; }
2481
2483 template <short_t s = 0>
2484 inline constexpr const spline_type &space() const noexcept {
2485 static_assert(s >= 0 && s < nspaces());
2486 return spline_;
2487 }
2488
2490 template <short_t s = 0> inline constexpr spline_type &space() noexcept {
2491 static_assert(s >= 0 && s < nspaces());
2492 return spline_;
2493 }
2494
2496 template <short_t s = 0>
2497 inline constexpr const boundary_type &boundary() const noexcept {
2498 static_assert(s >= 0 && s < nboundaries());
2499 return boundary_;
2500 }
2501
2504 template <short_t s = 0> inline constexpr boundary_type &boundary() noexcept {
2505 static_assert(s >= 0 && s < nboundaries());
2506 return boundary_;
2507 }
2508
2510 inline constexpr FunctionSpace clone() const noexcept {
2511 return FunctionSpace(*this);
2512 }
2513
2515 template <short_t... s> inline constexpr auto clone() const noexcept {
2516
2517 static_assert(((s >= 0 && s < nspaces()) && ... && true));
2518
2519 if constexpr (sizeof...(s) == 1)
2520 return FunctionSpace(*this);
2521 else
2522 return FunctionSpace<
2523 std::tuple<std::tuple_element_t<s, std::tuple<spline_type>>...>,
2524 std::tuple<std::tuple_element_t<s, std::tuple<boundary_type>>...>>(
2525 std::get<s>(std::make_tuple(spline_))...,
2526 std::get<s>(std::make_tuple(boundary_))...);
2527 }
2528
2530 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
2531 return spline_.as_tensor();
2532 }
2533
2535 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
2536 return boundary_.as_tensor();
2537 }
2538
2544 virtual inline torch::Tensor as_tensor() const noexcept {
2545 return spaces_as_tensor();
2546 }
2547
2550 virtual inline int64_t spaces_as_tensor_size() const noexcept {
2551 return spline_.as_tensor_size();
2552 }
2553
2556 virtual inline int64_t boundary_as_tensor_size() const noexcept {
2557 return boundary_.as_tensor_size();
2558 }
2559
2565 virtual inline int64_t as_tensor_size() const noexcept {
2566 return spaces_as_tensor_size();
2567 }
2568
2570 virtual inline FunctionSpace &
2571 spaces_from_tensor(const torch::Tensor &coeffs) noexcept {
2572 spline_.from_tensor(coeffs);
2573 return *this;
2574 }
2575
2578 virtual inline FunctionSpace &
2579 boundary_from_tensor(const torch::Tensor &coeffs) noexcept {
2580 boundary_.from_tensor(coeffs);
2581 return *this;
2582 }
2583
2585 virtual inline FunctionSpace &
2586 boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept {
2587 boundary_.from_full_tensor(coeffs);
2588 return *this;
2589 }
2590
2592 inline FunctionSpace &from_tensor(const torch::Tensor &coeffs) noexcept {
2593 spline_.from_tensor(coeffs);
2594 boundary_.from_full_tensor(coeffs);
2595 return *this;
2596 }
2597
2599 inline pugi::xml_document to_xml(int id = 0, std::string label = "") const {
2600 pugi::xml_document doc;
2601 pugi::xml_node root = doc.append_child("xml");
2602 to_xml(root, id, label);
2603
2604 return doc;
2605 }
2606
2608 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
2609 std::string label = "") const {
2610 return spline_.to_xml(root, id, label);
2611 }
2612
2614 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
2615 std::string label = "") {
2616 return from_xml(doc.child("xml"), id, label);
2617 }
2618
2620 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
2621 std::string label = "") {
2622 spline_.from_xml(root, id, label);
2623 return *this;
2624 }
2625
2627 nlohmann::json to_json() const override {
2628 auto json = nlohmann::json::array();
2629 json.push_back(spline_.to_json());
2630 json.push_back(boundary_.to_json());
2631 return json;
2632 }
2633
2636 const std::function<std::array<typename Spline::value_type,
2637 Spline::geoDim()>(
2638 const std::array<typename Spline::value_type, Spline::parDim()> &)>
2639 transformation) {
2640 spline_.transform(transformation);
2641 return *this;
2642 }
2643
2644private:
2647 template <functionspace comp = functionspace::interior,
2648 deriv deriv = deriv::func, bool memory_optimized = false,
2649 std::size_t... Is, typename... Xi>
2650 inline auto eval_(std::index_sequence<Is...>,
2651 const std::tuple<Xi...> &xi) const {
2652 if constexpr (comp == functionspace::interior)
2653 return std::tuple(
2654 spline_.template eval<deriv, memory_optimized>(std::get<Is>(xi))...);
2655 else if constexpr (comp == functionspace::boundary)
2656 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2657 std::get<Is>(xi))...);
2658 }
2659
2660 template <functionspace comp = functionspace::interior,
2661 deriv deriv = deriv::func, bool memory_optimized = false,
2662 std::size_t... Is, typename... Xi, typename... Knot_Indices>
2663 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
2664 const std::tuple<Knot_Indices...> &knot_indices) const {
2665 if constexpr (comp == functionspace::interior)
2666 return std::tuple(spline_.template eval<deriv, memory_optimized>(
2667 std::get<Is>(xi), std::get<Is>(knot_indices))...);
2668 else if constexpr (comp == functionspace::boundary)
2669 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2670 std::get<Is>(xi), std::get<Is>(knot_indices))...);
2671 }
2672
2673 template <functionspace comp = functionspace::interior,
2674 deriv deriv = deriv::func, bool memory_optimized = false,
2675 std::size_t... Is, typename... Xi, typename... Knot_Indices,
2676 typename... Coeff_Indices>
2677 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
2678 const std::tuple<Knot_Indices...> &knot_indices,
2679 const std::tuple<Coeff_Indices...> &coeff_indices) const {
2680 if constexpr (comp == functionspace::interior)
2681 return std::tuple(spline_.template eval<deriv, memory_optimized>(
2682 std::get<Is>(xi), std::get<Is>(knot_indices),
2683 std::get<Is>(coeff_indices))...);
2684 else if constexpr (comp == functionspace::boundary)
2685 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2686 std::get<Is>(xi), std::get<Is>(knot_indices),
2687 std::get<Is>(coeff_indices))...);
2688 }
2690
2691public:
2693 template <functionspace comp = functionspace::interior,
2694 deriv deriv = deriv::func, bool memory_optimized = false,
2695 typename Arg, typename... Args>
2696 inline auto eval(const Arg &arg, const Args &...args) const {
2697 if constexpr (comp == functionspace::interior)
2698 if constexpr (utils::is_tuple_v<Arg>)
2699 return eval_<comp, deriv, memory_optimized>(
2700 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
2701 else
2702 return spline_.template eval<deriv, memory_optimized>(arg, args...);
2703 else if constexpr (comp == functionspace::boundary) {
2704 if constexpr (utils::is_tuple_of_tuples_v<Arg>)
2705 return eval_<comp, deriv, memory_optimized>(
2706 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
2707 else
2708 return boundary_.template eval<deriv, memory_optimized>(arg, args...);
2709 }
2710 }
2711
2714 template <functionspace comp = functionspace::interior, typename... Args>
2715 inline auto eval_from_precomputed(const Args &...args) const {
2716 if constexpr (comp == functionspace::interior)
2717 return spline_.eval_from_precomputed(args...);
2718 else if constexpr (comp == functionspace::boundary)
2719 return boundary_.eval_from_precomputed(args...);
2720 }
2721
2722private:
2724 template <functionspace comp = functionspace::interior, std::size_t... Is,
2725 typename Xi>
2726 inline auto find_knot_indices_(std::index_sequence<Is...>,
2727 const Xi &xi) const {
2728 if constexpr (comp == functionspace::interior)
2729 return std::tuple(spline_.find_knot_indices(std::get<Is>(xi))...);
2730 else
2731 return std::tuple(boundary_.find_knot_indices(std::get<Is>(xi))...);
2732 }
2733
2734public:
2736 template <functionspace comp = functionspace::interior, typename Xi>
2737 inline auto find_knot_indices(const Xi &xi) const {
2738 if constexpr (comp == functionspace::interior)
2739 if constexpr (utils::is_tuple_v<Xi>)
2740 return find_knot_indices_<comp>(
2741 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
2742 else
2743 return spline_.find_knot_indices(xi);
2744 else if constexpr (comp == functionspace::boundary) {
2745 if constexpr (utils::is_tuple_of_tuples_v<Xi>)
2746 return find_knot_indices_<comp>(
2747 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
2748 else
2749 return boundary_.find_knot_indices(xi);
2750 }
2751 }
2752
2755 template <functionspace comp = functionspace::interior,
2756 deriv deriv = deriv::func, bool memory_optimized = false,
2757 typename... Args>
2758 inline auto eval_basfunc(const Args &...args) const {
2759 if constexpr (comp == functionspace::interior)
2760 return spline_.template eval_basfunc<deriv, memory_optimized>(args...);
2761 else if constexpr (comp == functionspace::boundary)
2762 return boundary_.template eval_basfunc<deriv, memory_optimized>(args...);
2763 }
2764
2765private:
2768 template <functionspace comp = functionspace::interior,
2769 bool memory_optimized = false, std::size_t... Is,
2770 typename Knot_Indices>
2771 inline auto find_coeff_indices_(std::index_sequence<Is...>,
2772 const Knot_Indices &knot_indices) const {
2773 if constexpr (comp == functionspace::interior)
2774 return std::tuple(spline_.template find_coeff_indices<memory_optimized>(
2775 std::get<Is>(knot_indices))...);
2776 else
2777 return std::tuple(boundary_.template find_coeff_indices<memory_optimized>(
2778 std::get<Is>(knot_indices))...);
2779 }
2780
2781public:
2784 template <functionspace comp = functionspace::interior,
2785 bool memory_optimized = false, typename Knot_Indices>
2786 inline auto find_coeff_indices(const Knot_Indices &knot_indices) const {
2787 if constexpr (comp == functionspace::interior)
2788 if constexpr (utils::is_tuple_v<Knot_Indices>)
2789 return find_coeff_indices_<comp, memory_optimized>(
2790 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
2791 knot_indices);
2792 else
2793 return spline_.template find_coeff_indices<memory_optimized>(
2794 knot_indices);
2795 else if constexpr (comp == functionspace::boundary) {
2796 if constexpr (utils::is_tuple_of_tuples_v<Knot_Indices>)
2797 return find_coeff_indices_<comp, memory_optimized>(
2798 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
2799 knot_indices);
2800 else
2801 return boundary_.template find_coeff_indices<memory_optimized>(
2802 knot_indices);
2803 }
2804 }
2805
2808 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
2809 spline_.uniform_refine(numRefine, dimRefine);
2810 boundary_.uniform_refine(numRefine, dimRefine);
2811 return *this;
2812 }
2813
2816 template <typename real_t> inline auto to(Options<real_t> options) const {
2817 return FunctionSpace<
2818 typename spline_type::template real_derived_self_type<real_t>,
2819 typename boundary_type::template real_derived_self_type<real_t>>(
2820 spline_.to(options), boundary_.to(options));
2821 }
2822
2825 inline auto to(torch::Device device) const {
2826 return FunctionSpace(spline_.to(device), boundary_.to(device));
2827 }
2828
2830 template <typename real_t> inline auto to() const {
2831 return FunctionSpace<
2832 typename spline_type::template real_derived_self_type<real_t>,
2833 typename boundary_type::template real_derived_self_type<real_t>>(
2834 spline_.template to<real_t>(), boundary_.template to<real_t>());
2835 }
2836
2838 inline auto scale(value_type s, int dim = -1) {
2839 spline_.scale(s, dim);
2840 boundary_.from_full_tensor(spline_.as_tensor());
2841 return *this;
2842 }
2843
2845 template <size_t N> inline auto scale(std::array<value_type, N> v) {
2846 spline_.scale(v);
2847 boundary_.from_full_tensor(spline_.as_tensor());
2848 return *this;
2849 }
2850
2852 template <size_t N> inline auto translate(std::array<value_type, N> v) {
2853 spline_.translate(v);
2854 boundary_.from_full_tensor(spline_.as_tensor());
2855 return *this;
2856 }
2857
2859 inline auto rotate(value_type angle) {
2860 spline_.rotate(angle);
2861 boundary_.from_full_tensor(spline_.as_tensor());
2862 return *this;
2863 }
2864
2866 inline auto rotate(std::array<value_type, 3> angle) {
2867 spline_.rotate(angle);
2868 boundary_.from_full_tensor(spline_.as_tensor());
2869 return *this;
2870 }
2871
2874 inline torch::serialize::OutputArchive &
2875 write(torch::serialize::OutputArchive &archive,
2876 const std::string &key = "functionspace") const {
2877 spline_.write(archive, key);
2878 boundary_.write(archive, key);
2879 return archive;
2880 }
2881
2884 inline torch::serialize::InputArchive &
2885 read(torch::serialize::InputArchive &archive,
2886 const std::string &key = "functionspace") {
2887 spline_.read(archive, key);
2888 boundary_.read(archive, key);
2889 return archive;
2890 }
2891
2893 inline virtual void
2894 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
2895 os << name() << "(\nspline = ";
2896 spline_.pretty_print(os);
2897 os << "\nboundary = ";
2898 boundary_.pretty_print(os);
2899 os << "\n)";
2900 }
2901
2902#define GENERATE_EXPR_MACRO(r, data, name) \
2903private: \
2904 template <functionspace comp = functionspace::interior, \
2905 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
2906 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2907 const std::tuple<Xi...> &xi) const { \
2908 if constexpr (comp == functionspace::interior) \
2909 return std::tuple( \
2910 spline_.template name<memory_optimized>(std::get<Is>(xi))...); \
2911 else if constexpr (comp == functionspace::boundary) \
2912 return std::tuple( \
2913 boundary_.template name<memory_optimized>(std::get<Is>(xi))...); \
2914 } \
2915 \
2916 template <functionspace comp = functionspace::interior, \
2917 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2918 typename... Knot_Indices> \
2919 inline auto BOOST_PP_CAT(name, _all_)( \
2920 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2921 const std::tuple<Knot_Indices...> &knot_indices) const { \
2922 if constexpr (comp == functionspace::interior) \
2923 return std::tuple(spline_.template name<memory_optimized>( \
2924 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2925 else if constexpr (comp == functionspace::boundary) \
2926 return std::tuple(boundary_.template name<memory_optimized>( \
2927 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2928 } \
2929 \
2930 template <functionspace comp = functionspace::interior, \
2931 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2932 typename... Knot_Indices, typename... Coeff_Indices> \
2933 inline auto BOOST_PP_CAT(name, _all_)( \
2934 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2935 const std::tuple<Knot_Indices...> &knot_indices, \
2936 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
2937 if constexpr (comp == functionspace::interior) \
2938 return std::tuple(spline_.template name<memory_optimized>( \
2939 std::get<Is>(xi), std::get<Is>(knot_indices), \
2940 std::get<Is>(coeff_indices))...); \
2941 else if constexpr (comp == functionspace::boundary) \
2942 return std::tuple(boundary_.template name<memory_optimized>( \
2943 std::get<Is>(xi), std::get<Is>(knot_indices), \
2944 std::get<Is>(coeff_indices))...); \
2945 } \
2946 \
2947public: \
2948 template <functionspace comp = functionspace::interior, \
2949 bool memory_optimized = false, typename Arg, typename... Args> \
2950 inline auto name(const Arg &arg, const Args &...args) const { \
2951 if constexpr (comp == functionspace::interior) \
2952 if constexpr (utils::is_tuple_v<Arg>) \
2953 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2954 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
2955 else \
2956 return spline_.template name<memory_optimized>(arg, args...); \
2957 else if constexpr (comp == functionspace::boundary) { \
2958 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
2959 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2960 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
2961 else \
2962 return boundary_.template name<memory_optimized>(arg, args...); \
2963 } \
2964 }
2965
2968 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
2970#undef GENERATE_EXPR_MACRO
2971
2972#define GENERATE_IEXPR_MACRO(r, data, name) \
2973private: \
2974 template <functionspace comp = functionspace::interior, \
2975 bool memory_optimized = false, std::size_t... Is, \
2976 typename Geometry, typename... Xi> \
2977 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2978 const Geometry &G, \
2979 const std::tuple<Xi...> &xi) const { \
2980 if constexpr (comp == functionspace::interior) \
2981 return std::tuple(spline_.template name<memory_optimized>( \
2982 G.space(), std::get<Is>(xi))...); \
2983 else if constexpr (comp == functionspace::boundary) \
2984 return std::tuple(boundary_.template name<memory_optimized>( \
2985 static_cast<typename Geometry::boundary_type::boundary_type>( \
2986 G.boundary().coeffs()), \
2987 std::get<Is>(xi))...); \
2988 } \
2989 \
2990 template <functionspace comp = functionspace::interior, \
2991 bool memory_optimized = false, std::size_t... Is, \
2992 typename Geometry, typename... Xi, typename... Knot_Indices, \
2993 typename... Knot_Indices_G> \
2994 inline auto BOOST_PP_CAT(name, _all_)( \
2995 std::index_sequence<Is...>, const Geometry &G, \
2996 const std::tuple<Xi...> &xi, \
2997 const std::tuple<Knot_Indices...> &knot_indices, \
2998 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
2999 if constexpr (comp == functionspace::interior) \
3000 return std::tuple(spline_.template name<memory_optimized>( \
3001 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
3002 std::get<Is>(knot_indices_G))...); \
3003 else if constexpr (comp == functionspace::boundary) \
3004 return std::tuple(boundary_.template name<memory_optimized>( \
3005 static_cast<typename Geometry::boundary_type::boundary_type>( \
3006 G.boundary().coeffs()), \
3007 std::get<Is>(xi), std::get<Is>(knot_indices), \
3008 std::get<Is>(knot_indices_G))...); \
3009 } \
3010 \
3011 template <functionspace comp = functionspace::interior, \
3012 bool memory_optimized = false, std::size_t... Is, \
3013 typename Geometry, typename... Xi, typename... Knot_Indices, \
3014 typename... Coeff_Indices, typename... Knot_Indices_G, \
3015 typename... Coeff_Indices_G> \
3016 inline auto BOOST_PP_CAT(name, _all_)( \
3017 std::index_sequence<Is...>, const Geometry &G, \
3018 const std::tuple<Xi...> &xi, \
3019 const std::tuple<Knot_Indices...> &knot_indices, \
3020 const std::tuple<Coeff_Indices...> &coeff_indices, \
3021 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
3022 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
3023 if constexpr (comp == functionspace::interior) \
3024 return std::tuple(spline_.template name<memory_optimized>( \
3025 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
3026 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3027 std::get<Is>(coeff_indices_G))...); \
3028 else if constexpr (comp == functionspace::boundary) \
3029 return std::tuple(boundary_.template name<memory_optimized>( \
3030 static_cast<typename Geometry::boundary_type::boundary_type>( \
3031 G.boundary().coeffs()), \
3032 std::get<Is>(xi), std::get<Is>(knot_indices), \
3033 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3034 std::get<Is>(coeff_indices_G))...); \
3035 } \
3036 \
3037public: \
3038 template <functionspace comp = functionspace::interior, \
3039 bool memory_optimized = false, typename Geometry, typename Arg, \
3040 typename... Args> \
3041 inline auto name(const Geometry &G, const Arg &arg, const Args &...args) \
3042 const { \
3043 if constexpr (comp == functionspace::interior) { \
3044 if constexpr (utils::is_tuple_v<Arg>) \
3045 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3046 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3047 args...); \
3048 else \
3049 return spline_.template name<memory_optimized>(G.space(), arg, \
3050 args...); \
3051 } else if constexpr (comp == functionspace::boundary) { \
3052 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
3053 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3054 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3055 args...); \
3056 else \
3057 return boundary_.template name<memory_optimized>( \
3058 static_cast<typename Geometry::boundary_type::boundary_type>( \
3059 G.boundary().coeffs()), \
3060 arg, args...); \
3061 } \
3062 }
3063
3066 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
3068#undef GENERATE_IEXPR_MACRO
3069};
3070
3072template <typename... Args> struct FunctionSpace_trait;
3073
3075template <typename Spline> struct FunctionSpace_trait<Spline> {
3077};
3078
3080template <typename Spline, typename Boundary>
3084
3086template <typename... Splines>
3087struct FunctionSpace_trait<std::tuple<Splines...>> {
3090};
3091
3093template <typename... Splines, typename... Boundaries>
3094struct FunctionSpace_trait<std::tuple<Splines...>, std::tuple<Boundaries...>> {
3096 utils::tuple_cat_t<Boundaries...>>;
3097};
3098
3100template <typename Spline, typename Boundary>
3104
3106template <typename... Splines, typename... Boundaries>
3107struct FunctionSpace_trait<std::tuple<FunctionSpace<Splines, Boundaries>...>> {
3108 using type =
3109 typename FunctionSpace_trait<utils::tuple_cat_t<Splines...>,
3110 utils::tuple_cat_t<Boundaries...>>::type;
3111};
3112
3113} // namespace detail
3114
3116 template<typename T>
3117 concept FunctionSpaceType = std::is_base_of_v<detail::FunctionSpaceType, T>;
3118
3120template <typename... Args>
3121using FunctionSpace = typename detail::FunctionSpace_trait<Args...>::type;
3122
3124template <typename Splines, typename Boundaries>
3125inline std::ostream &operator<<(std::ostream &os,
3127 obj.pretty_print(os);
3128 return os;
3129}
3130
3148template <typename Spline> using S = FunctionSpace<Spline>;
3149
3151template <typename Spline, short_t = Spline::parDim()> class TH;
3152
3162template <typename Spline>
3163class TH<Spline, 1>
3164 : public FunctionSpace<
3165 std::tuple<typename Spline::template derived_self_type<
3166 typename Spline::value_type, Spline::geoDim(),
3167 Spline::degree(0) + 1>,
3168 typename Spline::template derived_self_type<
3169 typename Spline::value_type, Spline::geoDim(),
3170 Spline::degree(0)>>> {
3171public:
3173 using Base = FunctionSpace<std::tuple<
3174 typename Spline::template derived_self_type<
3175 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3176 typename Spline::template derived_self_type<
3177 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3178
3181 TH(const std::array<int64_t, 1> &ncoeffs, enum init init = init::greville,
3184 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {
3185 static_assert(Spline::is_nonuniform(),
3186 "TH function space requires non-uniform splines");
3187 Base::template space<0>().reduce_continuity();
3188 }
3189
3190 TH(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3191 enum init init = init::greville,
3194 : Base({{kv[0].front + kv[0] + kv[0].back(), kv[1]}}, kv, init, options) {
3195 static_assert(Spline::is_nonuniform(),
3196 "TH function space requires non-uniform splines");
3197 Base::template space<0>().reduce_continuity();
3198 }
3200
3202};
3203
3215template <typename Spline>
3216class TH<Spline, 2>
3217 : public FunctionSpace<
3218 std::tuple<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) + 1, Spline::degree(1) + 1>,
3224 typename Spline::template derived_self_type<
3225 typename Spline::value_type, Spline::geoDim(),
3226 Spline::degree(0), Spline::degree(1)>>> {
3227public:
3230 std::tuple<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) + 1, Spline::degree(1) + 1>,
3236 typename Spline::template derived_self_type<
3237 typename Spline::value_type, Spline::geoDim(),
3238 Spline::degree(0), Spline::degree(1)>>>;
3239
3242 TH(const std::array<int64_t, 2> &ncoeffs, enum init init = init::greville,
3245 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
3246 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
3247 static_assert(Spline::is_nonuniform(),
3248 "TH function space requires non-uniform splines");
3249 Base::template space<0>().reduce_continuity();
3250 Base::template space<1>().reduce_continuity();
3251 }
3252
3253 TH(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3254 enum init init = init::greville,
3257 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3258 kv[1].front() + kv[1] + kv[1].back()}},
3259 {{kv[0].front() + kv[0] + kv[0].back(),
3260 kv[1].front() + kv[1] + kv[1].back()}},
3261 kv, init, options) {
3262 static_assert(Spline::is_nonuniform(),
3263 "TH function space requires non-uniform splines");
3264 Base::template space<0>().reduce_continuity();
3265 Base::template space<1>().reduce_continuity();
3266 }
3268
3270};
3271
3284template <typename Spline>
3285class TH<Spline, 3>
3286 : public FunctionSpace<std::tuple<
3287 typename Spline::template derived_self_type<
3288 typename Spline::value_type, Spline::geoDim(),
3289 Spline::degree(0) + 1, Spline::degree(1) + 1,
3290 Spline::degree(2) + 1>,
3291 typename Spline::template derived_self_type<
3292 typename Spline::value_type, Spline::geoDim(),
3293 Spline::degree(0) + 1, Spline::degree(1) + 1,
3294 Spline::degree(2) + 1>,
3295 typename Spline::template derived_self_type<
3296 typename Spline::value_type, Spline::geoDim(),
3297 Spline::degree(0) + 1, Spline::degree(1) + 1,
3298 Spline::degree(2) + 1>,
3299 typename Spline::template derived_self_type<
3300 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3301 Spline::degree(1), Spline::degree(2)>>> {
3302public:
3304 using Base = FunctionSpace<std::tuple<
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) + 1,
3313 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3314 typename Spline::template derived_self_type<
3315 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3316 Spline::degree(1), Spline::degree(2)>>>;
3317
3320 TH(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
3323 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3324 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3325 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
3326 options) {
3327 static_assert(Spline::is_nonuniform(),
3328 "TH function space requires non-uniform splines");
3329 Base::template space<0>().reduce_continuity();
3330 Base::template space<1>().reduce_continuity();
3331 Base::template space<2>().reduce_continuity();
3332 }
3333
3334 TH(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3335 enum init init = init::greville,
3338 : Base({{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[0].front() + kv[0] + kv[0].back(),
3345 kv[1].front() + kv[1] + kv[1].back(),
3346 kv[2].front() + kv[2] + kv[2].back()}},
3347 kv, init, options) {
3348 static_assert(Spline::is_nonuniform(),
3349 "TH function space requires non-uniform splines");
3350 Base::template space<0>().reduce_continuity();
3351 Base::template space<1>().reduce_continuity();
3352 Base::template space<2>().reduce_continuity();
3353 }
3355
3357};
3358
3372template <typename Spline>
3373class TH<Spline, 4>
3374 : public FunctionSpace<std::tuple<
3375 typename Spline::template derived_self_type<
3376 typename Spline::value_type, Spline::geoDim(),
3377 Spline::degree(0) + 1, Spline::degree(1) + 1,
3378 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3379 typename Spline::template derived_self_type<
3380 typename Spline::value_type, Spline::geoDim(),
3381 Spline::degree(0) + 1, Spline::degree(1) + 1,
3382 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3383 typename Spline::template derived_self_type<
3384 typename Spline::value_type, Spline::geoDim(),
3385 Spline::degree(0) + 1, Spline::degree(1) + 1,
3386 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3387 typename Spline::template derived_self_type<
3388 typename Spline::value_type, Spline::geoDim(),
3389 Spline::degree(0) + 1, Spline::degree(1) + 1,
3390 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3391 typename Spline::template derived_self_type<
3392 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3393 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3394public:
3396 using Base = FunctionSpace<std::tuple<
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) + 1,
3408 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3409 typename Spline::template derived_self_type<
3410 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3411 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3412
3415 TH(const std::array<int64_t, 4> &ncoeffs, enum init init = init::greville,
3418 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3419 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3420 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3421 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
3422 init, options) {
3423 static_assert(Spline::is_nonuniform(),
3424 "TH function space requires non-uniform splines");
3425 Base::template space<0>().reduce_continuity();
3426 Base::template space<1>().reduce_continuity();
3427 Base::template space<2>().reduce_continuity();
3428 Base::template space<3>().reduce_continuity();
3429 }
3430
3431 TH(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
3432 enum init init = init::greville,
3435 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3436 kv[1].front() + kv[1] + kv[1].back(),
3437 kv[2].front() + kv[2] + kv[2].back(),
3438 kv[3].front() + kv[3] + kv[3].back()}},
3439 {{kv[0].front() + kv[0] + kv[0].back(),
3440 kv[1].front() + kv[1] + kv[1].back(),
3441 kv[2].front() + kv[2] + kv[2].back(),
3442 kv[3].front() + kv[3] + kv[3].back()}},
3443 {{kv[0].front() + kv[0] + kv[0].back(),
3444 kv[1].front() + kv[1] + kv[1].back(),
3445 kv[2].front() + kv[2] + kv[2].back(),
3446 kv[3].front() + kv[3] + kv[3].back()}},
3447 {{kv[0].front() + kv[0] + kv[0].back(),
3448 kv[1].front() + kv[1] + kv[1].back(),
3449 kv[2].front() + kv[2] + kv[2].back(),
3450 kv[3].front() + kv[3] + kv[3].back()}},
3451 kv, init, options) {
3452 static_assert(Spline::is_nonuniform(),
3453 "TH function space requires non-uniform splines");
3454 Base::template space<0>().reduce_continuity();
3455 Base::template space<1>().reduce_continuity();
3456 Base::template space<2>().reduce_continuity();
3457 Base::template space<3>().reduce_continuity();
3458 }
3460
3462};
3463
3465
3467template <typename Spline, short_t = Spline::parDim()> class NE;
3468
3478template <typename Spline>
3479class NE<Spline, 1>
3480 : public FunctionSpace<
3481 std::tuple<typename Spline::template derived_self_type<
3482 typename Spline::value_type, Spline::geoDim(),
3483 Spline::degree(0) + 1>,
3484 typename Spline::template derived_self_type<
3485 typename Spline::value_type, Spline::geoDim(),
3486 Spline::degree(0)>>> {
3487public:
3489 using Base = FunctionSpace<std::tuple<
3490 typename Spline::template derived_self_type<
3491 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3492 typename Spline::template derived_self_type<
3493 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3494
3497 NE(const std::array<int64_t, 1> &ncoeffs, enum init init = init::greville,
3500 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
3501
3502 NE(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3503 enum init init = init::greville,
3506 : Base(kv, kv, init, options) {
3507 static_assert(Spline::is_nonuniform(),
3508 "Constructor only available for non-uniform splines");
3509 }
3511
3513};
3514
3525template <typename Spline>
3526class NE<Spline, 2>
3527 : public FunctionSpace<
3528 std::tuple<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) + 1, Spline::degree(1) + 1>,
3534 typename Spline::template derived_self_type<
3535 typename Spline::value_type, Spline::geoDim(),
3536 Spline::degree(0), Spline::degree(1)>>> {
3537public:
3540 std::tuple<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) + 1, Spline::degree(1) + 1>,
3546 typename Spline::template derived_self_type<
3547 typename Spline::value_type, Spline::geoDim(),
3548 Spline::degree(0), Spline::degree(1)>>>;
3549
3552 NE(const std::array<int64_t, 2> &ncoeffs, enum init init = init::greville,
3555 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
3556 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
3557 static_assert(Spline::is_nonuniform(),
3558 "NE function space requires non-uniform splines");
3559 Base::template space<0>().reduce_continuity(1, 1);
3560 Base::template space<1>().reduce_continuity(1, 0);
3561 }
3562
3563 NE(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3564 enum init init = init::greville,
3567 : Base(kv, kv, kv, init, options) {
3568 static_assert(Spline::is_nonuniform(),
3569 "NE function space requires non-uniform splines");
3570 Base::template space<0>().reduce_continuity(1, 1);
3571 Base::template space<1>().reduce_continuity(1, 0);
3572 }
3574
3576};
3577
3590template <typename Spline>
3591class NE<Spline, 3>
3592 : public FunctionSpace<std::tuple<
3593 typename Spline::template derived_self_type<
3594 typename Spline::value_type, Spline::geoDim(),
3595 Spline::degree(0) + 1, Spline::degree(1) + 1,
3596 Spline::degree(2) + 1>,
3597 typename Spline::template derived_self_type<
3598 typename Spline::value_type, Spline::geoDim(),
3599 Spline::degree(0) + 1, Spline::degree(1) + 1,
3600 Spline::degree(2) + 1>,
3601 typename Spline::template derived_self_type<
3602 typename Spline::value_type, Spline::geoDim(),
3603 Spline::degree(0) + 1, Spline::degree(1) + 1,
3604 Spline::degree(2) + 1>,
3605 typename Spline::template derived_self_type<
3606 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3607 Spline::degree(1), Spline::degree(2)>>> {
3608public:
3610 using Base = FunctionSpace<std::tuple<
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) + 1,
3619 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3620 typename Spline::template derived_self_type<
3621 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3622 Spline::degree(1), Spline::degree(2)>>>;
3623
3626 NE(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
3629 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3630 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3631 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
3632 options) {
3633 static_assert(Spline::is_nonuniform(),
3634 "NE function space requires non-uniform splines");
3635 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
3636 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
3637 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
3638 }
3639
3640 NE(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3641 enum init init = init::greville,
3644 : Base(kv, kv, kv, kv, init, options) {
3645 static_assert(Spline::is_nonuniform(),
3646 "NE function space requires non-uniform splines");
3647 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
3648 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
3649 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
3650 }
3652
3654};
3655
3669template <typename Spline>
3670class NE<Spline, 4>
3671 : public FunctionSpace<std::tuple<
3672 typename Spline::template derived_self_type<
3673 typename Spline::value_type, Spline::geoDim(),
3674 Spline::degree(0) + 1, Spline::degree(1) + 1,
3675 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3676 typename Spline::template derived_self_type<
3677 typename Spline::value_type, Spline::geoDim(),
3678 Spline::degree(0) + 1, Spline::degree(1) + 1,
3679 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3680 typename Spline::template derived_self_type<
3681 typename Spline::value_type, Spline::geoDim(),
3682 Spline::degree(0) + 1, Spline::degree(1) + 1,
3683 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3684 typename Spline::template derived_self_type<
3685 typename Spline::value_type, Spline::geoDim(),
3686 Spline::degree(0) + 1, Spline::degree(1) + 1,
3687 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3688 typename Spline::template derived_self_type<
3689 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3690 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3691public:
3693 using Base = FunctionSpace<std::tuple<
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) + 1,
3705 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3706 typename Spline::template derived_self_type<
3707 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3708 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3709
3712 NE(const std::array<int64_t, 4> &ncoeffs, enum init init = init::greville,
3715 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3716 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3717 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3718 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
3719 init, options) {
3720 static_assert(Spline::is_nonuniform(),
3721 "NE function space requires non-uniform splines");
3722 Base::template space<0>()
3723 .reduce_continuity(1, 1)
3724 .reduce_continuity(1, 2)
3725 .reduce_continuity(1, 3);
3726 Base::template space<1>()
3727 .reduce_continuity(1, 0)
3728 .reduce_continuity(1, 2)
3729 .reduce_continuity(1, 3);
3730 Base::template space<2>()
3731 .reduce_continuity(1, 0)
3732 .reduce_continuity(1, 1)
3733 .reduce_continuity(1, 3);
3734 Base::template space<3>()
3735 .reduce_continuity(1, 0)
3736 .reduce_continuity(1, 1)
3737 .reduce_continuity(1, 2);
3738 }
3739
3740 NE(const std::array<std::vector<typename Spline::value_type>,
3741 Spline::parDim()> &kv,
3742 enum init init = init::greville,
3745 : Base(kv, kv, kv, kv, kv, init, options) {
3746 static_assert(Spline::is_nonuniform(),
3747 "NE function space requires non-uniform splines");
3748 Base::template space<0>()
3749 .reduce_continuity(1, 1)
3750 .reduce_continuity(1, 2)
3751 .reduce_continuity(1, 3);
3752 Base::template space<1>()
3753 .reduce_continuity(1, 0)
3754 .reduce_continuity(1, 2)
3755 .reduce_continuity(1, 3);
3756 Base::template space<2>()
3757 .reduce_continuity(1, 0)
3758 .reduce_continuity(1, 1)
3759 .reduce_continuity(1, 3);
3760 Base::template space<3>()
3761 .reduce_continuity(1, 0)
3762 .reduce_continuity(1, 1)
3763 .reduce_continuity(1, 2);
3764 }
3766
3768};
3769
3771
3773template <typename Spline, short_t = Spline::parDim()> class RT;
3774
3784template <typename Spline>
3785class RT<Spline, 1>
3786 : public FunctionSpace<
3787 std::tuple<typename Spline::template derived_self_type<
3788 typename Spline::value_type, Spline::geoDim(),
3789 Spline::degree(0) + 1>,
3790 typename Spline::template derived_self_type<
3791 typename Spline::value_type, Spline::geoDim(),
3792 Spline::degree(0)>>> {
3793public:
3795 using Base = FunctionSpace<std::tuple<
3796 typename Spline::template derived_self_type<
3797 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3798 typename Spline::template derived_self_type<
3799 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3800
3803 RT(const std::array<int64_t, 1> &ncoeffs, enum init init = init::greville,
3806 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
3807
3808 RT(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3809 enum init init = init::greville,
3812 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}}, kv, init,
3813 options) {
3814 static_assert(Spline::is_nonuniform(),
3815 "Constructor only available for non-uniform splines");
3816 }
3818
3820};
3821
3833template <typename Spline>
3834class RT<Spline, 2>
3835 : public FunctionSpace<
3836 std::tuple<typename Spline::template derived_self_type<
3837 typename Spline::value_type, Spline::geoDim(),
3838 Spline::degree(0) + 1, Spline::degree(1)>,
3839 typename Spline::template derived_self_type<
3840 typename Spline::value_type, Spline::geoDim(),
3841 Spline::degree(0), Spline::degree(1) + 1>,
3842 typename Spline::template derived_self_type<
3843 typename Spline::value_type, Spline::geoDim(),
3844 Spline::degree(0), Spline::degree(1)>>> {
3845public:
3847 std::tuple<typename Spline::template derived_self_type<
3848 typename Spline::value_type, Spline::geoDim(),
3849 Spline::degree(0) + 1, Spline::degree(1)>,
3850 typename Spline::template derived_self_type<
3851 typename Spline::value_type, Spline::geoDim(),
3852 Spline::degree(0), Spline::degree(1) + 1>,
3853 typename Spline::template derived_self_type<
3854 typename Spline::value_type, Spline::geoDim(),
3855 Spline::degree(0), Spline::degree(1)>>>;
3856
3859 RT(const std::array<int64_t, 2> &ncoeffs, enum init init = init::greville,
3862 : Base(ncoeffs + utils::to_array(1_i64, 0_i64),
3863 ncoeffs + utils::to_array(0_i64, 1_i64), ncoeffs, init, options) {}
3864
3865 RT(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3866 enum init init = init::greville,
3869 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}},
3870 {{kv[0], kv[1].front() + kv[1] + kv[1].back()}}, kv, init,
3871 options) {
3872 static_assert(Spline::is_nonuniform(),
3873 "Constructor only available for non-uniform splines");
3874 }
3876
3878};
3879
3891template <typename Spline>
3892class RT<Spline, 3>
3893 : public FunctionSpace<std::tuple<
3894 typename Spline::template derived_self_type<
3895 typename Spline::value_type, Spline::geoDim(),
3896 Spline::degree(0) + 1, Spline::degree(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) + 1, Spline::degree(2)>,
3900 typename Spline::template derived_self_type<
3901 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3902 Spline::degree(1), Spline::degree(2) + 1>,
3903 typename Spline::template derived_self_type<
3904 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3905 Spline::degree(1), Spline::degree(2)>>> {
3906public:
3908 using Base = FunctionSpace<std::tuple<
3909 typename Spline::template derived_self_type<
3910 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3911 Spline::degree(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) + 1, Spline::degree(2)>,
3915 typename Spline::template derived_self_type<
3916 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3917 Spline::degree(1), Spline::degree(2) + 1>,
3918 typename Spline::template derived_self_type<
3919 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3920 Spline::degree(1), Spline::degree(2)>>>;
3921
3924 RT(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
3927 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
3928 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
3929 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), ncoeffs, init,
3930 options) {}
3931
3932 RT(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3933 enum init init = init::greville,
3936 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
3937 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
3938 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, kv, init,
3939 options) {
3940 static_assert(Spline::is_nonuniform(),
3941 "Constructor only available for non-uniform splines");
3942 }
3944
3946};
3947
3961template <typename Spline>
3962class RT<Spline, 4>
3963 : public FunctionSpace<std::tuple<
3964 typename Spline::template derived_self_type<
3965 typename Spline::value_type, Spline::geoDim(),
3966 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2),
3967 Spline::degree(3)>,
3968 typename Spline::template derived_self_type<
3969 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3970 Spline::degree(1) + 1, Spline::degree(2), 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) + 1, Spline::degree(3)>,
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) + 1>,
3977 typename Spline::template derived_self_type<
3978 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3979 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3980public:
3982 using Base = FunctionSpace<std::tuple<
3983 typename Spline::template derived_self_type<
3984 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3985 Spline::degree(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) + 1, Spline::degree(2), 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) + 1, Spline::degree(3)>,
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) + 1>,
3995 typename Spline::template derived_self_type<
3996 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3997 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3998
4001 RT(const std::array<int64_t, 4> &ncoeffs, enum init init = init::greville,
4004 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64, 0_i64),
4005 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64, 0_i64),
4006 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64, 0_i64),
4007 ncoeffs + utils::to_array(0_i64, 0_i64, 0_i64, 1_i64), ncoeffs,
4008 init, options) {}
4009
4010 RT(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
4011 enum init init = init::greville,
4014 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2], kv[3]}},
4015 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2], kv[3]}},
4016 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back(), kv[3]}},
4017 {{kv[0], kv[1], kv[2], kv[3].front() + kv[3] + kv[3].back()}}, kv,
4018 init, options) {
4019 static_assert(Spline::is_nonuniform(),
4020 "Constructor only available for non-uniform splines");
4021 }
4023
4025};
4026
4028
4030template <typename Spline, short_t = Spline::parDim()> class Hcurl;
4031
4043template <typename Spline>
4044class Hcurl<Spline, 3>
4045 : public FunctionSpace<std::tuple<
4046 typename Spline::template derived_self_type<
4047 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4048 Spline::degree(1) + 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), Spline::degree(2) + 1>,
4052 typename Spline::template derived_self_type<
4053 typename Spline::value_type, Spline::geoDim(),
4054 Spline::degree(0) + 1, Spline::degree(1) + 1,
4055 Spline::degree(2)>>> {
4056
4057public:
4059 using Base = FunctionSpace<std::tuple<
4060 typename Spline::template derived_self_type<
4061 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4062 Spline::degree(1) + 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), Spline::degree(2) + 1>,
4066 typename Spline::template derived_self_type<
4067 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4068 Spline::degree(1) + 1, Spline::degree(2)>>>;
4069
4072 Hcurl(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
4075 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
4076 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
4077 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), init, options) {}
4078
4079 Hcurl(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4080 enum init init = init::greville,
4083 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
4084 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
4085 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, init,
4086 options) {
4087 static_assert(Spline::is_nonuniform(),
4088 "Constructor only available for non-uniform splines");
4089 }
4092};
4093
4095
4097#undef IGANET_FUNCTIONSPACE_DEFAULT_OPS
4098
4099} // namespace iganet
#define GENERATE_IEXPR_MACRO(r, data, name)
Auto-generated functions.
Definition boundary.hpp:1777
#define GENERATE_EXPR_MACRO(r, data, name)
Definition boundary.hpp:1731
Multivariate B-splines.
#define GENERATE_EXPR_SEQ
Sequence of expression (parametric coordinates)
Definition bspline.hpp:41
#define GENERATE_IEXPR_SEQ
Sequence of expression (physical coordinates)
Definition bspline.hpp:47
Boundary (common high-level functionality)
Definition boundary.hpp:1124
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition boundary.hpp:1350
auto eval_from_precomputed(const std::tuple< Basfunc... > &basfunc, const std::tuple< Coeff_Indices... > &coeff_indices, const std::tuple< Numeval... > &numeval, const std::tuple< Sizes... > &sizes) const
Returns the value of the spline objects from precomputed basis function.
Definition boundary.hpp:1312
torch::serialize::InputArchive & read(torch::serialize::InputArchive &archive, const std::string &key="boundary")
Loads the boundary spline object from a torch::serialize::InputArchive object.
Definition boundary.hpp:1601
auto to(Options< real_t > options) const
Returns a copy of the boundary object with settings from options.
Definition boundary.hpp:1920
auto & from_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor.
Definition boundary.hpp:1202
torch::Tensor as_tensor() const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1147
auto & uniform_refine(int numRefine=1, int dim=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition boundary.hpp:1432
int64_t as_tensor_size() const
Returns the size of the single tensor representation of all spline objects.
Definition boundary.hpp:1168
torch::serialize::OutputArchive & write(torch::serialize::OutputArchive &archive, const std::string &key="boundary") const
Writes the boundary spline object into a torch::serialize::OutputArchive object.
Definition boundary.hpp:1570
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:4068
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:4072
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:4079
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:3493
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:3497
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:3502
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:3552
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:3548
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:3563
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:3626
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:3640
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:3622
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:3712
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:3740
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:3708
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:107
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:3799
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:3803
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:3808
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:3855
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:3859
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:3865
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:3920
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:3924
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:3932
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:3997
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:4001
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:4010
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:3181
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:3190
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:3177
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:3253
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:3238
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:3242
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:3320
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:3316
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:3334
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:3431
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:3415
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:3411
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:813
auto find_knot_indices(const utils::TensorArray< nspaces()> &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:635
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:654
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:583
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:260
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:1431
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:435
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:1860
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:793
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:889
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:963
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:251
pugi::xml_document to_xml(int id=0, std::string label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:373
auto & boundary() noexcept
Returns a non-constant reference to the -th boundary object.
Definition functionspace.hpp:166
auto boundingBox() const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:913
FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:172
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:1141
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:1021
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:762
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:1907
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:1845
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:196
torch::Tensor boundary_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:206
auto & space() noexcept
Returns a non-constant reference to the -th space.
Definition functionspace.hpp:153
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:740
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:865
std::tuple< Boundaries... > boundary_type
Boundary type.
Definition functionspace.hpp:71
FunctionSpace(std::tuple< Splines... > &&spline, std::tuple< Boundaries... > &&boundary)
Constructor.
Definition functionspace.hpp:130
std::common_type_t< typename Splines::value_type... > value_type
Value type.
Definition functionspace.hpp:62
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:561
virtual FunctionSpace & from_tensor(const torch::Tensor &tensor)
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:352
auto clone() const noexcept
Returns a clone of a subset of the function space.
Definition functionspace.hpp:175
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:1134
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:882
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:751
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:313
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:690
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:1603
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:325
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:476
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:1006
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:2066
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:334
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:731
auto scale_(std::index_sequence< Is... >, value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:822
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:670
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:363
auto boundingBox_(std::index_sequence< Is... >) const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:907
std::tuple< typename Boundaries::eval_type... > boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:74
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:407
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:1307
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:521
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:847
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:2047
auto eval(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects in the points xi
Definition functionspace.hpp:498
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:1089
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:2039
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:1465
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:1191
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:103
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:774
FunctionSpace(std::tuple< Splines... > &&spline)
Constructor.
Definition functionspace.hpp:120
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:1273
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:232
static constexpr short_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:142
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:784
std::tuple< utils::TensorArray< Splines::parDim()>... > eval_type
Spline evaluation type.
Definition functionspace.hpp:68
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:1438
static constexpr short_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:137
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:543
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:802
nlohmann::json to_json_(std::index_sequence< Is... >) const
Serialization to JSON.
Definition functionspace.hpp:416
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:699
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:241
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:900
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:1168
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:713
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:2089
const auto & boundary() const noexcept
Returns a constant reference to the -th boundary object.
Definition functionspace.hpp:159
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:95
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:382
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:1852
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:1035
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:223
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:1879
boundary_type boundary_
Boundaries.
Definition functionspace.hpp:81
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:1221
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:1446
const auto & space() const noexcept
Returns a constant reference to the -th function space.
Definition functionspace.hpp:147
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:1951
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:937
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:460
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:641
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:1360
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:277
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:391
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:830
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:620
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:508
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:1149
FunctionSpace(const std::tuple< Splines... > &spline)
Constructor.
Definition functionspace.hpp:115
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:948
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &tensor)
Sets the tuple of boundaries from a single-tensor representation.
Definition functionspace.hpp:346
torch::Tensor spaces_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:189
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &tensor)
Sets the tuple of spaces from a single-tensor representation.
Definition functionspace.hpp:304
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:1013
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:401
auto scale_(std::index_sequence< Is... >, std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:837
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:1505
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:2032
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:1057
auto translate_(std::index_sequence< Is... >, std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:854
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:608
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:445
std::tuple< Splines... > spline_type
Spline type.
Definition functionspace.hpp:65
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:2119
FunctionSpace(const std::tuple< Splines... > &spline, const std::tuple< Boundaries... > &boundary)
Constructor.
Definition functionspace.hpp:125
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:1288
auto rotate_(std::index_sequence< Is... >, value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:872
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:213
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:1280
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:922
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:1330
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:971
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:595
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:270
Function space.
Definition functionspace.hpp:2409
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:2808
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:2786
FunctionSpace(const Spline &spline)
Constructor.
Definition functionspace.hpp:2463
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:2845
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:2446
auto eval_basfunc(const Args &...args) const
Returns the values of the spline objects' basis functions in the points xi
Definition functionspace.hpp:2758
static constexpr short_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:2477
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:2565
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:2771
constexpr const boundary_type & boundary() const noexcept
Returns a constant reference to the -th boundary object.
Definition functionspace.hpp:2497
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the space.
Definition functionspace.hpp:2530
typename Boundary::eval_type boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:2425
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:2885
virtual int64_t boundary_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the boundary.
Definition functionspace.hpp:2556
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the boundary.
Definition functionspace.hpp:2535
constexpr boundary_type & boundary() noexcept
Returns a non-constant reference to the -th boundary object object.
Definition functionspace.hpp:2504
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:2838
Spline spline_type
Spline type.
Definition functionspace.hpp:2416
virtual int64_t spaces_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the space.
Definition functionspace.hpp:2550
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:2894
auto find_knot_indices(const Xi &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:2737
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:2650
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:2875
FunctionSpace(Spline &&spline)
Constructor.
Definition functionspace.hpp:2469
constexpr spline_type & space() noexcept
Returns a non-constant reference to the -th function space.
Definition functionspace.hpp:2490
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:2825
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:2614
auto eval(const Arg &arg, const Args &...args) const
Returns the values of the spline object in the points xi
Definition functionspace.hpp:2696
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:2677
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:2620
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:2866
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:2608
constexpr FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:2510
auto find_knot_indices_(std::index_sequence< Is... >, const Xi &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:2726
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:2859
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:2852
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:2816
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:2663
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:2579
pugi::xml_document to_xml(int id=0, std::string label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:2599
FunctionSpace(FunctionSpace &&)=default
Move constructor.
typename Spline::value_type value_type
Value type.
Definition functionspace.hpp:2413
boundary_type boundary_
Boundary.
Definition functionspace.hpp:2432
utils::TensorArray< Spline::parDim()> eval_type
Spline evaluation type.
Definition functionspace.hpp:2419
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &coeffs) noexcept
Sets the space from a single-tensor representation.
Definition functionspace.hpp:2571
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept
Sets the boundary from a single-tensor representation.
Definition functionspace.hpp:2586
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:2635
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:2544
FunctionSpace(const FunctionSpace &)=default
Copy constructor.
spline_type spline_
Spline.
Definition functionspace.hpp:2429
static constexpr short_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:2480
auto eval_from_precomputed(const Args &...args) const
Returns the value of the spline object from precomputed basis function.
Definition functionspace.hpp:2715
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:2627
FunctionSpace & from_tensor(const torch::Tensor &coeffs) noexcept
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:2592
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:2454
constexpr const spline_type & space() const noexcept
Returns a constant reference to the -th function space.
Definition functionspace.hpp:2484
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:2830
constexpr auto clone() const noexcept
Returns a subset of the tuple of function spaces.
Definition functionspace.hpp:2515
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
Concept to identify template parameters that are derived from iganet::details::FunctionSpaceType.
Definition functionspace.hpp:3117
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:3110
typename FunctionSpace_trait< Spline, Boundary >::type type
Definition functionspace.hpp:3102
std::ostream & operator<<(std::ostream &os, const FunctionSpace< Splines... > &obj)
Print (as string) a function space object.
Definition functionspace.hpp:2395
Forward declaration.
Definition functionspace.hpp:3072
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:1958
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:3148
functionspace
Enumerator for the function space component.
Definition functionspace.hpp:30
@ 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:3121
std::ostream & operator<<(std::ostream &os, const Boundary< Spline > &obj)
Print (as string) a Boundary object.
Definition boundary.hpp:1963
IGANET_FUNCTIONSPACE_TUPLE_WRAPPER(RT);.
Definition functionspace.hpp:4030
IGANET_FUNCTIONSPACE_TUPLE_WRAPPER(TH);.
Definition functionspace.hpp:3467
IGANET_FUNCTIONSPACE_TUPLE_WRAPPER(NE);.
Definition functionspace.hpp:3773
Taylor-Hood like function space.
Definition functionspace.hpp:3151
STL namespace.
Serialization prototype.
Definition serialize.hpp:31
Type traits.
Zip utility function.