16 #ifndef dealii_differentiation_ad_ad_number_traits_h
17 #define dealii_differentiation_ad_ad_number_traits_h
26 #include <boost/type_traits.hpp>
29 #include <type_traits>
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>(),
312 : std::conditional_t<
313 std::is_floating_point_v<typename ADNumberTrait::real_type>,
323 template <
typename ScalarType>
324 struct ADNumberInfoFromEnum<
327 std::enable_if_t<std::is_floating_point_v<ScalarType>>>
329 static const bool is_taped =
false;
330 using real_type = ScalarType;
331 using derivative_type = ScalarType;
332 static const unsigned int n_supported_derivative_levels = 0;
341 template <
typename ScalarType>
342 struct Marking<ScalarType,
343 std::enable_if_t<std::is_floating_point_v<ScalarType>>>
352 template <
typename ADNumberType>
354 independent_variable(
const ScalarType &in,
365 template <
typename ADNumberType>
367 dependent_variable(ADNumberType &,
const ScalarType &)
372 "Floating point numbers cannot be marked as dependent variables."));
380 template <
typename ADNumberType>
381 struct Marking<ADNumberType,
382 std::enable_if_t<boost::is_complex<ADNumberType>::value>>
387 template <
typename ScalarType>
389 independent_variable(
const ScalarType &in,
397 "Marking for complex numbers has not yet been implemented."));
404 template <
typename ScalarType>
406 dependent_variable(ADNumberType &,
const ScalarType &)
411 "Marking for complex numbers has not yet been implemented."));
418 template <
typename NumberType,
typename>
419 struct is_taped_ad_number : std::false_type
423 template <
typename NumberType,
typename>
424 struct is_tapeless_ad_number : std::false_type
428 template <
typename NumberType,
typename>
429 struct is_real_valued_ad_number : std::false_type
433 template <
typename NumberType,
typename>
434 struct is_complex_valued_ad_number : std::false_type
443 template <
typename NumberType>
445 : internal::HasRequiredADInfo<ADNumberTraits<std::decay_t<NumberType>>>
453 template <
typename NumberType>
454 struct is_taped_ad_number<
456 std::enable_if_t<ADNumberTraits<std::decay_t<NumberType>>::is_taped>>
465 template <
typename NumberType>
466 struct is_tapeless_ad_number<
468 std::enable_if_t<ADNumberTraits<std::decay_t<NumberType>>::is_tapeless>>
478 template <
typename NumberType>
479 struct is_real_valued_ad_number<
482 ADNumberTraits<std::decay_t<NumberType>>::is_real_valued>>
492 template <
typename NumberType>
493 struct is_complex_valued_ad_number<
496 ADNumberTraits<std::decay_t<NumberType>>::is_complex_valued>>
507 template <
typename Number>
508 struct RemoveComplexWrapper
519 template <
typename Number>
520 struct RemoveComplexWrapper<std::complex<Number>>
522 using type =
typename RemoveComplexWrapper<Number>::type;
531 template <
typename NumberType>
532 struct ExtractData<NumberType,
533 std::enable_if_t<std::is_floating_point_v<NumberType>>>
538 static const NumberType &
539 value(
const NumberType &x)
549 n_directional_derivatives(
const NumberType &)
559 directional_derivative(
const NumberType &,
const unsigned int)
571 template <
typename ADNumberType>
572 struct ExtractData<std::complex<ADNumberType>>
575 "Expected an auto-differentiable number.");
581 static std::complex<typename ADNumberTraits<ADNumberType>::scalar_type>
582 value(
const std::complex<ADNumberType> &x)
585 typename ADNumberTraits<ADNumberType>::scalar_type>(
586 ExtractData<ADNumberType>::value(x.real()),
587 ExtractData<ADNumberType>::value(x.imag()));
595 n_directional_derivatives(
const std::complex<ADNumberType> &x)
597 return ExtractData<ADNumberType>::n_directional_derivatives(x.real());
605 typename ADNumberTraits<ADNumberType>::derivative_type>
606 directional_derivative(
const std::complex<ADNumberType> &x,
607 const unsigned int direction)
610 typename ADNumberTraits<ADNumberType>::derivative_type>(
611 ExtractData<ADNumberType>::directional_derivative(x.real(),
613 ExtractData<ADNumberType>::directional_derivative(x.imag(),
619 template <
typename T>
625 template <
typename F>
627 value(
const F &f, std::enable_if_t<!is_ad_number<F>::value> * =
nullptr)
632 return ::internal::NumberType<T>::value(f);
641 template <
typename F>
644 std::enable_if_t<is_ad_number<F>::value &&
645 std::is_floating_point_v<T>> * =
nullptr)
650 return NumberType<T>::value(ExtractData<F>::value(f));
659 template <
typename F>
662 std::enable_if_t<is_ad_number<F>::value && is_ad_number<T>::value>
669 template <
typename T>
670 struct NumberType<std::complex<T>>
675 template <
typename F>
677 value(
const F &f, std::enable_if_t<!is_ad_number<F>::value> * =
nullptr)
682 return ::internal::NumberType<std::complex<T>>::value(f);
690 template <
typename F>
691 static std::complex<T>
693 std::enable_if_t<is_ad_number<F>::value &&
694 std::is_floating_point_v<T>> * =
nullptr)
699 return std::complex<T>(
700 NumberType<T>::value(ExtractData<F>::value(f)));
703 template <
typename F>
704 static std::complex<T>
705 value(
const std::complex<F> &f)
709 return std::complex<T>(NumberType<T>::value(f.real()),
710 NumberType<T>::value(f.imag()));
738 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
743 std::is_floating_point_v<ScalarType> ||
744 (boost::is_complex<ScalarType>::value &&
745 std::is_floating_point<
746 typename internal::RemoveComplexWrapper<ScalarType>::type>::value)>>
751 static constexpr
enum NumberTypes type_code = ADNumberTypeCode;
765 static const bool is_taped;
772 static const bool is_tapeless;
779 static const bool is_real_valued;
786 static const bool is_complex_valued;
793 static const unsigned int n_supported_derivative_levels;
801 static constexpr
bool is_taped = internal::ADNumberInfoFromEnum<
802 typename internal::RemoveComplexWrapper<ScalarType>::type,
803 ADNumberTypeCode>::is_taped;
810 static constexpr
bool is_tapeless =
811 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
818 static constexpr
bool is_real_valued =
819 (!boost::is_complex<ScalarType>::value);
826 static constexpr
bool is_complex_valued =
827 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
834 static constexpr
unsigned int n_supported_derivative_levels =
835 internal::ADNumberInfoFromEnum<
836 typename internal::RemoveComplexWrapper<ScalarType>::type,
837 ADNumberTypeCode>::n_supported_derivative_levels;
846 using scalar_type = ScalarType;
852 using real_type =
typename internal::ADNumberInfoFromEnum<
853 typename internal::RemoveComplexWrapper<ScalarType>::type,
854 ADNumberTypeCode>::real_type;
860 using complex_type = std::complex<real_type>;
866 using ad_type =
typename std::
867 conditional<is_real_valued, real_type, complex_type>::type;
872 using derivative_type = std::conditional_t<
874 typename internal::ADNumberInfoFromEnum<
875 typename internal::RemoveComplexWrapper<ScalarType>::type,
876 ADNumberTypeCode>::derivative_type,
877 std::complex<
typename internal::ADNumberInfoFromEnum<
878 typename internal::RemoveComplexWrapper<ScalarType>::type,
879 ADNumberTypeCode>::derivative_type>>;
885 static scalar_type get_scalar_value(
const ad_type &x)
894 internal::ExtractData<ad_type>::value(x));
901 static derivative_type get_directional_derivative(
902 const ad_type &x,
const unsigned int direction)
904 return internal::ExtractData<ad_type>::directional_derivative(
913 static unsigned int n_directional_derivatives(
const ad_type &x)
915 return internal::ExtractData<ad_type>::n_directional_derivatives(x);
919 static_assert((is_real_valued ==
true ?
920 std::is_same_v<ad_type, real_type> :
921 std::is_same_v<ad_type, complex_type>),
922 "Incorrect template type selected for ad_type");
924 static_assert((is_complex_valued ==
true ?
925 boost::is_complex<scalar_type>::value :
927 "Expected a complex float_type");
929 static_assert((is_complex_valued ==
true ?
930 boost::is_complex<ad_type>::value :
932 "Expected a complex ad_type");
937 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
938 const bool NumberTraits<
942 std::is_floating_point_v<ScalarType> ||
943 (boost::is_complex<ScalarType>::value &&
944 std::is_floating_point<
typename internal::RemoveComplexWrapper<
945 ScalarType>::type>::value)>>::is_taped =
946 internal::ADNumberInfoFromEnum<
947 typename internal::RemoveComplexWrapper<ScalarType>::type,
948 ADNumberTypeCode>::is_taped;
951 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
952 const bool NumberTraits<
956 std::is_floating_point_v<ScalarType> ||
957 (boost::is_complex<ScalarType>::value &&
958 std::is_floating_point<
typename internal::RemoveComplexWrapper<
959 ScalarType>::type>::value)>>::is_tapeless =
960 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_taped);
963 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
964 const bool NumberTraits<
968 std::is_floating_point_v<ScalarType> ||
969 (boost::is_complex<ScalarType>::value &&
970 std::is_floating_point<
typename internal::RemoveComplexWrapper<
971 ScalarType>::type>::value)>>::is_real_valued =
972 (!boost::is_complex<ScalarType>::value);
975 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
976 const bool NumberTraits<
980 std::is_floating_point_v<ScalarType> ||
981 (boost::is_complex<ScalarType>::value &&
982 std::is_floating_point<
typename internal::RemoveComplexWrapper<
983 ScalarType>::type>::value)>>::is_complex_valued =
984 !(NumberTraits<ScalarType, ADNumberTypeCode>::is_real_valued);
987 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
988 const unsigned int NumberTraits<
992 std::is_floating_point_v<ScalarType> ||
993 (boost::is_complex<ScalarType>::value &&
994 std::is_floating_point<
typename internal::RemoveComplexWrapper<
995 ScalarType>::type>::value)>>::n_supported_derivative_levels =
996 internal::ADNumberInfoFromEnum<
997 typename internal::RemoveComplexWrapper<ScalarType>::type,
998 ADNumberTypeCode>::n_supported_derivative_levels;
1002 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1003 constexpr
bool NumberTraits<
1007 std::is_floating_point_v<ScalarType> ||
1008 (boost::is_complex<ScalarType>::value &&
1009 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1010 ScalarType>::type>::value)>>::is_taped;
1013 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1014 constexpr
bool NumberTraits<
1018 std::is_floating_point_v<ScalarType> ||
1019 (boost::is_complex<ScalarType>::value &&
1020 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1021 ScalarType>::type>::value)>>::is_tapeless;
1024 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1025 constexpr
bool NumberTraits<
1029 std::is_floating_point_v<ScalarType> ||
1030 (boost::is_complex<ScalarType>::value &&
1031 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1032 ScalarType>::type>::value)>>::is_real_valued;
1035 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1036 constexpr
bool NumberTraits<
1040 std::is_floating_point_v<ScalarType> ||
1041 (boost::is_complex<ScalarType>::value &&
1042 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1043 ScalarType>::type>::value)>>::is_complex_valued;
1046 template <
typename ScalarType, enum NumberTypes ADNumberTypeCode>
1047 constexpr
unsigned int NumberTraits<
1051 std::is_floating_point_v<ScalarType> ||
1052 (boost::is_complex<ScalarType>::value &&
1053 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1054 ScalarType>::type>::value)>>::n_supported_derivative_levels;
1069 template <
typename ScalarType>
1070 struct NumberTraits<
1074 std::is_floating_point_v<ScalarType> ||
1075 (boost::is_complex<ScalarType>::value &&
1076 std::is_floating_point<
1077 typename internal::RemoveComplexWrapper<ScalarType>::type>::value)>>
1096 static const bool is_taped;
1103 static const bool is_tapeless;
1110 static const bool is_real_valued;
1117 static const bool is_complex_valued;
1124 static const unsigned int n_supported_derivative_levels;
1132 static constexpr
bool is_taped =
false;
1139 static constexpr
bool is_tapeless =
false;
1146 static constexpr
bool is_real_valued =
1147 (!boost::is_complex<ScalarType>::value);
1154 static constexpr
bool is_complex_valued = !is_real_valued;
1161 static constexpr
unsigned int n_supported_derivative_levels = 0;
1170 using scalar_type = ScalarType;
1177 typename ::numbers::NumberTraits<scalar_type>::real_type;
1183 using complex_type = std::complex<real_type>;
1189 using ad_type = ScalarType;
1194 using derivative_type = ScalarType;
1201 get_scalar_value(
const ad_type &x)
1210 static derivative_type
1211 get_directional_derivative(
const ad_type &,
const unsigned int)
1216 "Floating point/arithmetic numbers have no directional derivatives."));
1217 return derivative_type();
1226 n_directional_derivatives(
const ad_type &)
1231 "Floating point/arithmetic numbers have no directional derivatives."));
1238 template <
typename ScalarType>
1239 const bool NumberTraits<
1243 std::is_floating_point_v<ScalarType> ||
1244 (boost::is_complex<ScalarType>::value &&
1245 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1246 ScalarType>::type>::value)>>::is_taped =
false;
1249 template <
typename ScalarType>
1250 const bool NumberTraits<
1254 std::is_floating_point_v<ScalarType> ||
1255 (boost::is_complex<ScalarType>::value &&
1256 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1257 ScalarType>::type>::value)>>::is_tapeless =
false;
1260 template <
typename ScalarType>
1261 const bool NumberTraits<
1265 std::is_floating_point_v<ScalarType> ||
1266 (boost::is_complex<ScalarType>::value &&
1267 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1268 ScalarType>::type>::value)>>::is_real_valued =
1269 (!boost::is_complex<ScalarType>::value);
1272 template <
typename ScalarType>
1273 const bool NumberTraits<
1277 std::is_floating_point_v<ScalarType> ||
1278 (boost::is_complex<ScalarType>::value &&
1279 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1280 ScalarType>::type>::value)>>::is_complex_valued =
1281 !(NumberTraits<ScalarType, NumberTypes::none>::is_real_valued);
1284 template <
typename ScalarType>
1285 const unsigned int NumberTraits<
1289 std::is_floating_point_v<ScalarType> ||
1290 (boost::is_complex<ScalarType>::value &&
1291 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1292 ScalarType>::type>::value)>>::n_supported_derivative_levels = 0;
1296 template <
typename ScalarType>
1297 constexpr
bool NumberTraits<
1301 std::is_floating_point_v<ScalarType> ||
1302 (boost::is_complex<ScalarType>::value &&
1303 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1304 ScalarType>::type>::value)>>::is_taped;
1307 template <
typename ScalarType>
1308 constexpr
bool NumberTraits<
1312 std::is_floating_point_v<ScalarType> ||
1313 (boost::is_complex<ScalarType>::value &&
1314 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1315 ScalarType>::type>::value)>>::is_tapeless;
1318 template <
typename ScalarType>
1319 constexpr
bool NumberTraits<
1323 std::is_floating_point_v<ScalarType> ||
1324 (boost::is_complex<ScalarType>::value &&
1325 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1326 ScalarType>::type>::value)>>::is_real_valued;
1329 template <
typename ScalarType>
1330 constexpr
bool NumberTraits<
1334 std::is_floating_point_v<ScalarType> ||
1335 (boost::is_complex<ScalarType>::value &&
1336 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1337 ScalarType>::type>::value)>>::is_complex_valued;
1340 template <
typename ScalarType>
1341 constexpr
unsigned int NumberTraits<
1345 std::is_floating_point_v<ScalarType> ||
1346 (boost::is_complex<ScalarType>::value &&
1347 std::is_floating_point<
typename internal::RemoveComplexWrapper<
1348 ScalarType>::type>::value)>>::n_supported_derivative_levels;
1371 template <
typename ScalarType>
1372 struct ADNumberTraits<
1374 std::enable_if_t<std::is_floating_point_v<ScalarType>>>
1375 : NumberTraits<ScalarType, NumberTypes::none>
1381 template <
typename ComplexScalarType>
1382 struct ADNumberTraits<
1385 boost::is_complex<ComplexScalarType>::value &&
1386 std::is_floating_point_v<typename ComplexScalarType::value_type>>>
1387 : 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 DEAL_II_HOST_DEVICE_ALWAYS_INLINE const T & value(const T &t)