deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
tensor_product_polynomials.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2000 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_tensor_product_polynomials_h
14#define dealii_tensor_product_polynomials_h
15
16
17#include <deal.II/base/config.h>
18
21#include <deal.II/base/point.h>
24#include <deal.II/base/tensor.h>
26
27#include <vector>
28
30
31// Forward declarations for friends
32// TODO: We may be able to modify these classes so they aren't
33// required to be friends
34template <int dim>
36template <int dim>
38
72template <int dim, typename PolynomialType = Polynomials::Polynomial<double>>
74{
75public:
80 static constexpr unsigned int dimension = dim;
81
88 template <class Pol>
89 TensorProductPolynomials(const std::vector<Pol> &pols);
90
94 void
95 output_indices(std::ostream &out) const;
96
101 void
102 set_numbering(const std::vector<unsigned int> &renumber);
103
107 const std::vector<unsigned int> &
109
113 const std::vector<unsigned int> &
115
128 void
129 evaluate(const Point<dim> &unit_point,
130 std::vector<double> &values,
131 std::vector<Tensor<1, dim>> &grads,
132 std::vector<Tensor<2, dim>> &grad_grads,
133 std::vector<Tensor<3, dim>> &third_derivatives,
134 std::vector<Tensor<4, dim>> &fourth_derivatives) const override;
135
148 double
149 compute_value(const unsigned int i, const Point<dim> &p) const override;
150
165 template <int order>
167 compute_derivative(const unsigned int i, const Point<dim> &p) const;
168
172 virtual Tensor<1, dim>
173 compute_1st_derivative(const unsigned int i,
174 const Point<dim> &p) const override;
175
179 virtual Tensor<2, dim>
180 compute_2nd_derivative(const unsigned int i,
181 const Point<dim> &p) const override;
182
186 virtual Tensor<3, dim>
187 compute_3rd_derivative(const unsigned int i,
188 const Point<dim> &p) const override;
189
193 virtual Tensor<4, dim>
194 compute_4th_derivative(const unsigned int i,
195 const Point<dim> &p) const override;
196
210 compute_grad(const unsigned int i, const Point<dim> &p) const override;
211
225 compute_grad_grad(const unsigned int i, const Point<dim> &p) const override;
226
230 std::string
231 name() const override;
232
236 virtual std::unique_ptr<ScalarPolynomialsBase<dim>>
237 clone() const override;
238
242 virtual std::size_t
243 memory_consumption() const override;
244
249 std::vector<PolynomialType>
251
252protected:
256 std::vector<PolynomialType> polynomials;
257
261 std::vector<unsigned int> index_map;
262
266 std::vector<unsigned int> index_map_inverse;
267
274 void
275 compute_index(const unsigned int i,
276 std::array<unsigned int, dim> &indices) const;
277
282 friend class TensorProductPolynomialsBubbles<dim>;
283
288 friend class TensorProductPolynomialsConst<dim>;
289};
290
291
292
318template <int dim>
320{
321public:
338 const std::vector<std::vector<Polynomials::Polynomial<double>>>
339 &base_polynomials);
340
345 void
346 set_numbering(const std::vector<unsigned int> &renumber);
347
351 const std::vector<unsigned int> &
352 get_numbering() const;
353
357 const std::vector<unsigned int> &
358 get_numbering_inverse() const;
359
373 void
374 evaluate(const Point<dim> &unit_point,
375 std::vector<double> &values,
376 std::vector<Tensor<1, dim>> &grads,
377 std::vector<Tensor<2, dim>> &grad_grads,
378 std::vector<Tensor<3, dim>> &third_derivatives,
379 std::vector<Tensor<4, dim>> &fourth_derivatives) const override;
380
393 double
394 compute_value(const unsigned int i, const Point<dim> &p) const override;
395
410 template <int order>
412 compute_derivative(const unsigned int i, const Point<dim> &p) const;
413
417 virtual Tensor<1, dim>
418 compute_1st_derivative(const unsigned int i,
419 const Point<dim> &p) const override;
420
424 virtual Tensor<2, dim>
425 compute_2nd_derivative(const unsigned int i,
426 const Point<dim> &p) const override;
427
431 virtual Tensor<3, dim>
432 compute_3rd_derivative(const unsigned int i,
433 const Point<dim> &p) const override;
434
438 virtual Tensor<4, dim>
439 compute_4th_derivative(const unsigned int i,
440 const Point<dim> &p) const override;
441
455 compute_grad(const unsigned int i, const Point<dim> &p) const override;
456
470 compute_grad_grad(const unsigned int i, const Point<dim> &p) const override;
471
475 std::string
476 name() const override;
477
481 virtual std::unique_ptr<ScalarPolynomialsBase<dim>>
482 clone() const override;
483
484private:
488 const std::vector<std::vector<Polynomials::Polynomial<double>>> polynomials;
489
493 std::vector<unsigned int> index_map;
494
498 std::vector<unsigned int> index_map_inverse;
499
506 void
507 compute_index(const unsigned int i,
508 std::array<unsigned int, dim> &indices) const;
509
513 static unsigned int
515 const std::vector<std::vector<Polynomials::Polynomial<double>>> &pols);
516};
517
520#ifndef DOXYGEN
521
522
523/* ---------------- template and inline functions ---------- */
524
525
526template <int dim, typename PolynomialType>
527template <class Pol>
529 const std::vector<Pol> &pols)
530 : ScalarPolynomialsBase<dim>(1, Utilities::fixed_power<dim>(pols.size()))
531 , polynomials(pols.begin(), pols.end())
532 , index_map(this->n())
533 , index_map_inverse(this->n())
534{
535 // per default set this index map to identity. This map can be changed by
536 // the user through the set_numbering() function
537 for (unsigned int i = 0; i < this->n(); ++i)
538 {
539 index_map[i] = i;
540 index_map_inverse[i] = i;
541 }
542}
543
544
545template <int dim, typename PolynomialType>
546inline const std::vector<unsigned int> &
548{
549 return index_map;
550}
551
552
553template <int dim, typename PolynomialType>
554inline const std::vector<unsigned int> &
556{
557 return index_map_inverse;
558}
559
560
561template <int dim, typename PolynomialType>
562inline std::string
564{
565 return "TensorProductPolynomials";
566}
567
568
569template <int dim, typename PolynomialType>
570template <int order>
573 const unsigned int i,
574 const Point<dim> &p) const
575{
576 std::array<unsigned int, dim> indices;
577 compute_index(i, indices);
578
580 if constexpr (running_in_debug_mode())
581 for (auto &array : v)
582 array.fill(std::numeric_limits<double>::signaling_NaN());
583
584 for (unsigned int d = 0; d < dim; ++d)
585 {
586 polynomials[indices[d]].value(p[d], order, v[d].data());
587 }
588
589 if constexpr (order == 1)
590 {
591 Tensor<1, dim> derivative;
592 for (unsigned int d = 0; d < dim; ++d)
593 {
594 derivative[d] = 1.;
595 for (unsigned int x = 0; x < dim; ++x)
596 {
597 unsigned int x_order = 0;
598 if (d == x)
599 ++x_order;
600
601 derivative[d] *= v[x][x_order];
602 }
603 }
604
605 return derivative;
606 }
607 else if constexpr (order == 2)
608 {
609 Tensor<2, dim> derivative;
610 for (unsigned int d1 = 0; d1 < dim; ++d1)
611 for (unsigned int d2 = 0; d2 < dim; ++d2)
612 {
613 derivative[d1][d2] = 1.;
614 for (unsigned int x = 0; x < dim; ++x)
615 {
616 unsigned int x_order = 0;
617 if (d1 == x)
618 ++x_order;
619 if (d2 == x)
620 ++x_order;
621
622 derivative[d1][d2] *= v[x][x_order];
623 }
624 }
625
626 return derivative;
627 }
628 else if constexpr (order == 3)
629 {
630 Tensor<3, dim> derivative;
631 for (unsigned int d1 = 0; d1 < dim; ++d1)
632 for (unsigned int d2 = 0; d2 < dim; ++d2)
633 for (unsigned int d3 = 0; d3 < dim; ++d3)
634 {
635 derivative[d1][d2][d3] = 1.;
636 for (unsigned int x = 0; x < dim; ++x)
637 {
638 unsigned int x_order = 0;
639 if (d1 == x)
640 ++x_order;
641 if (d2 == x)
642 ++x_order;
643 if (d3 == x)
644 ++x_order;
645
646 derivative[d1][d2][d3] *= v[x][x_order];
647 }
648 }
649
650 return derivative;
651 }
652 else if constexpr (order == 4)
653 {
654 Tensor<4, dim> derivative;
655 for (unsigned int d1 = 0; d1 < dim; ++d1)
656 for (unsigned int d2 = 0; d2 < dim; ++d2)
657 for (unsigned int d3 = 0; d3 < dim; ++d3)
658 for (unsigned int d4 = 0; d4 < dim; ++d4)
659 {
660 derivative[d1][d2][d3][d4] = 1.;
661 for (unsigned int x = 0; x < dim; ++x)
662 {
663 unsigned int x_order = 0;
664 if (d1 == x)
665 ++x_order;
666 if (d2 == x)
667 ++x_order;
668 if (d3 == x)
669 ++x_order;
670 if (d4 == x)
671 ++x_order;
672
673 derivative[d1][d2][d3][d4] *= v[x][x_order];
674 }
675 }
676
677 return derivative;
678 }
679 else
680 {
682 return {};
683 }
684}
685
686
687
688template <>
689template <int order>
692 compute_derivative(const unsigned int, const Point<0> &) const
693{
695
696 return {};
697}
698
699
700
701template <int dim, typename PolynomialType>
702inline Tensor<1, dim>
704 const unsigned int i,
705 const Point<dim> &p) const
706{
707 return compute_derivative<1>(i, p);
708}
709
710
711
712template <int dim, typename PolynomialType>
713inline Tensor<2, dim>
715 const unsigned int i,
716 const Point<dim> &p) const
717{
718 return compute_derivative<2>(i, p);
719}
720
721
722
723template <int dim, typename PolynomialType>
724inline Tensor<3, dim>
726 const unsigned int i,
727 const Point<dim> &p) const
728{
729 return compute_derivative<3>(i, p);
730}
731
732
733
734template <int dim, typename PolynomialType>
735inline Tensor<4, dim>
737 const unsigned int i,
738 const Point<dim> &p) const
739{
740 return compute_derivative<4>(i, p);
741}
742
743
744
745template <int dim>
746template <int order>
749 const Point<dim> &p) const
750{
751 std::array<unsigned int, dim> indices;
752 compute_index(i, indices);
753
755 if constexpr (running_in_debug_mode())
756 for (auto &array : v)
757 array.fill(std::numeric_limits<double>::signaling_NaN());
758 for (unsigned int d = 0; d < dim; ++d)
759 {
760 polynomials[d][indices[d]].value(p[d], order, v[d].data());
761 }
762
763 if constexpr (order == 1)
764 {
765 Tensor<1, dim> derivative;
766 for (unsigned int d = 0; d < dim; ++d)
767 {
768 derivative[d] = 1.;
769 for (unsigned int x = 0; x < dim; ++x)
770 {
771 unsigned int x_order = 0;
772 if (d == x)
773 ++x_order;
774
775 derivative[d] *= v[x][x_order];
776 }
777 }
778
779 return derivative;
780 }
781 else if constexpr (order == 2)
782 {
783 Tensor<2, dim> derivative;
784 for (unsigned int d1 = 0; d1 < dim; ++d1)
785 for (unsigned int d2 = 0; d2 < dim; ++d2)
786 {
787 derivative[d1][d2] = 1.;
788 for (unsigned int x = 0; x < dim; ++x)
789 {
790 unsigned int x_order = 0;
791 if (d1 == x)
792 ++x_order;
793 if (d2 == x)
794 ++x_order;
795
796 derivative[d1][d2] *= v[x][x_order];
797 }
798 }
799
800 return derivative;
801 }
802 else if constexpr (order == 3)
803 {
804 Tensor<3, dim> derivative;
805 for (unsigned int d1 = 0; d1 < dim; ++d1)
806 for (unsigned int d2 = 0; d2 < dim; ++d2)
807 for (unsigned int d3 = 0; d3 < dim; ++d3)
808 {
809 derivative[d1][d2][d3] = 1.;
810 for (unsigned int x = 0; x < dim; ++x)
811 {
812 unsigned int x_order = 0;
813 if (d1 == x)
814 ++x_order;
815 if (d2 == x)
816 ++x_order;
817 if (d3 == x)
818 ++x_order;
819
820 derivative[d1][d2][d3] *= v[x][x_order];
821 }
822 }
823
824 return derivative;
825 }
826 else if constexpr (order == 4)
827 {
828 Tensor<4, dim> derivative;
829 for (unsigned int d1 = 0; d1 < dim; ++d1)
830 for (unsigned int d2 = 0; d2 < dim; ++d2)
831 for (unsigned int d3 = 0; d3 < dim; ++d3)
832 for (unsigned int d4 = 0; d4 < dim; ++d4)
833 {
834 derivative[d1][d2][d3][d4] = 1.;
835 for (unsigned int x = 0; x < dim; ++x)
836 {
837 unsigned int x_order = 0;
838 if (d1 == x)
839 ++x_order;
840 if (d2 == x)
841 ++x_order;
842 if (d3 == x)
843 ++x_order;
844 if (d4 == x)
845 ++x_order;
846
847 derivative[d1][d2][d3][d4] *= v[x][x_order];
848 }
849 }
850
851 return derivative;
852 }
853 else
854 {
856 return {};
857 }
858}
859
860
861
862template <>
863template <int order>
866 const Point<0> &) const
867{
869
870 return {};
871}
872
873
874
875template <int dim>
876inline Tensor<1, dim>
878 const Point<dim> &p) const
879{
880 return compute_derivative<1>(i, p);
881}
882
883
884
885template <int dim>
886inline Tensor<2, dim>
888 const Point<dim> &p) const
889{
890 return compute_derivative<2>(i, p);
891}
892
893
894
895template <int dim>
896inline Tensor<3, dim>
898 const Point<dim> &p) const
899{
900 return compute_derivative<3>(i, p);
901}
902
903
904
905template <int dim>
906inline Tensor<4, dim>
908 const Point<dim> &p) const
909{
910 return compute_derivative<4>(i, p);
911}
912
913
914
915template <int dim>
916inline std::string
918{
919 return "AnisotropicPolynomials";
920}
921
922
923
924#endif // DOXYGEN
926
927#endif
*  iterator end()
*  *  iterator begin()
void evaluate(const Point< dim > &unit_point, std::vector< double > &values, std::vector< Tensor< 1, dim > > &grads, std::vector< Tensor< 2, dim > > &grad_grads, std::vector< Tensor< 3, dim > > &third_derivatives, std::vector< Tensor< 4, dim > > &fourth_derivatives) const override
double compute_value(const unsigned int i, const Point< dim > &p) const override
void set_numbering(const std::vector< unsigned int > &renumber)
const std::vector< std::vector< Polynomials::Polynomial< double > > > polynomials
virtual Tensor< 1, dim > compute_1st_derivative(const unsigned int i, const Point< dim > &p) const override
static unsigned int get_n_tensor_pols(const std::vector< std::vector< Polynomials::Polynomial< double > > > &pols)
std::vector< unsigned int > index_map
virtual Tensor< 3, dim > compute_3rd_derivative(const unsigned int i, const Point< dim > &p) const override
void compute_index(const unsigned int i, std::array< unsigned int, dim > &indices) const
Tensor< 2, dim > compute_grad_grad(const unsigned int i, const Point< dim > &p) const override
virtual Tensor< 2, dim > compute_2nd_derivative(const unsigned int i, const Point< dim > &p) const override
Tensor< order, dim > compute_derivative(const unsigned int i, const Point< dim > &p) const
const std::vector< unsigned int > & get_numbering() const
std::string name() const override
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const override
std::vector< unsigned int > index_map_inverse
virtual Tensor< 4, dim > compute_4th_derivative(const unsigned int i, const Point< dim > &p) const override
const std::vector< unsigned int > & get_numbering_inverse() const
virtual std::unique_ptr< ScalarPolynomialsBase< dim > > clone() const override
Definition point.h:111
void evaluate(const Point< dim > &unit_point, std::vector< double > &values, std::vector< Tensor< 1, dim > > &grads, std::vector< Tensor< 2, dim > > &grad_grads, std::vector< Tensor< 3, dim > > &third_derivatives, std::vector< Tensor< 4, dim > > &fourth_derivatives) const override
void output_indices(std::ostream &out) const
void compute_index(const unsigned int i, std::array< unsigned int, dim > &indices) const
double compute_value(const unsigned int i, const Point< dim > &p) const override
virtual std::size_t memory_consumption() const override
virtual Tensor< 2, dim > compute_2nd_derivative(const unsigned int i, const Point< dim > &p) const override
const std::vector< unsigned int > & get_numbering() const
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const override
Tensor< order, dim > compute_derivative(const unsigned int i, const Point< dim > &p) const
virtual std::unique_ptr< ScalarPolynomialsBase< dim > > clone() const override
virtual Tensor< 1, dim > compute_1st_derivative(const unsigned int i, const Point< dim > &p) const override
std::vector< unsigned int > index_map
std::vector< unsigned int > index_map_inverse
std::vector< PolynomialType > get_underlying_polynomials() const
virtual Tensor< 3, dim > compute_3rd_derivative(const unsigned int i, const Point< dim > &p) const override
std::vector< PolynomialType > polynomials
void set_numbering(const std::vector< unsigned int > &renumber)
const std::vector< unsigned int > & get_numbering_inverse() const
Tensor< 2, dim > compute_grad_grad(const unsigned int i, const Point< dim > &p) const override
std::string name() const override
static constexpr unsigned int dimension
virtual Tensor< 4, dim > compute_4th_derivative(const unsigned int i, const Point< dim > &p) const override
TensorProductPolynomials(const std::vector< Pol > &pols)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
constexpr bool running_in_debug_mode()
Definition config.h:76
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define AssertThrow(cond, exc)
std::vector< index_type > data
Definition mpi.cc:734
std::size_t size
Definition mpi.cc:733
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
STL namespace.
typename internal::ndarray::HelperArray< T, Ns... >::type ndarray
Definition ndarray.h:105