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 <splines/bspline.hpp>
20#include <splines/boundary.hpp>
21#include <utils/container.hpp>
22#include <utils/tuple.hpp>
23#include <utils/zip.hpp>
24
25namespace iganet {
26
27using namespace literals;
28using utils::operator+;
29
31enum class functionspace : short_t {
32 interior = 0,
33 boundary = 1
34};
35
37#define IGANET_FUNCTIONSPACE_DEFAULT_OPS(FunctionSpace) \
38 FunctionSpace() = default; \
39 FunctionSpace(FunctionSpace &&) = default; \
40 FunctionSpace(const FunctionSpace &) = default;
41
42namespace detail {
43
44// @brief Concept to identify template parameters that have a templated
45// find_knot_indices function
46template <typename T>
47concept HasTemplatedFindKnotIndices = requires(T t, typename T::eval_type x) {
48 { t.template find_knot_indices<functionspace::interior>(x) };
49};
50
51// @brief Concept to identify template parameters that have a templated
52// find_coeff_indices function
53template <typename T>
54concept HasTemplatedFindCoeffIndices = requires(T t, typename T::eval_type x) {
55 { t.template find_coeff_indices<functionspace::interior>(x) };
56};
57
60
61// Forward declaration
62template <typename, typename> class FunctionSpace;
63
68template <typename... Splines, typename... Boundaries>
69// requires (SplineType<Splines> && ...) && (BoundaryType<Boundaries> && ...)
70class FunctionSpace<std::tuple<Splines...>, std::tuple<Boundaries...>>
71 : public FunctionSpaceType,
74
75public:
77 using value_type = std::common_type_t<typename Splines::value_type...>;
78
80 using spline_type = std::tuple<Splines...>;
81
83 using eval_type = std::tuple<utils::TensorArray<Splines::parDim()>...>;
84
86 using boundary_type = std::tuple<Boundaries...>;
87
89 using boundary_eval_type = std::tuple<typename Boundaries::eval_type...>;
90
92 template <std::size_t index>
93 inline static constexpr short_t geoDim() noexcept {
94 static_assert(index < nspaces());
95 return std::tuple_element_t<index, spline_type>::geoDim();
96 }
97
99 template <std::size_t index>
100 inline static constexpr short_t parDim() noexcept {
101 static_assert(index < nspaces());
102 return std::tuple_element_t<index, spline_type>::parDim();
103 }
104
107 template <std::size_t index>
108 inline static constexpr const auto& degrees() noexcept {
109 static_assert(index < nspaces());
110 return std::tuple_element_t<index, spline_type>::degrees();
111 }
112
115 template <std::size_t index>
116 inline static constexpr short_t degree(short_t i) noexcept {
117 static_assert(index < nspaces());
118 return std::tuple_element_t<index, spline_type>::degree(i);
119 }
120
121protected:
124
127
128public:
130 FunctionSpace() = default;
131
133 FunctionSpace(const FunctionSpace &) = default;
134
137
141 const std::array<int64_t, Splines::parDim()> &...ncoeffs,
142 enum init init = init::greville,
144 : spline_(Splines(ncoeffs, init, options)...),
145 boundary_(Boundaries(ncoeffs, init::none, options)...) {
147 }
148
150 const std::array<std::vector<typename Splines::value_type>,
151 Splines::parDim()> &...kv,
152 enum init init = init::greville,
154 : spline_(Splines(kv, init, options)...),
155 boundary_(Boundaries(kv, init::none, options)...) {
156
157 static_assert((Splines::is_nonuniform() && ... && true),
158 "Constructor is only available for non-uniform splines");
160 }
161
162 explicit FunctionSpace(const std::tuple<Splines...> &spline)
163 : spline_(spline) {
165 }
166
167 explicit FunctionSpace(std::tuple<Splines...> &&spline) : spline_(spline) {
169 }
170
171 explicit FunctionSpace(const std::tuple<Splines...> &spline,
172 const std::tuple<Boundaries...> &boundary)
173 : spline_(spline), boundary_(boundary) {}
174
175 explicit FunctionSpace(std::tuple<Splines...> &&spline,
176 std::tuple<Boundaries...> &&boundary)
177 : spline_(spline), boundary_(boundary) {}
179
181 inline static constexpr std::size_t nspaces() noexcept {
182 return sizeof...(Splines);
183 }
184
186 inline static constexpr std::size_t nboundaries() noexcept {
187 return sizeof...(Boundaries);
188 }
189
191 inline constexpr const auto &spaces() const noexcept { return spline_; }
192
194 inline constexpr auto &spaces() noexcept { return spline_; }
195
197 inline constexpr const auto &boundaries() const noexcept { return boundary_; }
198
200 inline constexpr auto &boundaries() noexcept { return boundary_; }
201
203 template <std::size_t index> inline const auto &space() const noexcept {
204 static_assert(index < nspaces());
205 return std::get<index>(spline_);
206 }
207
209 template <std::size_t index> inline auto &space() noexcept {
210 static_assert(index < nspaces());
211 return std::get<index>(spline_);
212 }
213
215 template <std::size_t index> inline const auto &boundary() const noexcept {
216 static_assert(index < nboundaries());
217 return std::get<index>(boundary_);
218 }
219
222 template <std::size_t index> inline auto &boundary() noexcept {
223 static_assert(index < nboundaries());
224 return std::get<index>(boundary_);
225 }
226
228 inline FunctionSpace clone() const noexcept { return FunctionSpace(*this); }
229
231 template <std::size_t... index> inline auto clone() const noexcept {
232
233 static_assert(((index < nspaces()) && ... && true));
234
235 return FunctionSpace<
236 std::tuple<std::tuple_element_t<index, spline_type>...>,
237 std::tuple<std::tuple_element_t<index, boundary_type>...>>(
238 std::make_tuple(std::get<index>(spline_)...),
239 std::make_tuple(std::get<index>(boundary_)...));
240 }
241
242private:
245 template <std::size_t... Is>
246 inline torch::Tensor
247 spaces_as_tensor_(std::index_sequence<Is...>) const noexcept {
248 return torch::cat({std::get<Is>(spline_).as_tensor()...});
249 }
250
251public:
254 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
255 return spaces_as_tensor_(
256 std::make_index_sequence<FunctionSpace::nspaces()>{});
257 }
258
259private:
262 template <std::size_t... Is>
263 inline torch::Tensor
264 boundary_as_tensor_(std::index_sequence<Is...>) const noexcept {
265 return torch::cat({std::get<Is>(boundary_).as_tensor()...});
266 }
267
268public:
271 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
272 return boundary_as_tensor_(
273 std::make_index_sequence<FunctionSpace::nboundaries()>{});
274 }
275
281 virtual inline torch::Tensor as_tensor() const noexcept {
282 return spaces_as_tensor();
283 }
284
285private:
288 template <std::size_t... Is>
289 inline int64_t
290 spaces_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
291 return std::apply(
292 [](auto... v) { return (v + ...); },
293 std::make_tuple(std::get<Is>(spline_).as_tensor_size()...));
294 }
295
296public:
299 virtual inline int64_t spaces_as_tensor_size() const noexcept {
300 return spaces_as_tensor_size_(
301 std::make_index_sequence<FunctionSpace::nspaces()>{});
302 }
303
304private:
307 template <std::size_t... Is>
308 inline int64_t
309 boundary_as_tensor_size_(std::index_sequence<Is...>) const noexcept {
310 return std::apply(
311 [](auto... v) { return (v + ...); },
312 std::make_tuple(std::get<Is>(boundary_).as_tensor_size()...));
313 }
314
315public:
318 virtual inline int64_t boundary_as_tensor_size() const noexcept {
319 return boundary_as_tensor_size_(
320 std::make_index_sequence<FunctionSpace::nboundaries()>{});
321 }
322
328 virtual inline int64_t as_tensor_size() const noexcept {
329 return spaces_as_tensor_size();
330 }
331
332private:
334 template <std::size_t... Is>
335 inline FunctionSpace &spaces_from_tensor_(std::index_sequence<Is...>,
336 const torch::Tensor &tensor) {
337
338 // Compute the partial sums of all function spaces
339 std::array<int64_t, sizeof...(Is)> partialSums{0};
340 auto partial_sums = [&partialSums,
341 this]<std::size_t... Js>(std::index_sequence<Js...>) {
342 ((std::get<Js + 1>(partialSums) =
343 std::get<Js>(partialSums) + std::get<Js>(spline_).as_tensor_size()),
344 ...);
345 };
346 partial_sums(std::make_index_sequence<FunctionSpace::nspaces() - 1>{});
347
348 // Call from_tensor for all function spaces
349 ((std::get<Is>(spline_).from_tensor(tensor.index(
350 {torch::indexing::Slice(partialSums[Is],
351 partialSums[Is] +
352 std::get<Is>(spline_).as_tensor_size()),
353 "..."}))),
354 ...);
355
356 return *this;
357 }
358
359public:
361 virtual inline FunctionSpace &
362 spaces_from_tensor(const torch::Tensor &tensor) {
363 return spaces_from_tensor_(
364 std::make_index_sequence<FunctionSpace::nspaces()>{}, tensor);
365 }
366
367private:
370 template <std::size_t... Is>
371 inline FunctionSpace &boundary_from_tensor_(std::index_sequence<Is...>,
372 const torch::Tensor &tensor) {
373 (std::get<Is>(boundary_).from_tensor(std::get<Is>(spline_).as_tensor()),
374 ...);
375
376 return *this;
377 }
378
379public:
382 virtual inline FunctionSpace &
383 boundary_from_tensor(const torch::Tensor &tensor) {
384 return boundary_from_tensor_(
385 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
386 }
387
388private:
390 template <std::size_t... Is>
391 inline FunctionSpace &
392 boundary_from_full_tensor_(std::index_sequence<Is...>,
393 const torch::Tensor &tensor) {
394 (std::get<Is>(boundary_).from_full_tensor(
395 std::get<Is>(spline_).as_tensor()),
396 ...);
397
398 return *this;
399 }
400
401public:
403 virtual inline FunctionSpace &
404 boundary_from_full_tensor(const torch::Tensor &tensor) {
405 return boundary_from_full_tensor_(
406 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
407 }
408
410 virtual inline FunctionSpace &from_tensor(const torch::Tensor &tensor) {
411 spaces_from_tensor_(std::make_index_sequence<FunctionSpace::nspaces()>{},
412 tensor);
413 boundary_from_full_tensor_(
414 std::make_index_sequence<FunctionSpace::nboundaries()>{}, tensor);
415 return *this;
416 }
417
418private:
420 template <std::size_t... Is>
421 inline pugi::xml_node &to_xml_(std::index_sequence<Is...>,
422 pugi::xml_node &root, int id = 0,
423 std::string label = "") const {
424
425 (std::get<Is>(spline_).to_xml(root, id, label, Is), ...);
426 return root;
427 }
428
429public:
431 inline pugi::xml_document to_xml(int id = 0,
432 const std::string &label = "") const {
433 pugi::xml_document doc;
434 pugi::xml_node root = doc.append_child("xml");
435 to_xml(root, id, label);
436
437 return doc;
438 }
439
441 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
442 std::string label = "") const {
443 return to_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
444 id, label);
445 }
446
447private:
449 template <std::size_t... Is>
450 inline FunctionSpace &from_xml_(std::index_sequence<Is...>,
451 const pugi::xml_node &root, int id = 0,
452 std::string label = "") {
453
454 (std::get<Is>(spline_).from_xml(root, id, label, Is), ...);
455 return *this;
456 }
457
458public:
460 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
461 const std::string &label = "") {
462 return from_xml(doc.child("xml"), id, label);
463 }
464
466 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
467 std::string label = "") {
468 return from_xml_(std::make_index_sequence<FunctionSpace::nspaces()>{}, root,
469 id, label);
470 }
471
472private:
474 template <std::size_t... Is>
475 nlohmann::json to_json_(std::index_sequence<Is...>) const {
476 auto json_this = nlohmann::json::array();
477 auto json_boundary = nlohmann::json::array();
478 (json_this.push_back(std::get<Is>(spline_).to_json()), ...);
479 (json_boundary.push_back(std::get<Is>(boundary_).to_json()), ...);
480
481 auto json = nlohmann::json::array();
482 for (auto [t, b] : utils::zip(json_this, json_boundary)) {
483 auto json_inner = nlohmann::json::array();
484 json_inner.push_back(t);
485 json_inner.push_back(b);
486 json.push_back(json_inner);
487 }
488
489 return json;
490 }
491
492public:
494 nlohmann::json to_json() const override {
495 return to_json_(std::make_index_sequence<FunctionSpace::nspaces()>{});
496 }
497
499 template <typename SplinesOther, typename BoundariesOther>
500 bool
502 bool result(true);
503
504 if (!std::is_same_v<spline_type, typename std::remove_cvref_t<
505 decltype(other)>::spline_type> ||
506 !std::is_same_v<boundary_type, typename std::remove_cvref_t<
507 decltype(other)>::boundary_type>)
508 return false;
509
510 result *= (spaces() == other.spaces());
511 result *= (boundaries() == other.boundaries());
512
513 return result;
514 }
515
516private:
519 template <functionspace comp = functionspace::interior,
520 deriv deriv = deriv::func, bool memory_optimized = false,
521 std::size_t... Is, typename... Xi>
522 inline auto eval_(std::index_sequence<Is...>,
523 const std::tuple<Xi...> &xi) const {
524 if constexpr (comp == functionspace::interior)
525 return std::tuple(
526 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
527 std::get<Is>(xi))...);
528 else if constexpr (comp == functionspace::boundary)
529 return std::tuple(
530 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
531 std::get<Is>(xi))...);
532 }
533
534 template <functionspace comp = functionspace::interior,
535 deriv deriv = deriv::func, bool memory_optimized = false,
536 std::size_t... Is, typename... Xi, typename... Knot_Indices>
537 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
538 const std::tuple<Knot_Indices...> &knot_indices) const {
539 if constexpr (comp == functionspace::interior)
540 return std::tuple(
541 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
542 std::get<Is>(xi), std::get<Is>(knot_indices))...);
543 else if constexpr (comp == functionspace::boundary)
544 return std::tuple(
545 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
546 std::get<Is>(xi), std::get<Is>(knot_indices))...);
547 }
548
549 template <functionspace comp = functionspace::interior,
550 deriv deriv = deriv::func, bool memory_optimized = false,
551 std::size_t... Is, typename... Xi, typename... Knot_Indices,
552 typename... Coeff_Indices>
553 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
554 const std::tuple<Knot_Indices...> &knot_indices,
555 const std::tuple<Coeff_Indices...> &coeff_indices) const {
556 if constexpr (comp == functionspace::interior)
557 return std::tuple(
558 std::get<Is>(spline_).template eval<deriv, memory_optimized>(
559 std::get<Is>(xi), std::get<Is>(knot_indices),
560 std::get<Is>(coeff_indices))...);
561 else if constexpr (comp == functionspace::boundary)
562 return std::tuple(
563 std::get<Is>(boundary_).template eval<deriv, memory_optimized>(
564 std::get<Is>(xi), std::get<Is>(knot_indices),
565 std::get<Is>(coeff_indices))...);
566 }
568
569public:
572 template <functionspace comp = functionspace::interior,
573 deriv deriv = deriv::func, bool memory_optimized = false,
574 typename... Xi>
575 inline auto eval(const std::tuple<Xi...> &xi) const {
576 static_assert(FunctionSpace::nspaces() == sizeof...(Xi),
577 "Size of Xi mismatches functionspace dimension");
578 return eval_<comp, deriv, memory_optimized>(
579 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
580 }
581
582 template <functionspace comp = functionspace::interior,
583 deriv deriv = deriv::func, bool memory_optimized = false,
584 typename... Xi, typename... Knot_Indices>
585 inline auto eval(const std::tuple<Xi...> &xi,
586 const std::tuple<Knot_Indices...> &knot_indices) const {
587 static_assert(
588 (FunctionSpace::nspaces() == sizeof...(Xi)) &&
589 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)),
590 "Sizes of Xi and Knot_Indices mismatch functionspace dimension");
591 return eval_<comp, deriv, memory_optimized>(
592 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
593 }
594
595 template <functionspace comp = functionspace::interior,
596 deriv deriv = deriv::func, bool memory_optimized = false,
597 typename... Xi, typename... Knot_Indices, typename... Coeff_Indices>
598 inline auto eval(const std::tuple<Xi...> &xi,
599 const std::tuple<Knot_Indices...> &knot_indices,
600 const std::tuple<Coeff_Indices...> &coeff_indices) const {
601 static_assert((FunctionSpace::nspaces() == sizeof...(Xi)) &&
602 (FunctionSpace::nspaces() == sizeof...(Knot_Indices)) &&
603 (FunctionSpace::nspaces() == sizeof...(Coeff_Indices)),
604 "Sizes of Xi, Knot_Indices and Coeff_Indices mismatch "
605 "functionspace dimension");
606 return eval_<comp, deriv, memory_optimized>(
607 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices,
608 coeff_indices);
609 }
611
612private:
616 template <functionspace comp = functionspace::interior, std::size_t... Is,
617 typename... Basfunc, typename... Coeff_Indices, typename... Numeval,
618 typename... Sizes>
619 inline auto
620 eval_from_precomputed_(std::index_sequence<Is...>,
621 const std::tuple<Basfunc...> &basfunc,
622 const std::tuple<Coeff_Indices...> &coeff_indices,
623 const std::tuple<Numeval...> &numeval,
624 const std::tuple<Sizes...> &sizes) const {
625 if constexpr (comp == functionspace::interior)
626 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
627 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
628 std::get<Is>(numeval), std::get<Is>(sizes))...);
629 else if constexpr (comp == functionspace::boundary)
630 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
631 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
632 std::get<Is>(numeval), std::get<Is>(sizes))...);
633 }
634
635 template <functionspace comp = functionspace::interior, std::size_t... Is,
636 typename... Basfunc, typename... Coeff_Indices, typename... Xi>
637 inline auto
638 eval_from_precomputed_(std::index_sequence<Is...>,
639 const std::tuple<Basfunc...> &basfunc,
640 const std::tuple<Coeff_Indices...> &coeff_indices,
641 const std::tuple<Xi...> &xi) const {
642 if constexpr (comp == functionspace::interior)
643 return std::tuple(std::get<Is>(spline_).eval_from_precomputed(
644 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
645 std::get<Is>(xi)[0].numel(), std::get<Is>(xi)[0].sizes())...);
646 else if constexpr (comp == functionspace::boundary)
647 return std::tuple(std::get<Is>(boundary_).eval_from_precomputed(
648 std::get<Is>(basfunc), std::get<Is>(coeff_indices),
649 std::get<Is>(xi))...);
650 }
652
653public:
657 template <functionspace comp = functionspace::interior, typename... Basfunc,
658 typename... Coeff_Indices, typename... Numeval, typename... Sizes>
659 inline auto
660 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
661 const std::tuple<Coeff_Indices...> &coeff_indices,
662 const std::tuple<Numeval...> &numeval,
663 const std::tuple<Sizes...> &sizes) const {
664 return eval_from_precomputed_<comp>(
665 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
666 coeff_indices, numeval, sizes);
667 }
668
669 template <functionspace comp = functionspace::interior, typename... Basfunc,
670 typename... Coeff_Indices, typename... Xi>
671 inline auto
672 eval_from_precomputed(const std::tuple<Basfunc...> &basfunc,
673 const std::tuple<Coeff_Indices...> &coeff_indices,
674 const std::tuple<Xi...> &xi) const {
675 return eval_from_precomputed_<comp>(
676 std::make_index_sequence<FunctionSpace::nspaces()>{}, basfunc,
677 coeff_indices, xi);
678 }
680
681private:
684 template <functionspace comp = functionspace::interior, std::size_t... Is>
685 inline auto
686 find_knot_indices_(std::index_sequence<Is...>,
687 const utils::TensorArray<nspaces()> &xi) const {
688 if constexpr (comp == functionspace::interior)
689 return std::tuple(std::get<Is>(spline_).find_knot_indices(xi)...);
690 else if constexpr (comp == functionspace::boundary)
691 return std::tuple(std::get<Is>(boundary_).find_knot_indices(xi)...);
692 }
693
694 template <functionspace comp = functionspace::interior, std::size_t... Is,
695 typename... Xi>
696 inline auto find_knot_indices_(std::index_sequence<Is...>,
697 const std::tuple<Xi...> &xi) const {
698 if constexpr (comp == functionspace::interior)
699 return std::tuple(
700 std::get<Is>(spline_).find_knot_indices(std::get<Is>(xi))...);
701 else if constexpr (comp == functionspace::boundary)
702 return std::tuple(
703 std::get<Is>(boundary_).find_knot_indices(std::get<Is>(xi))...);
704 }
706
707public:
710 template <functionspace comp = functionspace::interior>
711 inline auto find_knot_indices(const utils::TensorArray<nspaces()> &xi) const {
712 return find_knot_indices_<comp>(
713 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
714 }
715
716 template <functionspace comp = functionspace::interior, typename... Xi>
717 inline auto find_knot_indices(const std::tuple<Xi...> &xi) const {
718 return find_knot_indices_<comp>(
719 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
720 }
722
723private:
727 template <functionspace comp = functionspace::interior,
728 deriv deriv = deriv::func, bool memory_optimized = false,
729 std::size_t... Is, typename... Xi>
730 inline auto eval_basfunc_(std::index_sequence<Is...>,
731 const std::tuple<Xi...> &xi) const {
732 if constexpr (comp == functionspace::interior)
733 return std::tuple(
734 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
735 std::get<Is>(xi))...);
736 else if constexpr (comp == functionspace::boundary)
737 return std::tuple(std::get<Is>(boundary_)
738 .template eval_basfunc<deriv, memory_optimized>(
739 std::get<Is>(xi))...);
740 }
741
742 template <functionspace comp = functionspace::interior,
743 deriv deriv = deriv::func, bool memory_optimized = false,
744 std::size_t... Is, typename... Xi, typename... Knot_Indices>
745 inline auto
746 eval_basfunc_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
747 const std::tuple<Knot_Indices...> &knot_indices) const {
748 if constexpr (comp == functionspace::interior)
749 return std::tuple(
750 std::get<Is>(spline_).template eval_basfunc<deriv, memory_optimized>(
751 std::get<Is>(xi), std::get<Is>(knot_indices))...);
752 else if constexpr (comp == functionspace::boundary)
753 return std::tuple(
754 std::get<Is>(boundary_)
755 .template eval_basfunc<deriv, memory_optimized>(
756 std::get<Is>(xi), std::get<Is>(knot_indices))...);
757 }
759
760public:
763 template <functionspace comp = functionspace::interior,
764 deriv deriv = deriv::func, bool memory_optimized = false,
765 typename... Xi>
766 inline auto eval_basfunc(const std::tuple<Xi...> &xi) const {
767 return eval_basfunc_<comp, deriv, memory_optimized>(
768 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi);
769 }
770
771 template <functionspace comp = functionspace::interior,
772 deriv deriv = deriv::func, bool memory_optimized = false,
773 typename... Xi, typename... Knot_Indices>
774 inline auto
775 eval_basfunc(const std::tuple<Xi...> &xi,
776 const std::tuple<Knot_Indices...> &knot_indices) const {
777 return eval_basfunc_<comp, deriv, memory_optimized>(
778 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, knot_indices);
779 }
781
782private:
785 template <functionspace comp = functionspace::interior,
786 bool memory_optimized = false, std::size_t... Is,
787 typename... Knot_Indices>
788 inline auto
789 find_coeff_indices_(std::index_sequence<Is...>,
790 const std::tuple<Knot_Indices...> &knot_indices) const {
791 if constexpr (comp == functionspace::interior)
792 return std::tuple(
793 std::get<Is>(spline_).template find_coeff_indices<memory_optimized>(
794 std::get<Is>(knot_indices))...);
795 else if constexpr (comp == functionspace::boundary)
796 return std::tuple(
797 std::get<Is>(boundary_).template find_coeff_indices<memory_optimized>(
798 std::get<Is>(knot_indices))...);
799 }
800
801public:
804 template <functionspace comp = functionspace::interior,
805 bool memory_optimized = false, typename... Knot_Indices>
806 inline auto
807 find_coeff_indices(const std::tuple<Knot_Indices...> &knot_indices) const {
808 return find_coeff_indices_<comp, memory_optimized>(
809 std::make_index_sequence<FunctionSpace::nspaces()>{}, knot_indices);
810 }
811
812private:
815 template <std::size_t... Is, std::size_t... Js>
816 inline auto &uniform_refine_(std::index_sequence<Is...>,
817 std::index_sequence<Js...>, int numRefine = 1,
818 int dimRefine = -1) {
819 (std::get<Is>(spline_).uniform_refine(numRefine, dimRefine), ...);
820 (std::get<Js>(boundary_).uniform_refine(numRefine, dimRefine), ...);
821 return *this;
822 }
823
824public:
827 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
828 return uniform_refine_(
829 std::make_index_sequence<FunctionSpace::nspaces()>{},
830 std::make_index_sequence<FunctionSpace::nboundaries()>{}, numRefine,
831 dimRefine);
832 }
833
834private:
837 template <typename real_t, std::size_t... Is, std::size_t... Js>
838 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
839 Options<real_t> options) const {
840 return FunctionSpace<
841 typename Splines::template real_derived_self_type<real_t>...,
842 typename Boundaries::template real_derived_self_type<real_t>...>(
843 std::get<Is>(spline_).to(options)...,
844 std::get<Js>(boundary_).to(options)...);
845 }
846
847public:
850 template <typename real_t> inline auto to(Options<real_t> options) const {
851 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
852 std::make_index_sequence<FunctionSpace::nboundaries()>{},
853 options);
854 }
855
856private:
859 template <std::size_t... Is, std::size_t... Js>
860 inline auto to_(std::index_sequence<Is...>, std::index_sequence<Js...>,
861 torch::Device device) const {
862 return FunctionSpace(std::get<Is>(spline_).to(device)...,
863 std::get<Js>(boundary_).to(device)...);
864 }
865
866public:
869 inline auto to(torch::Device device) const {
870 return to_(std::make_index_sequence<FunctionSpace::nspaces()>{},
871 std::make_index_sequence<FunctionSpace::nboundaries()>{},
872 device);
873 }
874
875private:
877 template <typename real_t, std::size_t... Is, std::size_t... Js>
878 inline auto to_(std::index_sequence<Is...>,
879 std::index_sequence<Js...>) const {
880 return FunctionSpace<
881 typename Splines::template real_derived_self_type<real_t>...,
882 typename Boundaries::template real_derived_self_type<real_t>...>(
883 std::get<Is>(spline_).template to<real_t>()...,
884 std::get<Js>(boundary_).template to<real_t>()...);
885 }
886
887public:
889 template <typename real_t> inline auto to() const {
890 return to_<real_t>(
891 std::make_index_sequence<FunctionSpace::nspaces()>{},
892 std::make_index_sequence<FunctionSpace::nboundaries()>{});
893 }
894
895private:
897 template <std::size_t... Is>
898 inline auto scale_(std::index_sequence<Is...>, value_type s, int dim = -1) {
899 (std::get<Is>(spline_).scale(s, dim), ...);
901 return *this;
902 }
903
904public:
906 inline auto scale(value_type s, int dim = -1) {
907 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, s, dim);
908 }
909
910private:
912 template <std::size_t N, std::size_t... Is>
913 inline auto scale_(std::index_sequence<Is...>, std::array<value_type, N> v) {
914 (std::get<Is>(spline_).scale(v), ...);
915 (std::get<Is>(boundary_).from_full_tensor(
916 std::get<Is>(spline_).as_tensor()),
917 ...);
918 return *this;
919 }
920
921public:
923 template <std::size_t N> inline auto scale(std::array<value_type, N> v) {
924 return scale_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
925 }
926
927private:
929 template <std::size_t N, std::size_t... Is>
930 inline auto translate_(std::index_sequence<Is...>,
931 std::array<value_type, N> v) {
932 (std::get<Is>(spline_).translate(v), ...);
933 (std::get<Is>(boundary_).from_full_tensor(
934 std::get<Is>(spline_).as_tensor()),
935 ...);
936 return *this;
937 }
938
939public:
941 template <std::size_t N> inline auto translate(std::array<value_type, N> v) {
942 return translate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, v);
943 }
944
945private:
947 template <std::size_t... Is>
948 inline auto rotate_(std::index_sequence<Is...>, value_type angle) {
949 (std::get<Is>(spline_).rotate(angle), ...);
950 (std::get<Is>(boundary_).from_full_tensor(
951 std::get<Is>(spline_).as_tensor()),
952 ...);
953 return *this;
954 }
955
956public:
958 inline auto rotate(value_type angle) {
959 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
960 }
961
962private:
964 template <std::size_t... Is>
965 inline auto rotate_(std::index_sequence<Is...>,
966 std::array<value_type, 3> angle) {
967 (std::get<Is>(spline_).rotate(angle), ...);
968 (std::get<Is>(boundary_).from_full_tensor(
969 std::get<Is>(spline_).as_tensor()),
970 ...);
971 return *this;
972 }
973
974public:
976 inline auto rotate(std::array<value_type, 3> angle) {
977 return rotate_(std::make_index_sequence<FunctionSpace::nspaces()>{}, angle);
978 }
979
980private:
982 template <std::size_t... Is>
983 inline auto boundingBox_(std::index_sequence<Is...>) const {
984 return std::tuple(std::get<Is>(spline_).boundingBox()...);
985 }
986
987public:
989 inline auto boundingBox() const {
990 return boundingBox_(std::make_index_sequence<FunctionSpace::nspaces()>{});
991 }
992
993private:
996 template <std::size_t... Is>
997 inline torch::serialize::OutputArchive &
998 write_(std::index_sequence<Is...>, torch::serialize::OutputArchive &archive,
999 const std::string &key = "functionspace") const {
1000 (std::get<Is>(spline_).write(
1001 archive, key + ".fspace[" + std::to_string(Is) + "].interior"),
1002 ...);
1003 (std::get<Is>(boundary_).write(
1004 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
1005 ...);
1006 return archive;
1007 }
1008
1009public:
1012 inline torch::serialize::OutputArchive &
1013 write(torch::serialize::OutputArchive &archive,
1014 const std::string &key = "functionspace") const {
1015 write_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
1016 return archive;
1017 }
1018
1019private:
1022 template <std::size_t... Is>
1023 inline torch::serialize::InputArchive &
1024 read_(std::index_sequence<Is...>, torch::serialize::InputArchive &archive,
1025 const std::string &key = "functionspace") {
1026 (std::get<Is>(spline_).read(archive, key + ".fspace[" + std::to_string(Is) +
1027 "].interior"),
1028 ...);
1029 (std::get<Is>(boundary_).read(
1030 archive, key + ".fspace[" + std::to_string(Is) + "].boundary"),
1031 ...);
1032 return archive;
1033 }
1034
1035public:
1038 inline torch::serialize::InputArchive &
1039 read(torch::serialize::InputArchive &archive,
1040 const std::string &key = "functionspace") {
1041 read_(std::make_index_sequence<FunctionSpace::nspaces()>{}, archive, key);
1042 return archive;
1043 }
1044
1046 inline void pretty_print(std::ostream &os) const noexcept override {
1047
1048 auto pretty_print_ = [this,
1049 &os]<std::size_t... Is>(std::index_sequence<Is...>) {
1050 ((os << "\ninterior = ", std::get<Is>(spline_).pretty_print(os),
1051 os << "\nboundary = ", std::get<Is>(boundary_).pretty_print(os)),
1052 ...);
1053 };
1054
1055 pretty_print_(std::make_index_sequence<nspaces()>{});
1056 }
1057
1058 // clang-format off
1076 // clang-format on
1079 template <functionspace comp = functionspace::interior,
1080 bool memory_optimized = false>
1081 inline auto curl(const utils::TensorArray<nspaces()> &xi) const {
1082 return curl<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1083 }
1084
1085 template <functionspace comp = functionspace::interior,
1086 bool memory_optimized = false, typename... TensorArrays>
1087 inline auto curl(const utils::TensorArray<nspaces()> &xi,
1088 const std::tuple<TensorArrays...> &knot_indices) const {
1089 return curl<comp, memory_optimized>(xi, knot_indices,
1090 find_coeff_indices<comp>(knot_indices));
1091 }
1092
1093 template <functionspace comp = functionspace::interior,
1094 bool memory_optimized = false>
1095 inline auto curl(const utils::TensorArray1 &xi,
1096 const std::tuple<utils::TensorArray1> &knot_indices,
1097 const std::tuple<torch::Tensor> &coeff_indices) const {
1098
1099 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1100
1101 throw std::runtime_error("Unsupported parametric/geometric dimension");
1102
1104 }
1105
1106 template <functionspace comp = functionspace::interior,
1107 bool memory_optimized = false>
1108 inline auto
1110 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1111 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1112
1113 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1114 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1115 xi[0].sizes() == xi[1].sizes());
1116
1123 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1124 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1125 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1126 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1127 }
1128
1129 template <functionspace comp = functionspace::interior,
1130 bool memory_optimized = false>
1131 inline auto curl(const utils::TensorArray3 &xi,
1132 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1133 utils::TensorArray3> &knot_indices,
1134 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1135 &coeff_indices) const {
1136
1137 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1138 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1139 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1140 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1141
1146 *std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
1147 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] -
1148 *std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
1149 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1150 *std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
1151 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] -
1152 *std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
1153 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1154 *std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1155 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] -
1156 *std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1157 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1158 }
1159
1160 template <functionspace comp = functionspace::interior,
1161 bool memory_optimized = false>
1162 inline auto
1164 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1166 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1167 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[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1172 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1173 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1174 xi[2].sizes() == xi[3].sizes());
1175
1176 throw std::runtime_error("Unsupported parametric/geometric dimension");
1177
1179 }
1181
1206 template <functionspace comp = functionspace::interior,
1207 bool memory_optimized = false>
1208 inline auto div(const utils::TensorArray<nspaces()> &xi) const {
1209 return div<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1210 }
1211
1212 template <functionspace comp = functionspace::interior,
1213 bool memory_optimized = false, typename... TensorArrays>
1214 inline auto div(const utils::TensorArray<nspaces()> &xi,
1215 const std::tuple<TensorArrays...> &knot_indices) const {
1216 return div<comp, memory_optimized>(xi, knot_indices,
1217 find_coeff_indices<comp>(knot_indices));
1218 }
1219
1220 template <functionspace comp = functionspace::interior,
1221 bool memory_optimized = false>
1222 inline auto div(const utils::TensorArray1 &xi,
1223 const std::tuple<utils::TensorArray1> &knot_indices,
1224 const std::tuple<torch::Tensor> &coeff_indices) const {
1225
1226 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1227
1228 if constexpr (comp == functionspace::interior) {
1229 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1230 "div(.) for vector-valued spaces requires 1D variables");
1231
1233 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1234 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1235 }
1236 }
1237
1238 template <functionspace comp = functionspace::interior,
1239 bool memory_optimized = false>
1240 inline auto
1242 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1243 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1244
1245 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1246 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1247 xi[0].sizes() == xi[1].sizes());
1248
1249 if constexpr (comp == functionspace::interior) {
1250 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1251 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1252 "div(.) for vector-valued spaces requires 1D variables");
1253
1255 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1256 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1257 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1258 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1259 }
1260 }
1261
1262 template <functionspace comp = functionspace::interior,
1263 bool memory_optimized = false>
1264 inline auto div(const utils::TensorArray3 &xi,
1265 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1266 utils::TensorArray3> &knot_indices,
1267 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1268 &coeff_indices) const {
1269
1270 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1271 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1272 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1273 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1274
1275 if constexpr (comp == functionspace::interior) {
1276 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1277 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1278 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1279 "div(.) for vector-valued spaces requires 1D variables");
1280
1282 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1283 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1284 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1285 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1286 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1287 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1288 }
1289 }
1290
1291 template <functionspace comp = functionspace::interior,
1292 bool memory_optimized = false>
1293 inline auto
1295 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1297 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1298 torch::Tensor> &coeff_indices) const {
1299
1300 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1301 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1302 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1303 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1304 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1305 xi[2].sizes() == xi[3].sizes());
1306
1307 if constexpr (comp == functionspace::interior) {
1308 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1309 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1310 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1311 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1312 "div(.) for vector-valued spaces requires 1D variables");
1313
1315 *std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1316 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
1317 *std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1318 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
1319 *std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1320 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
1321 *std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1322 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1323 }
1324 }
1326
1344 template <functionspace comp = functionspace::interior,
1345 bool memory_optimized = false>
1346 inline auto grad(const utils::TensorArray<nspaces()> &xi) const {
1347 return grad<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1348 }
1349
1350 template <functionspace comp = functionspace::interior,
1351 bool memory_optimized = false, typename... TensorArrays>
1352 inline auto grad(const utils::TensorArray<nspaces()> &xi,
1353 const std::tuple<TensorArrays...> &knot_indices) const {
1354 return grad<comp, memory_optimized>(xi, knot_indices,
1355 find_coeff_indices<comp>(knot_indices));
1356 }
1357
1358 template <functionspace comp = functionspace::interior,
1359 bool memory_optimized = false>
1360 inline auto grad(const utils::TensorArray1 &xi,
1361 const std::tuple<utils::TensorArray1> &knot_indices,
1362 const std::tuple<torch::Tensor> &coeff_indices) const {
1363
1364 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1365
1366 if constexpr (comp == functionspace::interior) {
1367 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1368 "grad(.) for vector-valued spaces requires 1D variables");
1369
1371 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1372 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1373 }
1374 }
1375
1376 template <functionspace comp = functionspace::interior,
1377 bool memory_optimized = false>
1378 inline auto
1380 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1381 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1382
1383 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1384 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1385 xi[0].sizes() == xi[1].sizes());
1386
1387 if constexpr (comp == functionspace::interior) {
1388 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1389 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1390 "grad(.) for vector-valued spaces requires 1D variables");
1391
1393 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1394 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1395 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1396 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1397 }
1398 }
1399
1400 template <functionspace comp = functionspace::interior,
1401 bool memory_optimized = false>
1402 inline auto grad(const utils::TensorArray3 &xi,
1403 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1404 utils::TensorArray3> &knot_indices,
1405 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1406 &coeff_indices) const {
1407
1408 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1409 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1410 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1411 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1412
1413 if constexpr (comp == functionspace::interior) {
1414 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1415 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1416 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1417 "div(.) for vector-valued spaces requires 1D variables");
1418
1420 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1421 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1422 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1423 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1424 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1425 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
1426 }
1427 }
1428
1429 template <functionspace comp = functionspace::interior,
1430 bool memory_optimized = false>
1431 inline auto
1433 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1435 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1436 torch::Tensor> &coeff_indices) const {
1437
1438 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1439 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1440 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1441 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1442 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1443 xi[2].sizes() == xi[3].sizes());
1444
1445 if constexpr (comp == functionspace::interior) {
1446 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1447 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1448 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1449 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1450 "grad(.) for vector-valued spaces requires 1D variables");
1451
1453 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1454 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1455 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1456 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1457 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
1458 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
1459 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
1460 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
1461 }
1462 }
1464
1465 // clang-format off
1498 // clang-format on
1501 template <functionspace comp = functionspace::interior,
1502 bool memory_optimized = false>
1503 inline auto hess(const utils::TensorArray<nspaces()> &xi) const {
1504 return hess<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1505 }
1506
1507 template <functionspace comp = functionspace::interior,
1508 bool memory_optimized = false, typename... TensorArrays>
1509 inline auto hess(const utils::TensorArray<nspaces()> &xi,
1510 const std::tuple<TensorArrays...> &knot_indices) const {
1511 return hess<comp, memory_optimized>(xi, knot_indices,
1512 find_coeff_indices<comp>(knot_indices));
1513 }
1514
1515 template <functionspace comp = functionspace::interior,
1516 bool memory_optimized = false>
1517 inline auto hess(const utils::TensorArray1 &xi,
1518 const std::tuple<utils::TensorArray1> &knot_indices,
1519 const std::tuple<torch::Tensor> &coeff_indices) const {
1520
1521 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1522
1523 if constexpr (comp == functionspace::interior) {
1524 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1525 "hess(.) for vector-valued spaces requires 1D variables");
1526
1528 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1529 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)));
1530 }
1531 }
1532
1533 template <functionspace comp = functionspace::interior,
1534 bool memory_optimized = false>
1535 inline auto
1537 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1538 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1539
1540 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1541 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1542 xi[0].sizes() == xi[1].sizes());
1543
1544 if constexpr (comp == functionspace::interior) {
1545 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1546 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1547 "hess(.) for vector-valued spaces requires 1D variables");
1548
1550 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1551 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1552 std::get<0>(spline_)
1553 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1554 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1555 std::get<0>(spline_)
1556 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1557 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1558 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1559 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1560
1561 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1562 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1563 std::get<1>(spline_)
1564 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1565 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1566 std::get<1>(spline_)
1567 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1568 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1569 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1570 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)));
1571 }
1572 }
1573
1574 template <functionspace comp = functionspace::interior,
1575 bool memory_optimized = false>
1576 inline auto hess(const utils::TensorArray3 &xi,
1577 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1578 utils::TensorArray3> &knot_indices,
1579 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1580 &coeff_indices) const {
1581
1582 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1583 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1584 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1585 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1586
1587 if constexpr (comp == functionspace::interior) {
1588 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1589 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1590 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1591 "hess(.) for vector-valued spaces requires 1D variables");
1592
1594 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1595 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1596 std::get<0>(spline_)
1597 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1598 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1599 std::get<0>(spline_)
1600 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1601 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1602 std::get<0>(spline_)
1603 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1604 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1605 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1606 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1607 std::get<0>(spline_)
1608 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1609 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1610 std::get<0>(spline_)
1611 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1612 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1613 std::get<0>(spline_)
1614 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1615 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1616 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1617 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1618
1619 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1620 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1621 std::get<1>(spline_)
1622 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1623 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1624 std::get<1>(spline_)
1625 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1626 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1627 std::get<1>(spline_)
1628 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1629 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1630 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1631 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1632 std::get<1>(spline_)
1633 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1634 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1635 std::get<1>(spline_)
1636 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1637 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1638 std::get<1>(spline_)
1639 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1640 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1641 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1642 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1643
1644 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1645 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1646 std::get<2>(spline_)
1647 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1648 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1649 std::get<2>(spline_)
1650 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1651 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1652 std::get<2>(spline_)
1653 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1654 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1655 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1656 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1657 std::get<2>(spline_)
1658 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1659 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1660 std::get<2>(spline_)
1661 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1662 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1663 std::get<2>(spline_)
1664 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1665 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1666 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1667 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)));
1668 }
1669 }
1670
1671 template <functionspace comp = functionspace::interior,
1672 bool memory_optimized = false>
1673 inline auto
1675 const std::tuple<utils::TensorArray4, utils::TensorArray4,
1677 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
1678 torch::Tensor> &coeff_indices) const {
1679
1680 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1681 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1682 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1683 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
1684 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
1685 xi[2].sizes() == xi[3].sizes());
1686
1687 if constexpr (comp == functionspace::interior) {
1688 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1689 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1690 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
1691 std::tuple_element_t<3, spline_type>::geoDim() == 1,
1692 "hess(.) for vector-valued spaces requires 1D variables");
1693
1695 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1696 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1697 std::get<0>(spline_)
1698 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1699 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1700 std::get<0>(spline_)
1701 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1702 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1703 std::get<0>(spline_)
1704 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1705 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1706 std::get<0>(spline_)
1707 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1708 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1709 std::get<0>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1710 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1711 std::get<0>(spline_)
1712 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1713 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1714 std::get<0>(spline_)
1715 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1716 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1717 std::get<0>(spline_)
1718 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1719 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1720 std::get<0>(spline_)
1721 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1722 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1723 std::get<0>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1724 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1725 std::get<0>(spline_)
1726 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1727 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1728 std::get<0>(spline_)
1729 .template eval<deriv::dt + deriv::dx, memory_optimized>(
1730 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1731 std::get<0>(spline_)
1732 .template eval<deriv::dt + deriv::dy, memory_optimized>(
1733 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1734 std::get<0>(spline_)
1735 .template eval<deriv::dt + deriv::dz, memory_optimized>(
1736 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1737 std::get<0>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1738 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices)),
1739
1740 std::get<1>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1741 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1742 std::get<1>(spline_)
1743 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1744 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1745 std::get<1>(spline_)
1746 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1747 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1748 std::get<1>(spline_)
1749 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1750 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1751 std::get<1>(spline_)
1752 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1753 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1754 std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1755 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1756 std::get<1>(spline_)
1757 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1758 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1759 std::get<1>(spline_)
1760 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1761 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1762 std::get<1>(spline_)
1763 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1764 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1765 std::get<1>(spline_)
1766 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1767 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1768 std::get<1>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1769 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1770 std::get<1>(spline_)
1771 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1772 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1773 std::get<1>(spline_)
1774 .template eval<deriv::dt + deriv::dx, memory_optimized>(
1775 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1776 std::get<1>(spline_)
1777 .template eval<deriv::dt + deriv::dy, memory_optimized>(
1778 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1779 std::get<1>(spline_)
1780 .template eval<deriv::dt + deriv::dz, memory_optimized>(
1781 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1782 std::get<1>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1783 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices)),
1784
1785 std::get<2>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1786 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1787 std::get<2>(spline_)
1788 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1789 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1790 std::get<2>(spline_)
1791 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1792 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1793 std::get<2>(spline_)
1794 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1795 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1796 std::get<2>(spline_)
1797 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1798 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1799 std::get<2>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1800 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1801 std::get<2>(spline_)
1802 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1803 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1804 std::get<2>(spline_)
1805 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1806 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1807 std::get<2>(spline_)
1808 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1809 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1810 std::get<2>(spline_)
1811 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1812 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1813 std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1814 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1815 std::get<2>(spline_)
1816 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1817 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1818 std::get<2>(spline_)
1819 .template eval<deriv::dt + deriv::dx, memory_optimized>(
1820 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1821 std::get<2>(spline_)
1822 .template eval<deriv::dt + deriv::dy, memory_optimized>(
1823 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1824 std::get<2>(spline_)
1825 .template eval<deriv::dt + deriv::dz, memory_optimized>(
1826 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1827 std::get<2>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1828 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices)),
1829
1830 std::get<3>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
1831 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1832 std::get<3>(spline_)
1833 .template eval<deriv::dx + deriv::dy, memory_optimized>(
1834 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1835 std::get<3>(spline_)
1836 .template eval<deriv::dx + deriv::dz, memory_optimized>(
1837 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1838 std::get<3>(spline_)
1839 .template eval<deriv::dx + deriv::dt, memory_optimized>(
1840 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1841 std::get<3>(spline_)
1842 .template eval<deriv::dy + deriv::dx, memory_optimized>(
1843 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1844 std::get<3>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
1845 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1846 std::get<3>(spline_)
1847 .template eval<deriv::dy + deriv::dz, memory_optimized>(
1848 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1849 std::get<3>(spline_)
1850 .template eval<deriv::dy + deriv::dt, memory_optimized>(
1851 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1852 std::get<3>(spline_)
1853 .template eval<deriv::dz + deriv::dx, memory_optimized>(
1854 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1855 std::get<3>(spline_)
1856 .template eval<deriv::dz + deriv::dy, memory_optimized>(
1857 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1858 std::get<3>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
1859 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1860 std::get<3>(spline_)
1861 .template eval<deriv::dz + deriv::dt, memory_optimized>(
1862 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1863 std::get<3>(spline_)
1864 .template eval<deriv::dt + deriv::dx, memory_optimized>(
1865 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1866 std::get<3>(spline_)
1867 .template eval<deriv::dt + deriv::dy, memory_optimized>(
1868 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1869 std::get<3>(spline_)
1870 .template eval<deriv::dt + deriv::dz, memory_optimized>(
1871 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)),
1872 std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
1873 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices)));
1874 }
1875 }
1877
1878 // clang-format off
1912 // clang-format on
1914 template <functionspace comp = functionspace::interior,
1915 bool memory_optimized = false>
1916 inline auto jac(const utils::TensorArray<nspaces()> &xi) const {
1917 return jac<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
1918 }
1919
1920 template <functionspace comp = functionspace::interior,
1921 bool memory_optimized = false, typename... TensorArrays>
1922 inline auto jac(const utils::TensorArray<nspaces()> &xi,
1923 const std::tuple<TensorArrays...> &knot_indices) const {
1924 return jac<comp, memory_optimized>(xi, knot_indices,
1925 find_coeff_indices<comp>(knot_indices));
1926 }
1927
1928 template <functionspace comp = functionspace::interior,
1929 bool memory_optimized = false>
1930 inline auto jac(const utils::TensorArray1 &xi,
1931 const std::tuple<utils::TensorArray1> &knot_indices,
1932 const std::tuple<torch::Tensor> &coeff_indices) const {
1933
1934 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
1935
1936 if constexpr (comp == functionspace::interior) {
1937 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
1938 "jac(.) for vector-valued spaces requires 1D variables");
1939
1941 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1942 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
1943 }
1944 }
1945
1946 template <functionspace comp = functionspace::interior,
1947 bool memory_optimized = false>
1948 inline auto
1950 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
1951 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
1952
1953 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1954 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1955 xi[0].sizes() == xi[1].sizes());
1956
1957 if constexpr (comp == functionspace::interior) {
1958 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1959 std::tuple_element_t<1, spline_type>::geoDim() == 1,
1960 "jac(.) for vector-valued spaces requires 1D variables");
1961
1963 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1964 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1965 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1966 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1967
1968 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
1969 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
1970 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
1971 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
1972 }
1973 }
1974
1975 template <functionspace comp = functionspace::interior,
1976 bool memory_optimized = false>
1977 inline auto jac(const utils::TensorArray3 &xi,
1978 const std::tuple<utils::TensorArray3, utils::TensorArray3,
1979 utils::TensorArray3> &knot_indices,
1980 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
1981 &coeff_indices) const {
1982
1983 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
1984 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
1985 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
1986 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
1987
1988 if constexpr (comp == functionspace::interior) {
1989 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
1990 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
1991 std::tuple_element_t<2, spline_type>::geoDim() == 1,
1992 "jac(.) for vector-valued spaces requires 1D variables");
1993
1995 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
1996 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1997 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
1998 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
1999 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
2000 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2001
2002 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
2003 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2004 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
2005 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2006 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
2007 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2008
2009 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
2010 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2011 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
2012 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2013 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
2014 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
2015 }
2016 }
2017
2018 template <functionspace comp = functionspace::interior,
2019 bool memory_optimized = false>
2020 inline auto
2022 const std::tuple<utils::TensorArray4, utils::TensorArray4,
2024 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
2025 torch::Tensor> &coeff_indices) const {
2026
2027 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2028 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2029 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2030 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
2031 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
2032 xi[2].sizes() == xi[3].sizes());
2033
2034 if constexpr (comp == functionspace::interior) {
2035 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2036 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2037 std::tuple_element_t<2, spline_type>::geoDim() == 1,
2038 "jac(.) for vector-valued spaces requires 1D variables");
2039
2041 std::get<0>(spline_).template eval<deriv::dx, memory_optimized>(
2042 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2043 std::get<0>(spline_).template eval<deriv::dy, memory_optimized>(
2044 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2045 std::get<0>(spline_).template eval<deriv::dz, memory_optimized>(
2046 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2047 std::get<0>(spline_).template eval<deriv::dt, memory_optimized>(
2048 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0],
2049
2050 std::get<1>(spline_).template eval<deriv::dx, memory_optimized>(
2051 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2052 std::get<1>(spline_).template eval<deriv::dy, memory_optimized>(
2053 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2054 std::get<1>(spline_).template eval<deriv::dz, memory_optimized>(
2055 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2056 std::get<1>(spline_).template eval<deriv::dt, memory_optimized>(
2057 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0],
2058
2059 std::get<2>(spline_).template eval<deriv::dx, memory_optimized>(
2060 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2061 std::get<2>(spline_).template eval<deriv::dy, memory_optimized>(
2062 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2063 std::get<2>(spline_).template eval<deriv::dz, memory_optimized>(
2064 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2065 std::get<2>(spline_).template eval<deriv::dt, memory_optimized>(
2066 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0],
2067
2068 std::get<3>(spline_).template eval<deriv::dx, memory_optimized>(
2069 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2070 std::get<3>(spline_).template eval<deriv::dy, memory_optimized>(
2071 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2072 std::get<3>(spline_).template eval<deriv::dz, memory_optimized>(
2073 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0],
2074 std::get<3>(spline_).template eval<deriv::dt, memory_optimized>(
2075 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2076 }
2077 }
2079
2080 // clang-format off
2097 // clang-format on
2100 template <functionspace comp = functionspace::interior,
2101 bool memory_optimized = false>
2102 inline auto lapl(const utils::TensorArray<nspaces()> &xi) const {
2103 return lapl<comp, memory_optimized>(xi, find_knot_indices<comp>(xi));
2104 }
2105
2106 template <functionspace comp = functionspace::interior,
2107 bool memory_optimized = false, typename... TensorArrays>
2108 inline auto lapl(const utils::TensorArray<nspaces()> &xi,
2109 const std::tuple<TensorArrays...> &knot_indices) const {
2110 return lapl<comp, memory_optimized>(xi, knot_indices,
2111 find_coeff_indices<comp>(knot_indices));
2112 }
2113
2114 template <functionspace comp = functionspace::interior,
2115 bool memory_optimized = false>
2116 inline auto lapl(const utils::TensorArray1 &xi,
2117 const std::tuple<utils::TensorArray1> &knot_indices,
2118 const std::tuple<torch::Tensor> &coeff_indices) const {
2119
2120 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes());
2121
2122 if constexpr (comp == functionspace::interior) {
2123 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1,
2124 "lapl(.) for vector-valued spaces requires 1D variables");
2125
2127 std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2128 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0]);
2129 }
2130 }
2131
2132 template <functionspace comp = functionspace::interior,
2133 bool memory_optimized = false>
2134 inline auto
2136 const std::tuple<utils::TensorArray2, utils::TensorArray2> &knot_indices,
2137 const std::tuple<torch::Tensor, torch::Tensor> &coeff_indices) const {
2138
2139 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2140 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2141 xi[0].sizes() == xi[1].sizes());
2142
2143 if constexpr (comp == functionspace::interior) {
2144 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2145 std::tuple_element_t<1, spline_type>::geoDim() == 1,
2146 "lapl(.) for vector-valued spaces requires 1D variables");
2147
2149 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2150 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2151 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2152 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0]);
2153 }
2154 }
2155
2156 template <functionspace comp = functionspace::interior,
2157 bool memory_optimized = false>
2158 inline auto lapl(const utils::TensorArray3 &xi,
2159 const std::tuple<utils::TensorArray3, utils::TensorArray3,
2160 utils::TensorArray3> &knot_indices,
2161 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor>
2162 &coeff_indices) const {
2163
2164 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2165 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2166 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2167 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes());
2168
2169 if constexpr (comp == functionspace::interior) {
2170 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2171 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2172 std::tuple_element_t<2, spline_type>::geoDim() == 1,
2173 "div(.) for vector-valued spaces requires 1D variables");
2174
2176 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2177 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2178 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2179 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2180 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2181 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0]);
2182 }
2183 }
2184
2185 template <functionspace comp = functionspace::interior,
2186 bool memory_optimized = false>
2187 inline auto
2189 const std::tuple<utils::TensorArray4, utils::TensorArray4,
2191 const std::tuple<torch::Tensor, torch::Tensor, torch::Tensor,
2192 torch::Tensor> &coeff_indices) const {
2193
2194 assert(xi[0].sizes() == std::get<0>(knot_indices)[0].sizes() &&
2195 xi[1].sizes() == std::get<1>(knot_indices)[0].sizes() &&
2196 xi[2].sizes() == std::get<2>(knot_indices)[0].sizes() &&
2197 xi[3].sizes() == std::get<3>(knot_indices)[0].sizes() &&
2198 xi[0].sizes() == xi[1].sizes() && xi[1].sizes() == xi[2].sizes() &&
2199 xi[2].sizes() == xi[3].sizes());
2200
2201 if constexpr (comp == functionspace::interior) {
2202 static_assert(std::tuple_element_t<0, spline_type>::geoDim() == 1 &&
2203 std::tuple_element_t<1, spline_type>::geoDim() == 1 &&
2204 std::tuple_element_t<2, spline_type>::geoDim() == 1 &&
2205 std::tuple_element_t<3, spline_type>::geoDim() == 1,
2206 "div(.) for vector-valued spaces requires 1D variables");
2207
2209 *std::get<0>(spline_).template eval<deriv::dx ^ 2, memory_optimized>(
2210 xi, std::get<0>(knot_indices), std::get<0>(coeff_indices))[0] +
2211 *std::get<1>(spline_).template eval<deriv::dy ^ 2, memory_optimized>(
2212 xi, std::get<1>(knot_indices), std::get<1>(coeff_indices))[0] +
2213 *std::get<2>(spline_).template eval<deriv::dz ^ 2, memory_optimized>(
2214 xi, std::get<2>(knot_indices), std::get<2>(coeff_indices))[0] +
2215 *std::get<3>(spline_).template eval<deriv::dt ^ 2, memory_optimized>(
2216 xi, std::get<3>(knot_indices), std::get<3>(coeff_indices))[0]);
2217 }
2218 }
2220
2221#define GENERATE_EXPR_MACRO(r, data, name) \
2222private: \
2223 template <functionspace comp = functionspace::interior, \
2224 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
2225 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2226 const std::tuple<Xi...> &xi) const { \
2227 if constexpr (comp == functionspace::interior) \
2228 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2229 std::get<Is>(xi))...); \
2230 else if constexpr (comp == functionspace::boundary) \
2231 return std::tuple( \
2232 std::get<Is>(boundary_).template name<memory_optimized>( \
2233 std::get<Is>(xi))...); \
2234 } \
2235 \
2236 template <functionspace comp = functionspace::interior, \
2237 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2238 typename... Knot_Indices> \
2239 inline auto BOOST_PP_CAT(name, _all_)( \
2240 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2241 const std::tuple<Knot_Indices...> &knot_indices) const { \
2242 if constexpr (comp == functionspace::interior) \
2243 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2244 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2245 else if constexpr (comp == functionspace::boundary) \
2246 return std::tuple( \
2247 std::get<Is>(boundary_).template name<memory_optimized>( \
2248 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
2249 } \
2250 \
2251 template <functionspace comp = functionspace::interior, \
2252 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
2253 typename... Knot_Indices, typename... Coeff_Indices> \
2254 inline auto BOOST_PP_CAT(name, _all_)( \
2255 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
2256 const std::tuple<Knot_Indices...> &knot_indices, \
2257 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
2258 if constexpr (comp == functionspace::interior) \
2259 return std::tuple(std::get<Is>(spline_).template name<memory_optimized>( \
2260 std::get<Is>(xi), std::get<Is>(knot_indices), \
2261 std::get<Is>(coeff_indices))...); \
2262 else if constexpr (comp == functionspace::boundary) \
2263 return std::tuple( \
2264 std::get<Is>(boundary_).template name<memory_optimized>( \
2265 std::get<Is>(xi), std::get<Is>(knot_indices), \
2266 std::get<Is>(coeff_indices))...); \
2267 } \
2268 \
2269 template <functionspace comp = functionspace::interior, \
2270 bool memory_optimized = false, std::size_t... Is, std::size_t N> \
2271 inline auto BOOST_PP_CAT(name, _)(std::index_sequence<Is...>, \
2272 const utils::TensorArray<N> &xi) const { \
2273 if constexpr (comp == functionspace::interior) \
2274 return name<comp, memory_optimized>( \
2275 xi, std::tuple(std::get<Is>(spline_).find_knot_indices(xi)...)); \
2276 else if constexpr (comp == functionspace::boundary) \
2277 return name<comp, memory_optimized>( \
2278 xi, std::tuple(std::get<Is>(boundary_).find_knot_indices(xi)...)); \
2279 } \
2280 \
2281 template <functionspace comp = functionspace::interior, \
2282 bool memory_optimized = false, std::size_t... Is, std::size_t N, \
2283 typename... Knot_Indices> \
2284 inline auto BOOST_PP_CAT(name, _)( \
2285 std::index_sequence<Is...>, const utils::TensorArray<N> &xi, \
2286 const std::tuple<Knot_Indices...> &knot_indices) const { \
2287 if constexpr (comp == functionspace::interior) \
2288 return name<comp, memory_optimized>( \
2289 xi, knot_indices, \
2290 std::tuple(std::get<Is>(spline_).find_coeff_indices( \
2291 std::get<Is>(knot_indices))...)); \
2292 else if constexpr (comp == functionspace::boundary) \
2293 return name<comp, memory_optimized>( \
2294 xi, knot_indices, \
2295 std::tuple(std::get<Is>(boundary_).find_coeff_indices( \
2296 std::get<Is>(knot_indices))...)); \
2297 } \
2298 \
2299public: \
2300 template <functionspace comp = functionspace::interior, \
2301 bool memory_optimized = false, typename... Args> \
2302 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2303 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2304 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2305 } \
2306 \
2307 template <functionspace comp = functionspace::interior, \
2308 bool memory_optimized = false> \
2309 inline auto name(const torch::Tensor &xi) const { \
2310 return name<comp, memory_optimized>(utils::TensorArray1({xi})); \
2311 } \
2312 \
2313 template <functionspace comp = functionspace::interior, \
2314 bool memory_optimized = false, std::size_t N> \
2315 inline auto name(const utils::TensorArray<N> &xi) const { \
2316 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2317 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi); \
2318 } \
2319 \
2320 template <functionspace comp = functionspace::interior, \
2321 bool memory_optimized = false, std::size_t N, \
2322 typename... Knot_Indices> \
2323 inline auto name(const utils::TensorArray<N> &xi, \
2324 const std::tuple<Knot_Indices...> &knot_indices) const { \
2325 return BOOST_PP_CAT(name, _)<comp, memory_optimized>( \
2326 std::make_index_sequence<FunctionSpace::nspaces()>{}, xi, \
2327 knot_indices); \
2328 }
2329
2332 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
2334#undef GENERATE_EXPR_MACRO
2335
2336#define GENERATE_IEXPR_MACRO(r, data, name) \
2337private: \
2338 template <functionspace comp = functionspace::interior, \
2339 bool memory_optimized = false, std::size_t... Is, \
2340 typename Geometry, typename... Xi> \
2341 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
2342 const Geometry &G, \
2343 const std::tuple<Xi...> &xi) const { \
2344 if constexpr (comp == functionspace::interior) { \
2345 if constexpr (Geometry::nspaces() == 1) \
2346 return std::tuple( \
2347 std::get<Is>(spline_).template name<memory_optimized>( \
2348 G.space(), std::get<Is>(xi))...); \
2349 else if constexpr (Geometry::nspaces() == nspaces()) \
2350 return std::tuple( \
2351 std::get<Is>(spline_).template name<memory_optimized>( \
2352 G.template space<Is>(), std::get<Is>(xi))...); \
2353 } else if constexpr (comp == functionspace::boundary) { \
2354 if constexpr (Geometry::nboundaries() == 1) \
2355 return std::tuple( \
2356 std::get<Is>(boundary_).template name<memory_optimized>( \
2357 static_cast<typename Geometry::boundary_type::boundary_type>( \
2358 G.boundary().coeffs()), \
2359 std::get<Is>(xi))...); \
2360 else if constexpr (Geometry::nboundaries() == nboundaries()) \
2361 return std::tuple( \
2362 std::get<Is>(boundary_).template name<memory_optimized>( \
2363 G.template boundary<Is>().coeffs(), std::get<Is>(xi))...); \
2364 } \
2365 } \
2366 \
2367 template <functionspace comp = functionspace::interior, \
2368 bool memory_optimized = false, std::size_t... Is, \
2369 typename Geometry, typename... Xi, typename... Knot_Indices, \
2370 typename... Knot_Indices_G> \
2371 inline auto BOOST_PP_CAT(name, _all_)( \
2372 std::index_sequence<Is...>, const Geometry &G, \
2373 const std::tuple<Xi...> &xi, \
2374 const std::tuple<Knot_Indices...> &knot_indices, \
2375 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
2376 if constexpr (comp == functionspace::interior) { \
2377 if constexpr (Geometry::nspaces() == 1) \
2378 return std::tuple( \
2379 std::get<Is>(spline_).template name<memory_optimized>( \
2380 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2381 std::get<Is>(knot_indices_G))...); \
2382 else \
2383 return std::tuple( \
2384 std::get<Is>(spline_).template name<memory_optimized>( \
2385 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2386 std::get<Is>(knot_indices_G))...); \
2387 } else if constexpr (comp == functionspace::boundary) { \
2388 if constexpr (Geometry::nspaces() == 1) \
2389 return std::tuple( \
2390 std::get<Is>(boundary_).template name<memory_optimized>( \
2391 static_cast<typename Geometry::boundary_type::boundary_type>( \
2392 G.boundary().coeffs()), \
2393 std::get<Is>(xi), std::get<Is>(knot_indices), \
2394 std::get<Is>(knot_indices_G))...); \
2395 else \
2396 return std::tuple( \
2397 std::get<Is>(boundary_).template name<memory_optimized>( \
2398 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2399 std::get<Is>(knot_indices), std::get<Is>(knot_indices_G))...); \
2400 } \
2401 } \
2402 \
2403 template <functionspace comp = functionspace::interior, \
2404 bool memory_optimized = false, std::size_t... Is, \
2405 typename Geometry, typename... Xi, typename... Knot_Indices, \
2406 typename... Coeff_Indices, typename... Knot_Indices_G, \
2407 typename... Coeff_Indices_G> \
2408 inline auto BOOST_PP_CAT(name, _all_)( \
2409 std::index_sequence<Is...>, const Geometry &G, \
2410 const std::tuple<Xi...> &xi, \
2411 const std::tuple<Knot_Indices...> &knot_indices, \
2412 const std::tuple<Coeff_Indices...> &coeff_indices, \
2413 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
2414 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
2415 if constexpr (comp == functionspace::interior) { \
2416 if constexpr (Geometry::nspaces() == 1) \
2417 return std::tuple( \
2418 std::get<Is>(spline_).template name<memory_optimized>( \
2419 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
2420 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2421 std::get<Is>(coeff_indices_G))...); \
2422 else \
2423 return std::tuple( \
2424 std::get<Is>(spline_).template name<memory_optimized>( \
2425 std::get<Is>(G), std::get<Is>(xi), std::get<Is>(knot_indices), \
2426 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2427 std::get<Is>(coeff_indices_G))...); \
2428 } else if constexpr (comp == functionspace::boundary) { \
2429 if constexpr (Geometry::nspaces() == 1) \
2430 return std::tuple( \
2431 std::get<Is>(boundary_).template name<memory_optimized>( \
2432 static_cast<typename Geometry::boundary_type::boundary_type>( \
2433 G.boundary().coeffs()), \
2434 std::get<Is>(xi), std::get<Is>(knot_indices), \
2435 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
2436 std::get<Is>(coeff_indices_G))...); \
2437 else \
2438 return std::tuple( \
2439 std::get<Is>(boundary_).template name<memory_optimized>( \
2440 std::get<Is>(G).boundary().coeffs(), std::get<Is>(xi), \
2441 std::get<Is>(knot_indices), std::get<Is>(coeff_indices), \
2442 std::get<Is>(knot_indices_G), \
2443 std::get<Is>(coeff_indices_G))...); \
2444 } \
2445 } \
2446 \
2447public: \
2448 template <functionspace comp = functionspace::interior, \
2449 bool memory_optimized = false, typename... Args> \
2450 inline auto BOOST_PP_CAT(name, _all)(const Args &...args) const { \
2451 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
2452 std::make_index_sequence<FunctionSpace::nspaces()>{}, args...); \
2453 }
2454
2457 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
2459#undef GENERATE_IEXPR_MACRO
2460};
2461
2463template <typename... Splines>
2464inline std::ostream &operator<<(std::ostream &os,
2465 const FunctionSpace<Splines...> &obj) {
2466 obj.pretty_print(os);
2467 return os;
2468}
2469
2474template <typename Spline, typename Boundary>
2475// requires SplineType<Spline> && BoundaryType<Boundary>
2477 public utils::Serializable,
2478 private utils::FullQualifiedName {
2479
2480public:
2482 using value_type = Spline::value_type;
2483
2485 using spline_type = Spline;
2486
2488 using eval_type = utils::TensorArray<Spline::parDim()>;
2489
2492
2494 using boundary_eval_type = Boundary::eval_type;
2495
2497 template <std::size_t index=0>
2498 inline static constexpr short_t geoDim() noexcept {
2499 static_assert(index < nspaces());
2500 return spline_type::geoDim();
2501 }
2502
2504 template <std::size_t index=0>
2505 inline static constexpr short_t parDim() noexcept {
2506 static_assert(index < nspaces());
2507 return spline_type::parDim();
2508 }
2509
2512 template <std::size_t index=0>
2513 inline static constexpr const auto& degrees() noexcept {
2514 static_assert(index < nspaces());
2515 return spline_type::degrees();
2516 }
2517
2520 template <std::size_t index=0>
2521 inline static constexpr short_t degree(short_t i) noexcept {
2522 static_assert(index < nspaces());
2523 return spline_type::degree(i);
2524 }
2525
2526protected:
2529
2532
2533public:
2535 FunctionSpace() = default;
2536
2538 FunctionSpace(const FunctionSpace &) = default;
2539
2542
2546 const std::array<int64_t, Spline::parDim()> &ncoeffs,
2547 enum init init = init::greville,
2549 : spline_(ncoeffs, init, options),
2550 boundary_(ncoeffs, init::none, options) {
2551 boundary_.from_full_tensor(spline_.as_tensor());
2552 }
2553
2555 std::array<std::vector<value_type>, Spline::parDim()> kv,
2556 enum init init = init::greville,
2558 : spline_(kv, init, options), boundary_(kv, init::none, options) {
2559 static_assert(Spline::is_nonuniform(),
2560 "Constructor is only available for non-uniform splines");
2561 boundary_.from_full_tensor(spline_.as_tensor());
2562 }
2563
2564 explicit FunctionSpace(const Spline &spline)
2565 : spline_(spline),
2566 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2567 boundary_.from_full_tensor(spline_.as_tensor());
2568 }
2569
2570 explicit FunctionSpace(Spline &&spline)
2571 : spline_(spline),
2572 boundary_(spline.ncoeffs(), init::none, spline.options()) {
2573 boundary_.from_full_tensor(spline_.as_tensor());
2574 }
2576
2578 inline static constexpr std::size_t nspaces() noexcept { return 1; }
2579
2581 inline static constexpr std::size_t nboundaries() noexcept { return 1; }
2582
2584 inline constexpr const auto &spaces() const noexcept { return spline_; }
2585
2587 inline constexpr auto &spaces() noexcept { return spline_; }
2588
2590 inline constexpr const auto &boundaries() const noexcept { return boundary_; }
2591
2593 inline constexpr auto &boundaries() noexcept { return boundary_; }
2594
2596 template <std::size_t index = 0>
2597 inline constexpr const spline_type &space() const noexcept {
2598 static_assert(index < nspaces());
2599 return spline_;
2600 }
2601
2603 template <std::size_t index = 0>
2604 inline constexpr spline_type &space() noexcept {
2605 static_assert(index < nspaces());
2606 return spline_;
2607 }
2608
2610 template <std::size_t index = 0>
2611 inline constexpr const boundary_type &boundary() const noexcept {
2612 static_assert(index < nboundaries());
2613 return boundary_;
2614 }
2615
2618 template <std::size_t index = 0>
2619 inline constexpr boundary_type &boundary() noexcept {
2620 static_assert(index < nboundaries());
2621 return boundary_;
2622 }
2623
2625 inline constexpr FunctionSpace clone() const noexcept {
2626 return FunctionSpace(*this);
2627 }
2628
2630 template <std::size_t... index> inline constexpr auto clone() const noexcept {
2631
2632 static_assert(((index < nspaces()) && ... && true));
2633
2634 if constexpr (sizeof...(index) == 1)
2635 return FunctionSpace(*this);
2636 else
2637 return FunctionSpace<
2638 std::tuple<std::tuple_element_t<index, std::tuple<spline_type>>...>,
2639 std::tuple<
2640 std::tuple_element_t<index, std::tuple<boundary_type>>...>>(
2641 std::get<index>(std::make_tuple(spline_))...,
2642 std::get<index>(std::make_tuple(boundary_))...);
2643 }
2644
2646 virtual inline torch::Tensor spaces_as_tensor() const noexcept {
2647 return spline_.as_tensor();
2648 }
2649
2651 virtual inline torch::Tensor boundary_as_tensor() const noexcept {
2652 return boundary_.as_tensor();
2653 }
2654
2660 virtual inline torch::Tensor as_tensor() const noexcept {
2661 return spaces_as_tensor();
2662 }
2663
2666 virtual inline int64_t spaces_as_tensor_size() const noexcept {
2667 return spline_.as_tensor_size();
2668 }
2669
2672 virtual inline int64_t boundary_as_tensor_size() const noexcept {
2673 return boundary_.as_tensor_size();
2674 }
2675
2681 virtual inline int64_t as_tensor_size() const noexcept {
2682 return spaces_as_tensor_size();
2683 }
2684
2686 virtual inline FunctionSpace &
2687 spaces_from_tensor(const torch::Tensor &coeffs) noexcept {
2688 spline_.from_tensor(coeffs);
2689 return *this;
2690 }
2691
2694 virtual inline FunctionSpace &
2695 boundary_from_tensor(const torch::Tensor &coeffs) noexcept {
2696 boundary_.from_tensor(coeffs);
2697 return *this;
2698 }
2699
2701 virtual inline FunctionSpace &
2702 boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept {
2703 boundary_.from_full_tensor(coeffs);
2704 return *this;
2705 }
2706
2708 inline FunctionSpace &from_tensor(const torch::Tensor &coeffs) noexcept {
2709 spline_.from_tensor(coeffs);
2710 boundary_.from_full_tensor(coeffs);
2711 return *this;
2712 }
2713
2715 inline pugi::xml_document to_xml(int id = 0,
2716 const std::string &label = "") const {
2717 pugi::xml_document doc;
2718 pugi::xml_node root = doc.append_child("xml");
2719 to_xml(root, id, label);
2720
2721 return doc;
2722 }
2723
2725 inline pugi::xml_node &to_xml(pugi::xml_node &root, int id = 0,
2726 std::string label = "") const {
2727 return spline_.to_xml(root, id, label);
2728 }
2729
2731 inline FunctionSpace &from_xml(const pugi::xml_document &doc, int id = 0,
2732 const std::string &label = "") {
2733 return from_xml(doc.child("xml"), id, label);
2734 }
2735
2737 inline FunctionSpace &from_xml(const pugi::xml_node &root, int id = 0,
2738 std::string label = "") {
2739 spline_.from_xml(root, id, label);
2740 return *this;
2741 }
2742
2744 nlohmann::json to_json() const override {
2745 auto json = nlohmann::json::array();
2746 json.push_back(spline_.to_json());
2747 json.push_back(boundary_.to_json());
2748 return json;
2749 }
2750
2752 template <typename SplinesOther, typename BoundariesOther>
2753 bool
2755 bool result(true);
2756
2757 if (!std::is_same_v<spline_type, typename std::remove_cvref_t<
2758 decltype(other)>::spline_type> ||
2759 !std::is_same_v<boundary_type, typename std::remove_cvref_t<
2760 decltype(other)>::boundary_type>)
2761 return false;
2762
2763 result *= (spaces() == other.spaces());
2764 result *= (boundaries() == other.boundaries());
2765
2766 return result;
2767 }
2768
2771 const std::function<std::array<typename Spline::value_type,
2772 Spline::geoDim()>(
2773 const std::array<typename Spline::value_type, Spline::parDim()> &)>
2774 mapping) {
2775 spline_.transform(mapping);
2776 return *this;
2777 }
2778
2779private:
2782 template <functionspace comp = functionspace::interior,
2783 deriv deriv = deriv::func, bool memory_optimized = false,
2784 std::size_t... Is, typename... Xi>
2785 inline auto eval_(std::index_sequence<Is...>,
2786 const std::tuple<Xi...> &xi) const {
2787 if constexpr (comp == functionspace::interior)
2788 return std::tuple(
2789 spline_.template eval<deriv, memory_optimized>(std::get<Is>(xi))...);
2790 else if constexpr (comp == functionspace::boundary)
2791 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2792 std::get<Is>(xi))...);
2793 }
2794
2795 template <functionspace comp = functionspace::interior,
2796 deriv deriv = deriv::func, bool memory_optimized = false,
2797 std::size_t... Is, typename... Xi, typename... Knot_Indices>
2798 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
2799 const std::tuple<Knot_Indices...> &knot_indices) const {
2800 if constexpr (comp == functionspace::interior)
2801 return std::tuple(spline_.template eval<deriv, memory_optimized>(
2802 std::get<Is>(xi), std::get<Is>(knot_indices))...);
2803 else if constexpr (comp == functionspace::boundary)
2804 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2805 std::get<Is>(xi), std::get<Is>(knot_indices))...);
2806 }
2807
2808 template <functionspace comp = functionspace::interior,
2809 deriv deriv = deriv::func, bool memory_optimized = false,
2810 std::size_t... Is, typename... Xi, typename... Knot_Indices,
2811 typename... Coeff_Indices>
2812 inline auto eval_(std::index_sequence<Is...>, const std::tuple<Xi...> &xi,
2813 const std::tuple<Knot_Indices...> &knot_indices,
2814 const std::tuple<Coeff_Indices...> &coeff_indices) const {
2815 if constexpr (comp == functionspace::interior)
2816 return std::tuple(spline_.template eval<deriv, memory_optimized>(
2817 std::get<Is>(xi), std::get<Is>(knot_indices),
2818 std::get<Is>(coeff_indices))...);
2819 else if constexpr (comp == functionspace::boundary)
2820 return std::tuple(boundary_.template eval<deriv, memory_optimized>(
2821 std::get<Is>(xi), std::get<Is>(knot_indices),
2822 std::get<Is>(coeff_indices))...);
2823 }
2825
2826public:
2828 template <functionspace comp = functionspace::interior,
2829 deriv deriv = deriv::func, bool memory_optimized = false,
2830 typename Arg, typename... Args>
2831 inline auto eval(const Arg &arg, const Args &...args) const {
2832 if constexpr (comp == functionspace::interior)
2833 if constexpr (utils::is_tuple_v<Arg>)
2834 return eval_<comp, deriv, memory_optimized>(
2835 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
2836 else
2837 return spline_.template eval<deriv, memory_optimized>(arg, args...);
2838 else if constexpr (comp == functionspace::boundary) {
2839 if constexpr (utils::is_tuple_of_tuples_v<Arg>)
2840 return eval_<comp, deriv, memory_optimized>(
2841 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...);
2842 else
2843 return boundary_.template eval<deriv, memory_optimized>(arg, args...);
2844 }
2845 }
2846
2849 template <functionspace comp = functionspace::interior, typename... Args>
2850 inline auto eval_from_precomputed(const Args &...args) const {
2851 if constexpr (comp == functionspace::interior)
2852 return spline_.eval_from_precomputed(args...);
2853 else if constexpr (comp == functionspace::boundary)
2854 return boundary_.eval_from_precomputed(args...);
2855 }
2856
2857private:
2859 template <functionspace comp = functionspace::interior, std::size_t... Is,
2860 typename Xi>
2861 inline auto find_knot_indices_(std::index_sequence<Is...>,
2862 const Xi &xi) const {
2863 if constexpr (comp == functionspace::interior)
2864 return std::tuple(spline_.find_knot_indices(std::get<Is>(xi))...);
2865 else
2866 return std::tuple(boundary_.find_knot_indices(std::get<Is>(xi))...);
2867 }
2868
2869public:
2871 template <functionspace comp = functionspace::interior, typename Xi>
2872 inline auto find_knot_indices(const Xi &xi) const {
2873 if constexpr (comp == functionspace::interior)
2874 if constexpr (utils::is_tuple_v<Xi>)
2875 return find_knot_indices_<comp>(
2876 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
2877 else
2878 return spline_.find_knot_indices(xi);
2879 else if constexpr (comp == functionspace::boundary) {
2880 if constexpr (utils::is_tuple_of_tuples_v<Xi>)
2881 return find_knot_indices_<comp>(
2882 std::make_index_sequence<std::tuple_size_v<Xi>>{}, xi);
2883 else
2884 return boundary_.find_knot_indices(xi);
2885 }
2886 }
2887
2890 template <functionspace comp = functionspace::interior,
2891 deriv deriv = deriv::func, bool memory_optimized = false,
2892 typename... Args>
2893 inline auto eval_basfunc(const Args &...args) const {
2894 if constexpr (comp == functionspace::interior)
2895 return spline_.template eval_basfunc<deriv, memory_optimized>(args...);
2896 else if constexpr (comp == functionspace::boundary)
2897 return boundary_.template eval_basfunc<deriv, memory_optimized>(args...);
2898 }
2899
2900private:
2903 template <functionspace comp = functionspace::interior,
2904 bool memory_optimized = false, std::size_t... Is,
2905 typename Knot_Indices>
2906 inline auto find_coeff_indices_(std::index_sequence<Is...>,
2907 const Knot_Indices &knot_indices) const {
2908 if constexpr (comp == functionspace::interior)
2909 return std::tuple(spline_.template find_coeff_indices<memory_optimized>(
2910 std::get<Is>(knot_indices))...);
2911 else
2912 return std::tuple(boundary_.template find_coeff_indices<memory_optimized>(
2913 std::get<Is>(knot_indices))...);
2914 }
2915
2916public:
2919 template <functionspace comp = functionspace::interior,
2920 bool memory_optimized = false, typename Knot_Indices>
2921 inline auto find_coeff_indices(const Knot_Indices &knot_indices) const {
2922 if constexpr (comp == functionspace::interior)
2923 if constexpr (utils::is_tuple_v<Knot_Indices>)
2924 return find_coeff_indices_<comp, memory_optimized>(
2925 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
2926 knot_indices);
2927 else
2928 return spline_.template find_coeff_indices<memory_optimized>(
2929 knot_indices);
2930 else if constexpr (comp == functionspace::boundary) {
2931 if constexpr (utils::is_tuple_of_tuples_v<Knot_Indices>)
2932 return find_coeff_indices_<comp, memory_optimized>(
2933 std::make_index_sequence<std::tuple_size_v<Knot_Indices>>{},
2934 knot_indices);
2935 else
2936 return boundary_.template find_coeff_indices<memory_optimized>(
2937 knot_indices);
2938 }
2939 }
2940
2943 inline auto &uniform_refine(int numRefine = 1, int dimRefine = -1) {
2944 spline_.uniform_refine(numRefine, dimRefine);
2945 boundary_.uniform_refine(numRefine, dimRefine);
2946 return *this;
2947 }
2948
2951 template <typename real_t> inline auto to(Options<real_t> options) const {
2952 return FunctionSpace<
2953 typename spline_type::template real_derived_self_type<real_t>,
2954 typename boundary_type::template real_derived_self_type<real_t>>(
2955 spline_.to(options), boundary_.to(options));
2956 }
2957
2960 inline auto to(torch::Device device) const {
2961 return FunctionSpace(spline_.to(device), boundary_.to(device));
2962 }
2963
2965 template <typename real_t> inline auto to() const {
2966 return FunctionSpace<
2967 typename spline_type::template real_derived_self_type<real_t>,
2968 typename boundary_type::template real_derived_self_type<real_t>>(
2969 spline_.template to<real_t>(), boundary_.template to<real_t>());
2970 }
2971
2973 inline auto scale(value_type s, int dim = -1) {
2974 spline_.scale(s, dim);
2975 boundary_.from_full_tensor(spline_.as_tensor());
2976 return *this;
2977 }
2978
2980 template <std::size_t N> inline auto scale(std::array<value_type, N> v) {
2981 spline_.scale(v);
2982 boundary_.from_full_tensor(spline_.as_tensor());
2983 return *this;
2984 }
2985
2987 template <std::size_t N> inline auto translate(std::array<value_type, N> v) {
2988 spline_.translate(v);
2989 boundary_.from_full_tensor(spline_.as_tensor());
2990 return *this;
2991 }
2992
2994 inline auto rotate(value_type angle) {
2995 spline_.rotate(angle);
2996 boundary_.from_full_tensor(spline_.as_tensor());
2997 return *this;
2998 }
2999
3001 inline auto rotate(std::array<value_type, 3> angle) {
3002 spline_.rotate(angle);
3003 boundary_.from_full_tensor(spline_.as_tensor());
3004 return *this;
3005 }
3006
3009 inline torch::serialize::OutputArchive &
3010 write(torch::serialize::OutputArchive &archive,
3011 const std::string &key = "functionspace") const {
3012 spline_.write(archive, key);
3013 boundary_.write(archive, key);
3014 return archive;
3015 }
3016
3019 inline torch::serialize::InputArchive &
3020 read(torch::serialize::InputArchive &archive,
3021 const std::string &key = "functionspace") {
3022 spline_.read(archive, key);
3023 boundary_.read(archive, key);
3024 return archive;
3025 }
3026
3028 inline void pretty_print(std::ostream &os) const noexcept override {
3029 os << name() << "(\nspline = ";
3030 spline_.pretty_print(os);
3031 os << "\nboundary = ";
3032 boundary_.pretty_print(os);
3033 os << "\n)";
3034 }
3035
3036#define GENERATE_EXPR_MACRO(r, data, name) \
3037private: \
3038 template <functionspace comp = functionspace::interior, \
3039 bool memory_optimized = false, std::size_t... Is, typename... Xi> \
3040 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
3041 const std::tuple<Xi...> &xi) const { \
3042 if constexpr (comp == functionspace::interior) \
3043 return std::tuple( \
3044 spline_.template name<memory_optimized>(std::get<Is>(xi))...); \
3045 else if constexpr (comp == functionspace::boundary) \
3046 return std::tuple( \
3047 boundary_.template name<memory_optimized>(std::get<Is>(xi))...); \
3048 } \
3049 \
3050 template <functionspace comp = functionspace::interior, \
3051 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
3052 typename... Knot_Indices> \
3053 inline auto BOOST_PP_CAT(name, _all_)( \
3054 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
3055 const std::tuple<Knot_Indices...> &knot_indices) const { \
3056 if constexpr (comp == functionspace::interior) \
3057 return std::tuple(spline_.template name<memory_optimized>( \
3058 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
3059 else if constexpr (comp == functionspace::boundary) \
3060 return std::tuple(boundary_.template name<memory_optimized>( \
3061 std::get<Is>(xi), std::get<Is>(knot_indices))...); \
3062 } \
3063 \
3064 template <functionspace comp = functionspace::interior, \
3065 bool memory_optimized = false, std::size_t... Is, typename... Xi, \
3066 typename... Knot_Indices, typename... Coeff_Indices> \
3067 inline auto BOOST_PP_CAT(name, _all_)( \
3068 std::index_sequence<Is...>, const std::tuple<Xi...> &xi, \
3069 const std::tuple<Knot_Indices...> &knot_indices, \
3070 const std::tuple<Coeff_Indices...> &coeff_indices) const { \
3071 if constexpr (comp == functionspace::interior) \
3072 return std::tuple(spline_.template name<memory_optimized>( \
3073 std::get<Is>(xi), std::get<Is>(knot_indices), \
3074 std::get<Is>(coeff_indices))...); \
3075 else if constexpr (comp == functionspace::boundary) \
3076 return std::tuple(boundary_.template name<memory_optimized>( \
3077 std::get<Is>(xi), std::get<Is>(knot_indices), \
3078 std::get<Is>(coeff_indices))...); \
3079 } \
3080 \
3081public: \
3082 template <functionspace comp = functionspace::interior, \
3083 bool memory_optimized = false, typename Arg, typename... Args> \
3084 inline auto name(const Arg &arg, const Args &...args) const { \
3085 if constexpr (comp == functionspace::interior) \
3086 if constexpr (utils::is_tuple_v<Arg>) \
3087 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3088 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
3089 else \
3090 return spline_.template name<memory_optimized>(arg, args...); \
3091 else if constexpr (comp == functionspace::boundary) { \
3092 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
3093 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3094 std::make_index_sequence<std::tuple_size_v<Arg>>{}, arg, args...); \
3095 else \
3096 return boundary_.template name<memory_optimized>(arg, args...); \
3097 } \
3098 }
3099
3102 BOOST_PP_SEQ_FOR_EACH(GENERATE_EXPR_MACRO, _, GENERATE_EXPR_SEQ)
3104#undef GENERATE_EXPR_MACRO
3105
3106#define GENERATE_IEXPR_MACRO(r, data, name) \
3107private: \
3108 template <functionspace comp = functionspace::interior, \
3109 bool memory_optimized = false, std::size_t... Is, \
3110 typename Geometry, typename... Xi> \
3111 inline auto BOOST_PP_CAT(name, _all_)(std::index_sequence<Is...>, \
3112 const Geometry &G, \
3113 const std::tuple<Xi...> &xi) const { \
3114 if constexpr (comp == functionspace::interior) \
3115 return std::tuple(spline_.template name<memory_optimized>( \
3116 G.space(), std::get<Is>(xi))...); \
3117 else if constexpr (comp == functionspace::boundary) \
3118 return std::tuple(boundary_.template name<memory_optimized>( \
3119 static_cast<typename Geometry::boundary_type::boundary_type>( \
3120 G.boundary().coeffs()), \
3121 std::get<Is>(xi))...); \
3122 } \
3123 \
3124 template <functionspace comp = functionspace::interior, \
3125 bool memory_optimized = false, std::size_t... Is, \
3126 typename Geometry, typename... Xi, typename... Knot_Indices, \
3127 typename... Knot_Indices_G> \
3128 inline auto BOOST_PP_CAT(name, _all_)( \
3129 std::index_sequence<Is...>, const Geometry &G, \
3130 const std::tuple<Xi...> &xi, \
3131 const std::tuple<Knot_Indices...> &knot_indices, \
3132 const std::tuple<Knot_Indices_G...> &knot_indices_G) const { \
3133 if constexpr (comp == functionspace::interior) \
3134 return std::tuple(spline_.template name<memory_optimized>( \
3135 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
3136 std::get<Is>(knot_indices_G))...); \
3137 else if constexpr (comp == functionspace::boundary) \
3138 return std::tuple(boundary_.template name<memory_optimized>( \
3139 static_cast<typename Geometry::boundary_type::boundary_type>( \
3140 G.boundary().coeffs()), \
3141 std::get<Is>(xi), std::get<Is>(knot_indices), \
3142 std::get<Is>(knot_indices_G))...); \
3143 } \
3144 \
3145 template <functionspace comp = functionspace::interior, \
3146 bool memory_optimized = false, std::size_t... Is, \
3147 typename Geometry, typename... Xi, typename... Knot_Indices, \
3148 typename... Coeff_Indices, typename... Knot_Indices_G, \
3149 typename... Coeff_Indices_G> \
3150 inline auto BOOST_PP_CAT(name, _all_)( \
3151 std::index_sequence<Is...>, const Geometry &G, \
3152 const std::tuple<Xi...> &xi, \
3153 const std::tuple<Knot_Indices...> &knot_indices, \
3154 const std::tuple<Coeff_Indices...> &coeff_indices, \
3155 const std::tuple<Knot_Indices_G...> &knot_indices_G, \
3156 const std::tuple<Coeff_Indices_G...> &coeff_indices_G) const { \
3157 if constexpr (comp == functionspace::interior) \
3158 return std::tuple(spline_.template name<memory_optimized>( \
3159 G.space(), std::get<Is>(xi), std::get<Is>(knot_indices), \
3160 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3161 std::get<Is>(coeff_indices_G))...); \
3162 else if constexpr (comp == functionspace::boundary) \
3163 return std::tuple(boundary_.template name<memory_optimized>( \
3164 static_cast<typename Geometry::boundary_type::boundary_type>( \
3165 G.boundary().coeffs()), \
3166 std::get<Is>(xi), std::get<Is>(knot_indices), \
3167 std::get<Is>(coeff_indices), std::get<Is>(knot_indices_G), \
3168 std::get<Is>(coeff_indices_G))...); \
3169 } \
3170 \
3171public: \
3172 template <functionspace comp = functionspace::interior, \
3173 bool memory_optimized = false, typename Geometry, typename Arg, \
3174 typename... Args> \
3175 inline auto name(const Geometry &G, const Arg &arg, const Args &...args) \
3176 const { \
3177 if constexpr (comp == functionspace::interior) { \
3178 if constexpr (utils::is_tuple_v<Arg>) \
3179 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3180 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3181 args...); \
3182 else \
3183 return spline_.template name<memory_optimized>(G.space(), arg, \
3184 args...); \
3185 } else if constexpr (comp == functionspace::boundary) { \
3186 if constexpr (utils::is_tuple_of_tuples_v<Arg>) \
3187 return BOOST_PP_CAT(name, _all_)<comp, memory_optimized>( \
3188 std::make_index_sequence<std::tuple_size_v<Arg>>{}, G, arg, \
3189 args...); \
3190 else \
3191 return boundary_.template name<memory_optimized>( \
3192 static_cast<typename Geometry::boundary_type::boundary_type>( \
3193 G.boundary().coeffs()), \
3194 arg, args...); \
3195 } \
3196 }
3197
3200 BOOST_PP_SEQ_FOR_EACH(GENERATE_IEXPR_MACRO, _, GENERATE_IEXPR_SEQ)
3202#undef GENERATE_IEXPR_MACRO
3203};
3204
3206template <typename... Args> struct FunctionSpace_trait;
3207
3209template <typename Spline> struct FunctionSpace_trait<Spline> {
3211};
3212
3214template <typename Spline, typename Boundary>
3218
3220template <typename... Splines>
3221struct FunctionSpace_trait<std::tuple<Splines...>> {
3224};
3225
3227template <typename... Splines, typename... Boundaries>
3228struct FunctionSpace_trait<std::tuple<Splines...>, std::tuple<Boundaries...>> {
3230 utils::tuple_cat_t<Boundaries...>>;
3231};
3232
3236template <typename Spline, typename Boundary>
3240
3244template <typename... Splines, typename... Boundaries>
3245struct FunctionSpace_trait<std::tuple<FunctionSpace<Splines, Boundaries>...>> {
3247 utils::tuple_cat_t<Boundaries...>>::type;
3248};
3249
3250} // namespace detail
3251
3254template <typename T>
3255concept FunctionSpaceType = std::is_base_of_v<detail::FunctionSpaceType, T>;
3256
3258template <typename... Args>
3260
3262template <typename Splines, typename Boundaries>
3263inline std::ostream &operator<<(std::ostream &os,
3265 obj.pretty_print(os);
3266 return os;
3267}
3268
3286template <typename Spline> using S = FunctionSpace<Spline>;
3287
3289template <typename Spline, short_t = Spline::parDim()> class TH;
3290
3300template <typename Spline>
3301class TH<Spline, 1>
3302 : public FunctionSpace<
3303 std::tuple<typename Spline::template derived_self_type<
3304 typename Spline::value_type, Spline::geoDim(),
3305 Spline::degree(0) + 1>,
3306 typename Spline::template derived_self_type<
3307 typename Spline::value_type, Spline::geoDim(),
3308 Spline::degree(0)>>> {
3309public:
3311 using Base = FunctionSpace<std::tuple<
3312 typename Spline::template derived_self_type<
3313 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3314 typename Spline::template derived_self_type<
3315 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3316
3319 explicit TH(const std::array<int64_t, 1> &ncoeffs,
3320 enum init init = init::greville,
3323 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {
3324 static_assert(Spline::is_nonuniform(),
3325 "TH function space requires non-uniform splines");
3326 Base::template space<0>().reduce_continuity();
3327 }
3328
3329 explicit TH(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3330 enum init init = init::greville,
3333 : Base({{kv[0].front + kv[0] + kv[0].back(), kv[1]}}, kv, init, options) {
3334 static_assert(Spline::is_nonuniform(),
3335 "TH function space requires non-uniform splines");
3336 Base::template space<0>().reduce_continuity();
3337 }
3339
3341};
3342
3354template <typename Spline>
3355class TH<Spline, 2>
3356 : public FunctionSpace<
3357 std::tuple<typename Spline::template derived_self_type<
3358 typename Spline::value_type, Spline::geoDim(),
3359 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3360 typename Spline::template derived_self_type<
3361 typename Spline::value_type, Spline::geoDim(),
3362 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3363 typename Spline::template derived_self_type<
3364 typename Spline::value_type, Spline::geoDim(),
3365 Spline::degree(0), Spline::degree(1)>>> {
3366public:
3369 std::tuple<typename Spline::template derived_self_type<
3370 typename Spline::value_type, Spline::geoDim(),
3371 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3372 typename Spline::template derived_self_type<
3373 typename Spline::value_type, Spline::geoDim(),
3374 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3375 typename Spline::template derived_self_type<
3376 typename Spline::value_type, Spline::geoDim(),
3377 Spline::degree(0), Spline::degree(1)>>>;
3378
3381 explicit TH(const std::array<int64_t, 2> &ncoeffs,
3382 enum init init = init::greville,
3385 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
3386 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
3387 static_assert(Spline::is_nonuniform(),
3388 "TH function space requires non-uniform splines");
3389 Base::template space<0>().reduce_continuity();
3390 Base::template space<1>().reduce_continuity();
3391 }
3392
3393 explicit TH(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3394 enum init init = init::greville,
3397 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3398 kv[1].front() + kv[1] + kv[1].back()}},
3399 {{kv[0].front() + kv[0] + kv[0].back(),
3400 kv[1].front() + kv[1] + kv[1].back()}},
3401 kv, init, options) {
3402 static_assert(Spline::is_nonuniform(),
3403 "TH function space requires non-uniform splines");
3404 Base::template space<0>().reduce_continuity();
3405 Base::template space<1>().reduce_continuity();
3406 }
3408
3410};
3411
3424template <typename Spline>
3425class TH<Spline, 3>
3426 : public FunctionSpace<std::tuple<
3427 typename Spline::template derived_self_type<
3428 typename Spline::value_type, Spline::geoDim(),
3429 Spline::degree(0) + 1, Spline::degree(1) + 1,
3430 Spline::degree(2) + 1>,
3431 typename Spline::template derived_self_type<
3432 typename Spline::value_type, Spline::geoDim(),
3433 Spline::degree(0) + 1, Spline::degree(1) + 1,
3434 Spline::degree(2) + 1>,
3435 typename Spline::template derived_self_type<
3436 typename Spline::value_type, Spline::geoDim(),
3437 Spline::degree(0) + 1, Spline::degree(1) + 1,
3438 Spline::degree(2) + 1>,
3439 typename Spline::template derived_self_type<
3440 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3441 Spline::degree(1), Spline::degree(2)>>> {
3442public:
3444 using Base = FunctionSpace<std::tuple<
3445 typename Spline::template derived_self_type<
3446 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3447 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3448 typename Spline::template derived_self_type<
3449 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3450 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3451 typename Spline::template derived_self_type<
3452 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3453 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3454 typename Spline::template derived_self_type<
3455 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3456 Spline::degree(1), Spline::degree(2)>>>;
3457
3460 explicit TH(const std::array<int64_t, 3> &ncoeffs,
3461 enum init init = init::greville,
3464 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3465 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3466 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
3467 options) {
3468 static_assert(Spline::is_nonuniform(),
3469 "TH function space requires non-uniform splines");
3470 Base::template space<0>().reduce_continuity();
3471 Base::template space<1>().reduce_continuity();
3472 Base::template space<2>().reduce_continuity();
3473 }
3474
3475 explicit TH(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3476 enum init init = init::greville,
3479 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3480 kv[1].front() + kv[1] + kv[1].back(),
3481 kv[2].front() + kv[2] + kv[2].back()}},
3482 {{kv[0].front() + kv[0] + kv[0].back(),
3483 kv[1].front() + kv[1] + kv[1].back(),
3484 kv[2].front() + kv[2] + kv[2].back()}},
3485 {{kv[0].front() + kv[0] + kv[0].back(),
3486 kv[1].front() + kv[1] + kv[1].back(),
3487 kv[2].front() + kv[2] + kv[2].back()}},
3488 kv, init, options) {
3489 static_assert(Spline::is_nonuniform(),
3490 "TH function space requires non-uniform splines");
3491 Base::template space<0>().reduce_continuity();
3492 Base::template space<1>().reduce_continuity();
3493 Base::template space<2>().reduce_continuity();
3494 }
3496
3498};
3499
3513template <typename Spline>
3514class TH<Spline, 4>
3515 : public FunctionSpace<std::tuple<
3516 typename Spline::template derived_self_type<
3517 typename Spline::value_type, Spline::geoDim(),
3518 Spline::degree(0) + 1, Spline::degree(1) + 1,
3519 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3520 typename Spline::template derived_self_type<
3521 typename Spline::value_type, Spline::geoDim(),
3522 Spline::degree(0) + 1, Spline::degree(1) + 1,
3523 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3524 typename Spline::template derived_self_type<
3525 typename Spline::value_type, Spline::geoDim(),
3526 Spline::degree(0) + 1, Spline::degree(1) + 1,
3527 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3528 typename Spline::template derived_self_type<
3529 typename Spline::value_type, Spline::geoDim(),
3530 Spline::degree(0) + 1, Spline::degree(1) + 1,
3531 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3532 typename Spline::template derived_self_type<
3533 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3534 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3535public:
3537 using Base = FunctionSpace<std::tuple<
3538 typename Spline::template derived_self_type<
3539 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3540 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3541 typename Spline::template derived_self_type<
3542 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3543 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3544 typename Spline::template derived_self_type<
3545 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3546 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3547 typename Spline::template derived_self_type<
3548 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3549 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3550 typename Spline::template derived_self_type<
3551 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3552 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3553
3556 explicit TH(const std::array<int64_t, 4> &ncoeffs,
3557 enum init init = init::greville,
3560 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3561 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3562 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3563 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
3564 init, options) {
3565 static_assert(Spline::is_nonuniform(),
3566 "TH function space requires non-uniform splines");
3567 Base::template space<0>().reduce_continuity();
3568 Base::template space<1>().reduce_continuity();
3569 Base::template space<2>().reduce_continuity();
3570 Base::template space<3>().reduce_continuity();
3571 }
3572
3573 explicit TH(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
3574 enum init init = init::greville,
3577 : Base({{kv[0].front() + kv[0] + kv[0].back(),
3578 kv[1].front() + kv[1] + kv[1].back(),
3579 kv[2].front() + kv[2] + kv[2].back(),
3580 kv[3].front() + kv[3] + kv[3].back()}},
3581 {{kv[0].front() + kv[0] + kv[0].back(),
3582 kv[1].front() + kv[1] + kv[1].back(),
3583 kv[2].front() + kv[2] + kv[2].back(),
3584 kv[3].front() + kv[3] + kv[3].back()}},
3585 {{kv[0].front() + kv[0] + kv[0].back(),
3586 kv[1].front() + kv[1] + kv[1].back(),
3587 kv[2].front() + kv[2] + kv[2].back(),
3588 kv[3].front() + kv[3] + kv[3].back()}},
3589 {{kv[0].front() + kv[0] + kv[0].back(),
3590 kv[1].front() + kv[1] + kv[1].back(),
3591 kv[2].front() + kv[2] + kv[2].back(),
3592 kv[3].front() + kv[3] + kv[3].back()}},
3593 kv, init, options) {
3594 static_assert(Spline::is_nonuniform(),
3595 "TH function space requires non-uniform splines");
3596 Base::template space<0>().reduce_continuity();
3597 Base::template space<1>().reduce_continuity();
3598 Base::template space<2>().reduce_continuity();
3599 Base::template space<3>().reduce_continuity();
3600 }
3602
3604};
3605
3607template <typename Spline, short_t = Spline::parDim()> class NE;
3608
3618template <typename Spline>
3619class NE<Spline, 1>
3620 : public FunctionSpace<
3621 std::tuple<typename Spline::template derived_self_type<
3622 typename Spline::value_type, Spline::geoDim(),
3623 Spline::degree(0) + 1>,
3624 typename Spline::template derived_self_type<
3625 typename Spline::value_type, Spline::geoDim(),
3626 Spline::degree(0)>>> {
3627public:
3629 using Base = FunctionSpace<std::tuple<
3630 typename Spline::template derived_self_type<
3631 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3632 typename Spline::template derived_self_type<
3633 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3634
3637 explicit NE(const std::array<int64_t, 1> &ncoeffs,
3638 enum init init = init::greville,
3641 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
3642
3643 explicit NE(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3644 enum init init = init::greville,
3647 : Base(kv, kv, init, options) {
3648 static_assert(Spline::is_nonuniform(),
3649 "Constructor only available for non-uniform splines");
3650 }
3652
3654};
3655
3666template <typename Spline>
3667class NE<Spline, 2>
3668 : public FunctionSpace<
3669 std::tuple<typename Spline::template derived_self_type<
3670 typename Spline::value_type, Spline::geoDim(),
3671 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3672 typename Spline::template derived_self_type<
3673 typename Spline::value_type, Spline::geoDim(),
3674 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3675 typename Spline::template derived_self_type<
3676 typename Spline::value_type, Spline::geoDim(),
3677 Spline::degree(0), Spline::degree(1)>>> {
3678public:
3681 std::tuple<typename Spline::template derived_self_type<
3682 typename Spline::value_type, Spline::geoDim(),
3683 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3684 typename Spline::template derived_self_type<
3685 typename Spline::value_type, Spline::geoDim(),
3686 Spline::degree(0) + 1, Spline::degree(1) + 1>,
3687 typename Spline::template derived_self_type<
3688 typename Spline::value_type, Spline::geoDim(),
3689 Spline::degree(0), Spline::degree(1)>>>;
3690
3693 explicit NE(const std::array<int64_t, 2> &ncoeffs,
3694 enum init init = init::greville,
3697 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
3698 ncoeffs + utils::to_array(1_i64, 1_i64), ncoeffs, init, options) {
3699 static_assert(Spline::is_nonuniform(),
3700 "NE function space requires non-uniform splines");
3701 Base::template space<0>().reduce_continuity(1, 1);
3702 Base::template space<1>().reduce_continuity(1, 0);
3703 }
3704
3705 explicit NE(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
3706 enum init init = init::greville,
3709 : Base(kv, kv, kv, init, options) {
3710 static_assert(Spline::is_nonuniform(),
3711 "NE function space requires non-uniform splines");
3712 Base::template space<0>().reduce_continuity(1, 1);
3713 Base::template space<1>().reduce_continuity(1, 0);
3714 }
3716
3718};
3719
3732template <typename Spline>
3733class NE<Spline, 3>
3734 : public FunctionSpace<std::tuple<
3735 typename Spline::template derived_self_type<
3736 typename Spline::value_type, Spline::geoDim(),
3737 Spline::degree(0) + 1, Spline::degree(1) + 1,
3738 Spline::degree(2) + 1>,
3739 typename Spline::template derived_self_type<
3740 typename Spline::value_type, Spline::geoDim(),
3741 Spline::degree(0) + 1, Spline::degree(1) + 1,
3742 Spline::degree(2) + 1>,
3743 typename Spline::template derived_self_type<
3744 typename Spline::value_type, Spline::geoDim(),
3745 Spline::degree(0) + 1, Spline::degree(1) + 1,
3746 Spline::degree(2) + 1>,
3747 typename Spline::template derived_self_type<
3748 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3749 Spline::degree(1), Spline::degree(2)>>> {
3750public:
3752 using Base = FunctionSpace<std::tuple<
3753 typename Spline::template derived_self_type<
3754 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3755 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3756 typename Spline::template derived_self_type<
3757 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3758 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3759 typename Spline::template derived_self_type<
3760 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3761 Spline::degree(1) + 1, Spline::degree(2) + 1>,
3762 typename Spline::template derived_self_type<
3763 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3764 Spline::degree(1), Spline::degree(2)>>>;
3765
3768 explicit NE(const std::array<int64_t, 3> &ncoeffs,
3769 enum init init = init::greville,
3772 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3773 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
3774 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64), ncoeffs, init,
3775 options) {
3776 static_assert(Spline::is_nonuniform(),
3777 "NE function space requires non-uniform splines");
3778 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
3779 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
3780 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
3781 }
3782
3783 explicit NE(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
3784 enum init init = init::greville,
3787 : Base(kv, kv, kv, kv, init, options) {
3788 static_assert(Spline::is_nonuniform(),
3789 "NE function space requires non-uniform splines");
3790 Base::template space<0>().reduce_continuity(1, 1).reduce_continuity(1, 2);
3791 Base::template space<1>().reduce_continuity(1, 0).reduce_continuity(1, 2);
3792 Base::template space<2>().reduce_continuity(1, 0).reduce_continuity(1, 1);
3793 }
3795
3797};
3798
3812template <typename Spline>
3813class NE<Spline, 4>
3814 : public FunctionSpace<std::tuple<
3815 typename Spline::template derived_self_type<
3816 typename Spline::value_type, Spline::geoDim(),
3817 Spline::degree(0) + 1, Spline::degree(1) + 1,
3818 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3819 typename Spline::template derived_self_type<
3820 typename Spline::value_type, Spline::geoDim(),
3821 Spline::degree(0) + 1, Spline::degree(1) + 1,
3822 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3823 typename Spline::template derived_self_type<
3824 typename Spline::value_type, Spline::geoDim(),
3825 Spline::degree(0) + 1, Spline::degree(1) + 1,
3826 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3827 typename Spline::template derived_self_type<
3828 typename Spline::value_type, Spline::geoDim(),
3829 Spline::degree(0) + 1, Spline::degree(1) + 1,
3830 Spline::degree(2) + 1, Spline::degree(3) + 1>,
3831 typename Spline::template derived_self_type<
3832 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3833 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
3834public:
3836 using Base = FunctionSpace<std::tuple<
3837 typename Spline::template derived_self_type<
3838 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3839 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3840 typename Spline::template derived_self_type<
3841 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3842 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3843 typename Spline::template derived_self_type<
3844 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3845 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3846 typename Spline::template derived_self_type<
3847 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
3848 Spline::degree(1) + 1, Spline::degree(2) + 1, Spline::degree(3) + 1>,
3849 typename Spline::template derived_self_type<
3850 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
3851 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
3852
3855 explicit NE(const std::array<int64_t, 4> &ncoeffs,
3856 enum init init = init::greville,
3859 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3860 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3861 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64),
3862 ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64, 1_i64), ncoeffs,
3863 init, options) {
3864 static_assert(Spline::is_nonuniform(),
3865 "NE function space requires non-uniform splines");
3866 Base::template space<0>()
3867 .reduce_continuity(1, 1)
3868 .reduce_continuity(1, 2)
3869 .reduce_continuity(1, 3);
3870 Base::template space<1>()
3871 .reduce_continuity(1, 0)
3872 .reduce_continuity(1, 2)
3873 .reduce_continuity(1, 3);
3874 Base::template space<2>()
3875 .reduce_continuity(1, 0)
3876 .reduce_continuity(1, 1)
3877 .reduce_continuity(1, 3);
3878 Base::template space<3>()
3879 .reduce_continuity(1, 0)
3880 .reduce_continuity(1, 1)
3881 .reduce_continuity(1, 2);
3882 }
3883
3884 explicit NE(const std::array<std::vector<typename Spline::value_type>,
3885 Spline::parDim()> &kv,
3886 enum init init = init::greville,
3889 : Base(kv, kv, kv, kv, kv, init, options) {
3890 static_assert(Spline::is_nonuniform(),
3891 "NE function space requires non-uniform splines");
3892 Base::template space<0>()
3893 .reduce_continuity(1, 1)
3894 .reduce_continuity(1, 2)
3895 .reduce_continuity(1, 3);
3896 Base::template space<1>()
3897 .reduce_continuity(1, 0)
3898 .reduce_continuity(1, 2)
3899 .reduce_continuity(1, 3);
3900 Base::template space<2>()
3901 .reduce_continuity(1, 0)
3902 .reduce_continuity(1, 1)
3903 .reduce_continuity(1, 3);
3904 Base::template space<3>()
3905 .reduce_continuity(1, 0)
3906 .reduce_continuity(1, 1)
3907 .reduce_continuity(1, 2);
3908 }
3910
3912};
3913
3915template <typename Spline, short_t = Spline::parDim()> class RT;
3916
3926template <typename Spline>
3927class RT<Spline, 1>
3928 : public FunctionSpace<
3929 std::tuple<typename Spline::template derived_self_type<
3930 typename Spline::value_type, Spline::geoDim(),
3931 Spline::degree(0) + 1>,
3932 typename Spline::template derived_self_type<
3933 typename Spline::value_type, Spline::geoDim(),
3934 Spline::degree(0)>>> {
3935public:
3937 using Base = FunctionSpace<std::tuple<
3938 typename Spline::template derived_self_type<
3939 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1>,
3940 typename Spline::template derived_self_type<
3941 typename Spline::value_type, Spline::geoDim(), Spline::degree(0)>>>;
3942
3945 explicit RT(const std::array<int64_t, 1> &ncoeffs,
3946 enum init init = init::greville,
3949 : Base(ncoeffs + utils::to_array(1_i64), ncoeffs, init, options) {}
3950
3951 explicit RT(const std::array<std::vector<typename Spline::value_type>, 1> &kv,
3952 enum init init = init::greville,
3955 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}}, kv, init,
3956 options) {
3957 static_assert(Spline::is_nonuniform(),
3958 "Constructor only available for non-uniform splines");
3959 }
3961
3963};
3964
3976template <typename Spline>
3977class RT<Spline, 2>
3978 : public FunctionSpace<
3979 std::tuple<typename Spline::template derived_self_type<
3980 typename Spline::value_type, Spline::geoDim(),
3981 Spline::degree(0) + 1, Spline::degree(1)>,
3982 typename Spline::template derived_self_type<
3983 typename Spline::value_type, Spline::geoDim(),
3984 Spline::degree(0), Spline::degree(1) + 1>,
3985 typename Spline::template derived_self_type<
3986 typename Spline::value_type, Spline::geoDim(),
3987 Spline::degree(0), Spline::degree(1)>>> {
3988public:
3990 std::tuple<typename Spline::template derived_self_type<
3991 typename Spline::value_type, Spline::geoDim(),
3992 Spline::degree(0) + 1, Spline::degree(1)>,
3993 typename Spline::template derived_self_type<
3994 typename Spline::value_type, Spline::geoDim(),
3995 Spline::degree(0), Spline::degree(1) + 1>,
3996 typename Spline::template derived_self_type<
3997 typename Spline::value_type, Spline::geoDim(),
3998 Spline::degree(0), Spline::degree(1)>>>;
3999
4002 explicit RT(const std::array<int64_t, 2> &ncoeffs,
4003 enum init init = init::greville,
4006 : Base(ncoeffs + utils::to_array(1_i64, 0_i64),
4007 ncoeffs + utils::to_array(0_i64, 1_i64), ncoeffs, init, options) {}
4008
4009 explicit RT(const std::array<std::vector<typename Spline::value_type>, 2> &kv,
4010 enum init init = init::greville,
4013 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1]}},
4014 {{kv[0], kv[1].front() + kv[1] + kv[1].back()}}, kv, init,
4015 options) {
4016 static_assert(Spline::is_nonuniform(),
4017 "Constructor only available for non-uniform splines");
4018 }
4020
4022};
4023
4035template <typename Spline>
4036class RT<Spline, 3>
4037 : public FunctionSpace<std::tuple<
4038 typename Spline::template derived_self_type<
4039 typename Spline::value_type, Spline::geoDim(),
4040 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2)>,
4041 typename Spline::template derived_self_type<
4042 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4043 Spline::degree(1) + 1, Spline::degree(2)>,
4044 typename Spline::template derived_self_type<
4045 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4046 Spline::degree(1), Spline::degree(2) + 1>,
4047 typename Spline::template derived_self_type<
4048 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4049 Spline::degree(1), Spline::degree(2)>>> {
4050public:
4052 using Base = FunctionSpace<std::tuple<
4053 typename Spline::template derived_self_type<
4054 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4055 Spline::degree(1), Spline::degree(2)>,
4056 typename Spline::template derived_self_type<
4057 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4058 Spline::degree(1) + 1, Spline::degree(2)>,
4059 typename Spline::template derived_self_type<
4060 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4061 Spline::degree(1), Spline::degree(2) + 1>,
4062 typename Spline::template derived_self_type<
4063 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4064 Spline::degree(1), Spline::degree(2)>>>;
4065
4068 explicit RT(const std::array<int64_t, 3> &ncoeffs,
4069 enum init init = init::greville,
4072 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
4073 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
4074 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), ncoeffs, init,
4075 options) {}
4076
4077 explicit RT(const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4078 enum init init = init::greville,
4081 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
4082 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
4083 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, kv, init,
4084 options) {
4085 static_assert(Spline::is_nonuniform(),
4086 "Constructor only available for non-uniform splines");
4087 }
4089
4091};
4092
4106template <typename Spline>
4107class RT<Spline, 4>
4108 : public FunctionSpace<std::tuple<
4109 typename Spline::template derived_self_type<
4110 typename Spline::value_type, Spline::geoDim(),
4111 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2),
4112 Spline::degree(3)>,
4113 typename Spline::template derived_self_type<
4114 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4115 Spline::degree(1) + 1, Spline::degree(2), Spline::degree(3)>,
4116 typename Spline::template derived_self_type<
4117 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4118 Spline::degree(1), Spline::degree(2) + 1, Spline::degree(3)>,
4119 typename Spline::template derived_self_type<
4120 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4121 Spline::degree(1), Spline::degree(2), Spline::degree(3) + 1>,
4122 typename Spline::template derived_self_type<
4123 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4124 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>> {
4125public:
4127 using Base = FunctionSpace<std::tuple<
4128 typename Spline::template derived_self_type<
4129 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4130 Spline::degree(1), Spline::degree(2), Spline::degree(3)>,
4131 typename Spline::template derived_self_type<
4132 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4133 Spline::degree(1) + 1, Spline::degree(2), Spline::degree(3)>,
4134 typename Spline::template derived_self_type<
4135 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4136 Spline::degree(1), Spline::degree(2) + 1, Spline::degree(3)>,
4137 typename Spline::template derived_self_type<
4138 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4139 Spline::degree(1), Spline::degree(2), Spline::degree(3) + 1>,
4140 typename Spline::template derived_self_type<
4141 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4142 Spline::degree(1), Spline::degree(2), Spline::degree(3)>>>;
4143
4146 explicit RT(const std::array<int64_t, 4> &ncoeffs,
4147 enum init init = init::greville,
4150 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64, 0_i64),
4151 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64, 0_i64),
4152 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64, 0_i64),
4153 ncoeffs + utils::to_array(0_i64, 0_i64, 0_i64, 1_i64), ncoeffs,
4154 init, options) {}
4155
4156 explicit RT(const std::array<std::vector<typename Spline::value_type>, 4> &kv,
4157 enum init init = init::greville,
4160 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2], kv[3]}},
4161 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2], kv[3]}},
4162 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back(), kv[3]}},
4163 {{kv[0], kv[1], kv[2], kv[3].front() + kv[3] + kv[3].back()}}, kv,
4164 init, options) {
4165 static_assert(Spline::is_nonuniform(),
4166 "Constructor only available for non-uniform splines");
4167 }
4169
4171};
4172
4174template <typename Spline, short_t = Spline::parDim()> class Hcurl;
4175
4187template <typename Spline>
4188class Hcurl<Spline, 3>
4189 : public FunctionSpace<std::tuple<
4190 typename Spline::template derived_self_type<
4191 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4192 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4193 typename Spline::template derived_self_type<
4194 typename Spline::value_type, Spline::geoDim(),
4195 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2) + 1>,
4196 typename Spline::template derived_self_type<
4197 typename Spline::value_type, Spline::geoDim(),
4198 Spline::degree(0) + 1, Spline::degree(1) + 1,
4199 Spline::degree(2)>>> {
4200
4201public:
4203 using Base = FunctionSpace<std::tuple<
4204 typename Spline::template derived_self_type<
4205 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4206 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4207 typename Spline::template derived_self_type<
4208 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4209 Spline::degree(1), Spline::degree(2) + 1>,
4210 typename Spline::template derived_self_type<
4211 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4212 Spline::degree(1) + 1, Spline::degree(2)>>>;
4213
4216 explicit Hcurl(const std::array<int64_t, 3> &ncoeffs,
4217 enum init init = init::greville,
4220 : Base(ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
4221 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
4222 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), init, options) {}
4223
4224 explicit Hcurl(
4225 const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4226 enum init init = init::greville,
4229 : Base({{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
4230 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
4231 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}}, init,
4232 options) {
4233 static_assert(Spline::is_nonuniform(),
4234 "Constructor only available for non-uniform splines");
4235 }
4238};
4239
4241template <typename Spline, short_t = Spline::parDim()> class NE_RT_DG;
4242
4258template <typename Spline>
4259class NE_RT_DG<Spline, 2>
4260 : public FunctionSpace<std::tuple<
4261 // Vector potential field \f$ H^1(\Omega) \f$
4262 typename Spline::template derived_self_type<
4263 typename Spline::value_type, Spline::geoDim(),
4264 Spline::degree(0) + 1, Spline::degree(1) + 1>,
4265 // Velocity field \f$ \mathbf{H}(\mathbf{curl}, \Omega) \f$
4266 typename Spline::template derived_self_type<
4267 typename Spline::value_type, Spline::geoDim(),
4268 Spline::degree(0) + 1, Spline::degree(1)>,
4269 typename Spline::template derived_self_type<
4270 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4271 Spline::degree(1) + 1>,
4272 // Pressure field \f$ L^2(\Omega) \f$
4273 typename Spline::template derived_self_type<
4274 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4275 Spline::degree(1)>>> {
4276
4277public:
4279 using Base = FunctionSpace<std::tuple<
4280 // Vector potential field \f$ H^1(\Omega) \f$
4281 typename Spline::template derived_self_type<
4282 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4283 Spline::degree(1) + 1>,
4284 // Velocity field \f$ \mathbf{H}(\mathbf{curl}, \Omega) \f$
4285 typename Spline::template derived_self_type<
4286 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4287 Spline::degree(1)>,
4288 typename Spline::template derived_self_type<
4289 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4290 Spline::degree(1) + 1>,
4291 // Pressure field \f$ L^2(\Omega) \f$
4292 typename Spline::template derived_self_type<
4293 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4294 Spline::degree(1)>>>;
4295
4298 explicit NE_RT_DG(const std::array<int64_t, 2> &ncoeffs,
4299 enum init init = init::greville,
4302 : Base(ncoeffs + utils::to_array(1_i64, 1_i64),
4303 ncoeffs + utils::to_array(1_i64, 0_i64),
4304 ncoeffs + utils::to_array(0_i64, 1_i64), ncoeffs, init, options) {}
4305
4306 explicit NE_RT_DG(
4307 const std::array<std::vector<typename Spline::value_type>, 2> &kv,
4308 enum init init = init::greville,
4311 : Base({{kv[0].front() + kv[0] + kv[0].back(),
4312 kv[1].front() + kv[1] + kv[1].back()}},
4313 {{kv[0].front() + kv[0] + kv[0].back(), kv[1]}},
4314 {{kv[0], kv[1].front() + kv[1] + kv[1].back()}}, {{kv[0], kv[1]}},
4315 init, options) {
4316 static_assert(Spline::is_nonuniform(),
4317 "Constructor only available for non-uniform splines");
4318 }
4321};
4322
4339template <typename Spline>
4340class NE_RT_DG<Spline, 3>
4341 : public FunctionSpace<std::tuple<
4342 // Vector potential field \f$ H^1(\Omega) \f$
4343 typename Spline::template derived_self_type<
4344 typename Spline::value_type, Spline::geoDim(),
4345 Spline::degree(0) + 1, Spline::degree(1) + 1,
4346 Spline::degree(2) + 1>,
4347 // Velocity field \f$ \mathbf{H}(\mathbf{curl}, \Omega) \f$
4348 typename Spline::template derived_self_type<
4349 typename Spline::value_type, Spline::geoDim(),
4350 Spline::degree(0) + 1, Spline::degree(1), Spline::degree(2)>,
4351 typename Spline::template derived_self_type<
4352 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4353 Spline::degree(1) + 1, Spline::degree(2)>,
4354 typename Spline::template derived_self_type<
4355 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4356 Spline::degree(1), Spline::degree(2) + 1>,
4357 // Pressure field \f$ L^2(\Omega) \f$
4358 typename Spline::template derived_self_type<
4359 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4360 Spline::degree(1), Spline::degree(2)>>> {
4361
4362public:
4364 using Base = FunctionSpace<std::tuple<
4365 // Vector potential field \f$ H^1(\Omega) \f$
4366 typename Spline::template derived_self_type<
4367 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4368 Spline::degree(1) + 1, Spline::degree(2) + 1>,
4369 // Velocity field \f$ \mathbf{H}(\mathbf{curl}, \Omega) \f$
4370 typename Spline::template derived_self_type<
4371 typename Spline::value_type, Spline::geoDim(), Spline::degree(0) + 1,
4372 Spline::degree(1), Spline::degree(2)>,
4373 typename Spline::template derived_self_type<
4374 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4375 Spline::degree(1) + 1, Spline::degree(2)>,
4376 typename Spline::template derived_self_type<
4377 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4378 Spline::degree(1), Spline::degree(2) + 1>,
4379 // Pressure field \f$ L^2(\Omega) \f$
4380 typename Spline::template derived_self_type<
4381 typename Spline::value_type, Spline::geoDim(), Spline::degree(0),
4382 Spline::degree(1), Spline::degree(2)>>>;
4383
4386 explicit NE_RT_DG(const std::array<int64_t, 3> &ncoeffs,
4387 enum init init = init::greville,
4390 : Base(ncoeffs + utils::to_array(1_i64, 1_i64, 1_i64),
4391 ncoeffs + utils::to_array(1_i64, 0_i64, 0_i64),
4392 ncoeffs + utils::to_array(0_i64, 1_i64, 0_i64),
4393 ncoeffs + utils::to_array(0_i64, 0_i64, 1_i64), ncoeffs, init,
4394 options) {}
4395
4396 explicit NE_RT_DG(
4397 const std::array<std::vector<typename Spline::value_type>, 3> &kv,
4398 enum init init = init::greville,
4401 : Base({{kv[0].front() + kv[0] + kv[0].back(),
4402 kv[1].front() + kv[1] + kv[1].back(),
4403 kv[2].front() + kv[2] + kv[2].back()}},
4404 {{kv[0].front() + kv[0] + kv[0].back(), kv[1], kv[2]}},
4405 {{kv[0], kv[1].front() + kv[1] + kv[1].back(), kv[2]}},
4406 {{kv[0], kv[1], kv[2].front() + kv[2] + kv[2].back()}},
4407 {{kv[0], kv[1], kv[2]}}, init, options) {
4408 static_assert(Spline::is_nonuniform(),
4409 "Constructor only available for non-uniform splines");
4410 }
4413};
4414
4415#undef IGANET_FUNCTIONSPACE_DEFAULT_OPS
4416
4417} // namespace iganet
Boundary treatment.
#define GENERATE_IEXPR_MACRO(r, data, name)
Auto-generated functions.
Definition boundary.hpp:1797
#define GENERATE_EXPR_MACRO(r, data, name)
Definition boundary.hpp:1751
Multivariate B-splines.
#define GENERATE_EXPR_SEQ
Sequence of expression (parametric coordinates)
Definition bspline.hpp:40
#define GENERATE_IEXPR_SEQ
Sequence of expression (physical coordinates)
Definition bspline.hpp:46
Boundary (common high-level functionality)
Definition boundary.hpp:1143
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition boundary.hpp:1369
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:1331
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:1620
auto to(Options< real_t > options) const
Returns a copy of the boundary object with settings from options.
Definition boundary.hpp:1940
auto & from_tensor(const torch::Tensor &tensor)
Sets the coefficients of all spline objects from a single tensor.
Definition boundary.hpp:1221
torch::Tensor as_tensor() const
Returns all coefficients of all spline objects as a single tensor.
Definition boundary.hpp:1166
auto & uniform_refine(int numRefine=1, int dim=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition boundary.hpp:1451
int64_t as_tensor_size() const
Returns the size of the single tensor representation of all spline objects.
Definition boundary.hpp:1187
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:1589
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:4212
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:4216
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:4224
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:3633
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:3637
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:3643
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:3693
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:3689
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:3705
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:3768
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:3783
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:3764
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:3855
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:3884
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:3851
NE_RT_DG(const std::array< int64_t, 2 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4298
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)> > > Base
Base type.
Definition functionspace.hpp:4294
NE_RT_DG(const std::array< std::vector< typename Spline::value_type >, 2 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4306
NE_RT_DG(const std::array< std::vector< typename Spline::value_type >, 3 > &kv, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4396
NE_RT_DG(const std::array< int64_t, 3 > &ncoeffs, enum init init=init::greville, Options< typename Spline::value_type > options=iganet::Options< typename Spline::value_type >{})
Constructor.
Definition functionspace.hpp:4386
FunctionSpace< std::tuple< typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1)+1, Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0)+1, Spline::degree(1), Spline::degree(2)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1)+1, Spline::degree(2)>, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)+1 >, typename Spline::template derived_self_type< typename Spline::value_type, Spline::geoDim(), Spline::degree(0), Spline::degree(1), Spline::degree(2)> > > Base
Base type.
Definition functionspace.hpp:4382
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:104
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:3941
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:3945
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:3951
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:3998
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:4002
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:4009
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:4064
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:4068
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:4077
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:4142
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:4146
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:4156
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:3319
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:3329
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:3315
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:3393
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:3377
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:3381
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:3460
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:3456
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:3475
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:3573
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:3556
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:3552
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:889
auto find_knot_indices(const utils::TensorArray< nspaces()> &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:711
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:730
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:660
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:318
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:1503
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:494
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:1930
static constexpr short_t geoDim() noexcept
Returns the geometric dimensions of the index-th space.
Definition functionspace.hpp:93
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:869
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:965
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:1039
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:309
auto & boundary() noexcept
Returns a non-constant reference to the index-th boundary object.
Definition functionspace.hpp:222
auto boundingBox() const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:989
FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:228
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:1214
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:1095
static constexpr std::size_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:186
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:838
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:1977
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:1916
static constexpr const auto & degrees() noexcept
Returns a constant reference to the array of degrees of the index-th space.
Definition functionspace.hpp:108
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:254
torch::Tensor boundary_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:264
auto & space() noexcept
Returns a non-constant reference to the index-th space.
Definition functionspace.hpp:209
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:816
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:941
std::tuple< Boundaries... > boundary_type
Boundary type.
Definition functionspace.hpp:86
FunctionSpace(std::tuple< Splines... > &&spline, std::tuple< Boundaries... > &&boundary)
Constructor.
Definition functionspace.hpp:175
std::common_type_t< typename Splines::value_type... > value_type
Value type.
Definition functionspace.hpp:77
auto eval_from_precomputed_(std::index_sequence< Is... >, const std::tuple< Basfunc... > &basfunc, const std::tuple< Coeff_Indices... > &coeff_indices, const std::tuple< Xi... > &xi) const
Returns the value of the spline objects from precomputed basis function.
Definition functionspace.hpp:638
virtual FunctionSpace & from_tensor(const torch::Tensor &tensor)
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:410
auto clone() const noexcept
Returns a clone of a subset of the function space.
Definition functionspace.hpp:231
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:1208
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:958
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:827
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:371
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:766
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:1674
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:383
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:553
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:1081
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:2135
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:392
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:807
auto scale_(std::index_sequence< Is... >, value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:898
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:746
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:421
auto boundingBox_(std::index_sequence< Is... >) const
Computes the bounding boxes of the function space object.
Definition functionspace.hpp:983
std::tuple< typename Boundaries::eval_type... > boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:89
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:466
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:1379
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:598
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:923
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:2116
auto eval(const std::tuple< Xi... > &xi) const
Returns the values of the spline objects in the points xi
Definition functionspace.hpp:575
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:1163
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:2108
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:1536
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:1264
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:149
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:850
FunctionSpace(std::tuple< Splines... > &&spline)
Constructor.
Definition functionspace.hpp:167
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:1346
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:290
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:860
std::tuple< utils::TensorArray< Splines::parDim()>... > eval_type
Spline evaluation type.
Definition functionspace.hpp:83
auto hess(const utils::TensorArray< nspaces()> &xi, const std::tuple< TensorArrays... > &knot_indices) const
Returns a block-tensor with the Hessian of the function space object in the points xi with respect to...
Definition functionspace.hpp:1509
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:620
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:878
nlohmann::json to_json_(std::index_sequence< Is... >) const
Serialization to JSON.
Definition functionspace.hpp:475
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:775
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:299
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:976
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:1241
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:789
constexpr auto & boundaries() noexcept
Returns a non-constant reference to the tuple of boundary object.
Definition functionspace.hpp:200
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:2158
const auto & boundary() const noexcept
Returns a constant reference to the index-th boundary object.
Definition functionspace.hpp:215
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:140
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:441
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:1922
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:1109
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:281
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:1949
boundary_type boundary_
Boundaries.
Definition functionspace.hpp:126
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:1294
constexpr const auto & boundaries() const noexcept
Returns a constant reference to the tuple of boundary object.
Definition functionspace.hpp:197
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:1517
constexpr const auto & spaces() const noexcept
Returns a constant reference to the tuple of function spaces.
Definition functionspace.hpp:191
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the function space object.
Definition functionspace.hpp:1046
const auto & space() const noexcept
Returns a constant reference to the index-th function space.
Definition functionspace.hpp:203
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:2021
FunctionSpace & from_xml(const pugi::xml_document &doc, int id=0, const std::string &label="")
Updates the function space object from XML object.
Definition functionspace.hpp:460
static constexpr short_t degree(short_t i) noexcept
Returns a constant reference to the degree in the -th dimension of the index-th space.
Definition functionspace.hpp:116
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:1013
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:537
auto find_knot_indices(const std::tuple< Xi... > &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:717
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:1432
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:335
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:450
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:906
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:696
bool operator==(const FunctionSpace< SplinesOther, BoundariesOther > &other) const
Returns true if both function space objects are the same.
Definition functionspace.hpp:501
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:585
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:1222
FunctionSpace(const std::tuple< Splines... > &spline)
Constructor.
Definition functionspace.hpp:162
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:1024
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &tensor)
Sets the tuple of boundaries from a single-tensor representation.
Definition functionspace.hpp:404
torch::Tensor spaces_as_tensor_(std::index_sequence< Is... >) const noexcept
Returns a single-tensor representation of the tuple of spaces.
Definition functionspace.hpp:247
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &tensor)
Sets the tuple of spaces from a single-tensor representation.
Definition functionspace.hpp:362
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:1087
static constexpr short_t parDim() noexcept
Returns the parametric dimensions of the index-th space.
Definition functionspace.hpp:100
auto scale_(std::index_sequence< Is... >, std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:913
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:1576
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:2102
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:1131
constexpr auto & spaces() noexcept
Returns a non-constant reference to the tuple of function spaces.
Definition functionspace.hpp:194
auto translate_(std::index_sequence< Is... >, std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:930
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:686
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:522
std::tuple< Splines... > spline_type
Spline type.
Definition functionspace.hpp:80
auto lapl(const utils::TensorArray4 &xi, const std::tuple< utils::TensorArray4, utils::TensorArray4, utils::TensorArray4, utils::TensorArray4 > &knot_indices, const std::tuple< torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor > &coeff_indices) const
Returns a block-tensor with the Laplacian of the function space object in the points xi with respect ...
Definition functionspace.hpp:2188
FunctionSpace(const std::tuple< Splines... > &spline, const std::tuple< Boundaries... > &boundary)
Constructor.
Definition functionspace.hpp:171
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:1360
auto rotate_(std::index_sequence< Is... >, value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:948
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the tuple of boundaries.
Definition functionspace.hpp:271
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:1352
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:998
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:1402
static constexpr std::size_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:181
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:672
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:328
pugi::xml_document to_xml(int id=0, const std::string &label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:431
Function space.
Definition functionspace.hpp:2478
auto & uniform_refine(int numRefine=1, int dimRefine=-1)
Returns the spline objects with uniformly refined knot and coefficient vectors.
Definition functionspace.hpp:2943
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:2921
FunctionSpace(const Spline &spline)
Constructor.
Definition functionspace.hpp:2564
auto scale(std::array< value_type, N > v)
Scales the function space object by a vector.
Definition functionspace.hpp:2980
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:2545
auto eval_basfunc(const Args &...args) const
Returns the values of the spline objects' basis functions in the points xi
Definition functionspace.hpp:2893
virtual int64_t as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the function space object.
Definition functionspace.hpp:2681
bool operator==(const FunctionSpace< SplinesOther, BoundariesOther > &other) const
Returns true if both function space objects are the same.
Definition functionspace.hpp:2754
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:2906
constexpr const boundary_type & boundary() const noexcept
Returns a constant reference to the index-th boundary object.
Definition functionspace.hpp:2611
virtual torch::Tensor spaces_as_tensor() const noexcept
Returns a single-tensor representation of the space.
Definition functionspace.hpp:2646
pugi::xml_document to_xml(int id=0, const std::string &label="") const
Returns the function space object as XML object.
Definition functionspace.hpp:2715
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:3020
virtual int64_t boundary_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the boundary.
Definition functionspace.hpp:2672
static constexpr short_t geoDim() noexcept
Returns the geometric dimensions of the index-th space.
Definition functionspace.hpp:2498
FunctionSpace & transform(const std::function< std::array< typename Spline::value_type, Spline::geoDim()>(const std::array< typename Spline::value_type, Spline::parDim()> &)> mapping)
Transforms the coefficients based on the given mapping.
Definition functionspace.hpp:2770
virtual torch::Tensor boundary_as_tensor() const noexcept
Returns a single-tensor representation of the boundary.
Definition functionspace.hpp:2651
constexpr boundary_type & boundary() noexcept
Returns a non-constant reference to the index-th boundary object.
Definition functionspace.hpp:2619
static constexpr short_t parDim() noexcept
Returns the parametric dimensions of the index-th space.
Definition functionspace.hpp:2505
auto scale(value_type s, int dim=-1)
Scales the function space object by a scalar.
Definition functionspace.hpp:2973
Spline spline_type
Spline type.
Definition functionspace.hpp:2485
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the function space object.
Definition functionspace.hpp:3028
virtual int64_t spaces_as_tensor_size() const noexcept
Returns the size of the single-tensor representation of the space.
Definition functionspace.hpp:2666
FunctionSpace & from_xml(const pugi::xml_document &doc, int id=0, const std::string &label="")
Updates the function space object from XML object.
Definition functionspace.hpp:2731
auto find_knot_indices(const Xi &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:2872
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:2785
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:3010
FunctionSpace(Spline &&spline)
Constructor.
Definition functionspace.hpp:2570
Boundary::eval_type boundary_eval_type
Boundary evaluation type.
Definition functionspace.hpp:2494
constexpr spline_type & space() noexcept
Returns a non-constant reference to the index-th function space.
Definition functionspace.hpp:2604
auto to(torch::Device device) const
Returns a copy of the function space object with settings from device.
Definition functionspace.hpp:2960
auto eval(const Arg &arg, const Args &...args) const
Returns the values of the spline object in the points xi
Definition functionspace.hpp:2831
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:2812
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:2737
constexpr auto & spaces() noexcept
Returns a non-constant reference to the tuple of function spaces.
Definition functionspace.hpp:2587
auto rotate(std::array< value_type, 3 > angle)
Rotates the function space object by three angles in 3d.
Definition functionspace.hpp:3001
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:2725
static constexpr std::size_t nspaces() noexcept
Returns the number of function spaces.
Definition functionspace.hpp:2578
constexpr FunctionSpace clone() const noexcept
Returns a clone of the function space.
Definition functionspace.hpp:2625
auto find_knot_indices_(std::index_sequence< Is... >, const Xi &xi) const
Returns the knot indicies of knot spans containing xi
Definition functionspace.hpp:2861
auto rotate(value_type angle)
Rotates the function space object by an angle in 2d.
Definition functionspace.hpp:2994
static constexpr std::size_t nboundaries() noexcept
Returns the number of boundaries.
Definition functionspace.hpp:2581
static constexpr const auto & degrees() noexcept
Returns a constant reference to the array of degrees of the index-th space.
Definition functionspace.hpp:2513
constexpr const auto & spaces() const noexcept
Returns a constant reference to the tuple of function spaces.
Definition functionspace.hpp:2584
auto translate(std::array< value_type, N > v)
Translates the function space object by a vector.
Definition functionspace.hpp:2987
static constexpr short_t degree(short_t i) noexcept
Returns a constant reference to the degree in the -th dimension of the index-th space.
Definition functionspace.hpp:2521
auto to(Options< real_t > options) const
Returns a copy of the function space object with settings from options.
Definition functionspace.hpp:2951
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:2798
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:2695
constexpr auto & boundaries() noexcept
Returns a non-constant reference to the tuple of boundary object.
Definition functionspace.hpp:2593
FunctionSpace(FunctionSpace &&)=default
Move constructor.
boundary_type boundary_
Boundary.
Definition functionspace.hpp:2531
Boundary boundary_type
Boundary type.
Definition functionspace.hpp:2491
utils::TensorArray< Spline::parDim()> eval_type
Spline evaluation type.
Definition functionspace.hpp:2488
virtual FunctionSpace & spaces_from_tensor(const torch::Tensor &coeffs) noexcept
Sets the space from a single-tensor representation.
Definition functionspace.hpp:2687
virtual FunctionSpace & boundary_from_full_tensor(const torch::Tensor &coeffs) noexcept
Sets the boundary from a single-tensor representation.
Definition functionspace.hpp:2702
virtual torch::Tensor as_tensor() const noexcept
Returns a single-tensor representation of the function space object.
Definition functionspace.hpp:2660
constexpr const auto & boundaries() const noexcept
Returns a constant reference to the tuple of boundary object.
Definition functionspace.hpp:2590
FunctionSpace(const FunctionSpace &)=default
Copy constructor.
spline_type spline_
Spline.
Definition functionspace.hpp:2528
Spline::value_type value_type
Value type.
Definition functionspace.hpp:2482
auto eval_from_precomputed(const Args &...args) const
Returns the value of the spline object from precomputed basis function.
Definition functionspace.hpp:2850
nlohmann::json to_json() const override
Serialization to JSON.
Definition functionspace.hpp:2744
FunctionSpace & from_tensor(const torch::Tensor &coeffs) noexcept
Sets the function space object from a single-tensor representation.
Definition functionspace.hpp:2708
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:2554
constexpr const spline_type & space() const noexcept
Returns a constant reference to the index-th function space.
Definition functionspace.hpp:2597
auto to() const
Returns a copy of the function space object with real_t type.
Definition functionspace.hpp:2965
constexpr auto clone() const noexcept
Returns a subset of the tuple of function spaces.
Definition functionspace.hpp:2630
Full qualified name descriptor.
Definition fqn.hpp:22
virtual const std::string & name() const noexcept
Returns the full qualified name of the object.
Definition fqn.hpp:28
Concept to identify template parameters that are derived from iganet::details::FunctionSpaceType.
Definition functionspace.hpp:3255
Definition functionspace.hpp:54
Definition functionspace.hpp:47
Container utility functions.
#define IGANET_FUNCTIONSPACE_DEFAULT_OPS(FunctionSpace)
Macro: Implements the default methods of a function space.
Definition functionspace.hpp:37
FunctionSpace_trait< Spline, Boundary >::type type
Definition functionspace.hpp:3238
FunctionSpace_trait< utils::tuple_cat_t< Splines... >, utils::tuple_cat_t< Boundaries... > >::type type
Definition functionspace.hpp:3247
std::ostream & operator<<(std::ostream &os, const FunctionSpace< Splines... > &obj)
Print (as string) a function space object.
Definition functionspace.hpp:2464
Forward declaration.
Definition functionspace.hpp:3206
TensorArray< 4 > TensorArray4
Definition tensorarray.hpp:32
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:26
auto zip(T &&...seqs)
Definition zip.hpp:97
TensorArray< 3 > TensorArray3
Definition tensorarray.hpp:31
TensorArray< 1 > TensorArray1
Definition tensorarray.hpp:29
tuple_cat< Tuples... >::type tuple_cat_t
Alias for tuple_cat::type.
Definition tuple.hpp:71
TensorArray< 2 > TensorArray2
Definition tensorarray.hpp:30
Forward declaration of BlockTensor.
Definition blocktensor.hpp:43
Definition core.hpp:72
deriv
Enumerator for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:72
BoundaryCommon< BoundaryCore< Spline, Spline::parDim()> > Boundary
Boundary.
Definition boundary.hpp:1978
detail::FunctionSpace_trait< Args... >::type FunctionSpace
Function space alias.
Definition functionspace.hpp:3259
std::ostream & operator<<(std::ostream &os, const MemoryDebugger< id > &obj)
Print (as string) a memory debugger object.
Definition memory.hpp:125
init
Enumerator for specifying the initialization of B-spline coefficients.
Definition bspline.hpp:55
FunctionSpace< Spline > S
Spline function space .
Definition functionspace.hpp:3286
functionspace
Enumerator for the function space component.
Definition functionspace.hpp:31
@ none
Definition boundary.hpp:38
short int short_t
Definition core.hpp:74
H(curl) function space.
Definition functionspace.hpp:4174
Nedelec like function space.
Definition functionspace.hpp:3607
Nedelec-Raviart-Thomas-$P$ triple function space.
Definition functionspace.hpp:4241
Raviart-Thomas like function space.
Definition functionspace.hpp:3915
Taylor-Hood like function space.
Definition functionspace.hpp:3289
STL namespace.
Serialization prototype.
Definition serialize.hpp:29
Tuple utility functions.
Zip utility function.