Reference documentation for deal.II version GIT 9d46a3bd8c 2023-10-03 12:10:02+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\}}\)
template_constraints.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2003 - 2023 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_template_constraints_h
17 #define dealii_template_constraints_h
18 
19 
20 #include <deal.II/base/config.h>
21 
24 
25 #include <complex>
26 #include <type_traits>
27 #include <utility>
28 
29 
31 
32 // Detection idiom adapted from Version 2 of the C++ Extensions for Library
33 // Fundamentals, ISO/IEC TS 19568:2017
34 namespace internal
35 {
41  namespace SupportsOperation
42  {
43  template <class...>
44  using void_t = void;
45 
52  template <class Default,
53  class AlwaysVoid,
54  template <class...>
55  class Op,
56  class... Args>
57  struct detector
58  {
59  using value_t = std::false_type;
60  using type = Default;
61  };
62 
75  template <class Default, template <class...> class Op, class... Args>
76  struct detector<Default, void_t<Op<Args...>>, Op, Args...>
77  {
78  using value_t = std::true_type;
79  using type = Op<Args...>;
80  };
81 
82 
88  {};
89 
94  struct nonesuch : private nonesuch_base
95  {
96  ~nonesuch() = delete;
97  nonesuch(const nonesuch &) = delete;
98  void
99  operator=(const nonesuch &) = delete;
100  };
101 
102  template <class Default, template <class...> class Op, class... Args>
103  using detected_or = detector<Default, void, Op, Args...>;
104 
105  template <template <class...> class Op, class... Args>
106  using is_detected = typename detected_or<nonesuch, Op, Args...>::value_t;
107 
108  template <template <class...> class Op, class... Args>
109  using detected_t = typename detected_or<nonesuch, Op, Args...>::type;
110 
111  template <class Default, template <class...> class Op, class... Args>
112  using detected_or_t = typename detected_or<Default, Op, Args...>::type;
113 
114  template <class Expected, template <class...> class Op, class... Args>
115  using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
116 
117  template <class To, template <class...> class Op, class... Args>
119  std::is_convertible<detected_t<Op, Args...>, To>;
120  } // namespace SupportsOperation
121 
122 
157  template <template <class...> class Op, class... Args>
158  constexpr bool is_supported_operation =
159  SupportsOperation::is_detected<Op, Args...>::value;
160 } // namespace internal
161 
162 
163 
164 namespace internal
165 {
166  namespace TemplateConstraints
167  {
176  template <bool... Values>
177  struct all_true
178  {
179  static constexpr bool value = (Values && ...);
180  };
181 
182 
187  template <bool... Values>
188  struct any_true
189  {
190  static constexpr bool value = (Values || ...);
191  };
192  } // namespace TemplateConstraints
193 } // namespace internal
194 
201 template <class Base, class... Derived>
203 {
205  std::is_base_of_v<Base, Derived>...>::value;
206 };
207 
208 
209 
216 template <typename Type, class... Types>
218 {
220  std::is_same_v<Type, Types>...>::value;
221 };
222 
223 
224 
231 template <typename Type, class... Types>
233 {
235  std::is_same_v<Type, Types>...>::value;
236 };
237 
238 
239 
240 /*
241  * A generalization of `std::enable_if` that only works if
242  * <i>all</i> of the given boolean template parameters are
243  * true. See [here](https://en.cppreference.com/w/cpp/types/enable_if)
244  * for what `std::enable_if` does.
245  *
246  * @note
247  * In contrast to `std::enable_if`, this template has no additional
248  * template type (which for `std::enable_if` is defaulted to `void`).
249  * As a consequence, this structure cannot be used for anything other
250  * than enabling or disabling a template declaration; in particular
251  * it cannot be used to set the return type of a function as one might
252  * do with something like
253  * @code
254  * template <typename T>
255  * typename std::enable_if<std::is_floating_point_v<T>, T>::type
256  * abs (const T t);
257  * @endcode
258  * which declares a function template `abs()` that can only be
259  * instantiated if `T` is a floating point type; this function then
260  * returns an object of type `T` as indicated by the last argument to
261  * `std::enable_if`. The reason `enable_if_all` does not allow providing
262  * this additional type is that variadic templates (here, the list of
263  * `bool` arguments) must be the last template argument.
264  */
265 template <bool... Values>
267  : std::enable_if<internal::TemplateConstraints::all_true<Values...>::value>
268 {};
269 
270 
271 
272 /*
273  * A generalization of `std::enable_if_t` that only works if
274  * <i>all</i> of the given boolean template parameters are
275  * true. See [here](https://en.cppreference.com/w/cpp/types/enable_if)
276  * for what `std::enable_if_t` does.
277  *
278  * @note
279  * In contrast to `std::enable_if_t`, this template has no additional
280  * template type (which for `std::enable_if` is defaulted to `void`).
281  * As a consequence, this structure cannot be used for anything other
282  * than enabling or disabling a template declaration; in particular
283  * it cannot be used to set the return type of a function as one might
284  * do with something like
285  * @code
286  * template <typename T>
287  * std::enable_if_t<std::is_floating_point_v<T>, T>
288  * abs (const T t);
289  * @endcode
290  * which declares a function template `abs()` that can only be
291  * instantiated if `T` is a floating point type; this function then
292  * returns an object of type `T` as indicated by the last argument to
293  * `std::enable_if`. The reason `enable_if_all` does not allow providing
294  * this additional type is that variadic templates (here, the list of
295  * `bool` arguments) must be the last template argument.
296  */
297 template <bool... Values>
298 using enable_if_all_t = typename enable_if_all<Values...>::type;
299 
300 
306 template <typename T>
308  decltype(std::begin(std::declval<T>()), std::end(std::declval<T>()));
309 
310 template <typename T>
311 constexpr bool has_begin_and_end =
312  internal::is_supported_operation<begin_and_end_t, T>;
313 
314 
322 template <typename T>
324 
325 
331 template <typename ArgType, typename ValueType>
333 {
334  ValueType value;
335  ValueType
336  operator()(const ArgType &)
337  {
338  return value;
339  }
340 };
341 
342 
343 
361 {
366  template <typename T>
367  static bool
368  equal(const T *p1, const T *p2)
369  {
370  return (p1 == p2);
371  }
372 
373 
380  template <typename T, typename U>
381  static bool
382  equal(const T *, const U *)
383  {
384  return false;
385  }
386 };
387 
388 
389 
390 namespace internal
391 {
402  template <typename T, typename U>
404  {
405  using type = decltype(std::declval<T>() * std::declval<U>());
406  };
407 
408 } // namespace internal
409 
410 
411 
458 template <typename T, typename U>
460 {
461  using type =
462  typename internal::ProductTypeImpl<std::decay_t<T>, std::decay_t<U>>::type;
463 };
464 
465 namespace internal
466 {
467  // Annoyingly, there is no std::complex<T>::operator*(U) for scalars U
468  // other than T (not even in C++11, or C++14). We provide our own overloads
469  // in base/complex_overloads.h, but in order for them to work, we have to
470  // manually specify all products we want to allow:
471 
472  template <typename T>
473  struct ProductTypeImpl<std::complex<T>, std::complex<T>>
474  {
475  using type = std::complex<T>;
476  };
477 
478  template <typename T, typename U>
479  struct ProductTypeImpl<std::complex<T>, std::complex<U>>
480  {
481  using type = std::complex<typename ProductType<T, U>::type>;
482  };
483 
484  template <typename U>
485  struct ProductTypeImpl<double, std::complex<U>>
486  {
487  using type = std::complex<typename ProductType<double, U>::type>;
488  };
489 
490  template <typename T>
491  struct ProductTypeImpl<std::complex<T>, double>
492  {
493  using type = std::complex<typename ProductType<T, double>::type>;
494  };
495 
496  template <typename U>
497  struct ProductTypeImpl<float, std::complex<U>>
498  {
499  using type = std::complex<typename ProductType<float, U>::type>;
500  };
501 
502  template <typename T>
503  struct ProductTypeImpl<std::complex<T>, float>
504  {
505  using type = std::complex<typename ProductType<T, float>::type>;
506  };
507 
508 } // namespace internal
509 
510 
511 
567 template <typename T>
569 
570 
571 template <>
573 {
574  using type = double;
575 };
576 
577 template <>
578 struct EnableIfScalar<float>
579 {
580  using type = float;
581 };
582 
583 template <>
584 struct EnableIfScalar<long double>
585 {
586  using type = long double;
587 };
588 
589 template <>
590 struct EnableIfScalar<int>
591 {
592  using type = int;
593 };
594 
595 template <>
596 struct EnableIfScalar<unsigned int>
597 {
598  using type = unsigned int;
599 };
600 
601 template <typename T>
602 struct EnableIfScalar<std::complex<T>>
603 {
604  using type = std::complex<T>;
605 };
606 
607 
608 // Forward declarations of vector types
609 template <typename Number>
610 class Vector;
611 
612 template <typename Number>
613 class BlockVector;
614 
615 namespace LinearAlgebra
616 {
617  template <typename Number>
618  class Vector;
619 
620  template <typename Number>
621  class BlockVector;
622 
623  namespace distributed
624  {
625  template <typename Number, typename MemorySpace>
626  class Vector;
627 
628  template <typename Number>
629  class BlockVector;
630  } // namespace distributed
631 } // namespace LinearAlgebra
632 
633 #ifdef DEAL_II_WITH_PETSC
634 namespace PETScWrappers
635 {
636  class VectorBase;
637  class Vector;
638  class BlockVector;
639 
640  namespace MPI
641  {
642  class Vector;
643  class BlockVector;
644 
645  class SparseMatrix;
646  class BlockSparseMatrix;
647  } // namespace MPI
648 } // namespace PETScWrappers
649 #endif
650 
651 #ifdef DEAL_II_WITH_TRILINOS
653 {
654  namespace MPI
655  {
656  class Vector;
657  class BlockVector;
658  } // namespace MPI
659 } // namespace TrilinosWrappers
660 
661 namespace LinearAlgebra
662 {
663  namespace EpetraWrappers
664  {
665  class Vector;
666  }
667 
668 # ifdef DEAL_II_TRILINOS_WITH_TPETRA
669  namespace TpetraWrappers
670  {
671  template <typename Number>
672  class Vector;
673  }
674 # endif
675 } // namespace LinearAlgebra
676 #endif
677 
678 
679 
684 namespace concepts
685 {
686 #if defined(DEAL_II_HAVE_CXX20) || defined(DOXYGEN)
696  template <int dim, int spacedim>
698  (dim >= 1 && spacedim <= 3 && dim <= spacedim);
699 
700  namespace internal
701  {
708  template <typename T>
709  inline constexpr bool is_dealii_vector_type = false;
710 
711  template <typename Number>
712  inline constexpr bool is_dealii_vector_type<::Vector<Number>> = true;
713 
714  template <typename Number>
715  inline constexpr bool is_dealii_vector_type<::BlockVector<Number>> =
716  true;
717 
718  template <typename Number>
719  inline constexpr bool
720  is_dealii_vector_type<::LinearAlgebra::BlockVector<Number>> = true;
721 
722  template <typename Number, typename MemorySpace>
723  inline constexpr bool is_dealii_vector_type<
725 
726  template <typename Number>
727  inline constexpr bool is_dealii_vector_type<
729 
730 # ifdef DEAL_II_WITH_PETSC
731  template <>
732  inline constexpr bool is_dealii_vector_type<::PETScWrappers::Vector> =
733  true;
734 
735  template <>
736  inline constexpr bool
737  is_dealii_vector_type<::PETScWrappers::BlockVector> = true;
738 
739  template <>
740  inline constexpr bool
741  is_dealii_vector_type<::PETScWrappers::MPI::Vector> = true;
742 
743  template <>
744  inline constexpr bool
745  is_dealii_vector_type<::PETScWrappers::MPI::BlockVector> = true;
746 # endif
747 
748 # ifdef DEAL_II_WITH_TRILINOS
749  template <>
750  inline constexpr bool
751  is_dealii_vector_type<::TrilinosWrappers::MPI::Vector> = true;
752 
753  template <>
754  inline constexpr bool
755  is_dealii_vector_type<::TrilinosWrappers::MPI::BlockVector> = true;
756 
757  template <>
758  inline constexpr bool
759  is_dealii_vector_type<::LinearAlgebra::EpetraWrappers::Vector> =
760  true;
761 
762 # ifdef DEAL_II_TRILINOS_WITH_TPETRA
763  template <typename Number>
764  inline constexpr bool is_dealii_vector_type<
766 # endif
767 # endif
768 
769 
777  template <typename T>
778  inline constexpr bool is_dealii_petsc_vector_type = false;
779 
780 # ifdef DEAL_II_WITH_PETSC
781  template <>
782  inline constexpr bool
783  is_dealii_petsc_vector_type<::PETScWrappers::VectorBase> = true;
784 
785  template <>
786  inline constexpr bool
787  is_dealii_petsc_vector_type<::PETScWrappers::Vector> = true;
788 
789  template <>
790  inline constexpr bool
791  is_dealii_petsc_vector_type<::PETScWrappers::BlockVector> = true;
792 
793  template <>
794  inline constexpr bool
795  is_dealii_petsc_vector_type<::PETScWrappers::MPI::Vector> = true;
796 
797  template <>
798  inline constexpr bool
799  is_dealii_petsc_vector_type<::PETScWrappers::MPI::BlockVector> =
800  true;
801 # endif
802 
803 
811  template <typename T>
812  inline constexpr bool is_dealii_petsc_matrix_type = false;
813 
814 # ifdef DEAL_II_WITH_PETSC
815  template <>
816  inline constexpr bool
817  is_dealii_petsc_matrix_type<::PETScWrappers::MPI::SparseMatrix> =
818  true;
819 
820  template <>
821  inline constexpr bool is_dealii_petsc_matrix_type<
823 # endif
824  } // namespace internal
825 
826 
838  template <typename VectorType>
840  internal::is_dealii_vector_type<std::remove_cv_t<VectorType>>;
841 
851  template <typename VectorType>
853  is_dealii_vector_type<VectorType> && (std::is_const_v<VectorType> == false);
854 
863  template <typename VectorType>
865  internal::is_dealii_petsc_vector_type<VectorType>;
866 
875  template <typename VectorType>
877  internal::is_dealii_petsc_matrix_type<VectorType>;
878 #endif
879 } // namespace concepts
880 
881 
882 template <int dim, int spacedim>
883 DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
884 class Triangulation;
885 
886 template <int dim, int spacedim>
887 DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
888 class DoFHandler;
889 
890 namespace parallel
891 {
892  namespace distributed
893  {
894  template <int dim, int spacedim>
895  DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
896  class Triangulation;
897  }
898  namespace shared
899  {
900  template <int dim, int spacedim>
901  DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
902  class Triangulation;
903  }
904  namespace fullydistributed
905  {
906  template <int dim, int spacedim>
907  DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
908  class Triangulation;
909  }
910 } // namespace parallel
911 
912 namespace concepts
913 {
914 #if defined(DEAL_II_HAVE_CXX20) || defined(DOXYGEN)
915  namespace internal
916  {
917  template <typename T>
918  inline constexpr bool is_triangulation_or_dof_handler = false;
919 
920  template <int dim, int spacedim>
921  inline constexpr bool
922  is_triangulation_or_dof_handler<Triangulation<dim, spacedim>> = true;
923 
924  template <int dim, int spacedim>
925  inline constexpr bool is_triangulation_or_dof_handler<
927 
928  template <int dim, int spacedim>
929  inline constexpr bool is_triangulation_or_dof_handler<
931 
932  template <int dim, int spacedim>
933  inline constexpr bool is_triangulation_or_dof_handler<
935 
936  template <int dim, int spacedim>
937  inline constexpr bool
938  is_triangulation_or_dof_handler<DoFHandler<dim, spacedim>> = true;
939  } // namespace internal
940 
941 
949  template <typename MeshType>
951  internal::is_triangulation_or_dof_handler<MeshType>;
952 
959  template <typename VectorType>
960  concept is_vector_space_vector = requires(VectorType U,
961  VectorType V,
962  VectorType W,
963  typename VectorType::value_type a,
964  typename VectorType::value_type b,
965  typename VectorType::value_type s) {
966  // Check local type requirements:
967  typename VectorType::value_type;
968  typename VectorType::size_type;
969  typename VectorType::real_type;
970 
971  // Check some assignment and reinit operations;
972  U.reinit(V);
973  U.reinit(V, /* omit_zeroing_entries= */ true);
974 
975  U = V;
976  U = a; // assignment of scalar
977 
978  U.equ(a, V);
979 
980  // Check scaling operations
981  U *= a;
982  U /= a;
983 
984  U.scale(V);
985 
986  // Vector additions:
987  U += V;
988  U -= V;
989 
990  U.add(a);
991  U.add(a, V);
992  U.add(a, V, b, W);
993 
994  U.sadd(s, a, V);
995 
996  // Norms and similar stuff:
997  {
998  U.mean_value()
999  } -> std::convertible_to<typename VectorType::value_type>;
1000 
1001  {
1002  U.l1_norm()
1003  } -> std::convertible_to<typename VectorType::real_type>;
1004 
1005  {
1006  U.l2_norm()
1007  } -> std::convertible_to<typename VectorType::real_type>;
1008 
1009  {
1010  U.linfty_norm()
1011  } -> std::convertible_to<typename VectorType::real_type>;
1012 
1013  // Dot products:
1014  {
1015  U *V
1016  } -> std::convertible_to<typename VectorType::value_type>;
1017 
1018  {
1019  U.add_and_dot(a, V, W)
1020  } -> std::convertible_to<typename VectorType::value_type>;
1021 
1022  // Some queries:
1023  {
1024  U.size()
1025  } -> std::convertible_to<typename VectorType::size_type>;
1026 
1027  {
1028  U.all_zero()
1029  } -> std::same_as<bool>;
1030  };
1031 
1032 #endif
1033 
1034 } // namespace concepts
1035 
1036 
1037 
1039 
1040 #endif
Definition: vector.h:110
#define DEAL_II_DEPRECATED
Definition: config.h:178
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:477
#define DEAL_II_CXX20_REQUIRES(condition)
Definition: config.h:166
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:478
requires((concepts::is_dealii_petsc_vector_type< VectorType >||std::constructible_from< VectorType, Vec >) &&(concepts::is_dealii_petsc_matrix_type< PMatrixType >||std::constructible_from< PMatrixType, Mat >) &&(concepts::is_dealii_petsc_matrix_type< AMatrixType >||std::constructible_from< AMatrixType, Mat >)) class TimeStepper
Definition: petsc_ts.h:320
static const char U
static const char T
static const char V
types::global_dof_index size_type
Definition: cuda_kernels.h:45
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
VectorType::value_type * begin(VectorType &V)
VectorType::value_type * end(VectorType &V)
constexpr bool is_dealii_petsc_matrix_type
constexpr bool is_triangulation_or_dof_handler
constexpr bool is_dealii_petsc_vector_type
constexpr bool is_dealii_vector_type
concept is_writable_dealii_vector_type
concept is_triangulation_or_dof_handler
concept is_dealii_vector_type
concept is_dealii_petsc_vector_type
concept is_vector_space_vector
concept is_dealii_petsc_matrix_type
concept is_valid_dim_spacedim
typename detected_or< Default, Op, Args... >::type detected_or_t
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
typename detected_or< nonesuch, Op, Args... >::value_t is_detected
typename detected_or< nonesuch, Op, Args... >::type detected_t
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
constexpr bool is_supported_operation
static bool equal(const T *p1, const T *p2)
static bool equal(const T *, const U *)
typename internal::ProductTypeImpl< std::decay_t< T >, std::decay_t< U > >::type type
static constexpr bool value
ValueType operator()(const ArgType &)
std::complex< typename ProductType< double, U >::type > type
std::complex< typename ProductType< float, U >::type > type
std::complex< typename ProductType< T, double >::type > type
std::complex< typename ProductType< T, float >::type > type
std::complex< typename ProductType< T, U >::type > type
decltype(std::declval< T >() *std::declval< U >()) type
void operator=(const nonesuch &)=delete
nonesuch(const nonesuch &)=delete
static constexpr bool value
static constexpr bool value
typename enable_if_all< Values... >::type enable_if_all_t
decltype(std::begin(std::declval< T >()), std::end(std::declval< T >())) begin_and_end_t
constexpr bool has_begin_and_end