15#ifndef dealii_differentiation_ad_ad_number_traits_h
16#define dealii_differentiation_ad_ad_number_traits_h
25#include <boost/type_traits.hpp>
47 template <
typename ScalarType,
66 template <
typename ADNumberType,
typename T =
void>
106 template <
typename ScalarType,
141 template <
typename ADNumberType,
typename T =
void>
174 template <
typename ADNumberType,
typename T =
void>
190 template <
typename ADNumberTrait,
typename T =
void>
208 template <
typename T>
216 template <
typename Number>
228 template <
typename NumberType>
238 template <
typename NumberType,
typename =
void>
248 template <
typename NumberType,
typename =
void>
258 template <
typename NumberType,
typename =
void>
268 template <
typename NumberType,
typename =
void>
287 template <
typename ADNumberTrait,
typename>
288 struct HasRequiredADInfo : std::false_type
303 template <
typename ADNumberTrait>
304 struct HasRequiredADInfo<
306 decltype((void)ADNumberTrait::type_code,
307 (void)ADNumberTrait::is_taped,
308 (void)std::declval<typename ADNumberTrait::real_type>(),
309 (void)std::declval<typename ADNumberTrait::derivative_type>(),
311 : std::conditional_t<
312 std::is_floating_point_v<typename ADNumberTrait::real_type>,
322 template <
typename ScalarType>
323 struct ADNumberInfoFromEnum<
326 std::enable_if_t<std::is_floating_point_v<ScalarType>>>
328 static const bool is_taped =
false;
329 using real_type = ScalarType;
330 using derivative_type = ScalarType;
331 static const unsigned int n_supported_derivative_levels = 0;
340 template <
typename ScalarType>
341 struct Marking<ScalarType,
342 std::enable_if_t<std::is_floating_point_v<ScalarType>>>
351 template <
typename ADNumberType>
353 independent_variable(
const ScalarType &in,
364 template <
typename ADNumberType>
366 dependent_variable(ADNumberType &,
const ScalarType &)
371 "Floating point numbers cannot be marked as dependent variables."));
379 template <
typename ADNumberType>
380 struct Marking<ADNumberType,
381 std::enable_if_t<boost::is_complex<ADNumberType>::value>>
386 template <
typename ScalarType>
388 independent_variable(
const ScalarType &in,
396 "Marking for complex numbers has not yet been implemented."));
403 template <
typename ScalarType>
405 dependent_variable(ADNumberType &,
const ScalarType &)
410 "Marking for complex numbers has not yet been implemented."));
417 template <
typename NumberType,
typename>
418 struct is_taped_ad_number : std::false_type
422 template <
typename NumberType,
typename>
423 struct is_tapeless_ad_number : std::false_type
427 template <
typename NumberType,
typename>
428 struct is_real_valued_ad_number : std::false_type
432 template <
typename NumberType,
typename>
433 struct is_complex_valued_ad_number : std::false_type
442 template <
typename NumberType>
444 : internal::HasRequiredADInfo<ADNumberTraits<std::decay_t<NumberType>>>
452 template <
typename NumberType>
453 struct is_taped_ad_number<
455 std::enable_if_t<ADNumberTraits<std::decay_t<NumberType>>::is_taped>>
464 template <
typename NumberType>
465 struct is_tapeless_ad_number<
467 std::enable_if_t<ADNumberTraits<std::decay_t<NumberType>>::is_tapeless>>
477 template <
typename NumberType>
478 struct is_real_valued_ad_number<
481 ADNumberTraits<std::decay_t<NumberType>>::is_real_valued>>
491 template <
typename NumberType>
492 struct is_complex_valued_ad_number<
495 ADNumberTraits<std::decay_t<NumberType>>::is_complex_valued>>
506 template <
typename Number>
507 struct RemoveComplexWrapper
518 template <
typename Number>
519 struct RemoveComplexWrapper<
std::complex<Number>>
521 using type =
typename RemoveComplexWrapper<Number>::type;
530 template <
typename NumberType>
531 struct ExtractData<NumberType,
532 std::enable_if_t<std::is_floating_point_v<NumberType>>>
537 static const NumberType &
538 value(
const NumberType &x)
548 n_directional_derivatives(
const NumberType &)
558 directional_derivative(
const NumberType &,
const unsigned int)
570 template <
typename ADNumberType>
571 struct ExtractData<
std::complex<ADNumberType>>
574 "Expected an auto-differentiable number.");
580 static std::complex<typename ADNumberTraits<ADNumberType>::scalar_type>
581 value(
const std::complex<ADNumberType> &x)
584 typename ADNumberTraits<ADNumberType>::scalar_type>(
585 ExtractData<ADNumberType>::value(x.real()),
586 ExtractData<ADNumberType>::value(x.imag()));
594 n_directional_derivatives(
const std::complex<ADNumberType> &x)
596 return ExtractData<ADNumberType>::n_directional_derivatives(x.real());
604 typename ADNumberTraits<ADNumberType>::derivative_type>
605 directional_derivative(
const std::complex<ADNumberType> &x,
606 const unsigned int direction)
609 typename ADNumberTraits<ADNumberType>::derivative_type>(
610 ExtractData<ADNumberType>::directional_derivative(x.real(),
612 ExtractData<ADNumberType>::directional_derivative(x.imag(),
618 template <
typename T>
624 template <
typename F>
626 value(
const F &f, std::enable_if_t<!is_ad_number<F>::value> * =
nullptr)
631 return ::internal::NumberType<T>::value(f);
640 template <
typename F>
643 std::enable_if_t<is_ad_number<F>::value &&
644 std::is_floating_point_v<T>> * =
nullptr)
649 return NumberType<T>::value(ExtractData<F>::value(f));
658 template <
typename F>
661 std::enable_if_t<is_ad_number<F>::value && is_ad_number<T>::value>
668 template <
typename T>
669 struct NumberType<
std::complex<T>>
674 template <
typename F>
676 value(
const F &f, std::enable_if_t<!is_ad_number<F>::value> * =
nullptr)
681 return ::internal::NumberType<std::complex<T>>::value(f);
689 template <
typename F>
690 static std::complex<T>
692 std::enable_if_t<is_ad_number<F>::value &&
693 std::is_floating_point_v<T>> * =
nullptr)
698 return std::complex<T>(
699 NumberType<T>::value(ExtractData<F>::value(f)));
702 template <
typename F>
703 static std::complex<T>
704 value(
const std::complex<F> &f)
708 return std::complex<T>(NumberType<T>::value(f.real()),
709 NumberType<T>::value(f.imag()));
737 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
742 std::is_floating_point_v<ScalarType> ||
743 (boost::is_complex<ScalarType>::value &&
744 std::is_floating_point<
745 typename internal::RemoveComplexWrapper<ScalarType>::type>::value)>>
750 static constexpr enum NumberTypes type_code = ADNumberTypeCode;
764 static const bool is_taped;
771 static const bool is_tapeless;
778 static const bool is_real_valued;
785 static const bool is_complex_valued;
792 static const unsigned int n_supported_derivative_levels;
800 static constexpr bool is_taped = internal::ADNumberInfoFromEnum<
801 typename internal::RemoveComplexWrapper<ScalarType>::type,
802 ADNumberTypeCode>::is_taped;
809 static constexpr bool is_tapeless =
810 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
817 static constexpr bool is_real_valued =
818 (!boost::is_complex<ScalarType>::value);
825 static constexpr bool is_complex_valued =
826 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
833 static constexpr unsigned int n_supported_derivative_levels =
834 internal::ADNumberInfoFromEnum<
835 typename internal::RemoveComplexWrapper<ScalarType>::type,
836 ADNumberTypeCode>::n_supported_derivative_levels;
845 using scalar_type = ScalarType;
851 using real_type =
typename internal::ADNumberInfoFromEnum<
852 typename internal::RemoveComplexWrapper<ScalarType>::type,
853 ADNumberTypeCode>::real_type;
859 using complex_type = std::complex<real_type>;
865 using ad_type =
typename std::
866 conditional<is_real_valued, real_type, complex_type>::type;
871 using derivative_type = std::conditional_t<
873 typename internal::ADNumberInfoFromEnum<
874 typename internal::RemoveComplexWrapper<ScalarType>::type,
875 ADNumberTypeCode>::derivative_type,
876 std::complex<
typename internal::ADNumberInfoFromEnum<
877 typename internal::RemoveComplexWrapper<ScalarType>::type,
878 ADNumberTypeCode>::derivative_type>>;
884 static scalar_type get_scalar_value(
const ad_type &x)
893 internal::ExtractData<ad_type>::value(x));
900 static derivative_type get_directional_derivative(
901 const ad_type &x,
const unsigned int direction)
903 return internal::ExtractData<ad_type>::directional_derivative(
912 static unsigned int n_directional_derivatives(
const ad_type &x)
914 return internal::ExtractData<ad_type>::n_directional_derivatives(x);
918 static_assert((is_real_valued ==
true ?
919 std::is_same_v<ad_type, real_type> :
920 std::is_same_v<ad_type, complex_type>),
921 "Incorrect template type selected for ad_type");
923 static_assert((is_complex_valued ==
true ?
924 boost::is_complex<scalar_type>::value :
926 "Expected a complex float_type");
928 static_assert((is_complex_valued ==
true ?
929 boost::is_complex<ad_type>::value :
931 "Expected a complex ad_type");
936 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
937 const bool NumberTraits<
941 std::is_floating_point_v<ScalarType> ||
942 (boost::is_complex<ScalarType>::value &&
943 std::is_floating_point<
typename internal::RemoveComplexWrapper<
944 ScalarType>::type>::value)>>::is_taped =
945 internal::ADNumberInfoFromEnum<
946 typename internal::RemoveComplexWrapper<ScalarType>::type,
947 ADNumberTypeCode>::is_taped;
950 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
951 const bool NumberTraits<
955 std::is_floating_point_v<ScalarType> ||
956 (boost::is_complex<ScalarType>::value &&
957 std::is_floating_point<
typename internal::RemoveComplexWrapper<
958 ScalarType>::type>::value)>>::is_tapeless =
959 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
962 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
963 const bool NumberTraits<
967 std::is_floating_point_v<ScalarType> ||
968 (boost::is_complex<ScalarType>::value &&
969 std::is_floating_point<
typename internal::RemoveComplexWrapper<
970 ScalarType>::type>::value)>>::is_real_valued =
971 (!boost::is_complex<ScalarType>::value);
974 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
975 const bool NumberTraits<
979 std::is_floating_point_v<ScalarType> ||
980 (boost::is_complex<ScalarType>::value &&
981 std::is_floating_point<
typename internal::RemoveComplexWrapper<
982 ScalarType>::type>::value)>>::is_complex_valued =
983 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
986 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
987 const unsigned int NumberTraits<
991 std::is_floating_point_v<ScalarType> ||
992 (boost::is_complex<ScalarType>::value &&
993 std::is_floating_point<
typename internal::RemoveComplexWrapper<
994 ScalarType>::type>::value)>>::n_supported_derivative_levels =
995 internal::ADNumberInfoFromEnum<
996 typename internal::RemoveComplexWrapper<ScalarType>::type,
997 ADNumberTypeCode>::n_supported_derivative_levels;
1001 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1002 constexpr bool NumberTraits<
1006 std::is_floating_point_v<ScalarType> ||
1007 (boost::is_complex<ScalarType>::value &&
1008 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1009 ScalarType>::type>::value)>>::is_taped;
1012 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1013 constexpr bool NumberTraits<
1017 std::is_floating_point_v<ScalarType> ||
1018 (boost::is_complex<ScalarType>::value &&
1019 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1020 ScalarType>::type>::value)>>::is_tapeless;
1023 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1024 constexpr bool NumberTraits<
1028 std::is_floating_point_v<ScalarType> ||
1029 (boost::is_complex<ScalarType>::value &&
1030 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1031 ScalarType>::type>::value)>>::is_real_valued;
1034 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1035 constexpr bool NumberTraits<
1039 std::is_floating_point_v<ScalarType> ||
1040 (boost::is_complex<ScalarType>::value &&
1041 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1042 ScalarType>::type>::value)>>::is_complex_valued;
1045 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1046 constexpr unsigned int NumberTraits<
1050 std::is_floating_point_v<ScalarType> ||
1051 (boost::is_complex<ScalarType>::value &&
1052 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1053 ScalarType>::type>::value)>>::n_supported_derivative_levels;
1068 template <
typename ScalarType>
1069 struct NumberTraits<
1073 std::is_floating_point_v<ScalarType> ||
1074 (boost::is_complex<ScalarType>::value &&
1075 std::is_floating_point<
1076 typename internal::RemoveComplexWrapper<ScalarType>::type>::value)>>
1095 static const bool is_taped;
1102 static const bool is_tapeless;
1109 static const bool is_real_valued;
1116 static const bool is_complex_valued;
1123 static const unsigned int n_supported_derivative_levels;
1131 static constexpr bool is_taped =
false;
1138 static constexpr bool is_tapeless =
false;
1145 static constexpr bool is_real_valued =
1146 (!boost::is_complex<ScalarType>::value);
1153 static constexpr bool is_complex_valued = !is_real_valued;
1160 static constexpr unsigned int n_supported_derivative_levels = 0;
1169 using scalar_type = ScalarType;
1176 typename ::numbers::NumberTraits<scalar_type>::real_type;
1182 using complex_type = std::complex<real_type>;
1188 using ad_type = ScalarType;
1193 using derivative_type = ScalarType;
1200 get_scalar_value(
const ad_type &x)
1209 static derivative_type
1210 get_directional_derivative(
const ad_type &,
const unsigned int)
1215 "Floating point/arithmetic numbers have no directional derivatives."));
1216 return derivative_type();
1225 n_directional_derivatives(
const ad_type &)
1230 "Floating point/arithmetic numbers have no directional derivatives."));
1237 template <
typename ScalarType>
1238 const bool NumberTraits<
1242 std::is_floating_point_v<ScalarType> ||
1243 (boost::is_complex<ScalarType>::value &&
1244 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1245 ScalarType>::type>::value)>>::is_taped =
false;
1248 template <
typename ScalarType>
1249 const bool NumberTraits<
1253 std::is_floating_point_v<ScalarType> ||
1254 (boost::is_complex<ScalarType>::value &&
1255 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1256 ScalarType>::type>::value)>>::is_tapeless =
false;
1259 template <
typename ScalarType>
1260 const bool NumberTraits<
1264 std::is_floating_point_v<ScalarType> ||
1265 (boost::is_complex<ScalarType>::value &&
1266 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1267 ScalarType>::type>::value)>>::is_real_valued =
1268 (!boost::is_complex<ScalarType>::value);
1271 template <
typename ScalarType>
1272 const bool NumberTraits<
1276 std::is_floating_point_v<ScalarType> ||
1277 (boost::is_complex<ScalarType>::value &&
1278 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1279 ScalarType>::type>::value)>>::is_complex_valued =
1280 !(NumberTraits<ScalarType, NumberTypes::none>::is_real_valued);
1283 template <
typename ScalarType>
1284 const unsigned int NumberTraits<
1288 std::is_floating_point_v<ScalarType> ||
1289 (boost::is_complex<ScalarType>::value &&
1290 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1291 ScalarType>::type>::value)>>::n_supported_derivative_levels = 0;
1295 template <
typename ScalarType>
1296 constexpr bool NumberTraits<
1300 std::is_floating_point_v<ScalarType> ||
1301 (boost::is_complex<ScalarType>::value &&
1302 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1303 ScalarType>::type>::value)>>::is_taped;
1306 template <
typename ScalarType>
1307 constexpr bool NumberTraits<
1311 std::is_floating_point_v<ScalarType> ||
1312 (boost::is_complex<ScalarType>::value &&
1313 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1314 ScalarType>::type>::value)>>::is_tapeless;
1317 template <
typename ScalarType>
1318 constexpr bool NumberTraits<
1322 std::is_floating_point_v<ScalarType> ||
1323 (boost::is_complex<ScalarType>::value &&
1324 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1325 ScalarType>::type>::value)>>::is_real_valued;
1328 template <
typename ScalarType>
1329 constexpr bool NumberTraits<
1333 std::is_floating_point_v<ScalarType> ||
1334 (boost::is_complex<ScalarType>::value &&
1335 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1336 ScalarType>::type>::value)>>::is_complex_valued;
1339 template <
typename ScalarType>
1340 constexpr unsigned int NumberTraits<
1344 std::is_floating_point_v<ScalarType> ||
1345 (boost::is_complex<ScalarType>::value &&
1346 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1347 ScalarType>::type>::value)>>::n_supported_derivative_levels;
1370 template <
typename ScalarType>
1371 struct ADNumberTraits<
1373 std::enable_if_t<std::is_floating_point_v<ScalarType>>>
1374 : NumberTraits<ScalarType, NumberTypes::none>
1380 template <
typename ComplexScalarType>
1381 struct ADNumberTraits<
1384 boost::is_complex<ComplexScalarType>::value &&
1385 std::is_floating_point_v<typename ComplexScalarType::value_type>>>
1386 : NumberTraits<ComplexScalarType, NumberTypes::none>
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE const T & value(const T &t)