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
47template <typename, typename>
48class FunctionSpace;
49
54template <typename... Splines, typename... Boundaries>
55// requires (SplineType<Splines> && ...) && (BoundaryType<Boundaries> && ...)
56class FunctionSpace<std::tuple<Splines...>, std::tuple<Boundaries...>>
58
59public:
61 using value_type = std::common_type_t<typename Splines::value_type...>;
62
64 using spline_type = std::tuple<Splines...>;
65
67 using eval_type = std::tuple<utils::TensorArray<Splines::parDim()>...>;
68
70 using boundary_type = std::tuple<Boundaries...>;
71
73 using boundary_eval_type = std::tuple<typename Boundaries::eval_type...>;
74
75protected:
78
81
82public:
84 FunctionSpace() = default;
85
87 FunctionSpace(const FunctionSpace &) = default;
88
91
94 FunctionSpace(const std::array<int64_t, Splines::parDim()> &...ncoeffs,
97 : spline_({ncoeffs, init, options}...),
98 boundary_({ncoeffs, init::none, options}...) {
100 }
101
102 FunctionSpace(const std::array<std::vector<typename Splines::value_type>,
103 Splines::parDim()> &...kv,
104 enum init init = init::greville,
106 : spline_({kv, init, options}...),
107 boundary_({kv, init::none, options}...) {
108
109 static_assert((Splines::is_nonuniform() && ... && true),
110 "Constructor is only available for non-uniform splines");
112 }
113
114 explicit FunctionSpace(const std::tuple<Splines...> &spline)
115 : spline_(spline) {
117 }
118
119 explicit FunctionSpace(std::tuple<Splines...> &&spline)
120 : spline_(spline) {
122 }
123
124 explicit FunctionSpace(const std::tuple<Splines...> &spline,
125 const std::tuple<Boundaries...> &boundary)
126 : spline_(spline), boundary_(boundary) {}
127
128 explicit FunctionSpace(std::tuple<Splines...> &&spline,
129 std::tuple<Boundaries...> &&boundary)
130 : spline_(spline), boundary_(boundary) {}
132
134 inline static constexpr std::size_t nspaces() noexcept {
135 return sizeof...(Splines);
136 }
137
139 inline static constexpr std::size_t nboundaries() noexcept {
140 return sizeof...(Boundaries);
141 }
142
144 template <std::size_t index> inline const auto &space() const noexcept {
145 static_assert(index >= 0 && index < nspaces());
146 return std::get<index>(spline_);
147 }
148
150 template <std::size_t index> inline auto &space() noexcept {
151 static_assert(index >= 0 && index < nspaces());
152 return std::get<index>(spline_);
153 }
154
156 template <std::size_t index> inline const auto &boundary() const noexcept {
157 static_assert(index >= 0 && index < nboundaries());
158 return std::get<index>(boundary_);
159 }
160
163 template <std::size_t index> inline auto &boundary() noexcept {
164 static_assert(index >= 0 && index < nboundaries());
165 return std::get<index>(boundary_);
166 }
167
169 inline FunctionSpace clone() const noexcept { return FunctionSpace(*this); }
170
172 template <std::size_t... index> inline auto clone() const noexcept {
173
174 static_assert(((index >= 0 && index < nspaces()) && ... && true));
175
177 std::tuple<std::tuple_element_t<index, boundary_type>...>>(
178 std::make_tuple(std::get<index>(spline_)...), std::make_tuple(std::get<index>(boundary_)...));
179 }
180
181private:
184 template <std::size_t... Is>
185 inline torch::Tensor
186 spaces_as_tensor_(std::index_sequence<Is...>) const noexcept {
187 return torch::cat({std::get<Is>(spline_).as_tensor()...});
188 }
189
190public:
193 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
194 return spaces_as_tensor_(
195 std::make_index_sequence<FunctionSpace::nspaces()>{});
196 }
197
198private:
201 template <std::size_t... Is>
202 inline torch::Tensor
203 boundary_as_tensor_(std::index_sequence<Is...>) const noexcept {
204 return torch::cat({std::get<Is>(boundary_).as_tensor()...});
205 }
206
207public:
210 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
211 return boundary_as_tensor_(
212 std::make_index_sequence<FunctionSpace::nboundaries()>{});
213 }
214
220 virtual inline torch::Tensor as_tensor() const noexcept {
221 return spaces_as_tensor();
222 }
223
224private:
227 template <std::size_t... Is>
228 inline int64_t
229 spaces_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
230 return std::apply(
231 [](auto... v) { return (v + ...); },
232 std::make_tuple(std::get<Is>(spline_).as_tensor_size()...));
233 }
234
235public:
238 virtual inline int64_t spaces_as_tensor_size() const noexcept {
239 return spaces_as_tensor_size_(
240 std::make_index_sequence<FunctionSpace::nspaces()>{});
241 }
242
243private:
246 template <std::size_t... Is>
247 inline int64_t
248 boundary_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
249 return std::apply(
250 [](auto... v) { return (v + ...); },
251 std::make_tuple(std::get<Is>(boundary_).as_tensor_size()...));
252 }
253
254public:
257 virtual inline int64_t boundary_as_tensor_size() const noexcept {
258 return boundary_as_tensor_size_(
259 std::make_index_sequence<FunctionSpace::nboundaries()>{});
260 }
261
267 virtual inline int64_t as_tensor_size() const noexcept {
268 return spaces_as_tensor_size();
269 }
270
271private:
273 template <std::size_t... Is>
274 inline FunctionSpace &spaces_from_tensor_(std::index_sequence<Is...>,
275 const torch::Tensor &tensor) {
276
277 // Compute the partial sums of all function spaces
278 std::array<int64_t, sizeof...(Is)> partialSums{0};
279 auto partial_sums = [&partialSums,
280 this]<std::size_t... Js>(std::index_sequence<Js...>) {
281 ((std::get<Js + 1>(partialSums) =
282 std::get<Js>(partialSums) + std::get<Js>(spline_).as_tensor_size()),
283 ...);
284 };
285 partial_sums(std::make_index_sequence<FunctionSpace::nspaces() - 1>{});
286
287 // Call from_tensor for all function spaces
288 ((std::get<Is>(spline_).from_tensor(tensor.index(
289 {torch::indexing::Slice(partialSums[Is],
290 partialSums[Is] +
291 std::get<Is>(spline_).as_tensor_size()),
292 "..."}))),
293 ...);
294
295 return *this;
296 }
297
298public:
300 virtual inline FunctionSpace &
301 spaces_from_tensor(const torch::Tensor &tensor) {
302 return spaces_from_tensor_(
303 std::make_index_sequence<FunctionSpace::nspaces()>{}, tensor);
304 }
305
306private:
309 template <std::size_t... Is>
310 inline FunctionSpace &boundary_from_tensor_(std::index_sequence<Is...>,
311 const torch::Tensor &tensor) {
312 (std::get<Is>(boundary_).from_tensor(std::get<Is>(spline_).as_tensor()),
313 ...);
314
315 return *this;
316 }
317
318public:
321 virtual inline FunctionSpace &
322 boundary_from_tensor(const torch::Tensor &tensor) {
323 return boundary_from_tensor_(
324 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
325 }
326
327private:
329 template <std::size_t... Is>
330 inline FunctionSpace &
331 boundary_from_full_tensor_(std::index_sequence<Is...>,
332 const torch::Tensor &tensor) {
333 (std::get<Is>(boundary_).from_full_tensor(
334 std::get<Is>(spline_).as_tensor()),
335 ...);
336
337 return *this;
338 }
339
340public:
342 virtual inline FunctionSpace &
343 boundary_from_full_tensor(const torch::Tensor &tensor) {
344 return boundary_from_full_tensor_(
345 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
346 }
347
349 virtual inline FunctionSpace &from_tensor(const torch::Tensor &tensor) {
350 spaces_from_tensor_(std::make_index_sequence<FunctionSpace::nspaces()>{},
351 tensor);
352 boundary_from_full_tensor_(
353 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
354 return *this;
355 }
356
357private:
359 template <std::size_t... Is>
360 inline pugi::xml_node &to_xml_(std::index_sequence<Is...>,
361 pugi::xml_node &root, int id = 0,
362 std::string label = "") const {
363
364 (std::get<Is>(spline_).to_xml(root, id, label, Is), ...);
365 return root;
366 }
367
368public:
370 inline pugi::xml_document to_xml(int id = 0, std::string label = "") const {
371 pugi::xml_document doc;
372 pugi::xml_node root = doc.append_child("xml");
373 to_xml(root, id, label);
374
375 return doc;
376 }
377
379 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
380 std::string label = "") const {
381 return to_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
382 id, label);
383 }
384
385private:
387 template <std::size_t... Is>
388 inline FunctionSpace &from_xml_(std::index_sequence<Is...>,
389 const pugi::xml_node &root, int id = 0,
390 std::string label = "") {
391
392 (std::get<Is>(spline_).from_xml(root, id, label, Is), ...);
393 return *this;
394 }
395
396public:
398 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
399 std::string label = "") {
400 return from_xml(doc.child("xml"), id, label);
401 }
402
404 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
405 std::string label = "") {
406 return from_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
407 id, label);
408 }
409
410private:
412 template <std::size_t... Is>
413 nlohmann::json to_json_(std::index_sequence<Is...>) const {
414 auto json_this = nlohmann::json::array();
415 auto json_boundary = nlohmann::json::array();
416 (json_this.push_back(std::get<Is>(spline_).to_json()), ...);
417 (json_boundary.push_back(std::get<Is>(boundary_).to_json()), ...);
418
419 auto json = nlohmann::json::array();
420 for (auto [t, b] : utils::zip(json_this, json_boundary)) {
421 auto json_inner = nlohmann::json::array();
422 json_inner.push_back(t);
423 json_inner.push_back(b);
424 json.push_back(json_inner);
425 }
426
427 return json;
428 }
429
430public:
432 nlohmann::json to_json() const override {
433 return to_json_(std::make_index_sequence<FunctionSpace::nspaces()>{});
434 }
435
436private:
439 template <functionspace comp = functionspace::interior,
440 deriv deriv = deriv::func, bool memory_optimized = false,
441 std::size_t... Is, typename... Xi>
442 inline auto eval_(std::index_sequence<Is...>,
443 const std::tuple<Xi...> &xi) const {
444 if constexpr (comp == functionspace::interior)
445 return std::tuple(
446 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
447 std::get<Is>(xi))...);
448 else if constexpr (comp == functionspace::boundary)
449 return std::tuple(
450 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
451 std::get<Is>(xi))...);
452 }
453
454 template <functionspace comp = functionspace::interior,
455 deriv deriv = deriv::func, bool memory_optimized = false,
456 std::size_t... Is, typename... Xi, typename... Knot_Indices>
457 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
458 const std::tuple<Knot_Indices...> &knot_indices) const {
459 if constexpr (comp == functionspace::interior)
460 return std::tuple(
461 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
462 std::get<Is>(xi), std::get<Is>(knot_indices))...);
463 else if constexpr (comp == functionspace::boundary)
464 return std::tuple(
465 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
466 std::get<Is>(xi), std::get<Is>(knot_indices))...);
467 }
468
469 template <functionspace comp = functionspace::interior,
470 deriv deriv = deriv::func, bool memory_optimized = false,
471 std::size_t... Is, typename... Xi, typename... Knot_Indices,
472 typename... Coeff_Indices>
473 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
474 const std::tuple<Knot_Indices...> &knot_indices,
475 const std::tuple<Coeff_Indices...> &coeff_indices) const {
476 if constexpr (comp == functionspace::interior)
477 return std::tuple(
478 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
479 std::get<Is>(xi), std::get<Is>(knot_indices),
480 std::get<Is>(coeff_indices))...);
481 else if constexpr (comp == functionspace::boundary)
482 return std::tuple(
483 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
484 std::get<Is>(xi), std::get<Is>(knot_indices),
485 std::get<Is>(coeff_indices))...);
486 }
488
489public:
492 template <functionspace comp = functionspace::interior,
493 deriv deriv = deriv::func, bool memory_optimized = false,
494 typename... Xi>
495 inline auto eval(const std::tuple<Xi...> &xi) const {
496 static_assert(FunctionSpace::nspaces() == sizeof...(Xi),
497 "Size of Xi mismatches functionspace dimension");
498 return eval_<comp, deriv, memory_optimized>(
499 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
500 }
501
502 template <functionspace comp = functionspace::interior,
503 deriv deriv = deriv::func, bool memory_optimized = false,
504 typename... Xi, typename... Knot_Indices>
505 inline auto eval(const std::tuple<Xi...> &xi,
506 const std::tuple<Knot_Indices...> &knot_indices) const {
507 static_assert(
508 (FunctionSpace::nspaces() == sizeof...(Xi)) &&
509 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)),
510 "Sizes of Xi and Knot_Indices mismatch functionspace dimension");
511 return eval_<comp, deriv, memory_optimized>(
512 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
513 }
514
515 template <functionspace comp = functionspace::interior,
516 deriv deriv = deriv::func, bool memory_optimized = false,
517 typename... Xi, typename... Knot_Indices, typename... Coeff_Indices>
518 inline auto eval(const std::tuple<Xi...> &xi,
519 const std::tuple<Knot_Indices...> &knot_indices,
520 const std::tuple<Coeff_Indices...> &coeff_indices) const {
521 static_assert((FunctionSpace::nspaces() == sizeof...(Xi)) &&
522 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)) &&
523 (FunctionSpace::nspaces() == sizeof...(Coeff_Indices)),
524 "Sizes of Xi, Knot_Indices and Coeff_Indices mismatch "
525 "functionspace dimension");
526 return eval_<comp, deriv, memory_optimized>(
527 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices,
528 coeff_indices);
529 }
531
532private:
536 template <functionspace comp = functionspace::interior, std::size_t... Is,
537 typename... Basfunc, typename... Coeff_Indices, typename... Numeval,
538 typename... Sizes>
539 inline auto
540 eval_from_precomputed_(std::index_sequence<Is...>,
541 const std::tuple<Basfunc...> &basfunc,
542 const std::tuple<Coeff_Indices...> &coeff_indices,
543 const std::tuple<Numeval...> &numeval,
544 const std::tuple<Sizes...> &sizes) const {
545 if constexpr (comp == functionspace::interior)
546 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
547 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
548 std::get<Is>(numeval), std::get<Is>(sizes))...);
549 else if constexpr (comp == functionspace::boundary)
550 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
551 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
552 std::get<Is>(numeval), std::get<Is>(sizes))...);
553 }
554
555 template <functionspace comp = functionspace::interior, std::size_t... Is,
556 typename... Basfunc, typename... Coeff_Indices, typename... Xi>
557 inline auto
558 eval_from_precomputed_(std::index_sequence<Is...>,
559 const std::tuple<Basfunc...> &basfunc,
560 const std::tuple<Coeff_Indices...> &coeff_indices,
561 const std::tuple<Xi...> &xi) const {
562 if constexpr (comp == functionspace::interior)
563 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
564 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
565 std::get<Is>(xi)[0].numel(), std::get<Is>(xi)[0].sizes())...);
566 else if constexpr (comp == functionspace::boundary)
567 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
568 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
569 std::get<Is>(xi))...);
570 }
572
573public:
577 template <functionspace comp = functionspace::interior, typename... Basfunc,
578 typename... Coeff_Indices, typename... Numeval, typename... Sizes>
579 inline auto
580 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
581 const std::tuple<Coeff_Indices...> &coeff_indices,
582 const std::tuple<Numeval...> &numeval,
583 const std::tuple<Sizes...> &sizes) const {
584 return eval_from_precomputed_<comp>(
585 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
586 coeff_indices, numeval, sizes);
587 }
588
589 template <functionspace comp = functionspace::interior, typename... Basfunc,
590 typename... Coeff_Indices, typename... Xi>
591 inline auto
592 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
593 const std::tuple<Coeff_Indices...> &coeff_indices,
594 const std::tuple<Xi...> &xi) const {
595 return eval_from_precomputed_<comp>(
596 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
597 coeff_indices, xi);
598 }
600
601private:
604 template <functionspace comp = functionspace::interior, std::size_t... Is>
605 inline auto find_knot_indices_(std::index_sequence<Is...>,
606 const utils::TensorArray<nspaces()> &xi) const {
607 if constexpr (comp == functionspace::interior)
608 return std::tuple(
609 std::get<Is>(spline_).find_knot_indices(xi)...);
610 else if constexpr (comp == functionspace::boundary)
611 return std::tuple(
612 std::get<Is>(boundary_).find_knot_indices(xi)...);
613 }
614
615 template <functionspace comp = functionspace::interior, std::size_t... Is,
616 typename... Xi>
617 inline auto find_knot_indices_(std::index_sequence<Is...>,
618 const std::tuple<Xi...> &xi) const {
619 if constexpr (comp == functionspace::interior)
620 return std::tuple(
621 std::get<Is>(spline_).find_knot_indices(std::get<Is>(xi))...);
622 else if constexpr (comp == functionspace::boundary)
623 return std::tuple(
624 std::get<Is>(boundary_).find_knot_indices(std::get<Is>(xi))...);
625 }
627
628public:
631 template <functionspace comp = functionspace::interior>
632 inline auto find_knot_indices(const utils::TensorArray<nspaces()> &xi) const {
633 return find_knot_indices_<comp>(
634 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
635 }
636
637 template <functionspace comp = functionspace::interior, typename... Xi>
638 inline auto find_knot_indices(const std::tuple<Xi...> &xi) const {
639 return find_knot_indices_<comp>(
640 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
641 }
643
644private:
648 template <functionspace comp = functionspace::interior,
649 deriv deriv = deriv::func, bool memory_optimized = false,
650 std::size_t... Is, typename... Xi>
651 inline auto eval_basfunc_(std::index_sequence<Is...>,
652 const std::tuple<Xi...> &xi) const {
653 if constexpr (comp == functionspace::interior)
654 return std::tuple(
655 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
656 std::get<Is>(xi))...);
657 else if constexpr (comp == functionspace::boundary)
658 return std::tuple(std::get<Is>(boundary_)
659 .template eval_basfunc<deriv, memory_optimized>(
660 std::get<Is>(xi))...);
661 }
662
663 template <functionspace comp = functionspace::interior,
664 deriv deriv = deriv::func, bool memory_optimized = false,
665 std::size_t... Is, typename... Xi, typename... Knot_Indices>
666 inline auto
667 eval_basfunc_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
668 const std::tuple<Knot_Indices...> &knot_indices) const {
669 if constexpr (comp == functionspace::interior)
670 return std::tuple(
671 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
672 std::get<Is>(xi), std::get<Is>(knot_indices))...);
673 else if constexpr (comp == functionspace::boundary)
674 return std::tuple(
675 std::get<Is>(boundary_)
676 .template eval_basfunc<deriv, memory_optimized>(
677 std::get<Is>(xi), std::get<Is>(knot_indices))...);
678 }
680
681public:
684 template <functionspace comp = functionspace::interior,
685 deriv deriv = deriv::func, bool memory_optimized = false,
686 typename... Xi>
687 inline auto eval_basfunc(const std::tuple<Xi...> &xi) const {
688 return eval_basfunc_<comp, deriv, memory_optimized>(
689 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
690 }
691
692 template <functionspace comp = functionspace::interior,
693 deriv deriv = deriv::func, bool memory_optimized = false,
694 typename... Xi, typename... Knot_Indices>
695 inline auto
696 eval_basfunc(const std::tuple<Xi...> &xi,
697 const std::tuple<Knot_Indices...> &knot_indices) const {
698 return eval_basfunc_<comp, deriv, memory_optimized>(
699 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
700 }
702
703private:
706 template <functionspace comp = functionspace::interior,
707 bool memory_optimized = false, std::size_t... Is,
708 typename... Knot_Indices>
709 inline auto
710 find_coeff_indices_(std::index_sequence<Is...>,
711 const std::tuple<Knot_Indices...> &knot_indices) const {
712 if constexpr (comp == functionspace::interior)
713 return std::tuple(
714 std::get<Is>(spline_).template find_coeff_indices<memory_optimized>(
715 std::get<Is>(knot_indices))...);
716 else if constexpr (comp == functionspace::boundary)
717 return std::tuple(
718 std::get<Is>(boundary_).template find_coeff_indices<memory_optimized>(
719 std::get<Is>(knot_indices))...);
720 }
721
722public:
725 template <functionspace comp = functionspace::interior,
726 bool memory_optimized = false, typename... Knot_Indices>
727 inline auto
728 find_coeff_indices(const std::tuple<Knot_Indices...> &knot_indices) const {
729 return find_coeff_indices_<comp, memory_optimized>(
730 std::make_index_sequence<FunctionSpace::nspaces()>{}, knot_indices);
731 }
732
733private:
736 template <std::size_t... Is, std::size_t... Js>
737 inline auto &uniform_refine_(std::index_sequence<Is...>,
738 std::index_sequence<Js...>, int numRefine = 1,
739 int dimRefine = -1) {
740 (std::get<Is>(spline_).uniform_refine(numRefine, dimRefine), ...);
741 (std::get<Js>(boundary_).uniform_refine(numRefine, dimRefine), ...);
742 return *this;
743 }
744
745public:
748 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
749 return uniform_refine_(
750 std::make_index_sequence<FunctionSpace::nspaces()>{},
751 std::make_index_sequence<FunctionSpace::nboundaries()>{}, numRefine,
752 dimRefine);
753 }
754
755private:
758 template <typename real_t, std::size_t... Is, std::size_t... Js>
759 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
760 Options<real_t> options) const {
761 return FunctionSpace<
762 typename Splines::template real_derived_self_type<real_t>...,
763 typename Boundaries::template real_derived_self_type<real_t>...>(
764 std::get<Is>(spline_).to(options)...,
765 std::get<Js>(boundary_).to(options)...);
766 }
767
768public:
771 template <typename real_t> inline auto to(Options<real_t> options) const {
772 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
773 std::make_index_sequence<FunctionSpace::nboundaries()>{},
774 options);
775 }
776
777private:
780 template <std::size_t... Is, std::size_t... Js>
781 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
782 torch::Device device) const {
783 return FunctionSpace(std::get<Is>(spline_).to(device)...,
784 std::get<Js>(boundary_).to(device)...);
785 }
786
787public:
790 inline auto to(torch::Device device) const {
791 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
792 std::make_index_sequence<FunctionSpace::nboundaries()>{},
793 device);
794 }
795
796private:
798 template <typename real_t, std::size_t... Is, std::size_t... Js>
799 inline auto to_(std::index_sequence<Is...>,
800 std::index_sequence<Js...>) const {
801 return FunctionSpace<
802 typename Splines::template real_derived_self_type<real_t>...,
803 typename Boundaries::template real_derived_self_type<real_t>...>(
804 std::get<Is>(spline_).template to<real_t>()...,
805 std::get<Js>(boundary_).template to<real_t>()...);
806 }
807
808public:
810 template <typename real_t> inline auto to() const {
811 return to_<real_t>(
812 std::make_index_sequence<FunctionSpace::nspaces()>{},
813 std::make_index_sequence<FunctionSpace::nboundaries()>{});
814 }
815
816private:
818 template <std::size_t... Is>
819 inline auto scale_(std::index_sequence<Is...>, value_type s, int dim = -1) {
820 (std::get<Is>(spline_).scale(s, dim), ...);
822 return *this;
823 }
824
825public:
827 inline auto scale(value_type s, int dim = -1) {
828 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, s, dim);
829 }
830
831private:
833 template <std::size_t N, std::size_t... Is>
834 inline auto scale_(std::index_sequence<Is...>, std::array<value_type, N> v) {
835 (std::get<Is>(spline_).scale(v), ...);
836 (std::get<Is>(boundary_).from_full_tensor(
837 std::get<Is>(spline_).as_tensor()),
838 ...);
839 return *this;
840 }
841
842public:
844 template <std::size_t N> inline auto scale(std::array<value_type, N> v) {
845 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
846 }
847
848private:
850 template <std::size_t N, std::size_t... Is>
851 inline auto translate_(std::index_sequence<Is...>,
852 std::array<value_type, N> v) {
853 (std::get<Is>(spline_).translate(v), ...);
854 (std::get<Is>(boundary_).from_full_tensor(
855 std::get<Is>(spline_).as_tensor()),
856 ...);
857 return *this;
858 }
859
860public:
862 template <std::size_t N> inline auto translate(std::array<value_type, N> v) {
863 return translate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
864 }
865
866private:
868 template <std::size_t... Is>
869 inline auto rotate_(std::index_sequence<Is...>, value_type angle) {
870 (std::get<Is>(spline_).rotate(angle), ...);
871 (std::get<Is>(boundary_).from_full_tensor(
872 std::get<Is>(spline_).as_tensor()),
873 ...);
874 return *this;
875 }
876
877public:
879 inline auto rotate(value_type angle) {
880 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
881 }
882
883private:
885 template <std::size_t... Is>
886 inline auto rotate_(std::index_sequence<Is...>,
887 std::array<value_type, 3> angle) {
888 (std::get<Is>(spline_).rotate(angle), ...);
889 (std::get<Is>(boundary_).from_full_tensor(
890 std::get<Is>(spline_).as_tensor()),
891 ...);
892 return *this;
893 }
894
895public:
897 inline auto rotate(std::array<value_type, 3> angle) {
898 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
899 }
900
901private:
903 template <std::size_t... Is>
904 inline auto boundingBox_(std::index_sequence<Is...>) const {
905 return std::tuple(std::get<Is>(spline_).boundingBox()...);
906 }
907
908public:
910 inline auto boundingBox() const {
911 return boundingBox_(std::make_index_sequence<FunctionSpace::nspaces()>{});
912 }
913
914private:
917 template <std::size_t... Is>
918 inline torch::serialize::OutputArchive &
919 write_(std::index_sequence<Is...>, torch::serialize::OutputArchive &archive,
920 const std::string &key = "functionspace") const {
921 (std::get<Is>(spline_).write(
922 archive, key + ".fspace[" + std::to_string(Is) + "].interior"),
923 ...);
924 (std::get<Is>(boundary_).write(
925 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
926 ...);
927 return archive;
928 }
929
930public:
933 inline torch::serialize::OutputArchive &
934 write(torch::serialize::OutputArchive &archive,
935 const std::string &key = "functionspace") const {
936 write_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
937 return archive;
938 }
939
940private:
943 template <std::size_t... Is>
944 inline torch::serialize::InputArchive &
945 read_(std::index_sequence<Is...>, torch::serialize::InputArchive &archive,
946 const std::string &key = "functionspace") {
947 (std::get<Is>(spline_).read(archive, key + ".fspace[" + std::to_string(Is) +
948 "].interior"),
949 ...);
950 (std::get<Is>(boundary_).read(
951 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
952 ...);
953 return archive;
954 }
955
956public:
959 inline torch::serialize::InputArchive &
960 read(torch::serialize::InputArchive &archive,
961 const std::string &key = "functionspace") {
962 read_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
963 return archive;
964 }
965
967 inline virtual void
968 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
969
970 auto pretty_print_ = [this,
971 &os]<std::size_t... Is>(std::index_sequence<Is...>) {
972 ((os << "\ninterior = ", std::get<Is>(spline_).pretty_print(os),
973 os << "\nboundary = ", std::get<Is>(boundary_).pretty_print(os)),
974 ...);
975 };
976
977 pretty_print_(std::make_index_sequence<nspaces()>{});
978 }
979
980 // clang-format off
998 // clang-format off
1001 template <functionspace comp = functionspace::interior,
1002 bool memory_optimized = false>
1003 inline auto curl(const utils::TensorArray<nspaces()> &xi) const {
1004 return curl<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1005 }
1006
1007 template <functionspace comp = functionspace::interior,
1008 bool memory_optimized = false,
1009 typename... TensorArrays>
1010 inline auto curl(const utils::TensorArray<nspaces()> &xi,
1011 const std::tuple<TensorArrays...> &knot_indices) const {
1012 return curl<comp, memory_optimized>(xi, knot_indices,
1013 find_coeff_indices<comp>(knot_indices));
1014 }
1015
1016 template <functionspace comp = functionspace::interior,
1017 bool memory_optimized = false>
1018 inline auto curl(const utils::TensorArray1 &xi,
1019 const std::tuple<utils::TensorArray1> &knot_indices,
1020 const std::tuple<torch::Tensor> &coeff_indices) const {
1021
1022 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1023
1024 throw std::runtime_error("Unsupported parametric/geometric dimension");
1025
1027 }
1028
1029 template <functionspace comp = functionspace::interior,
1030 bool memory_optimized = false>
1031 inline auto
1033 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1034 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1035
1036 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1037 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1038 xi[0].sizes() == xi[1].sizes());
1039
1046 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1047 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1048 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1049 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1050 }
1051
1052 template <functionspace comp = functionspace::interior,
1053 bool memory_optimized = false>
1054 inline auto curl(const utils::TensorArray3 &xi,
1055 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1056 utils::TensorArray3> &knot_indices,
1057 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1058 &coeff_indices) const {
1059
1060 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1061 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1062 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1063 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1064
1069 *std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1070 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] -
1071 *std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1072 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1073 *std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1074 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] -
1075 *std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1076 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1077 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1078 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1079 *std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1080 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1081 }
1082
1083 template <functionspace comp = functionspace::interior,
1084 bool memory_optimized = false>
1085 inline auto
1087 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1089 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1090 torch::Tensor> &coeff_indices) const {
1091
1092 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1093 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1094 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1095 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1096 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1097 xi[2].sizes() == xi[3].sizes());
1098
1099 throw std::runtime_error("Unsupported parametric/geometric dimension");
1100
1102 }
1104
1129 template <functionspace comp = functionspace::interior,
1130 bool memory_optimized = false>
1131 inline auto div(const utils::TensorArray<nspaces()> &xi) const {
1132 return div<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1133 }
1134
1135 template <functionspace comp = functionspace::interior,
1136 bool memory_optimized = false,
1137 typename... TensorArrays>
1138 inline auto div(const utils::TensorArray<nspaces()> &xi,
1139 const std::tuple<TensorArrays...> &knot_indices) const {
1140 return div<comp, memory_optimized>(xi, knot_indices,
1141 find_coeff_indices<comp>(knot_indices));
1142 }
1143
1144 template <functionspace comp = functionspace::interior,
1145 bool memory_optimized = false>
1146 inline auto div(const utils::TensorArray1 &xi,
1147 const std::tuple<utils::TensorArray1> &knot_indices,
1148 const std::tuple<torch::Tensor> &coeff_indices) const {
1149
1150 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1151
1152 if constexpr (comp == functionspace::interior) {
1153 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1154 "div(.) for vector-valued spaces requires 1D variables");
1155
1157 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1158 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1159 }
1160 }
1161
1162 template <functionspace comp = functionspace::interior,
1163 bool memory_optimized = false>
1164 inline auto
1166 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1167 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1168
1169 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1170 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1171 xi[0].sizes() == xi[1].sizes());
1172
1173 if constexpr (comp == functionspace::interior) {
1174 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1175 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1176 "div(.) for vector-valued spaces requires 1D variables");
1177
1179 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1180 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1181 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1182 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1183 }
1184 }
1185
1186 template <functionspace comp = functionspace::interior,
1187 bool memory_optimized = false>
1188 inline auto div(const utils::TensorArray3 &xi,
1189 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1190 utils::TensorArray3> &knot_indices,
1191 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1192 &coeff_indices) const {
1193
1194 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1195 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1196 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1197 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1198
1199 if constexpr (comp == functionspace::interior) {
1200 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1201 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1202 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1203 "div(.) for vector-valued spaces requires 1D variables");
1204
1206 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1207 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1208 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1209 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1210 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1211 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1212 }
1213 }
1214
1215 template <functionspace comp = functionspace::interior,
1216 bool memory_optimized = false>
1217 inline auto
1219 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1221 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1222 torch::Tensor> &coeff_indices) const {
1223
1224 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1225 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1226 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1227 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1228 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1229 xi[2].sizes() == xi[3].sizes());
1230
1231 if constexpr (comp == functionspace::interior) {
1232 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1233 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1234 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1235 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1236 "div(.) for vector-valued spaces requires 1D variables");
1237
1239 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1240 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1241 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1242 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1243 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1244 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
1245 *std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1246 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1247 }
1248 }
1250
1268 template <functionspace comp = functionspace::interior,
1269 bool memory_optimized = false>
1270 inline auto grad(const utils::TensorArray<nspaces()> &xi) const {
1271 return grad<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1272 }
1273
1274 template <functionspace comp = functionspace::interior,
1275 bool memory_optimized = false,
1276 typename... TensorArrays>
1277 inline auto grad(const utils::TensorArray<nspaces()> &xi,
1278 const std::tuple<TensorArrays...> &knot_indices) const {
1279 return grad<comp, memory_optimized>(xi, knot_indices,
1280 find_coeff_indices<comp>(knot_indices));
1281 }
1282
1283 template <functionspace comp = functionspace::interior,
1284 bool memory_optimized = false>
1285 inline auto grad(const utils::TensorArray1 &xi,
1286 const std::tuple<utils::TensorArray1> &knot_indices,
1287 const std::tuple<torch::Tensor> &coeff_indices) const {
1288
1289 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1290
1291 if constexpr (comp == functionspace::interior) {
1292 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1293 "grad(.) for vector-valued spaces requires 1D variables");
1294
1296 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1297 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1298 }
1299 }
1300
1301 template <functionspace comp = functionspace::interior,
1302 bool memory_optimized = false>
1303 inline auto
1305 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1306 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1307
1308 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1309 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1310 xi[0].sizes() == xi[1].sizes());
1311
1312 if constexpr (comp == functionspace::interior) {
1313 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1314 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1315 "grad(.) for vector-valued spaces requires 1D variables");
1316
1318 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1319 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1320 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1321 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1322 }
1323 }
1324
1325 template <functionspace comp = functionspace::interior,
1326 bool memory_optimized = false>
1327 inline auto grad(const utils::TensorArray3 &xi,
1328 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1329 utils::TensorArray3> &knot_indices,
1330 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1331 &coeff_indices) const {
1332
1333 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1334 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1335 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1336 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1337
1338 if constexpr (comp == functionspace::interior) {
1339 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1340 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1341 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1342 "div(.) for vector-valued spaces requires 1D variables");
1343
1345 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1346 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1347 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1348 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1349 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1350 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1351 }
1352 }
1353
1354 template <functionspace comp = functionspace::interior,
1355 bool memory_optimized = false>
1356 inline auto
1358 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1360 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1361 torch::Tensor> &coeff_indices) const {
1362
1363 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1364 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1365 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1366 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1367 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1368 xi[2].sizes() == xi[3].sizes());
1369
1370 if constexpr (comp == functionspace::interior) {
1371 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1372 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1373 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1374 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1375 "grad(.) for vector-valued spaces requires 1D variables");
1376
1378 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1379 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1380 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1381 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1382 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1383 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1384 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1385 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1386 }
1387 }
1389
1390 // clang-format off
1423 // clang-format on
1426 template <functionspace comp = functionspace::interior,
1427 bool memory_optimized = false>
1428 inline auto hess(const utils::TensorArray<nspaces()> &xi) const {
1429 return hess<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1430 }
1431
1432 template <functionspace comp = functionspace::interior,
1433 bool memory_optimized = false,
1434 typename... TensorArrays>
1435 inline auto hess(const utils::TensorArray<nspaces()> &xi,
1436 const std::tuple<TensorArrays...> &knot_indices) const {
1437 return hess<comp, memory_optimized>(xi, knot_indices,
1438 find_coeff_indices<comp>(knot_indices));
1439 }
1440
1441 template <functionspace comp = functionspace::interior,
1442 bool memory_optimized = false>
1443 inline auto hess(const utils::TensorArray1 &xi,
1444 const std::tuple<utils::TensorArray1> &knot_indices,
1445 const std::tuple<torch::Tensor> &coeff_indices) const {
1446
1447 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1448
1449 if constexpr (comp == functionspace::interior) {
1450 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1451 "hess(.) for vector-valued spaces requires 1D variables");
1452
1454 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1455 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)));
1456 }
1457 }
1458
1459 template <functionspace comp = functionspace::interior,
1460 bool memory_optimized = false>
1461 inline auto
1463 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1464 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1465
1466 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1467 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1468 xi[0].sizes() == xi[1].sizes());
1469
1470 if constexpr (comp == functionspace::interior) {
1471 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1472 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1473 "hess(.) for vector-valued spaces requires 1D variables");
1474
1476 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1477 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1478 std::get<0>(spline_)
1479 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1480 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1481 std::get<0>(spline_)
1482 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1483 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1484 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1485 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1486
1487 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1488 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1489 std::get<1>(spline_)
1490 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1491 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1492 std::get<1>(spline_)
1493 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1494 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1495 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1496 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)));
1497 }
1498 }
1499
1500 template <functionspace comp = functionspace::interior,
1501 bool memory_optimized = false>
1502 inline auto hess(const utils::TensorArray3 &xi,
1503 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1504 utils::TensorArray3> &knot_indices,
1505 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1506 &coeff_indices) const {
1507
1508 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1509 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1510 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1511 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1512
1513 if constexpr (comp == functionspace::interior) {
1514 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1515 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1516 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1517 "hess(.) for vector-valued spaces requires 1D variables");
1518
1520 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1521 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1522 std::get<0>(spline_)
1523 .template eval<deriv::dx + deriv::dy, 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::dz, memory_optimized>(
1527 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1528 std::get<0>(spline_)
1529 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1530 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1531 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1532 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1533 std::get<0>(spline_)
1534 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1535 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1536 std::get<0>(spline_)
1537 .template eval<deriv::dz + deriv::dx, 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::dy, memory_optimized>(
1541 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1542 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1543 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1544
1545 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1546 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1547 std::get<1>(spline_)
1548 .template eval<deriv::dx + deriv::dy, 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::dz, memory_optimized>(
1552 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1553 std::get<1>(spline_)
1554 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1555 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1556 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1557 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1558 std::get<1>(spline_)
1559 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1560 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1561 std::get<1>(spline_)
1562 .template eval<deriv::dz + deriv::dx, 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::dy, memory_optimized>(
1566 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1567 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1568 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1569
1570 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1571 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1572 std::get<2>(spline_)
1573 .template eval<deriv::dx + deriv::dy, 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::dz, memory_optimized>(
1577 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1578 std::get<2>(spline_)
1579 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1580 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1581 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1582 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1583 std::get<2>(spline_)
1584 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1585 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1586 std::get<2>(spline_)
1587 .template eval<deriv::dz + deriv::dx, 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::dy, memory_optimized>(
1591 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1592 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1593 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)));
1594 }
1595 }
1596
1597 template <functionspace comp = functionspace::interior,
1598 bool memory_optimized = false>
1599 inline auto
1601 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1603 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1604 torch::Tensor> &coeff_indices) const {
1605
1606 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1607 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1608 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1609 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1610 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1611 xi[2].sizes() == xi[3].sizes());
1612
1613 if constexpr (comp == functionspace::interior) {
1614 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1615 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1616 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1617 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1618 "hess(.) for vector-valued spaces requires 1D variables");
1619
1621 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1622 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1623 std::get<0>(spline_)
1624 .template eval<deriv::dx + deriv::dy, 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::dz, 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::dt, memory_optimized>(
1631 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1632 std::get<0>(spline_)
1633 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1634 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1635 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1636 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1637 std::get<0>(spline_)
1638 .template eval<deriv::dy + deriv::dz, 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::dt, memory_optimized>(
1642 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1643 std::get<0>(spline_)
1644 .template eval<deriv::dz + deriv::dx, 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::dy, memory_optimized>(
1648 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1649 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1650 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1651 std::get<0>(spline_)
1652 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1653 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1654 std::get<0>(spline_)
1655 .template eval<deriv::dt + deriv::dx, 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::dy, 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::dz, memory_optimized>(
1662 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1663 std::get<0>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1664 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1665
1666 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1667 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1668 std::get<1>(spline_)
1669 .template eval<deriv::dx + deriv::dy, 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::dz, 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::dt, memory_optimized>(
1676 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1677 std::get<1>(spline_)
1678 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1679 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1680 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1681 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1682 std::get<1>(spline_)
1683 .template eval<deriv::dy + deriv::dz, 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::dt, memory_optimized>(
1687 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1688 std::get<1>(spline_)
1689 .template eval<deriv::dz + deriv::dx, 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::dy, memory_optimized>(
1693 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1694 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1695 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1696 std::get<1>(spline_)
1697 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1698 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1699 std::get<1>(spline_)
1700 .template eval<deriv::dt + deriv::dx, 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::dy, 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::dz, memory_optimized>(
1707 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1708 std::get<1>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1709 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1710
1711 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1712 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1713 std::get<2>(spline_)
1714 .template eval<deriv::dx + deriv::dy, 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::dz, 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::dt, memory_optimized>(
1721 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1722 std::get<2>(spline_)
1723 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1724 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1725 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1726 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1727 std::get<2>(spline_)
1728 .template eval<deriv::dy + deriv::dz, 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::dt, memory_optimized>(
1732 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1733 std::get<2>(spline_)
1734 .template eval<deriv::dz + deriv::dx, 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::dy, memory_optimized>(
1738 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1739 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1740 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1741 std::get<2>(spline_)
1742 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1743 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1744 std::get<2>(spline_)
1745 .template eval<deriv::dt + deriv::dx, 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::dy, 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::dz, memory_optimized>(
1752 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1753 std::get<2>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1754 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1755
1756 std::get<3>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1757 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1758 std::get<3>(spline_)
1759 .template eval<deriv::dx + deriv::dy, 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::dz, 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::dt, memory_optimized>(
1766 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1767 std::get<3>(spline_)
1768 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1769 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1770 std::get<3>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1771 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1772 std::get<3>(spline_)
1773 .template eval<deriv::dy + deriv::dz, 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::dt, memory_optimized>(
1777 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1778 std::get<3>(spline_)
1779 .template eval<deriv::dz + deriv::dx, 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::dy, memory_optimized>(
1783 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1784 std::get<3>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1785 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1786 std::get<3>(spline_)
1787 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1788 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1789 std::get<3>(spline_)
1790 .template eval<deriv::dt + deriv::dx, 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::dy, 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::dz, memory_optimized>(
1797 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1798 std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1799 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)));
1800 }
1801 }
1803
1804 // clang-format off
1838 // clang-format on
1840 template <functionspace comp = functionspace::interior,
1841 bool memory_optimized = false>
1842 inline auto jac(const utils::TensorArray<nspaces()> &xi) const {
1843 return jac<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1844 }
1845
1846 template <functionspace comp = functionspace::interior,
1847 bool memory_optimized = false,
1848 typename... TensorArrays>
1849 inline auto jac(const utils::TensorArray<nspaces()> &xi,
1850 const std::tuple<TensorArrays...> &knot_indices) const {
1851 return jac<comp, memory_optimized>(xi, knot_indices,
1852 find_coeff_indices<comp>(knot_indices));
1853 }
1854
1855 template <functionspace comp = functionspace::interior,
1856 bool memory_optimized = false>
1857 inline auto jac(const utils::TensorArray1 &xi,
1858 const std::tuple<utils::TensorArray1> &knot_indices,
1859 const std::tuple<torch::Tensor> &coeff_indices) const {
1860
1861 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1862
1863 if constexpr (comp == functionspace::interior) {
1864 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1865 "jac(.) for vector-valued spaces requires 1D variables");
1866
1868 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1869 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1870 }
1871 }
1872
1873 template <functionspace comp = functionspace::interior,
1874 bool memory_optimized = false>
1875 inline auto
1877 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1878 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1879
1880 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1881 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1882 xi[0].sizes() == xi[1].sizes());
1883
1884 if constexpr (comp == functionspace::interior) {
1885 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1886 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1887 "jac(.) for vector-valued spaces requires 1D variables");
1888
1890 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1891 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1892 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1893 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1894
1895 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1896 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1897 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1898 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1899 }
1900 }
1901
1902 template <functionspace comp = functionspace::interior,
1903 bool memory_optimized = false>
1904 inline auto jac(const utils::TensorArray3 &xi,
1905 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1906 utils::TensorArray3> &knot_indices,
1907 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1908 &coeff_indices) const {
1909
1910 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1911 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1912 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1913 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1914
1915 if constexpr (comp == functionspace::interior) {
1916 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1917 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1918 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1919 "jac(.) for vector-valued spaces requires 1D variables");
1920
1922 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1923 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1924 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1925 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1926 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1927 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1928
1929 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1930 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1931 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1932 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1933 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1934 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1935
1936 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1937 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1938 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1939 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1940 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1941 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1942 }
1943 }
1944
1945 template <functionspace comp = functionspace::interior,
1946 bool memory_optimized = false>
1947 inline auto
1949 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1951 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1952 torch::Tensor> &coeff_indices) const {
1953
1954 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1955 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1956 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1957 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1958 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1959 xi[2].sizes() == xi[3].sizes());
1960
1961 if constexpr (comp == functionspace::interior) {
1962 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1963 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1964 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1965 "jac(.) for vector-valued spaces requires 1D variables");
1966
1968 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1969 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1970 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1971 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1972 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1973 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1974 std::get<0>(spline_).template eval<deriv::dt, memory_optimized>(
1975 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1976
1977 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1978 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1979 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1980 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1981 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1982 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1983 std::get<1>(spline_).template eval<deriv::dt, memory_optimized>(
1984 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1985
1986 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1987 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1988 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1989 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1990 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1991 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1992 std::get<2>(spline_).template eval<deriv::dt, memory_optimized>(
1993 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1994
1995 std::get<3>(spline_).template eval<deriv::dx, memory_optimized>(
1996 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
1997 std::get<3>(spline_).template eval<deriv::dy, memory_optimized>(
1998 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
1999 std::get<3>(spline_).template eval<deriv::dz, memory_optimized>(
2000 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2001 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
2002 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2003 }
2004 }
2006
2007 // clang-format off
2024 // clang-format on
2027 template <functionspace comp = functionspace::interior,
2028 bool memory_optimized = false>
2029 inline auto lapl(const utils::TensorArray<nspaces()> &xi) const {
2030 return lapl<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
2031 }
2032
2033 template <functionspace comp = functionspace::interior,
2034 bool memory_optimized = false,
2035 typename... TensorArrays>
2036 inline auto lapl(const utils::TensorArray<nspaces()> &xi,
2037 const std::tuple<TensorArrays...> &knot_indices) const {
2038 return lapl<comp, memory_optimized>(xi, knot_indices,
2039 find_coeff_indices<comp>(knot_indices));
2040 }
2041
2042 template <functionspace comp = functionspace::interior,
2043 bool memory_optimized = false>
2044 inline auto lapl(const utils::TensorArray1 &xi,
2045 const std::tuple<utils::TensorArray1> &knot_indices,
2046 const std::tuple<torch::Tensor> &coeff_indices) const {
2047
2048 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
2049
2050 if constexpr (comp == functionspace::interior) {
2051 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
2052 "lapl(.) for vector-valued spaces requires 1D variables");
2053
2055 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2056 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
2057 }
2058 }
2059
2060 template <functionspace comp = functionspace::interior,
2061 bool memory_optimized = false>
2062 inline auto
2064 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
2065 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
2066
2067 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2068 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2069 xi[0].sizes() == xi[1].sizes());
2070
2071 if constexpr (comp == functionspace::interior) {
2072 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2073 std::tuple_element_t<1, spline_type>::geoDim() == 1,
2074 "lapl(.) for vector-valued spaces requires 1D variables");
2075
2077 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2078 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2079 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2080 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
2081 }
2082 }
2083
2084 template <functionspace comp = functionspace::interior,
2085 bool memory_optimized = false>
2086 inline auto lapl(const utils::TensorArray3 &xi,
2087 const std::tuple<utils::TensorArray3, utils::TensorArray3,
2088 utils::TensorArray3> &knot_indices,
2089 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
2090 &coeff_indices) const {
2091
2092 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2093 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2094 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2095 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
2096
2097 if constexpr (comp == functionspace::interior) {
2098 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2099 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2100 std::tuple_element_t<2, spline_type>::geoDim() == 1,
2101 "div(.) for vector-valued spaces requires 1D variables");
2102
2104 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2105 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2106 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2107 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2108 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2109 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
2110 }
2111 }
2112
2113 template <functionspace comp = functionspace::interior,
2114 bool memory_optimized = false>
2115 inline auto
2117 const std::tuple<utils::TensorArray4, utils::TensorArray4,
2119 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
2120 torch::Tensor> &coeff_indices) const {
2121
2122 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2123 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2124 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2125 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
2126 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
2127 xi[2].sizes() == xi[3].sizes());
2128
2129 if constexpr (comp == functionspace::interior) {
2130 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2131 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2132 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
2133 std::tuple_element_t<3, spline_type>::geoDim() == 1,
2134 "div(.) for vector-valued spaces requires 1D variables");
2135
2137 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2138 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2139 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2140 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2141 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2142 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
2143 *std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
2144 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2145 }
2146 }
2148
2149#define GENERATE_EXPR_MACRO(r, data, name) \
2150private: \
2151 template <functionspace comp = functionspace::interior, \
2152 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
2153 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2154 const std::tuple<Xi...> &xi) const { \
2155 if constexpr (comp == functionspace::interior) \
2156 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2157 std::get<Is>(xi))...); \
2158 else if constexpr (comp == functionspace::boundary) \
2159 return std::tuple( \
2160 std::get<Is>(boundary_).template name<memory_optimized>( \
2161 std::get<Is>(xi))...); \
2162 } \
2163 \
2164 template <functionspace comp = functionspace::interior, \
2165 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2166 typename... Knot_Indices> \
2167 inline auto BOOST_PP_CAT(name, _all_)( \
2168 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2169 const std::tuple<Knot_Indices...> &knot_indices) const { \
2170 if constexpr (comp == functionspace::interior) \
2171 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2172 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2173 else if constexpr (comp == functionspace::boundary) \
2174 return std::tuple( \
2175 std::get<Is>(boundary_).template name<memory_optimized>( \
2176 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2177 } \
2178 \
2179 template <functionspace comp = functionspace::interior, \
2180 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2181 typename... Knot_Indices, typename... Coeff_Indices> \
2182 inline auto BOOST_PP_CAT(name, _all_)( \
2183 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2184 const std::tuple<Knot_Indices...> &knot_indices, \
2185 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
2186 if constexpr (comp == functionspace::interior) \
2187 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2188 std::get<Is>(xi), std::get<Is>(knot_indices), \
2189 std::get<Is>(coeff_indices))...); \
2190 else if constexpr (comp == functionspace::boundary) \
2191 return std::tuple( \
2192 std::get<Is>(boundary_).template name<memory_optimized>( \
2193 std::get<Is>(xi), std::get<Is>(knot_indices), \
2194 std::get<Is>(coeff_indices))...); \
2195 } \
2196 \
2197 template <functionspace comp = functionspace::interior, \
2198 bool memory_optimized = false, std::size_t... Is, std::size_t N> \
2199 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
2200 const utils::TensorArray<N> &xi) const { \
2201 if constexpr (comp == functionspace::interior) \
2202 return name<comp, memory_optimized>( \
2203 xi, std::tuple(std::get<Is>(spline_).find_knot_indices(xi)...)); \
2204 else if constexpr (comp == functionspace::boundary) \
2205 return name<comp, memory_optimized>( \
2206 xi, std::tuple(std::get<Is>(boundary_).find_knot_indices(xi)...)); \
2207 } \
2208 \
2209 template <functionspace comp = functionspace::interior, \
2210 bool memory_optimized = false, std::size_t... Is, std::size_t N, \
2211 typename... Knot_Indices> \
2212 inline auto BOOST_PP_CAT(name, _)( \
2213 std::index_sequence<Is...>, const utils::TensorArray<N> &xi, \
2214 const std::tuple<Knot_Indices...> &knot_indices) const { \
2215 if constexpr (comp == functionspace::interior) \
2216 return name<comp, memory_optimized>( \
2217 xi, knot_indices, \
2218 std::tuple(std::get<Is>(spline_).find_coeff_indices( \
2219 std::get<Is>(knot_indices))...)); \
2220 else if constexpr (comp == functionspace::boundary) \
2221 return name<comp, memory_optimized>( \
2222 xi, knot_indices, \
2223 std::tuple(std::get<Is>(boundary_).find_coeff_indices( \
2224 std::get<Is>(knot_indices))...)); \
2225 } \
2226 \
2227public: \
2228 template <functionspace comp = functionspace::interior, \
2229 bool memory_optimized = false, typename... Args> \
2230 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2231 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2232 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2233 } \
2234 \
2235 template <functionspace comp = functionspace::interior, \
2236 bool memory_optimized = false> \
2237 inline auto name(const torch::Tensor &xi) const { \
2238 return name<comp, memory_optimized>(utils::TensorArray1({xi})); \
2239 } \
2240 \
2241 template <functionspace comp = functionspace::interior, \
2242 bool memory_optimized = false, std::size_t N> \
2243 inline auto name(const utils::TensorArray<N> &xi) const { \
2244 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2245 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi); \
2246 } \
2247 \
2248 template <functionspace comp = functionspace::interior, \
2249 bool memory_optimized = false, std::size_t N, \
2250 typename... Knot_Indices> \
2251 inline auto name(const utils::TensorArray<N> &xi, \
2252 const std::tuple<Knot_Indices...> &knot_indices) const { \
2253 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2254 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, \
2255 knot_indices); \
2256 }
2257
2260 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
2262#undef GENERATE_EXPR_MACRO
2263
2264#define GENERATE_IEXPR_MACRO(r, data, name) \
2265private: \
2266 template <functionspace comp = functionspace::interior, \
2267 bool memory_optimized = false, std::size_t... Is, \
2268 typename Geometry, typename... Xi> \
2269 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2270 const Geometry &G, \
2271 const std::tuple<Xi...> &xi) const { \
2272 if constexpr (comp == functionspace::interior) { \
2273 if constexpr (Geometry::nspaces() == 1) \
2274 return std::tuple( \
2275 std::get<Is>(spline_).template name<memory_optimized>( \
2276 G.space(), std::get<Is>(xi))...); \
2277 else if constexpr (Geometry::nspaces() == nspaces()) \
2278 return std::tuple( \
2279 std::get<Is>(spline_).template name<memory_optimized>( \
2280 G.template space<Is>(), std::get<Is>(xi))...); \
2281 } else if constexpr (comp == functionspace::boundary) { \
2282 if constexpr (Geometry::nboundaries() == 1) \
2283 return std::tuple( \
2284 std::get<Is>(boundary_).template name<memory_optimized>( \
2285 static_cast<typename Geometry::boundary_type::boundary_type>( \
2286 G.boundary().coeffs()), \
2287 std::get<Is>(xi))...); \
2288 else if constexpr (Geometry::nboundaries() == nboundaries()) \
2289 return std::tuple( \
2290 std::get<Is>(boundary_).template name<memory_optimized>( \
2291 G.template boundary<Is>().coeffs(), std::get<Is>(xi))...); \
2292 } \
2293 } \
2294 \
2295 template <functionspace comp = functionspace::interior, \
2296 bool memory_optimized = false, std::size_t... Is, \
2297 typename Geometry, typename... Xi, typename... Knot_Indices, \
2298 typename... Knot_Indices_G> \
2299 inline auto BOOST_PP_CAT(name, _all_)( \
2300 std::index_sequence<Is...>, const Geometry &G, \
2301 const std::tuple<Xi...> &xi, \
2302 const std::tuple<Knot_Indices...> &knot_indices, \
2303 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
2304 if constexpr (comp == functionspace::interior) { \
2305 if constexpr (Geometry::nspaces() == 1) \
2306 return std::tuple( \
2307 std::get<Is>(spline_).template name<memory_optimized>( \
2308 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2309 std::get<Is>(knot_indices_G))...); \
2310 else \
2311 return std::tuple( \
2312 std::get<Is>(spline_).template name<memory_optimized>( \
2313 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2314 std::get<Is>(knot_indices_G))...); \
2315 } else if constexpr (comp == functionspace::boundary) { \
2316 if constexpr (Geometry::nspaces() == 1) \
2317 return std::tuple( \
2318 std::get<Is>(boundary_).template name<memory_optimized>( \
2319 static_cast<typename Geometry::boundary_type::boundary_type>( \
2320 G.boundary().coeffs()), \
2321 std::get<Is>(xi), std::get<Is>(knot_indices), \
2322 std::get<Is>(knot_indices_G))...); \
2323 else \
2324 return std::tuple( \
2325 std::get<Is>(boundary_).template name<memory_optimized>( \
2326 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2327 std::get<Is>(knot_indices), std::get<Is>(knot_indices_G))...); \
2328 } \
2329 } \
2330 \
2331 template <functionspace comp = functionspace::interior, \
2332 bool memory_optimized = false, std::size_t... Is, \
2333 typename Geometry, typename... Xi, typename... Knot_Indices, \
2334 typename... Coeff_Indices, typename... Knot_Indices_G, \
2335 typename... Coeff_Indices_G> \
2336 inline auto BOOST_PP_CAT(name, _all_)( \
2337 std::index_sequence<Is...>, const Geometry &G, \
2338 const std::tuple<Xi...> &xi, \
2339 const std::tuple<Knot_Indices...> &knot_indices, \
2340 const std::tuple<Coeff_Indices...> &coeff_indices, \
2341 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
2342 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
2343 if constexpr (comp == functionspace::interior) { \
2344 if constexpr (Geometry::nspaces() == 1) \
2345 return std::tuple( \
2346 std::get<Is>(spline_).template name<memory_optimized>( \
2347 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2348 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2349 std::get<Is>(coeff_indices_G))...); \
2350 else \
2351 return std::tuple( \
2352 std::get<Is>(spline_).template name<memory_optimized>( \
2353 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2354 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2355 std::get<Is>(coeff_indices_G))...); \
2356 } else if constexpr (comp == functionspace::boundary) { \
2357 if constexpr (Geometry::nspaces() == 1) \
2358 return std::tuple( \
2359 std::get<Is>(boundary_).template name<memory_optimized>( \
2360 static_cast<typename Geometry::boundary_type::boundary_type>( \
2361 G.boundary().coeffs()), \
2362 std::get<Is>(xi), std::get<Is>(knot_indices), \
2363 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2364 std::get<Is>(coeff_indices_G))...); \
2365 else \
2366 return std::tuple( \
2367 std::get<Is>(boundary_).template name<memory_optimized>( \
2368 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2369 std::get<Is>(knot_indices), std::get<Is>(coeff_indices), \
2370 std::get<Is>(knot_indices_G), \
2371 std::get<Is>(coeff_indices_G))...); \
2372 } \
2373 } \
2374 \
2375public: \
2376 template <functionspace comp = functionspace::interior, \
2377 bool memory_optimized = false, typename... Args> \
2378 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2379 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2380 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2381 }
2382
2385 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
2387#undef GENERATE_IEXPR_MACRO
2388};
2389
2391template <typename... Splines>
2392inline std::ostream &operator<<(std::ostream &os,
2393 const FunctionSpace<Splines...> &obj) {
2394 obj.pretty_print(os);
2395 return os;
2396}
2397
2402template <typename Spline, typename Boundary>
2403// requires SplineType<Spline> && BoundaryType<Boundary>
2405 public utils::Serializable,
2406 private utils::FullQualifiedName {
2407
2408public:
2410 using value_type = typename Spline::value_type;
2411
2413 using spline_type = Spline;
2414
2416 using eval_type = utils::TensorArray<Spline::parDim()>;
2417
2420
2422 using boundary_eval_type = typename Boundary::eval_type;
2423
2424protected:
2427
2430
2431public:
2433 FunctionSpace() = default;
2434
2436 FunctionSpace(const FunctionSpace &) = default;
2437
2440
2443 FunctionSpace(const std::array<int64_t, Spline::parDim()> &ncoeffs,
2444 enum init init = init::greville,
2446 : spline_(ncoeffs, init, options),
2447 boundary_(ncoeffs, init::none, options) {
2448 boundary_.from_full_tensor(spline_.as_tensor());
2449 }
2450
2451 FunctionSpace(std::array<std::vector<value_type>, Spline::parDim()> kv,
2452 enum init init = init::greville,
2454 : spline_(kv, init, options), boundary_(kv, init::none, options) {
2455 static_assert(Spline::is_nonuniform(),
2456 "Constructor is only available for non-uniform splines");
2457 boundary_.from_full_tensor(spline_.as_tensor());
2458 }
2459
2460 explicit FunctionSpace(const Spline &spline)
2461 : spline_(spline),
2462 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2463 boundary_.from_full_tensor(spline_.as_tensor());
2464 }
2465
2466 explicit FunctionSpace(Spline &&spline)
2467 : spline_(spline),
2468 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2469 boundary_.from_full_tensor(spline_.as_tensor());
2470 }
2472
2474 inline static constexpr std::size_t nspaces() noexcept { return 1; }
2475
2477 inline static constexpr std::size_t nboundaries() noexcept { return 1; }
2478
2480 template <std::size_t index = 0>
2481 inline constexpr const spline_type &space() const noexcept {
2482 static_assert(index >= 0 && index < nspaces());
2483 return spline_;
2484 }
2485
2487 template <std::size_t index = 0> inline constexpr spline_type &space() noexcept {
2488 static_assert(index >= 0 && index < nspaces());
2489 return spline_;
2490 }
2491
2493 template <std::size_t index = 0>
2494 inline constexpr const boundary_type &boundary() const noexcept {
2495 static_assert(index >= 0 && index < nboundaries());
2496 return boundary_;
2497 }
2498
2501 template <std::size_t index = 0> inline constexpr boundary_type &boundary() noexcept {
2502 static_assert(index >= 0 && index < nboundaries());
2503 return boundary_;
2504 }
2505
2507 inline constexpr FunctionSpace clone() const noexcept {
2508 return FunctionSpace(*this);
2509 }
2510
2512 template <std::size_t... index> inline constexpr auto clone() const noexcept {
2513
2514 static_assert(((index >= 0 && index < nspaces()) && ... && true));
2515
2516 if constexpr (sizeof...(index) == 1)
2517 return FunctionSpace(*this);
2518 else
2519 return FunctionSpace<
2520 std::tuple<std::tuple_element_t<index, std::tuple<spline_type>>...>,
2521 std::tuple<std::tuple_element_t<index, std::tuple<boundary_type>>...>>(
2522 std::get<index>(std::make_tuple(spline_))...,
2523 std::get<index>(std::make_tuple(boundary_))...);
2524 }
2525
2527 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
2528 return spline_.as_tensor();
2529 }
2530
2532 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
2533 return boundary_.as_tensor();
2534 }
2535
2541 virtual inline torch::Tensor as_tensor() const noexcept {
2542 return spaces_as_tensor();
2543 }
2544
2547 virtual inline int64_t spaces_as_tensor_size() const noexcept {
2548 return spline_.as_tensor_size();
2549 }
2550
2553 virtual inline int64_t boundary_as_tensor_size() const noexcept {
2554 return boundary_.as_tensor_size();
2555 }
2556
2562 virtual inline int64_t as_tensor_size() const noexcept {
2563 return spaces_as_tensor_size();
2564 }
2565
2567 virtual inline FunctionSpace &
2568 spaces_from_tensor(const torch::Tensor &coeffs) noexcept {
2569 spline_.from_tensor(coeffs);
2570 return *this;
2571 }
2572
2575 virtual inline FunctionSpace &
2576 boundary_from_tensor(const torch::Tensor &coeffs) noexcept {
2577 boundary_.from_tensor(coeffs);
2578 return *this;
2579 }
2580
2582 virtual inline FunctionSpace &
2583 boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept {
2584 boundary_.from_full_tensor(coeffs);
2585 return *this;
2586 }
2587
2589 inline FunctionSpace &from_tensor(const torch::Tensor &coeffs) noexcept {
2590 spline_.from_tensor(coeffs);
2591 boundary_.from_full_tensor(coeffs);
2592 return *this;
2593 }
2594
2596 inline pugi::xml_document to_xml(int id = 0, std::string label = "") const {
2597 pugi::xml_document doc;
2598 pugi::xml_node root = doc.append_child("xml");
2599 to_xml(root, id, label);
2600
2601 return doc;
2602 }
2603
2605 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
2606 std::string label = "") const {
2607 return spline_.to_xml(root, id, label);
2608 }
2609
2611 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
2612 std::string label = "") {
2613 return from_xml(doc.child("xml"), id, label);
2614 }
2615
2617 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
2618 std::string label = "") {
2619 spline_.from_xml(root, id, label);
2620 return *this;
2621 }
2622
2624 nlohmann::json to_json() const override {
2625 auto json = nlohmann::json::array();
2626 json.push_back(spline_.to_json());
2627 json.push_back(boundary_.to_json());
2628 return json;
2629 }
2630
2633 const std::function<std::array<typename Spline::value_type,
2634 Spline::geoDim()>(
2635 const std::array<typename Spline::value_type, Spline::parDim()> &)>
2636 transformation) {
2637 spline_.transform(transformation);
2638 return *this;
2639 }
2640
2641private:
2644 template <functionspace comp = functionspace::interior,
2645 deriv deriv = deriv::func, bool memory_optimized = false,
2646 std::size_t... Is, typename... Xi>
2647 inline auto eval_(std::index_sequence<Is...>,
2648 const std::tuple<Xi...> &xi) const {
2649 if constexpr (comp == functionspace::interior)
2650 return std::tuple(
2651 spline_.template eval<deriv, memory_optimized>(std::get<Is>(xi))...);
2652 else if constexpr (comp == functionspace::boundary)
2653 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2654 std::get<Is>(xi))...);
2655 }
2656
2657 template <functionspace comp = functionspace::interior,
2658 deriv deriv = deriv::func, bool memory_optimized = false,
2659 std::size_t... Is, typename... Xi, typename... Knot_Indices>
2660 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
2661 const std::tuple<Knot_Indices...> &knot_indices) const {
2662 if constexpr (comp == functionspace::interior)
2663 return std::tuple(spline_.template eval<deriv, memory_optimized>(
2664 std::get<Is>(xi), std::get<Is>(knot_indices))...);
2665 else if constexpr (comp == functionspace::boundary)
2666 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2667 std::get<Is>(xi), std::get<Is>(knot_indices))...);
2668 }
2669
2670 template <functionspace comp = functionspace::interior,
2671 deriv deriv = deriv::func, bool memory_optimized = false,
2672 std::size_t... Is, typename... Xi, typename... Knot_Indices,
2673 typename... Coeff_Indices>
2674 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
2675 const std::tuple<Knot_Indices...> &knot_indices,
2676 const std::tuple<Coeff_Indices...> &coeff_indices) const {
2677 if constexpr (comp == functionspace::interior)
2678 return std::tuple(spline_.template eval<deriv, memory_optimized>(
2679 std::get<Is>(xi), std::get<Is>(knot_indices),
2680 std::get<Is>(coeff_indices))...);
2681 else if constexpr (comp == functionspace::boundary)
2682 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2683 std::get<Is>(xi), std::get<Is>(knot_indices),
2684 std::get<Is>(coeff_indices))...);
2685 }
2687
2688public:
2690 template <functionspace comp = functionspace::interior,
2691 deriv deriv = deriv::func, bool memory_optimized = false,
2692 typename Arg, typename... Args>
2693 inline auto eval(const Arg &arg, const Args &...args) const {
2694 if constexpr (comp == functionspace::interior)
2695 if constexpr (utils::is_tuple_v<Arg>)
2696 return eval_<comp, deriv, memory_optimized>(
2697 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
2698 else
2699 return spline_.template eval<deriv, memory_optimized>(arg, args...);
2700 else if constexpr (comp == functionspace::boundary) {
2701 if constexpr (utils::is_tuple_of_tuples_v<Arg>)
2702 return eval_<comp, deriv, memory_optimized>(
2703 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
2704 else
2705 return boundary_.template eval<deriv, memory_optimized>(arg, args...);
2706 }
2707 }
2708
2711 template <functionspace comp = functionspace::interior, typename... Args>
2712 inline auto eval_from_precomputed(const Args &...args) const {
2713 if constexpr (comp == functionspace::interior)
2714 return spline_.eval_from_precomputed(args...);
2715 else if constexpr (comp == functionspace::boundary)
2716 return boundary_.eval_from_precomputed(args...);
2717 }
2718
2719private:
2721 template <functionspace comp = functionspace::interior, std::size_t... Is,
2722 typename Xi>
2723 inline auto find_knot_indices_(std::index_sequence<Is...>,
2724 const Xi &xi) const {
2725 if constexpr (comp == functionspace::interior)
2726 return std::tuple(spline_.find_knot_indices(std::get<Is>(xi))...);
2727 else
2728 return std::tuple(boundary_.find_knot_indices(std::get<Is>(xi))...);
2729 }
2730
2731public:
2733 template <functionspace comp = functionspace::interior, typename Xi>
2734 inline auto find_knot_indices(const Xi &xi) const {
2735 if constexpr (comp == functionspace::interior)
2736 if constexpr (utils::is_tuple_v<Xi>)
2737 return find_knot_indices_<comp>(
2738 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
2739 else
2740 return spline_.find_knot_indices(xi);
2741 else if constexpr (comp == functionspace::boundary) {
2742 if constexpr (utils::is_tuple_of_tuples_v<Xi>)
2743 return find_knot_indices_<comp>(
2744 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
2745 else
2746 return boundary_.find_knot_indices(xi);
2747 }
2748 }
2749
2752 template <functionspace comp = functionspace::interior,
2753 deriv deriv = deriv::func, bool memory_optimized = false,
2754 typename... Args>
2755 inline auto eval_basfunc(const Args &...args) const {
2756 if constexpr (comp == functionspace::interior)
2757 return spline_.template eval_basfunc<deriv, memory_optimized>(args...);
2758 else if constexpr (comp == functionspace::boundary)
2759 return boundary_.template eval_basfunc<deriv, memory_optimized>(args...);
2760 }
2761
2762private:
2765 template <functionspace comp = functionspace::interior,
2766 bool memory_optimized = false, std::size_t... Is,
2767 typename Knot_Indices>
2768 inline auto find_coeff_indices_(std::index_sequence<Is...>,
2769 const Knot_Indices &knot_indices) const {
2770 if constexpr (comp == functionspace::interior)
2771 return std::tuple(spline_.template find_coeff_indices<memory_optimized>(
2772 std::get<Is>(knot_indices))...);
2773 else
2774 return std::tuple(boundary_.template find_coeff_indices<memory_optimized>(
2775 std::get<Is>(knot_indices))...);
2776 }
2777
2778public:
2781 template <functionspace comp = functionspace::interior,
2782 bool memory_optimized = false, typename Knot_Indices>
2783 inline auto find_coeff_indices(const Knot_Indices &knot_indices) const {
2784 if constexpr (comp == functionspace::interior)
2785 if constexpr (utils::is_tuple_v<Knot_Indices>)
2786 return find_coeff_indices_<comp, memory_optimized>(
2787 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
2788 knot_indices);
2789 else
2790 return spline_.template find_coeff_indices<memory_optimized>(
2791 knot_indices);
2792 else if constexpr (comp == functionspace::boundary) {
2793 if constexpr (utils::is_tuple_of_tuples_v<Knot_Indices>)
2794 return find_coeff_indices_<comp, memory_optimized>(
2795 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
2796 knot_indices);
2797 else
2798 return boundary_.template find_coeff_indices<memory_optimized>(
2799 knot_indices);
2800 }
2801 }
2802
2805 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
2806 spline_.uniform_refine(numRefine, dimRefine);
2807 boundary_.uniform_refine(numRefine, dimRefine);
2808 return *this;
2809 }
2810
2813 template <typename real_t> inline auto to(Options<real_t> options) const {
2814 return FunctionSpace<
2815 typename spline_type::template real_derived_self_type<real_t>,
2816 typename boundary_type::template real_derived_self_type<real_t>>(
2817 spline_.to(options), boundary_.to(options));
2818 }
2819
2822 inline auto to(torch::Device device) const {
2823 return FunctionSpace(spline_.to(device), boundary_.to(device));
2824 }
2825
2827 template <typename real_t> inline auto to() const {
2828 return FunctionSpace<
2829 typename spline_type::template real_derived_self_type<real_t>,
2830 typename boundary_type::template real_derived_self_type<real_t>>(
2831 spline_.template to<real_t>(), boundary_.template to<real_t>());
2832 }
2833
2835 inline auto scale(value_type s, int dim = -1) {
2836 spline_.scale(s, dim);
2837 boundary_.from_full_tensor(spline_.as_tensor());
2838 return *this;
2839 }
2840
2842 template <std::size_t N> inline auto scale(std::array<value_type, N> v) {
2843 spline_.scale(v);
2844 boundary_.from_full_tensor(spline_.as_tensor());
2845 return *this;
2846 }
2847
2849 template <std::size_t N> inline auto translate(std::array<value_type, N> v) {
2850 spline_.translate(v);
2851 boundary_.from_full_tensor(spline_.as_tensor());
2852 return *this;
2853 }
2854
2856 inline auto rotate(value_type angle) {
2857 spline_.rotate(angle);
2858 boundary_.from_full_tensor(spline_.as_tensor());
2859 return *this;
2860 }
2861
2863 inline auto rotate(std::array<value_type, 3> angle) {
2864 spline_.rotate(angle);
2865 boundary_.from_full_tensor(spline_.as_tensor());
2866 return *this;
2867 }
2868
2871 inline torch::serialize::OutputArchive &
2872 write(torch::serialize::OutputArchive &archive,
2873 const std::string &key = "functionspace") const {
2874 spline_.write(archive, key);
2875 boundary_.write(archive, key);
2876 return archive;
2877 }
2878
2881 inline torch::serialize::InputArchive &
2882 read(torch::serialize::InputArchive &archive,
2883 const std::string &key = "functionspace") {
2884 spline_.read(archive, key);
2885 boundary_.read(archive, key);
2886 return archive;
2887 }
2888
2890 inline virtual void
2891 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
2892 os << name() << "(\nspline = ";
2893 spline_.pretty_print(os);
2894 os << "\nboundary = ";
2895 boundary_.pretty_print(os);
2896 os << "\n)";
2897 }
2898
2899#define GENERATE_EXPR_MACRO(r, data, name) \
2900private: \
2901 template <functionspace comp = functionspace::interior, \
2902 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
2903 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2904 const std::tuple<Xi...> &xi) const { \
2905 if constexpr (comp == functionspace::interior) \
2906 return std::tuple( \
2907 spline_.template name<memory_optimized>(std::get<Is>(xi))...); \
2908 else if constexpr (comp == functionspace::boundary) \
2909 return std::tuple( \
2910 boundary_.template name<memory_optimized>(std::get<Is>(xi))...); \
2911 } \
2912 \
2913 template <functionspace comp = functionspace::interior, \
2914 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2915 typename... Knot_Indices> \
2916 inline auto BOOST_PP_CAT(name, _all_)( \
2917 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2918 const std::tuple<Knot_Indices...> &knot_indices) const { \
2919 if constexpr (comp == functionspace::interior) \
2920 return std::tuple(spline_.template name<memory_optimized>( \
2921 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2922 else if constexpr (comp == functionspace::boundary) \
2923 return std::tuple(boundary_.template name<memory_optimized>( \
2924 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2925 } \
2926 \
2927 template <functionspace comp = functionspace::interior, \
2928 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2929 typename... Knot_Indices, typename... Coeff_Indices> \
2930 inline auto BOOST_PP_CAT(name, _all_)( \
2931 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2932 const std::tuple<Knot_Indices...> &knot_indices, \
2933 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
2934 if constexpr (comp == functionspace::interior) \
2935 return std::tuple(spline_.template name<memory_optimized>( \
2936 std::get<Is>(xi), std::get<Is>(knot_indices), \
2937 std::get<Is>(coeff_indices))...); \
2938 else if constexpr (comp == functionspace::boundary) \
2939 return std::tuple(boundary_.template name<memory_optimized>( \
2940 std::get<Is>(xi), std::get<Is>(knot_indices), \
2941 std::get<Is>(coeff_indices))...); \
2942 } \
2943 \
2944public: \
2945 template <functionspace comp = functionspace::interior, \
2946 bool memory_optimized = false, typename Arg, typename... Args> \
2947 inline auto name(const Arg &arg, const Args &...args) const { \
2948 if constexpr (comp == functionspace::interior) \
2949 if constexpr (utils::is_tuple_v<Arg>) \
2950 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2951 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
2952 else \
2953 return spline_.template name<memory_optimized>(arg, args...); \
2954 else if constexpr (comp == functionspace::boundary) { \
2955 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
2956 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2957 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
2958 else \
2959 return boundary_.template name<memory_optimized>(arg, args...); \
2960 } \
2961 }
2962
2965 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
2967#undef GENERATE_EXPR_MACRO
2968
2969#define GENERATE_IEXPR_MACRO(r, data, name) \
2970private: \
2971 template <functionspace comp = functionspace::interior, \
2972 bool memory_optimized = false, std::size_t... Is, \
2973 typename Geometry, typename... Xi> \
2974 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2975 const Geometry &G, \
2976 const std::tuple<Xi...> &xi) const { \
2977 if constexpr (comp == functionspace::interior) \
2978 return std::tuple(spline_.template name<memory_optimized>( \
2979 G.space(), std::get<Is>(xi))...); \
2980 else if constexpr (comp == functionspace::boundary) \
2981 return std::tuple(boundary_.template name<memory_optimized>( \
2982 static_cast<typename Geometry::boundary_type::boundary_type>( \
2983 G.boundary().coeffs()), \
2984 std::get<Is>(xi))...); \
2985 } \
2986 \
2987 template <functionspace comp = functionspace::interior, \
2988 bool memory_optimized = false, std::size_t... Is, \
2989 typename Geometry, typename... Xi, typename... Knot_Indices, \
2990 typename... Knot_Indices_G> \
2991 inline auto BOOST_PP_CAT(name, _all_)( \
2992 std::index_sequence<Is...>, const Geometry &G, \
2993 const std::tuple<Xi...> &xi, \
2994 const std::tuple<Knot_Indices...> &knot_indices, \
2995 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
2996 if constexpr (comp == functionspace::interior) \
2997 return std::tuple(spline_.template name<memory_optimized>( \
2998 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2999 std::get<Is>(knot_indices_G))...); \
3000 else if constexpr (comp == functionspace::boundary) \
3001 return std::tuple(boundary_.template name<memory_optimized>( \
3002 static_cast<typename Geometry::boundary_type::boundary_type>( \
3003 G.boundary().coeffs()), \
3004 std::get<Is>(xi), std::get<Is>(knot_indices), \
3005 std::get<Is>(knot_indices_G))...); \
3006 } \
3007 \
3008 template <functionspace comp = functionspace::interior, \
3009 bool memory_optimized = false, std::size_t... Is, \
3010 typename Geometry, typename... Xi, typename... Knot_Indices, \
3011 typename... Coeff_Indices, typename... Knot_Indices_G, \
3012 typename... Coeff_Indices_G> \
3013 inline auto BOOST_PP_CAT(name, _all_)( \
3014 std::index_sequence<Is...>, const Geometry &G, \
3015 const std::tuple<Xi...> &xi, \
3016 const std::tuple<Knot_Indices...> &knot_indices, \
3017 const std::tuple<Coeff_Indices...> &coeff_indices, \
3018 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
3019 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
3020 if constexpr (comp == functionspace::interior) \
3021 return std::tuple(spline_.template name<memory_optimized>( \
3022 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
3023 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3024 std::get<Is>(coeff_indices_G))...); \
3025 else if constexpr (comp == functionspace::boundary) \
3026 return std::tuple(boundary_.template name<memory_optimized>( \
3027 static_cast<typename Geometry::boundary_type::boundary_type>( \
3028 G.boundary().coeffs()), \
3029 std::get<Is>(xi), std::get<Is>(knot_indices), \
3030 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3031 std::get<Is>(coeff_indices_G))...); \
3032 } \
3033 \
3034public: \
3035 template <functionspace comp = functionspace::interior, \
3036 bool memory_optimized = false, typename Geometry, typename Arg, \
3037 typename... Args> \
3038 inline auto name(const Geometry &G, const Arg &arg, const Args &...args) \
3039 const { \
3040 if constexpr (comp == functionspace::interior) { \
3041 if constexpr (utils::is_tuple_v<Arg>) \
3042 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3043 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3044 args...); \
3045 else \
3046 return spline_.template name<memory_optimized>(G.space(), arg, \
3047 args...); \
3048 } else if constexpr (comp == functionspace::boundary) { \
3049 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
3050 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3051 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3052 args...); \
3053 else \
3054 return boundary_.template name<memory_optimized>( \
3055 static_cast<typename Geometry::boundary_type::boundary_type>( \
3056 G.boundary().coeffs()), \
3057 arg, args...); \
3058 } \
3059 }
3060
3063 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
3065#undef GENERATE_IEXPR_MACRO
3066};
3067
3069template <typename... Args> struct FunctionSpace_trait;
3070
3072template <typename Spline> struct FunctionSpace_trait<Spline> {
3074};
3075
3077template <typename Spline, typename Boundary>
3081
3083template <typename... Splines>
3084struct FunctionSpace_trait<std::tuple<Splines...>> {
3087};
3088
3090template <typename... Splines, typename... Boundaries>
3091struct FunctionSpace_trait<std::tuple<Splines...>, std::tuple<Boundaries...>> {
3093 utils::tuple_cat_t<Boundaries...>>;
3094};
3095
3099template <typename Spline, typename Boundary>
3103
3107template <typename... Splines, typename... Boundaries>
3108struct FunctionSpace_trait<std::tuple<FunctionSpace<Splines, Boundaries>...>> {
3109 using type =
3110 typename FunctionSpace_trait<utils::tuple_cat_t<Splines...>,
3111 utils::tuple_cat_t<Boundaries...>>::type;
3112};
3113
3114} // namespace detail
3115
3117 template<typename T>
3118 concept FunctionSpaceType = std::is_base_of_v<detail::FunctionSpaceType, T>;
3119
3121template <typename... Args>
3122using FunctionSpace = typename detail::FunctionSpace_trait<Args...>::type;
3123
3125template <typename Splines, typename Boundaries>
3126inline std::ostream &operator<<(std::ostream &os,
3128 obj.pretty_print(os);
3129 return os;
3130}
3131
3149template <typename Spline> using S = FunctionSpace<Spline>;
3150
3152template <typename Spline, short_t = Spline::parDim()> class TH;
3153
3163template <typename Spline>
3164class TH<Spline, 1>
3165 : public FunctionSpace<
3166 std::tuple<typename Spline::template derived_self_type<
3167 typename Spline::value_type, Spline::geoDim(),
3168 Spline::degree(0) + 1>,
3169 typename Spline::template derived_self_type<
3170 typename Spline::value_type, Spline::geoDim(),
3171 Spline::degree(0)>>> {
3172public:
3174 using Base = FunctionSpace<std::tuple<
3175 typename Spline::template derived_self_type<
3176 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3177 typename Spline::template derived_self_type<
3178 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3179
3182 TH(const std::array<int64_t, 1> &ncoeffs, enum init init = init::greville,
3185 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {
3186 static_assert(Spline::is_nonuniform(),
3187 "TH function space requires non-uniform splines");
3188 Base::template space<0>().reduce_continuity();
3189 }
3190
3191 TH(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3192 enum init init = init::greville,
3195 : Base({{kv[0].front + kv[0] + kv[0].back(), kv[1]}}, kv, init, options) {
3196 static_assert(Spline::is_nonuniform(),
3197 "TH function space requires non-uniform splines");
3198 Base::template space<0>().reduce_continuity();
3199 }
3201
3203};
3204
3216template <typename Spline>
3217class TH<Spline, 2>
3218 : public FunctionSpace<
3219 std::tuple<typename Spline::template derived_self_type<
3220 typename Spline::value_type, Spline::geoDim(),
3221 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3222 typename Spline::template derived_self_type<
3223 typename Spline::value_type, Spline::geoDim(),
3224 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3225 typename Spline::template derived_self_type<
3226 typename Spline::value_type, Spline::geoDim(),
3227 Spline::degree(0), Spline::degree(1)>>> {
3228public:
3231 std::tuple<typename Spline::template derived_self_type<
3232 typename Spline::value_type, Spline::geoDim(),
3233 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3234 typename Spline::template derived_self_type<
3235 typename Spline::value_type, Spline::geoDim(),
3236 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3237 typename Spline::template derived_self_type<
3238 typename Spline::value_type, Spline::geoDim(),
3239 Spline::degree(0), Spline::degree(1)>>>;
3240
3243 TH(const std::array<int64_t, 2> &ncoeffs, enum init init = init::greville,
3246 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
3247 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
3248 static_assert(Spline::is_nonuniform(),
3249 "TH function space requires non-uniform splines");
3250 Base::template space<0>().reduce_continuity();
3251 Base::template space<1>().reduce_continuity();
3252 }
3253
3254 TH(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3255 enum init init = init::greville,
3258 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3259 kv[1].front() + kv[1] + kv[1].back()}},
3260 {{kv[0].front() + kv[0] + kv[0].back(),
3261 kv[1].front() + kv[1] + kv[1].back()}},
3262 kv, init, options) {
3263 static_assert(Spline::is_nonuniform(),
3264 "TH function space requires non-uniform splines");
3265 Base::template space<0>().reduce_continuity();
3266 Base::template space<1>().reduce_continuity();
3267 }
3269
3271};
3272
3285template <typename Spline>
3286class TH<Spline, 3>
3287 : public FunctionSpace<std::tuple<
3288 typename Spline::template derived_self_type<
3289 typename Spline::value_type, Spline::geoDim(),
3290 Spline::degree(0) + 1, Spline::degree(1) + 1,
3291 Spline::degree(2) + 1>,
3292 typename Spline::template derived_self_type<
3293 typename Spline::value_type, Spline::geoDim(),
3294 Spline::degree(0) + 1, Spline::degree(1) + 1,
3295 Spline::degree(2) + 1>,
3296 typename Spline::template derived_self_type<
3297 typename Spline::value_type, Spline::geoDim(),
3298 Spline::degree(0) + 1, Spline::degree(1) + 1,
3299 Spline::degree(2) + 1>,
3300 typename Spline::template derived_self_type<
3301 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3302 Spline::degree(1), Spline::degree(2)>>> {
3303public:
3305 using Base = FunctionSpace<std::tuple<
3306 typename Spline::template derived_self_type<
3307 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3308 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3309 typename Spline::template derived_self_type<
3310 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3311 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3312 typename Spline::template derived_self_type<
3313 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3314 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3315 typename Spline::template derived_self_type<
3316 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3317 Spline::degree(1), Spline::degree(2)>>>;
3318
3321 TH(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
3324 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3325 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3326 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
3327 options) {
3328 static_assert(Spline::is_nonuniform(),
3329 "TH function space requires non-uniform splines");
3330 Base::template space<0>().reduce_continuity();
3331 Base::template space<1>().reduce_continuity();
3332 Base::template space<2>().reduce_continuity();
3333 }
3334
3335 TH(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3336 enum init init = init::greville,
3339 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3340 kv[1].front() + kv[1] + kv[1].back(),
3341 kv[2].front() + kv[2] + kv[2].back()}},
3342 {{kv[0].front() + kv[0] + kv[0].back(),
3343 kv[1].front() + kv[1] + kv[1].back(),
3344 kv[2].front() + kv[2] + kv[2].back()}},
3345 {{kv[0].front() + kv[0] + kv[0].back(),
3346 kv[1].front() + kv[1] + kv[1].back(),
3347 kv[2].front() + kv[2] + kv[2].back()}},
3348 kv, init, options) {
3349 static_assert(Spline::is_nonuniform(),
3350 "TH function space requires non-uniform splines");
3351 Base::template space<0>().reduce_continuity();
3352 Base::template space<1>().reduce_continuity();
3353 Base::template space<2>().reduce_continuity();
3354 }
3356
3358};
3359
3373template <typename Spline>
3374class TH<Spline, 4>
3375 : public FunctionSpace<std::tuple<
3376 typename Spline::template derived_self_type<
3377 typename Spline::value_type, Spline::geoDim(),
3378 Spline::degree(0) + 1, Spline::degree(1) + 1,
3379 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3380 typename Spline::template derived_self_type<
3381 typename Spline::value_type, Spline::geoDim(),
3382 Spline::degree(0) + 1, Spline::degree(1) + 1,
3383 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3384 typename Spline::template derived_self_type<
3385 typename Spline::value_type, Spline::geoDim(),
3386 Spline::degree(0) + 1, Spline::degree(1) + 1,
3387 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3388 typename Spline::template derived_self_type<
3389 typename Spline::value_type, Spline::geoDim(),
3390 Spline::degree(0) + 1, Spline::degree(1) + 1,
3391 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3392 typename Spline::template derived_self_type<
3393 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3394 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3395public:
3397 using Base = FunctionSpace<std::tuple<
3398 typename Spline::template derived_self_type<
3399 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3400 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3401 typename Spline::template derived_self_type<
3402 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3403 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3404 typename Spline::template derived_self_type<
3405 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3406 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3407 typename Spline::template derived_self_type<
3408 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3409 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3410 typename Spline::template derived_self_type<
3411 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3412 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3413
3416 TH(const std::array<int64_t, 4> &ncoeffs, enum init init = init::greville,
3419 : Base(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),
3422 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
3423 init, options) {
3424 static_assert(Spline::is_nonuniform(),
3425 "TH function space requires non-uniform splines");
3426 Base::template space<0>().reduce_continuity();
3427 Base::template space<1>().reduce_continuity();
3428 Base::template space<2>().reduce_continuity();
3429 Base::template space<3>().reduce_continuity();
3430 }
3431
3432 TH(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
3433 enum init init = init::greville,
3436 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3437 kv[1].front() + kv[1] + kv[1].back(),
3438 kv[2].front() + kv[2] + kv[2].back(),
3439 kv[3].front() + kv[3] + kv[3].back()}},
3440 {{kv[0].front() + kv[0] + kv[0].back(),
3441 kv[1].front() + kv[1] + kv[1].back(),
3442 kv[2].front() + kv[2] + kv[2].back(),
3443 kv[3].front() + kv[3] + kv[3].back()}},
3444 {{kv[0].front() + kv[0] + kv[0].back(),
3445 kv[1].front() + kv[1] + kv[1].back(),
3446 kv[2].front() + kv[2] + kv[2].back(),
3447 kv[3].front() + kv[3] + kv[3].back()}},
3448 {{kv[0].front() + kv[0] + kv[0].back(),
3449 kv[1].front() + kv[1] + kv[1].back(),
3450 kv[2].front() + kv[2] + kv[2].back(),
3451 kv[3].front() + kv[3] + kv[3].back()}},
3452 kv, init, options) {
3453 static_assert(Spline::is_nonuniform(),
3454 "TH function space requires non-uniform splines");
3455 Base::template space<0>().reduce_continuity();
3456 Base::template space<1>().reduce_continuity();
3457 Base::template space<2>().reduce_continuity();
3458 Base::template space<3>().reduce_continuity();
3459 }
3461
3463};
3464
3466
3468template <typename Spline, short_t = Spline::parDim()> class NE;
3469
3479template <typename Spline>
3480class NE<Spline, 1>
3481 : public FunctionSpace<
3482 std::tuple<typename Spline::template derived_self_type<
3483 typename Spline::value_type, Spline::geoDim(),
3484 Spline::degree(0) + 1>,
3485 typename Spline::template derived_self_type<
3486 typename Spline::value_type, Spline::geoDim(),
3487 Spline::degree(0)>>> {
3488public:
3490 using Base = FunctionSpace<std::tuple<
3491 typename Spline::template derived_self_type<
3492 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3493 typename Spline::template derived_self_type<
3494 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3495
3498 NE(const std::array<int64_t, 1> &ncoeffs, enum init init = init::greville,
3501 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
3502
3503 NE(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3504 enum init init = init::greville,
3507 : Base(kv, kv, init, options) {
3508 static_assert(Spline::is_nonuniform(),
3509 "Constructor only available for non-uniform splines");
3510 }
3512
3514};
3515
3526template <typename Spline>
3527class NE<Spline, 2>
3528 : public FunctionSpace<
3529 std::tuple<typename Spline::template derived_self_type<
3530 typename Spline::value_type, Spline::geoDim(),
3531 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3532 typename Spline::template derived_self_type<
3533 typename Spline::value_type, Spline::geoDim(),
3534 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3535 typename Spline::template derived_self_type<
3536 typename Spline::value_type, Spline::geoDim(),
3537 Spline::degree(0), Spline::degree(1)>>> {
3538public:
3541 std::tuple<typename Spline::template derived_self_type<
3542 typename Spline::value_type, Spline::geoDim(),
3543 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3544 typename Spline::template derived_self_type<
3545 typename Spline::value_type, Spline::geoDim(),
3546 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3547 typename Spline::template derived_self_type<
3548 typename Spline::value_type, Spline::geoDim(),
3549 Spline::degree(0), Spline::degree(1)>>>;
3550
3553 NE(const std::array<int64_t, 2> &ncoeffs, enum init init = init::greville,
3556 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
3557 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
3558 static_assert(Spline::is_nonuniform(),
3559 "NE function space requires non-uniform splines");
3560 Base::template space<0>().reduce_continuity(1, 1);
3561 Base::template space<1>().reduce_continuity(1, 0);
3562 }
3563
3564 NE(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3565 enum init init = init::greville,
3568 : Base(kv, kv, kv, init, options) {
3569 static_assert(Spline::is_nonuniform(),
3570 "NE function space requires non-uniform splines");
3571 Base::template space<0>().reduce_continuity(1, 1);
3572 Base::template space<1>().reduce_continuity(1, 0);
3573 }
3575
3577};
3578
3591template <typename Spline>
3592class NE<Spline, 3>
3593 : public FunctionSpace<std::tuple<
3594 typename Spline::template derived_self_type<
3595 typename Spline::value_type, Spline::geoDim(),
3596 Spline::degree(0) + 1, Spline::degree(1) + 1,
3597 Spline::degree(2) + 1>,
3598 typename Spline::template derived_self_type<
3599 typename Spline::value_type, Spline::geoDim(),
3600 Spline::degree(0) + 1, Spline::degree(1) + 1,
3601 Spline::degree(2) + 1>,
3602 typename Spline::template derived_self_type<
3603 typename Spline::value_type, Spline::geoDim(),
3604 Spline::degree(0) + 1, Spline::degree(1) + 1,
3605 Spline::degree(2) + 1>,
3606 typename Spline::template derived_self_type<
3607 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3608 Spline::degree(1), Spline::degree(2)>>> {
3609public:
3611 using Base = FunctionSpace<std::tuple<
3612 typename Spline::template derived_self_type<
3613 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3614 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3615 typename Spline::template derived_self_type<
3616 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3617 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3618 typename Spline::template derived_self_type<
3619 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3620 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3621 typename Spline::template derived_self_type<
3622 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3623 Spline::degree(1), Spline::degree(2)>>>;
3624
3627 NE(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
3630 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3631 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3632 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
3633 options) {
3634 static_assert(Spline::is_nonuniform(),
3635 "NE function space requires non-uniform splines");
3636 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
3637 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
3638 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
3639 }
3640
3641 NE(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3642 enum init init = init::greville,
3645 : Base(kv, kv, kv, kv, init, options) {
3646 static_assert(Spline::is_nonuniform(),
3647 "NE function space requires non-uniform splines");
3648 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
3649 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
3650 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
3651 }
3653
3655};
3656
3670template <typename Spline>
3671class NE<Spline, 4>
3672 : public FunctionSpace<std::tuple<
3673 typename Spline::template derived_self_type<
3674 typename Spline::value_type, Spline::geoDim(),
3675 Spline::degree(0) + 1, Spline::degree(1) + 1,
3676 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3677 typename Spline::template derived_self_type<
3678 typename Spline::value_type, Spline::geoDim(),
3679 Spline::degree(0) + 1, Spline::degree(1) + 1,
3680 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3681 typename Spline::template derived_self_type<
3682 typename Spline::value_type, Spline::geoDim(),
3683 Spline::degree(0) + 1, Spline::degree(1) + 1,
3684 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3685 typename Spline::template derived_self_type<
3686 typename Spline::value_type, Spline::geoDim(),
3687 Spline::degree(0) + 1, Spline::degree(1) + 1,
3688 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3689 typename Spline::template derived_self_type<
3690 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3691 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3692public:
3694 using Base = FunctionSpace<std::tuple<
3695 typename Spline::template derived_self_type<
3696 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3697 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3698 typename Spline::template derived_self_type<
3699 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3700 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3701 typename Spline::template derived_self_type<
3702 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3703 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3704 typename Spline::template derived_self_type<
3705 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3706 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3707 typename Spline::template derived_self_type<
3708 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3709 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3710
3713 NE(const std::array<int64_t, 4> &ncoeffs, enum init init = init::greville,
3716 : Base(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),
3719 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
3720 init, options) {
3721 static_assert(Spline::is_nonuniform(),
3722 "NE function space requires non-uniform splines");
3723 Base::template space<0>()
3724 .reduce_continuity(1, 1)
3725 .reduce_continuity(1, 2)
3726 .reduce_continuity(1, 3);
3727 Base::template space<1>()
3728 .reduce_continuity(1, 0)
3729 .reduce_continuity(1, 2)
3730 .reduce_continuity(1, 3);
3731 Base::template space<2>()
3732 .reduce_continuity(1, 0)
3733 .reduce_continuity(1, 1)
3734 .reduce_continuity(1, 3);
3735 Base::template space<3>()
3736 .reduce_continuity(1, 0)
3737 .reduce_continuity(1, 1)
3738 .reduce_continuity(1, 2);
3739 }
3740
3741 NE(const std::array<std::vector<typename Spline::value_type>,
3742 Spline::parDim()> &kv,
3743 enum init init = init::greville,
3746 : Base(kv, kv, kv, kv, kv, init, options) {
3747 static_assert(Spline::is_nonuniform(),
3748 "NE function space requires non-uniform splines");
3749 Base::template space<0>()
3750 .reduce_continuity(1, 1)
3751 .reduce_continuity(1, 2)
3752 .reduce_continuity(1, 3);
3753 Base::template space<1>()
3754 .reduce_continuity(1, 0)
3755 .reduce_continuity(1, 2)
3756 .reduce_continuity(1, 3);
3757 Base::template space<2>()
3758 .reduce_continuity(1, 0)
3759 .reduce_continuity(1, 1)
3760 .reduce_continuity(1, 3);
3761 Base::template space<3>()
3762 .reduce_continuity(1, 0)
3763 .reduce_continuity(1, 1)
3764 .reduce_continuity(1, 2);
3765 }
3767
3769};
3770
3772
3774template <typename Spline, short_t = Spline::parDim()> class RT;
3775
3785template <typename Spline>
3786class RT<Spline, 1>
3787 : public FunctionSpace<
3788 std::tuple<typename Spline::template derived_self_type<
3789 typename Spline::value_type, Spline::geoDim(),
3790 Spline::degree(0) + 1>,
3791 typename Spline::template derived_self_type<
3792 typename Spline::value_type, Spline::geoDim(),
3793 Spline::degree(0)>>> {
3794public:
3796 using Base = FunctionSpace<std::tuple<
3797 typename Spline::template derived_self_type<
3798 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3799 typename Spline::template derived_self_type<
3800 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3801
3804 RT(const std::array<int64_t, 1> &ncoeffs, enum init init = init::greville,
3807 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
3808
3809 RT(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3810 enum init init = init::greville,
3813 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}}, kv, init,
3814 options) {
3815 static_assert(Spline::is_nonuniform(),
3816 "Constructor only available for non-uniform splines");
3817 }
3819
3821};
3822
3834template <typename Spline>
3835class RT<Spline, 2>
3836 : public FunctionSpace<
3837 std::tuple<typename Spline::template derived_self_type<
3838 typename Spline::value_type, Spline::geoDim(),
3839 Spline::degree(0) + 1, Spline::degree(1)>,
3840 typename Spline::template derived_self_type<
3841 typename Spline::value_type, Spline::geoDim(),
3842 Spline::degree(0), Spline::degree(1) + 1>,
3843 typename Spline::template derived_self_type<
3844 typename Spline::value_type, Spline::geoDim(),
3845 Spline::degree(0), Spline::degree(1)>>> {
3846public:
3848 std::tuple<typename Spline::template derived_self_type<
3849 typename Spline::value_type, Spline::geoDim(),
3850 Spline::degree(0) + 1, Spline::degree(1)>,
3851 typename Spline::template derived_self_type<
3852 typename Spline::value_type, Spline::geoDim(),
3853 Spline::degree(0), Spline::degree(1) + 1>,
3854 typename Spline::template derived_self_type<
3855 typename Spline::value_type, Spline::geoDim(),
3856 Spline::degree(0), Spline::degree(1)>>>;
3857
3860 RT(const std::array<int64_t, 2> &ncoeffs, enum init init = init::greville,
3863 : Base(ncoeffs + utils::to_array(1_i64, 0_i64),
3864 ncoeffs + utils::to_array(0_i64, 1_i64), ncoeffs, init, options) {}
3865
3866 RT(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3867 enum init init = init::greville,
3870 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}},
3871 {{kv[0], kv[1].front() + kv[1] + kv[1].back()}}, kv, init,
3872 options) {
3873 static_assert(Spline::is_nonuniform(),
3874 "Constructor only available for non-uniform splines");
3875 }
3877
3879};
3880
3892template <typename Spline>
3893class RT<Spline, 3>
3894 : public FunctionSpace<std::tuple<
3895 typename Spline::template derived_self_type<
3896 typename Spline::value_type, Spline::geoDim(),
3897 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2)>,
3898 typename Spline::template derived_self_type<
3899 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3900 Spline::degree(1) + 1, Spline::degree(2)>,
3901 typename Spline::template derived_self_type<
3902 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3903 Spline::degree(1), Spline::degree(2) + 1>,
3904 typename Spline::template derived_self_type<
3905 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3906 Spline::degree(1), Spline::degree(2)>>> {
3907public:
3909 using Base = FunctionSpace<std::tuple<
3910 typename Spline::template derived_self_type<
3911 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3912 Spline::degree(1), Spline::degree(2)>,
3913 typename Spline::template derived_self_type<
3914 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3915 Spline::degree(1) + 1, Spline::degree(2)>,
3916 typename Spline::template derived_self_type<
3917 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3918 Spline::degree(1), Spline::degree(2) + 1>,
3919 typename Spline::template derived_self_type<
3920 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3921 Spline::degree(1), Spline::degree(2)>>>;
3922
3925 RT(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
3928 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
3929 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
3930 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), ncoeffs, init,
3931 options) {}
3932
3933 RT(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3934 enum init init = init::greville,
3937 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
3938 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
3939 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, kv, init,
3940 options) {
3941 static_assert(Spline::is_nonuniform(),
3942 "Constructor only available for non-uniform splines");
3943 }
3945
3947};
3948
3962template <typename Spline>
3963class RT<Spline, 4>
3964 : public FunctionSpace<std::tuple<
3965 typename Spline::template derived_self_type<
3966 typename Spline::value_type, Spline::geoDim(),
3967 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2),
3968 Spline::degree(3)>,
3969 typename Spline::template derived_self_type<
3970 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3971 Spline::degree(1) + 1, Spline::degree(2), Spline::degree(3)>,
3972 typename Spline::template derived_self_type<
3973 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3974 Spline::degree(1), Spline::degree(2) + 1, Spline::degree(3)>,
3975 typename Spline::template derived_self_type<
3976 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3977 Spline::degree(1), Spline::degree(2), Spline::degree(3) + 1>,
3978 typename Spline::template derived_self_type<
3979 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3980 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3981public:
3983 using Base = FunctionSpace<std::tuple<
3984 typename Spline::template derived_self_type<
3985 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3986 Spline::degree(1), Spline::degree(2), Spline::degree(3)>,
3987 typename Spline::template derived_self_type<
3988 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3989 Spline::degree(1) + 1, Spline::degree(2), Spline::degree(3)>,
3990 typename Spline::template derived_self_type<
3991 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3992 Spline::degree(1), Spline::degree(2) + 1, Spline::degree(3)>,
3993 typename Spline::template derived_self_type<
3994 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3995 Spline::degree(1), Spline::degree(2), Spline::degree(3) + 1>,
3996 typename Spline::template derived_self_type<
3997 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3998 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3999
4002 RT(const std::array<int64_t, 4> &ncoeffs, enum init init = init::greville,
4005 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64, 0_i64),
4006 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64, 0_i64),
4007 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64, 0_i64),
4008 ncoeffs + utils::to_array(0_i64, 0_i64, 0_i64, 1_i64), ncoeffs,
4009 init, options) {}
4010
4011 RT(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
4012 enum init init = init::greville,
4015 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2], kv[3]}},
4016 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2], kv[3]}},
4017 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back(), kv[3]}},
4018 {{kv[0], kv[1], kv[2], kv[3].front() + kv[3] + kv[3].back()}}, kv,
4019 init, options) {
4020 static_assert(Spline::is_nonuniform(),
4021 "Constructor only available for non-uniform splines");
4022 }
4024
4026};
4027
4029
4031template <typename Spline, short_t = Spline::parDim()> class Hcurl;
4032
4044template <typename Spline>
4045class Hcurl<Spline, 3>
4046 : public FunctionSpace<std::tuple<
4047 typename Spline::template derived_self_type<
4048 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4049 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4050 typename Spline::template derived_self_type<
4051 typename Spline::value_type, Spline::geoDim(),
4052 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2) + 1>,
4053 typename Spline::template derived_self_type<
4054 typename Spline::value_type, Spline::geoDim(),
4055 Spline::degree(0) + 1, Spline::degree(1) + 1,
4056 Spline::degree(2)>>> {
4057
4058public:
4060 using Base = FunctionSpace<std::tuple<
4061 typename Spline::template derived_self_type<
4062 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4063 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4064 typename Spline::template derived_self_type<
4065 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4066 Spline::degree(1), Spline::degree(2) + 1>,
4067 typename Spline::template derived_self_type<
4068 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4069 Spline::degree(1) + 1, Spline::degree(2)>>>;
4070
4073 Hcurl(const std::array<int64_t, 3> &ncoeffs, enum init init = init::greville,
4076 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
4077 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
4078 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), init, options) {}
4079
4080 Hcurl(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4081 enum init init = init::greville,
4084 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
4085 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
4086 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, init,
4087 options) {
4088 static_assert(Spline::is_nonuniform(),
4089 "Constructor only available for non-uniform splines");
4090 }
4093};
4094
4096
4098#undef IGANET_FUNCTIONSPACE_DEFAULT_OPS
4099
4100} // 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:4069
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:4073
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:4080
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:3494
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:3498
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:3503
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:3553
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:3549
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:3564
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:3627
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:3641
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:3623
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:3713
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:3741
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:3709
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:3800
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:3804
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:3809
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:3856
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:3860
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:3866
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:3921
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:3925
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:3933
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:3998
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:4002
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:4011
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:3182
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:3191
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:3178
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:3254
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:3239
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:3243
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:3321
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:3317
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:3335
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:3432
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:3416
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:3412
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:810
auto find_knot_indices(const utils::TensorArray< nspaces()> &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:632
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:651
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:580
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:257
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:1428
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:432
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:1857
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:790
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:886
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:960
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:248
pugi::xml_document to_xml(int id=0, std::string label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:370
auto & boundary() noexcept
Returns a non-constant reference to the index-th boundary object.
Definition functionspace.hpp:163
auto boundingBox() const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:910
FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:169
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:1138
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:1018
static constexpr std::size_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:139
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:759
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:1904
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:1842
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:193
torch::Tensor boundary_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:203
auto & space() noexcept
Returns a non-constant reference to the index-th space.
Definition functionspace.hpp:150
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:737
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:862
std::tuple< Boundaries... > boundary_type
Boundary type.
Definition functionspace.hpp:70
FunctionSpace(std::tuple< Splines... > &&spline, std::tuple< Boundaries... > &&boundary)
Constructor.
Definition functionspace.hpp:128
std::common_type_t< typename Splines::value_type... > value_type
Value type.
Definition functionspace.hpp:61
auto eval_from_precomputed_(std::index_sequence< Is... >, const std::tuple< Basfunc... > &basfunc, const std::tuple< Coeff_Indices... > &coeff_indices, const std::tuple< Xi... > &xi) const
Returns the value of the spline objects from precomputed basis function.
Definition functionspace.hpp:558
virtual FunctionSpace & from_tensor(const torch::Tensor &tensor)
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:349
auto clone() const noexcept
Returns a clone of a subset of the function space.
Definition functionspace.hpp:172
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:1131
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:879
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:748
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:310
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:687
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:1600
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:322
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:473
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:1003
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:2063
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:331
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:728
auto scale_(std::index_sequence< Is... >, value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:819
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:667
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:360
auto boundingBox_(std::index_sequence< Is... >) const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:904
std::tuple< typename Boundaries::eval_type... > boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:73
FunctionSpace & from_xml(const pugi::xml_node &root, int id=0, std::string label="")
Updates the function space object from XML node.
Definition functionspace.hpp:404
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:1304
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:518
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:844
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:2044
auto eval(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects in the points xi
Definition functionspace.hpp:495
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:1086
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:2036
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:1462
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:1188
FunctionSpace(const std::array< std::vector< typename Splines::value_type >, Splines::parDim()> &...kv, enum init init=init::greville, Options< value_type > options=iganet::Options< value_type >{})
Constructor.
Definition functionspace.hpp:102
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:771
FunctionSpace(std::tuple< Splines... > &&spline)
Constructor.
Definition functionspace.hpp:119
auto grad(const utils::TensorArray< nspaces()> &xi) const
Returns a block-tensor with the gradient of the function space object in the points xi with respect t...
Definition functionspace.hpp:1270
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:229
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:781
std::tuple< utils::TensorArray< Splines::parDim()>... > eval_type
Spline evaluation type.
Definition functionspace.hpp:67
auto hess(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Returns a block-tensor with the Hessian of the function space object in the points xi with respect to...
Definition functionspace.hpp:1435
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:540
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:799
nlohmann::json to_json_(std::index_sequence< Is... >) const
Serialization to JSON.
Definition functionspace.hpp:413
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:696
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:238
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:897
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:1165
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:710
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:2086
const auto & boundary() const noexcept
Returns a constant reference to the index-th boundary object.
Definition functionspace.hpp:156
FunctionSpace(const std::array< int64_t, Splines::parDim()> &...ncoeffs, enum init init=init::greville, Options< value_type > options=iganet::Options< value_type >{})
Constructor.
Definition functionspace.hpp:94
pugi::xml_node & to_xml(pugi::xml_node &root, int id=0, std::string label="") const
Returns the function space object as XML node.
Definition functionspace.hpp:379
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:1849
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:1032
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:220
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:1876
boundary_type boundary_
Boundaries.
Definition functionspace.hpp:80
auto div(const utils::TensorArray4 &xi, const std::tuple< utils::TensorArray4, utils::TensorArray4, utils::TensorArray4, utils::TensorArray4 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Returns a block-tensor with the divergence of the function space object with respect to the parametri...
Definition functionspace.hpp:1218
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:1443
const auto & space() const noexcept
Returns a constant reference to the index-th function space.
Definition functionspace.hpp:144
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:1948
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:934
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:457
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:638
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:1357
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:274
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:388
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:827
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:617
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:505
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:1146
FunctionSpace(const std::tuple< Splines... > &spline)
Constructor.
Definition functionspace.hpp:114
torch::serialize::InputArchive & read_(std::index_sequence< Is... >, torch::serialize::InputArchive &archive, const std::string &key="functionspace")
Loads the function space object from a torch::serialize::InputArchive object.
Definition functionspace.hpp:945
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &tensor)
Sets the tuple of boundaries from a single-tensor representation.
Definition functionspace.hpp:343
torch::Tensor spaces_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:186
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &tensor)
Sets the tuple of spaces from a single-tensor representation.
Definition functionspace.hpp:301
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:1010
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:398
auto scale_(std::index_sequence< Is... >, std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:834
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:1502
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:2029
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:1054
auto translate_(std::index_sequence< Is... >, std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:851
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:605
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:442
std::tuple< Splines... > spline_type
Spline type.
Definition functionspace.hpp:64
auto lapl(const utils::TensorArray4 &xi, const std::tuple< utils::TensorArray4, utils::TensorArray4, utils::TensorArray4, utils::TensorArray4 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Returns a block-tensor with the Laplacian of the function space object in the points xi with respect ...
Definition functionspace.hpp:2116
FunctionSpace(const std::tuple< Splines... > &spline, const std::tuple< Boundaries... > &boundary)
Constructor.
Definition functionspace.hpp:124
auto grad(const utils::TensorArray1 &xi, const std::tuple< utils::TensorArray1 > &knot_indices, const std::tuple< torch::Tensor > &coeff_indices) const
Returns a block-tensor with the gradient of the function space object in the points xi with respect t...
Definition functionspace.hpp:1285
auto rotate_(std::index_sequence< Is... >, value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:869
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:210
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:1277
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:919
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:1327
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:968
static constexpr std::size_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:134
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:592
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:267
Function space.
Definition functionspace.hpp:2406
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:2805
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:2783
FunctionSpace(const Spline &spline)
Constructor.
Definition functionspace.hpp:2460
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:2842
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:2443
auto eval_basfunc(const Args &...args) const
Returns the values of the spline objects' basis functions in the points xi
Definition functionspace.hpp:2755
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:2562
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:2768
constexpr const boundary_type & boundary() const noexcept
Returns a constant reference to the index-th boundary object.
Definition functionspace.hpp:2494
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the space.
Definition functionspace.hpp:2527
typename Boundary::eval_type boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:2422
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:2882
virtual int64_t boundary_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the boundary.
Definition functionspace.hpp:2553
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the boundary.
Definition functionspace.hpp:2532
constexpr boundary_type & boundary() noexcept
Returns a non-constant reference to the index-th boundary object object.
Definition functionspace.hpp:2501
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:2835
Spline spline_type
Spline type.
Definition functionspace.hpp:2413
virtual int64_t spaces_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the space.
Definition functionspace.hpp:2547
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:2891
auto find_knot_indices(const Xi &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:2734
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:2647
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:2872
FunctionSpace(Spline &&spline)
Constructor.
Definition functionspace.hpp:2466
constexpr spline_type & space() noexcept
Returns a non-constant reference to the index-th function space.
Definition functionspace.hpp:2487
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:2822
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:2611
auto eval(const Arg &arg, const Args &...args) const
Returns the values of the spline object in the points xi
Definition functionspace.hpp:2693
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:2674
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:2617
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:2863
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:2605
static constexpr std::size_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:2474
constexpr FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:2507
auto find_knot_indices_(std::index_sequence< Is... >, const Xi &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:2723
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:2856
static constexpr std::size_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:2477
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:2849
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:2813
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:2660
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:2576
pugi::xml_document to_xml(int id=0, std::string label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:2596
FunctionSpace(FunctionSpace &&)=default
Move constructor.
typename Spline::value_type value_type
Value type.
Definition functionspace.hpp:2410
boundary_type boundary_
Boundary.
Definition functionspace.hpp:2429
utils::TensorArray< Spline::parDim()> eval_type
Spline evaluation type.
Definition functionspace.hpp:2416
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &coeffs) noexcept
Sets the space from a single-tensor representation.
Definition functionspace.hpp:2568
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept
Sets the boundary from a single-tensor representation.
Definition functionspace.hpp:2583
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:2632
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:2541
FunctionSpace(const FunctionSpace &)=default
Copy constructor.
spline_type spline_
Spline.
Definition functionspace.hpp:2426
auto eval_from_precomputed(const Args &...args) const
Returns the value of the spline object from precomputed basis function.
Definition functionspace.hpp:2712
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:2624
FunctionSpace & from_tensor(const torch::Tensor &coeffs) noexcept
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:2589
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:2451
constexpr const spline_type & space() const noexcept
Returns a constant reference to the index-th function space.
Definition functionspace.hpp:2481
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:2827
constexpr auto clone() const noexcept
Returns a subset of the tuple of function spaces.
Definition functionspace.hpp:2512
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:3118
Container utility functions.
#define IGANET_FUNCTIONSPACE_DEFAULT_OPS(FunctionSpace)
Macro: Implements the default methods of a function space.
Definition functionspace.hpp:36
typename FunctionSpace_trait< utils::tuple_cat_t< Splines... >, utils::tuple_cat_t< Boundaries... > >::type type
Definition functionspace.hpp:3111
typename FunctionSpace_trait< Spline, Boundary >::type type
Definition functionspace.hpp:3101
std::ostream & operator<<(std::ostream &os, const FunctionSpace< Splines... > &obj)
Print (as string) a function space object.
Definition functionspace.hpp:2392
Forward declaration.
Definition functionspace.hpp:3069
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:3149
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:3122
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:4031
IGANET_FUNCTIONSPACE_TUPLE_WRAPPER(TH);.
Definition functionspace.hpp:3468
IGANET_FUNCTIONSPACE_TUPLE_WRAPPER(NE);.
Definition functionspace.hpp:3774
Taylor-Hood like function space.
Definition functionspace.hpp:3152
STL namespace.
Serialization prototype.
Definition serialize.hpp:31
Type traits.
Zip utility function.