16 #ifndef dealii_differentiation_ad_ad_number_traits_h 17 #define dealii_differentiation_ad_ad_number_traits_h 19 #include <deal.II/base/exceptions.h> 20 #include <deal.II/base/numbers.h> 22 #include <deal.II/differentiation/ad/ad_number_types.h> 24 #include <boost/type_traits.hpp> 27 #include <type_traits> 29 DEAL_II_NAMESPACE_OPEN
48 template <
typename ScalarType,
69 template <
typename ADNumberType,
typename T =
void>
111 template <
typename ScalarType,
148 template <
typename ADNumberType,
typename T =
void>
183 template <
typename ADNumberType,
typename T =
void>
201 template <
typename ADNumberTrait,
typename T =
void>
221 template <
typename T>
231 template <
typename Number>
245 template <
typename NumberType>
257 template <
typename NumberType,
typename =
void>
269 template <
typename NumberType,
typename =
void>
281 template <
typename NumberType,
typename =
void>
293 template <
typename NumberType,
typename =
void>
312 template <
typename ADNumberTrait,
typename>
313 struct HasRequiredADInfo : std::false_type
328 template <
typename ADNumberTrait>
329 struct HasRequiredADInfo<
331 decltype((void)ADNumberTrait::type_code,
332 (void)ADNumberTrait::is_taped,
333 (void)std::declval<typename ADNumberTrait::real_type>(),
334 (void)std::declval<typename ADNumberTrait::derivative_type>(),
337 std::is_floating_point<typename ADNumberTrait::real_type>::value,
339 std::true_type>::type
347 template <
typename ScalarType>
348 struct ADNumberInfoFromEnum<
351 typename std::enable_if<
352 std::is_floating_point<ScalarType>::value>::type>
354 static const bool is_taped =
false;
355 using real_type = ScalarType;
356 using derivative_type = ScalarType;
357 static const unsigned int n_supported_derivative_levels = 0;
366 template <
typename ScalarType>
367 struct Marking<ScalarType,
368 typename
std::enable_if<
369 std::is_floating_point<ScalarType>::value>::type>
378 template <
typename ADNumberType>
380 independent_variable(
const ScalarType &in,
391 template <
typename ADNumberType>
393 dependent_variable(ADNumberType &,
const ScalarType &)
398 "Floating point numbers cannot be marked as dependent variables."));
406 template <
typename ADNumberType>
409 typename
std::enable_if<boost::is_complex<ADNumberType>::value>::type>
414 template <
typename ScalarType>
416 independent_variable(
const ScalarType &in,
424 "Marking for complex numbers has not yet been implemented."));
431 template <
typename ScalarType>
433 dependent_variable(ADNumberType &,
const ScalarType &)
438 "Marking for complex numbers has not yet been implemented."));
445 template <
typename NumberType,
typename>
446 struct is_taped_ad_number : std::false_type
450 template <
typename NumberType,
typename>
451 struct is_tapeless_ad_number : std::false_type
455 template <
typename NumberType,
typename>
456 struct is_real_valued_ad_number : std::false_type
460 template <
typename NumberType,
typename>
461 struct is_complex_valued_ad_number : std::false_type
470 template <
typename NumberType>
472 : internal::HasRequiredADInfo<
473 ADNumberTraits<typename std::decay<NumberType>::type>>
481 template <
typename NumberType>
482 struct is_taped_ad_number<
484 typename
std::enable_if<
485 ADNumberTraits<typename std::decay<NumberType>::type>::is_taped>::type>
494 template <
typename NumberType>
495 struct is_tapeless_ad_number<
497 typename
std::enable_if<ADNumberTraits<
498 typename std::decay<NumberType>::type>::is_tapeless>::type>
508 template <
typename NumberType>
509 struct is_real_valued_ad_number<
511 typename
std::enable_if<ADNumberTraits<
512 typename std::decay<NumberType>::type>::is_real_valued>::type>
522 template <
typename NumberType>
523 struct is_complex_valued_ad_number<
525 typename
std::enable_if<ADNumberTraits<
526 typename std::decay<NumberType>::type>::is_complex_valued>::type>
537 template <
typename Number>
538 struct RemoveComplexWrapper
549 template <
typename Number>
550 struct RemoveComplexWrapper<
std::complex<Number>>
552 using type =
typename RemoveComplexWrapper<Number>::type;
561 template <
typename NumberType>
562 struct ExtractData<NumberType,
563 typename
std::enable_if<
564 std::is_floating_point<NumberType>::value>::type>
569 static const NumberType &
570 value(
const NumberType &x)
580 n_directional_derivatives(
const NumberType &)
590 directional_derivative(
const NumberType &,
const unsigned int)
602 template <
typename ADNumberType>
603 struct ExtractData<
std::complex<ADNumberType>>
606 "Expected an auto-differentiable number.");
612 static std::complex<typename ADNumberTraits<ADNumberType>::scalar_type>
613 value(
const std::complex<ADNumberType> &x)
616 typename ADNumberTraits<ADNumberType>::scalar_type>(
617 ExtractData<ADNumberType>::value(x.real()),
618 ExtractData<ADNumberType>::value(x.imag()));
626 n_directional_derivatives(
const std::complex<ADNumberType> &x)
628 return ExtractData<ADNumberType>::n_directional_derivatives(x.real());
636 typename ADNumberTraits<ADNumberType>::derivative_type>
637 directional_derivative(
const std::complex<ADNumberType> &x,
638 const unsigned int direction)
641 typename ADNumberTraits<ADNumberType>::derivative_type>(
642 ExtractData<ADNumberType>::directional_derivative(x.real(),
644 ExtractData<ADNumberType>::directional_derivative(x.imag(),
650 template <
typename T>
656 template <
typename F>
659 typename std::enable_if<!is_ad_number<F>::value>::type * =
664 return ::internal::NumberType<T>::value(f);
673 template <
typename F>
676 typename std::enable_if<is_ad_number<F>::value &&
677 std::is_floating_point<T>::value>::type
683 return NumberType<T>::value(ExtractData<F>::value(f));
692 template <
typename F>
695 typename std::enable_if<is_ad_number<F>::value &&
696 is_ad_number<T>::value>::type * =
nullptr)
702 template <
typename T>
703 struct NumberType<
std::complex<T>>
708 template <
typename F>
712 typename std::enable_if<!is_ad_number<F>::value>::type * =
nullptr)
717 return ::internal::NumberType<std::complex<T>>::value(f);
725 template <
typename F>
726 static std::complex<T>
728 typename std::enable_if<is_ad_number<F>::value &&
729 std::is_floating_point<T>::value>::type
735 return std::complex<T>(
736 NumberType<T>::value(ExtractData<F>::value(f)));
739 template <
typename F>
740 static std::complex<T>
741 value(
const std::complex<F> &f)
745 return std::complex<T>(NumberType<T>::value(f.real()),
746 NumberType<T>::value(f.imag()));
774 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
778 typename
std::enable_if<
779 std::is_floating_point<ScalarType>::value ||
780 (boost::is_complex<ScalarType>::value &&
781 std::is_floating_point<typename internal::RemoveComplexWrapper<
782 ScalarType>::type>::value)>::type>
787 static constexpr
enum NumberTypes type_code = ADNumberTypeCode;
801 static const bool is_taped;
808 static const bool is_tapeless;
815 static const bool is_real_valued;
822 static const bool is_complex_valued;
829 static const unsigned int n_supported_derivative_levels;
837 static constexpr
bool is_taped = internal::ADNumberInfoFromEnum<
838 typename internal::RemoveComplexWrapper<ScalarType>::type,
839 ADNumberTypeCode>::is_taped;
846 static constexpr
bool is_tapeless =
847 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
854 static constexpr
bool is_real_valued =
855 (!boost::is_complex<ScalarType>::value);
862 static constexpr
bool is_complex_valued =
863 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
870 static constexpr
unsigned int n_supported_derivative_levels =
871 internal::ADNumberInfoFromEnum<
872 typename internal::RemoveComplexWrapper<ScalarType>::type,
873 ADNumberTypeCode>::n_supported_derivative_levels;
882 using scalar_type = ScalarType;
888 using real_type =
typename internal::ADNumberInfoFromEnum<
889 typename internal::RemoveComplexWrapper<ScalarType>::type,
890 ADNumberTypeCode>::real_type;
896 using complex_type = std::complex<real_type>;
902 using ad_type =
typename std::
903 conditional<is_real_valued, real_type, complex_type>::type;
908 using derivative_type =
typename std::conditional<
910 typename internal::ADNumberInfoFromEnum<
911 typename internal::RemoveComplexWrapper<ScalarType>::type,
912 ADNumberTypeCode>::derivative_type,
913 std::complex<
typename internal::ADNumberInfoFromEnum<
914 typename internal::RemoveComplexWrapper<ScalarType>::type,
915 ADNumberTypeCode>::derivative_type>>::type;
921 static scalar_type get_scalar_value(
const ad_type &x)
930 internal::ExtractData<ad_type>::value(x));
937 static derivative_type get_directional_derivative(
938 const ad_type &x,
const unsigned int direction)
940 return internal::ExtractData<ad_type>::directional_derivative(
949 static unsigned int n_directional_derivatives(
const ad_type &x)
951 return internal::ExtractData<ad_type>::n_directional_derivatives(x);
955 static_assert((is_real_valued ==
true ?
956 std::is_same<ad_type, real_type>::value :
957 std::is_same<ad_type, complex_type>::value),
958 "Incorrect template type selected for ad_type");
960 static_assert((is_complex_valued ==
true ?
961 boost::is_complex<scalar_type>::value :
963 "Expected a complex float_type");
965 static_assert((is_complex_valued ==
true ?
966 boost::is_complex<ad_type>::value :
968 "Expected a complex ad_type");
973 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
974 const bool NumberTraits<
977 typename std::enable_if<
978 std::is_floating_point<ScalarType>::value ||
979 (boost::is_complex<ScalarType>::value &&
980 std::is_floating_point<
typename internal::RemoveComplexWrapper<
981 ScalarType>::type>::value)>::type>::is_taped =
982 internal::ADNumberInfoFromEnum<
983 typename internal::RemoveComplexWrapper<ScalarType>::type,
984 ADNumberTypeCode>::is_taped;
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_tapeless =
996 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
999 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1000 const bool 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>::is_real_valued =
1008 (!boost::is_complex<ScalarType>::value);
1011 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1012 const bool NumberTraits<
1015 typename std::enable_if<
1016 std::is_floating_point<ScalarType>::value ||
1017 (boost::is_complex<ScalarType>::value &&
1018 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1019 ScalarType>::type>::value)>::type>::is_complex_valued =
1020 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
1023 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1024 const unsigned int NumberTraits<
1027 typename std::enable_if<
1028 std::is_floating_point<ScalarType>::value ||
1029 (boost::is_complex<ScalarType>::value &&
1030 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1031 ScalarType>::type>::value)>::type>::n_supported_derivative_levels =
1032 internal::ADNumberInfoFromEnum<
1033 typename internal::RemoveComplexWrapper<ScalarType>::type,
1034 ADNumberTypeCode>::n_supported_derivative_levels;
1038 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1039 constexpr
bool NumberTraits<
1042 typename std::enable_if<
1043 std::is_floating_point<ScalarType>::value ||
1044 (boost::is_complex<ScalarType>::value &&
1045 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1046 ScalarType>::type>::value)>::type>::is_taped;
1049 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1050 constexpr
bool NumberTraits<
1053 typename std::enable_if<
1054 std::is_floating_point<ScalarType>::value ||
1055 (boost::is_complex<ScalarType>::value &&
1056 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1057 ScalarType>::type>::value)>::type>::is_tapeless;
1060 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1061 constexpr
bool NumberTraits<
1064 typename std::enable_if<
1065 std::is_floating_point<ScalarType>::value ||
1066 (boost::is_complex<ScalarType>::value &&
1067 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1068 ScalarType>::type>::value)>::type>::is_real_valued;
1071 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1072 constexpr
bool NumberTraits<
1075 typename std::enable_if<
1076 std::is_floating_point<ScalarType>::value ||
1077 (boost::is_complex<ScalarType>::value &&
1078 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1079 ScalarType>::type>::value)>::type>::is_complex_valued;
1082 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1083 constexpr
unsigned int NumberTraits<
1086 typename std::enable_if<
1087 std::is_floating_point<ScalarType>::value ||
1088 (boost::is_complex<ScalarType>::value &&
1089 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1090 ScalarType>::type>::value)>::type>::n_supported_derivative_levels;
1105 template <
typename ScalarType>
1106 struct NumberTraits<
1109 typename std::enable_if<
1110 std::is_floating_point<ScalarType>::value ||
1111 (boost::is_complex<ScalarType>::value &&
1112 std::is_floating_point<typename internal::RemoveComplexWrapper<
1113 ScalarType>::type>::value)>::type>
1132 static const bool is_taped;
1139 static const bool is_tapeless;
1146 static const bool is_real_valued;
1153 static const bool is_complex_valued;
1160 static const unsigned int n_supported_derivative_levels;
1168 static constexpr
bool is_taped =
false;
1175 static constexpr
bool is_tapeless =
false;
1182 static constexpr
bool is_real_valued =
1183 (!boost::is_complex<ScalarType>::value);
1190 static constexpr
bool is_complex_valued = !is_real_valued;
1197 static constexpr
unsigned int n_supported_derivative_levels = 0;
1206 using scalar_type = ScalarType;
1213 typename ::numbers::NumberTraits<scalar_type>::real_type;
1219 using complex_type = std::complex<real_type>;
1225 using ad_type = ScalarType;
1230 using derivative_type = ScalarType;
1237 get_scalar_value(
const ad_type &x)
1246 static derivative_type
1247 get_directional_derivative(
const ad_type &,
const unsigned int)
1252 "Floating point/arithmetic numbers have no directional derivatives."));
1253 return derivative_type();
1262 n_directional_derivatives(
const ad_type &)
1267 "Floating point/arithmetic numbers have no directional derivatives."));
1274 template <
typename ScalarType>
1275 const bool NumberTraits<
1278 typename std::enable_if<
1279 std::is_floating_point<ScalarType>::value ||
1280 (boost::is_complex<ScalarType>::value &&
1281 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1282 ScalarType>::type>::value)>::type>::is_taped =
false;
1285 template <
typename ScalarType>
1286 const bool NumberTraits<
1289 typename std::enable_if<
1290 std::is_floating_point<ScalarType>::value ||
1291 (boost::is_complex<ScalarType>::value &&
1292 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1293 ScalarType>::type>::value)>::type>::is_tapeless =
false;
1296 template <
typename ScalarType>
1297 const bool 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>::is_real_valued =
1305 (!boost::is_complex<ScalarType>::value);
1308 template <
typename ScalarType>
1309 const bool NumberTraits<
1312 typename std::enable_if<
1313 std::is_floating_point<ScalarType>::value ||
1314 (boost::is_complex<ScalarType>::value &&
1315 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1316 ScalarType>::type>::value)>::type>::is_complex_valued =
1317 !(NumberTraits<ScalarType, NumberTypes::none>::is_real_valued);
1320 template <
typename ScalarType>
1321 const unsigned int 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>::n_supported_derivative_levels =
1333 template <
typename ScalarType>
1334 constexpr
bool NumberTraits<
1337 typename std::enable_if<
1338 std::is_floating_point<ScalarType>::value ||
1339 (boost::is_complex<ScalarType>::value &&
1340 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1341 ScalarType>::type>::value)>::type>::is_taped;
1344 template <
typename ScalarType>
1345 constexpr
bool NumberTraits<
1348 typename std::enable_if<
1349 std::is_floating_point<ScalarType>::value ||
1350 (boost::is_complex<ScalarType>::value &&
1351 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1352 ScalarType>::type>::value)>::type>::is_tapeless;
1355 template <
typename ScalarType>
1356 constexpr
bool NumberTraits<
1359 typename std::enable_if<
1360 std::is_floating_point<ScalarType>::value ||
1361 (boost::is_complex<ScalarType>::value &&
1362 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1363 ScalarType>::type>::value)>::type>::is_real_valued;
1366 template <
typename ScalarType>
1367 constexpr
bool NumberTraits<
1370 typename std::enable_if<
1371 std::is_floating_point<ScalarType>::value ||
1372 (boost::is_complex<ScalarType>::value &&
1373 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1374 ScalarType>::type>::value)>::type>::is_complex_valued;
1377 template <
typename ScalarType>
1378 constexpr
unsigned int NumberTraits<
1381 typename std::enable_if<
1382 std::is_floating_point<ScalarType>::value ||
1383 (boost::is_complex<ScalarType>::value &&
1384 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1385 ScalarType>::type>::value)>::type>::n_supported_derivative_levels;
1408 template <
typename ScalarType>
1409 struct ADNumberTraits<
1411 typename
std::enable_if<std::is_floating_point<ScalarType>::value>::type>
1412 : NumberTraits<ScalarType, NumberTypes::none>
1418 template <
typename ComplexScalarType>
1419 struct ADNumberTraits<
1421 typename
std::enable_if<
1422 boost::is_complex<ComplexScalarType>::value &&
1423 std::is_floating_point<typename ComplexScalarType::value_type>::value>::
1424 type> : NumberTraits<ComplexScalarType, NumberTypes::none>
1435 template <
typename ADNumberType>
1437 is_nan(
const typename std::enable_if<
1439 ADNumberType>::type &x)
1448 DEAL_II_NAMESPACE_CLOSE
#define AssertThrow(cond, exc)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
bool is_nan(const double x)