16#ifndef dealii_differentiation_ad_ad_number_traits_h
17#define dealii_differentiation_ad_ad_number_traits_h
26#include <boost/type_traits.hpp>
48 template <
typename ScalarType,
67 template <
typename ADNumberType,
typename T =
void>
107 template <
typename ScalarType,
142 template <
typename ADNumberType,
typename T =
void>
175 template <
typename ADNumberType,
typename T =
void>
191 template <
typename ADNumberTrait,
typename T =
void>
209 template <
typename T>
217 template <
typename Number>
229 template <
typename NumberType>
239 template <
typename NumberType,
typename =
void>
249 template <
typename NumberType,
typename =
void>
259 template <
typename NumberType,
typename =
void>
269 template <
typename NumberType,
typename =
void>
288 template <
typename ADNumberTrait,
typename>
289 struct HasRequiredADInfo : std::false_type
304 template <
typename ADNumberTrait>
305 struct HasRequiredADInfo<
307 decltype((void)ADNumberTrait::type_code,
308 (void)ADNumberTrait::is_taped,
309 (void)std::declval<typename ADNumberTrait::real_type>(),
310 (void)std::declval<typename ADNumberTrait::derivative_type>(),
313 std::is_floating_point<typename ADNumberTrait::real_type>::value,
315 std::true_type>::type
323 template <
typename ScalarType>
324 struct ADNumberInfoFromEnum<
327 typename std::enable_if<
328 std::is_floating_point<ScalarType>::value>::type>
330 static const bool is_taped =
false;
331 using real_type = ScalarType;
332 using derivative_type = ScalarType;
333 static const unsigned int n_supported_derivative_levels = 0;
342 template <
typename ScalarType>
343 struct Marking<ScalarType,
344 typename
std::enable_if<
345 std::is_floating_point<ScalarType>::value>::type>
354 template <
typename ADNumberType>
356 independent_variable(
const ScalarType &in,
367 template <
typename ADNumberType>
369 dependent_variable(ADNumberType &,
const ScalarType &)
374 "Floating point numbers cannot be marked as dependent variables."));
382 template <
typename ADNumberType>
385 typename
std::enable_if<boost::is_complex<ADNumberType>::value>::type>
390 template <
typename ScalarType>
392 independent_variable(
const ScalarType &in,
400 "Marking for complex numbers has not yet been implemented."));
407 template <
typename ScalarType>
409 dependent_variable(ADNumberType &,
const ScalarType &)
414 "Marking for complex numbers has not yet been implemented."));
421 template <
typename NumberType,
typename>
422 struct is_taped_ad_number : std::false_type
426 template <
typename NumberType,
typename>
427 struct is_tapeless_ad_number : std::false_type
431 template <
typename NumberType,
typename>
432 struct is_real_valued_ad_number : std::false_type
436 template <
typename NumberType,
typename>
437 struct is_complex_valued_ad_number : std::false_type
446 template <
typename NumberType>
448 : internal::HasRequiredADInfo<
449 ADNumberTraits<typename std::decay<NumberType>::type>>
457 template <
typename NumberType>
458 struct is_taped_ad_number<
460 typename
std::enable_if<
461 ADNumberTraits<typename std::decay<NumberType>::type>::is_taped>::type>
470 template <
typename NumberType>
471 struct is_tapeless_ad_number<
473 typename
std::enable_if<ADNumberTraits<
474 typename std::decay<NumberType>::type>::is_tapeless>::type>
484 template <
typename NumberType>
485 struct is_real_valued_ad_number<
487 typename
std::enable_if<ADNumberTraits<
488 typename std::decay<NumberType>::type>::is_real_valued>::type>
498 template <
typename NumberType>
499 struct is_complex_valued_ad_number<
501 typename
std::enable_if<ADNumberTraits<
502 typename std::decay<NumberType>::type>::is_complex_valued>::type>
513 template <
typename Number>
514 struct RemoveComplexWrapper
525 template <
typename Number>
526 struct RemoveComplexWrapper<
std::complex<Number>>
528 using type =
typename RemoveComplexWrapper<Number>::type;
537 template <
typename NumberType>
538 struct ExtractData<NumberType,
539 typename
std::enable_if<
540 std::is_floating_point<NumberType>::value>::type>
545 static const NumberType &
546 value(
const NumberType &x)
556 n_directional_derivatives(
const NumberType &)
566 directional_derivative(
const NumberType &,
const unsigned int)
578 template <
typename ADNumberType>
579 struct ExtractData<
std::complex<ADNumberType>>
582 "Expected an auto-differentiable number.");
588 static std::complex<typename ADNumberTraits<ADNumberType>::scalar_type>
589 value(
const std::complex<ADNumberType> &x)
592 typename ADNumberTraits<ADNumberType>::scalar_type>(
593 ExtractData<ADNumberType>::value(x.real()),
594 ExtractData<ADNumberType>::value(x.imag()));
602 n_directional_derivatives(
const std::complex<ADNumberType> &x)
604 return ExtractData<ADNumberType>::n_directional_derivatives(x.real());
612 typename ADNumberTraits<ADNumberType>::derivative_type>
613 directional_derivative(
const std::complex<ADNumberType> &x,
614 const unsigned int direction)
617 typename ADNumberTraits<ADNumberType>::derivative_type>(
618 ExtractData<ADNumberType>::directional_derivative(x.real(),
620 ExtractData<ADNumberType>::directional_derivative(x.imag(),
626 template <
typename T>
632 template <
typename F>
635 typename std::enable_if<!is_ad_number<F>::value>::type * =
640 return ::internal::NumberType<T>::value(f);
649 template <
typename F>
652 typename std::enable_if<is_ad_number<F>::value &&
653 std::is_floating_point<T>::value>::type
659 return NumberType<T>::value(ExtractData<F>::value(f));
668 template <
typename F>
671 typename std::enable_if<is_ad_number<F>::value &&
672 is_ad_number<T>::value>::type * =
nullptr)
678 template <
typename T>
679 struct NumberType<
std::complex<T>>
684 template <
typename F>
688 typename std::enable_if<!is_ad_number<F>::value>::type * =
nullptr)
693 return ::internal::NumberType<std::complex<T>>::value(f);
701 template <
typename F>
702 static std::complex<T>
704 typename std::enable_if<is_ad_number<F>::value &&
705 std::is_floating_point<T>::value>::type
711 return std::complex<T>(
712 NumberType<T>::value(ExtractData<F>::value(f)));
715 template <
typename F>
716 static std::complex<T>
717 value(
const std::complex<F> &f)
721 return std::complex<T>(NumberType<T>::value(f.real()),
722 NumberType<T>::value(f.imag()));
750 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
754 typename
std::enable_if<
755 std::is_floating_point<ScalarType>::value ||
756 (boost::is_complex<ScalarType>::value &&
757 std::is_floating_point<typename internal::RemoveComplexWrapper<
758 ScalarType>::type>::value)>::type>
763 static constexpr enum NumberTypes type_code = ADNumberTypeCode;
777 static const bool is_taped;
784 static const bool is_tapeless;
791 static const bool is_real_valued;
798 static const bool is_complex_valued;
805 static const unsigned int n_supported_derivative_levels;
813 static constexpr bool is_taped = internal::ADNumberInfoFromEnum<
814 typename internal::RemoveComplexWrapper<ScalarType>::type,
815 ADNumberTypeCode>::is_taped;
822 static constexpr bool is_tapeless =
823 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
830 static constexpr bool is_real_valued =
831 (!boost::is_complex<ScalarType>::value);
838 static constexpr bool is_complex_valued =
839 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
846 static constexpr unsigned int n_supported_derivative_levels =
847 internal::ADNumberInfoFromEnum<
848 typename internal::RemoveComplexWrapper<ScalarType>::type,
849 ADNumberTypeCode>::n_supported_derivative_levels;
858 using scalar_type = ScalarType;
864 using real_type =
typename internal::ADNumberInfoFromEnum<
865 typename internal::RemoveComplexWrapper<ScalarType>::type,
866 ADNumberTypeCode>::real_type;
872 using complex_type = std::complex<real_type>;
878 using ad_type =
typename std::
879 conditional<is_real_valued, real_type, complex_type>::type;
884 using derivative_type =
typename std::conditional<
886 typename internal::ADNumberInfoFromEnum<
887 typename internal::RemoveComplexWrapper<ScalarType>::type,
888 ADNumberTypeCode>::derivative_type,
889 std::complex<
typename internal::ADNumberInfoFromEnum<
890 typename internal::RemoveComplexWrapper<ScalarType>::type,
891 ADNumberTypeCode>::derivative_type>>::type;
897 static scalar_type get_scalar_value(
const ad_type &x)
906 internal::ExtractData<ad_type>::value(x));
913 static derivative_type get_directional_derivative(
914 const ad_type &x,
const unsigned int direction)
916 return internal::ExtractData<ad_type>::directional_derivative(
925 static unsigned int n_directional_derivatives(
const ad_type &x)
927 return internal::ExtractData<ad_type>::n_directional_derivatives(x);
931 static_assert((is_real_valued ==
true ?
932 std::is_same<ad_type, real_type>::value :
933 std::is_same<ad_type, complex_type>::value),
934 "Incorrect template type selected for ad_type");
936 static_assert((is_complex_valued ==
true ?
937 boost::is_complex<scalar_type>::value :
939 "Expected a complex float_type");
941 static_assert((is_complex_valued ==
true ?
942 boost::is_complex<ad_type>::value :
944 "Expected a complex ad_type");
949 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
950 const bool NumberTraits<
953 typename std::enable_if<
954 std::is_floating_point<ScalarType>::value ||
955 (boost::is_complex<ScalarType>::value &&
956 std::is_floating_point<
typename internal::RemoveComplexWrapper<
957 ScalarType>::type>::value)>::type>::is_taped =
958 internal::ADNumberInfoFromEnum<
959 typename internal::RemoveComplexWrapper<ScalarType>::type,
960 ADNumberTypeCode>::is_taped;
963 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
964 const bool NumberTraits<
967 typename std::enable_if<
968 std::is_floating_point<ScalarType>::value ||
969 (boost::is_complex<ScalarType>::value &&
970 std::is_floating_point<
typename internal::RemoveComplexWrapper<
971 ScalarType>::type>::value)>::type>::is_tapeless =
972 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
975 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
976 const bool NumberTraits<
979 typename std::enable_if<
980 std::is_floating_point<ScalarType>::value ||
981 (boost::is_complex<ScalarType>::value &&
982 std::is_floating_point<
typename internal::RemoveComplexWrapper<
983 ScalarType>::type>::value)>::type>::is_real_valued =
984 (!boost::is_complex<ScalarType>::value);
987 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
988 const bool NumberTraits<
991 typename std::enable_if<
992 std::is_floating_point<ScalarType>::value ||
993 (boost::is_complex<ScalarType>::value &&
994 std::is_floating_point<
typename internal::RemoveComplexWrapper<
995 ScalarType>::type>::value)>::type>::is_complex_valued =
996 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
999 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1000 const unsigned int NumberTraits<
1003 typename std::enable_if<
1004 std::is_floating_point<ScalarType>::value ||
1005 (boost::is_complex<ScalarType>::value &&
1006 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1007 ScalarType>::type>::value)>::type>::n_supported_derivative_levels =
1008 internal::ADNumberInfoFromEnum<
1009 typename internal::RemoveComplexWrapper<ScalarType>::type,
1010 ADNumberTypeCode>::n_supported_derivative_levels;
1014 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1015 constexpr bool NumberTraits<
1018 typename std::enable_if<
1019 std::is_floating_point<ScalarType>::value ||
1020 (boost::is_complex<ScalarType>::value &&
1021 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1022 ScalarType>::type>::value)>::type>::is_taped;
1025 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1026 constexpr bool NumberTraits<
1029 typename std::enable_if<
1030 std::is_floating_point<ScalarType>::value ||
1031 (boost::is_complex<ScalarType>::value &&
1032 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1033 ScalarType>::type>::value)>::type>::is_tapeless;
1036 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1037 constexpr bool NumberTraits<
1040 typename std::enable_if<
1041 std::is_floating_point<ScalarType>::value ||
1042 (boost::is_complex<ScalarType>::value &&
1043 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1044 ScalarType>::type>::value)>::type>::is_real_valued;
1047 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1048 constexpr bool NumberTraits<
1051 typename std::enable_if<
1052 std::is_floating_point<ScalarType>::value ||
1053 (boost::is_complex<ScalarType>::value &&
1054 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1055 ScalarType>::type>::value)>::type>::is_complex_valued;
1058 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1059 constexpr unsigned int NumberTraits<
1062 typename std::enable_if<
1063 std::is_floating_point<ScalarType>::value ||
1064 (boost::is_complex<ScalarType>::value &&
1065 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1066 ScalarType>::type>::value)>::type>::n_supported_derivative_levels;
1081 template <
typename ScalarType>
1082 struct NumberTraits<
1085 typename std::enable_if<
1086 std::is_floating_point<ScalarType>::value ||
1087 (boost::is_complex<ScalarType>::value &&
1088 std::is_floating_point<typename internal::RemoveComplexWrapper<
1089 ScalarType>::type>::value)>::type>
1108 static const bool is_taped;
1115 static const bool is_tapeless;
1122 static const bool is_real_valued;
1129 static const bool is_complex_valued;
1136 static const unsigned int n_supported_derivative_levels;
1144 static constexpr bool is_taped =
false;
1151 static constexpr bool is_tapeless =
false;
1158 static constexpr bool is_real_valued =
1159 (!boost::is_complex<ScalarType>::value);
1166 static constexpr bool is_complex_valued = !is_real_valued;
1173 static constexpr unsigned int n_supported_derivative_levels = 0;
1182 using scalar_type = ScalarType;
1189 typename ::numbers::NumberTraits<scalar_type>::real_type;
1195 using complex_type = std::complex<real_type>;
1201 using ad_type = ScalarType;
1206 using derivative_type = ScalarType;
1213 get_scalar_value(
const ad_type &x)
1222 static derivative_type
1223 get_directional_derivative(
const ad_type &,
const unsigned int)
1228 "Floating point/arithmetic numbers have no directional derivatives."));
1229 return derivative_type();
1238 n_directional_derivatives(
const ad_type &)
1243 "Floating point/arithmetic numbers have no directional derivatives."));
1250 template <
typename ScalarType>
1251 const bool NumberTraits<
1254 typename std::enable_if<
1255 std::is_floating_point<ScalarType>::value ||
1256 (boost::is_complex<ScalarType>::value &&
1257 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1258 ScalarType>::type>::value)>::type>::is_taped =
false;
1261 template <
typename ScalarType>
1262 const bool NumberTraits<
1265 typename std::enable_if<
1266 std::is_floating_point<ScalarType>::value ||
1267 (boost::is_complex<ScalarType>::value &&
1268 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1269 ScalarType>::type>::value)>::type>::is_tapeless =
false;
1272 template <
typename ScalarType>
1273 const bool NumberTraits<
1276 typename std::enable_if<
1277 std::is_floating_point<ScalarType>::value ||
1278 (boost::is_complex<ScalarType>::value &&
1279 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1280 ScalarType>::type>::value)>::type>::is_real_valued =
1281 (!boost::is_complex<ScalarType>::value);
1284 template <
typename ScalarType>
1285 const bool NumberTraits<
1288 typename std::enable_if<
1289 std::is_floating_point<ScalarType>::value ||
1290 (boost::is_complex<ScalarType>::value &&
1291 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1292 ScalarType>::type>::value)>::type>::is_complex_valued =
1293 !(NumberTraits<ScalarType, NumberTypes::none>::is_real_valued);
1296 template <
typename ScalarType>
1297 const unsigned int NumberTraits<
1300 typename std::enable_if<
1301 std::is_floating_point<ScalarType>::value ||
1302 (boost::is_complex<ScalarType>::value &&
1303 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1304 ScalarType>::type>::value)>::type>::n_supported_derivative_levels =
1309 template <
typename ScalarType>
1310 constexpr bool NumberTraits<
1313 typename std::enable_if<
1314 std::is_floating_point<ScalarType>::value ||
1315 (boost::is_complex<ScalarType>::value &&
1316 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1317 ScalarType>::type>::value)>::type>::is_taped;
1320 template <
typename ScalarType>
1321 constexpr bool NumberTraits<
1324 typename std::enable_if<
1325 std::is_floating_point<ScalarType>::value ||
1326 (boost::is_complex<ScalarType>::value &&
1327 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1328 ScalarType>::type>::value)>::type>::is_tapeless;
1331 template <
typename ScalarType>
1332 constexpr bool NumberTraits<
1335 typename std::enable_if<
1336 std::is_floating_point<ScalarType>::value ||
1337 (boost::is_complex<ScalarType>::value &&
1338 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1339 ScalarType>::type>::value)>::type>::is_real_valued;
1342 template <
typename ScalarType>
1343 constexpr bool NumberTraits<
1346 typename std::enable_if<
1347 std::is_floating_point<ScalarType>::value ||
1348 (boost::is_complex<ScalarType>::value &&
1349 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1350 ScalarType>::type>::value)>::type>::is_complex_valued;
1353 template <
typename ScalarType>
1354 constexpr unsigned int NumberTraits<
1357 typename std::enable_if<
1358 std::is_floating_point<ScalarType>::value ||
1359 (boost::is_complex<ScalarType>::value &&
1360 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1361 ScalarType>::type>::value)>::type>::n_supported_derivative_levels;
1384 template <
typename ScalarType>
1385 struct ADNumberTraits<
1387 typename
std::enable_if<std::is_floating_point<ScalarType>::value>::type>
1388 : NumberTraits<ScalarType, NumberTypes::none>
1394 template <
typename ComplexScalarType>
1395 struct ADNumberTraits<
1397 typename
std::enable_if<
1398 boost::is_complex<ComplexScalarType>::value &&
1399 std::is_floating_point<typename ComplexScalarType::value_type>::value>::
1400 type> : 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)
Tensor< 2, dim, Number > F(const Tensor< 2, dim, Number > &Grad_u)
static constexpr const T & value(const T &t)