From a2c3e82d4681b18c7825b6d789dd3cc44262238d Mon Sep 17 00:00:00 2001 From: Jean-Paul Pelteret Date: Fri, 3 Nov 2017 13:47:04 +0100 Subject: [PATCH] Add core headers for internally supported AD numbers - Type codes - Type traits --- include/deal.II/differentiation/ad.h | 3 + .../differentiation/ad/ad_number_traits.h | 1060 +++++++++++++++++ .../differentiation/ad/ad_number_types.h | 86 ++ 3 files changed, 1149 insertions(+) create mode 100644 include/deal.II/differentiation/ad/ad_number_traits.h create mode 100644 include/deal.II/differentiation/ad/ad_number_types.h diff --git a/include/deal.II/differentiation/ad.h b/include/deal.II/differentiation/ad.h index 5e6f28a7ef..482fbb5ccf 100644 --- a/include/deal.II/differentiation/ad.h +++ b/include/deal.II/differentiation/ad.h @@ -20,6 +20,9 @@ #if defined(DEAL_II_WITH_ADOLC) || defined(DEAL_II_WITH_TRILINOS) +#include +#include + DEAL_II_NAMESPACE_OPEN /** diff --git a/include/deal.II/differentiation/ad/ad_number_traits.h b/include/deal.II/differentiation/ad/ad_number_traits.h new file mode 100644 index 0000000000..810b53d59f --- /dev/null +++ b/include/deal.II/differentiation/ad/ad_number_traits.h @@ -0,0 +1,1060 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2016 - 2017 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + +#ifndef dealii_differentiation_ad_ad_number_traits_h +#define dealii_differentiation_ad_ad_number_traits_h + +#include +#include + +#include + +#include +#include + +DEAL_II_NAMESPACE_OPEN + +namespace Differentiation +{ + namespace AD + { + + /** + * A number traits class to help describe some characteristic + * information about auto-differentiable numbers. + * + * @tparam ScalarType A real or complex floating point number. + * @tparam ADNumberTypeCode An enumeration specifying the type + * code for the supported auto-differentiable counterpart + * to the given @p ScalarType. + * @tparam T An arbitrary type resulting from the application of + * the SFINAE idiom to selectively specialize this class. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct NumberTraits; + + + + /** + * A number traits class to help describe some characteristic + * information about auto-differentiable numbers. This class is only + * specialized (and, therefore, only made constructible) if the + * @p ADNumberType template parameter is indeed a supported + * auto-differentiable number. + * + * @tparam ADNumberType A type corresponding to a supported + * auto-differentiable number. + * @tparam T An arbitrary type resulting from the application of + * the SFINAE idiom to selectively specialize this class. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct ADNumberTraits; + + + /** + * This namespace defines the classes that help provide a unified interface + * to all auto-differentiation numbers. + */ + namespace internal + { + + // The following three classes, namely ADNumberInfoFromEnum, Marking, and + // ExtractData, are those that need to be implemented for each new + // auto-differentiable number type. This information is then used by + // NumberTraits and ADNumberTraits to provide a uniform interface, as used + // by our drivers, to the underlying number types. + + + /** + * A struct that defines some fundamental information about a + * auto-differentiable number based on the @p ScalarType and the + * AD-enumeration selected by @p ADNumberTypeCode. This information is + * used in other convenience classes and templated functions to + * automatically determine information about the auto-differentiable + * number that has been selected to wrap the @p ScalarType. + * + * The specializations of this class have to implement the following + * member data and type definitions: + * @code + * + * // State whether the auto-differentiable number uses taping or not. + * static const bool is_taped; + * // The real-type for the auto-differentiable number + * typedef real_type; + * // The type of number returned when taking the first derivative of the @p real_type. + * typedef derivative_type; + * // The number of derivative levels computable from the @p real_type. + * static const unsigned int n_supported_derivative_levels; + * + * @endcode + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct ADNumberInfoFromEnum; + + + /** + * A struct to assist with the marking of AD numbers that represent + * independent and dependent variables. + * + * The specializations of this class have to implement the following + * member functions: + * @code + * + * // Initialize the state of an independent variable. + * static void + * independent_variable(const ScalarType &in, + * const unsigned int index, + * const unsigned int n_independent_variables, + * ADNumberType &out) + * + * // Initialize the state of a dependent variable. + * static void + * dependent_variable(ADNumberType &out, + * const ADNumberType &func); + * + * @endcode + * where @p ADNumberType is the auto-differentiable number type and + * @p ScalarType is its floating point counterpart. + * + * @tparam ADNumberType A type corresponding to a supported + * auto-differentiable number. + * @tparam T An arbitrary type resulting from the application of + * the SFINAE idiom to selectively specialize this class. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct Marking; + + + /** + * A struct to help extract certain information associated with + * auto-differentiable numbers. + * + * The specializations of this class have to implement the following + * member data and type definitions: + * @code + * + * // Extract the real scalar value. + * static scalar_type + * value (const ADNumberType &x); + * + * // Extract the number of directional derivatives. + * static unsigned int + * n_directional_derivatives (const ADNumberType &x); + * + * // Extract the directional derivative in the specified @p direction. + * static derivative_type + * directional_derivative (const ADNumberType &x, + * const unsigned int direction); + * + * @endcode + * where @p ADNumberType is the auto-differentiable number type. + * + * @tparam ADNumberType A type corresponding to a supported + * auto-differentiable number. + * @tparam T An arbitrary type resulting from the application of + * the SFINAE idiom to selectively specialize this class. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct ExtractData; + + + /** + * A struct that checks that the data expected to be stored in a specialization + * of the ADNumberInfoFromEnum struct has been supplied. By default it is + * assumed that the input type does not satisfy the necessary conditions to + * construct this class. + * + * @tparam ADNumberTrait A class that examined whether it contains the necessary + * information to satisfy the requirements for being an internally + * supported auto-differentiable number. + * @tparam T An arbitrary type resulting from the application of + * the SFINAE idiom to selectively specialize this class. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct HasRequiredADInfo; + + + /** + * Provide a convenience function to assist in the casting of some + * number types to other number types. On top of the standard class + * definition given in @p base/numbers.h , this extension allows the + * conversion of automatic-differentiation numbers to generic floats. + * + * This is necessary because Adol-C doesn't provide a convenient + * way to convert from an @p ADNumberType to floats (@p T) other than + * the real-type equivalent that its associated with. For Sacado, and + * likely other AD number types, the floating point value stored in + * an @p ADNumberType must be extracted through some function that is + * specific to each type of AD number. This requires some specialist + * intervention to get at this data. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct NumberType; + + + /** + * A small struct to remove the @p std::complex wrapper + * around a number. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct RemoveComplexWrapper; + + } // namespace internal + + + /** + * A struct to indicate whether a given @p NumberType is a supported + * auto-differentiable number or not. By default, numbers are not + * considered to have the necessary characteristics to fulfill this + * condition. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct is_ad_number; + + + /** + * A struct to indicate whether a given @p NumberType is a taped + * auto-differentiable number or not. By default, numbers are not + * considered to have the necessary characteristics to fulfill this + * condition. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct is_taped_ad_number; + + + /** + * A struct to indicate whether a given @p NumberType is a tapeless + * auto-differentiable number or not. By default, numbers are not + * considered to have the necessary characteristics to fulfill this + * condition. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct is_tapeless_ad_number; + + + /** + * A struct to indicate whether a given @p NumberType is a real-valued + * auto-differentiable number or not. By default, numbers are not + * considered to have the necessary characteristics to fulfill this + * condition. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct is_real_valued_ad_number; + + + /** + * A struct to indicate whether a given @p NumberType is a complex-valued + * auto-differentiable number or not. By default, numbers are not + * considered to have the necessary characteristics to fulfill this + * condition. + * + * @author Jean-Paul Pelteret, 2017 + */ + template + struct is_complex_valued_ad_number; + + } // namespace AD +} // namespace Differentiation + + +/* --------------------------- inline and template functions and specializations ------------------------- */ + + +#ifndef DOXYGEN + + +namespace Differentiation +{ + namespace AD + { + namespace internal + { + template + struct HasRequiredADInfo + : std::false_type + { }; + + + /** + * Specialization to detect whether the input AD number + * is internally supported or not. In particular, we + * check to see that it has been assigned a type_code and + * has other basic characteristics necessary for the + * internal interface of both the AD and SD drivers. + * + * The implementation of this struct follows this suggestion: + * https://stackoverflow.com/a/16000226 + */ + template + struct HasRequiredADInfo (), + (void) std::declval(), + void() )> : std::true_type + { }; + + + /** + * A dummy specialization for floating point numbers. This is helpful + * for nested auto-differentiable numbers, where a recursive marking + * mechanism can be employed (e.g. Sacado types). + */ + template + struct Marking::value + >::type> + { + /** + * Initialize the state of an independent variable. + * + * With a nested marking approach it is sometimes + * necessary to initialise the value of an intermediate + * value that may be a floating point number. + */ + template + static void + independent_variable(const ScalarType &in, + const unsigned int , + const unsigned int , + ADNumberType &out) + { + out = in; + } + + /* + * Initialize the state of a dependent variable. + */ + template + static void + dependent_variable(ADNumberType &, + const ScalarType &) + { + AssertThrow(false, ExcMessage("Floating point numbers cannot be marked as dependent variables.")); + } + }; + + + /** + * A specialization of the marking strategy for complex numbers. + */ + template + struct Marking::value + >::type> + { + + /* + * Initialize the state of an independent variable. + */ + template + static void + independent_variable(const ScalarType &in, + const unsigned int , + const unsigned int , + ADNumberType &out) + { + AssertThrow(false, ExcMessage("Marking for complex numbers has not yet been implemented.")); + out = in; + } + + /* + * Initialize the state of a dependent variable. + */ + template + static void + dependent_variable(ADNumberType &, + const ScalarType &) + { + AssertThrow(false, ExcMessage("Marking for complex numbers has not yet been implemented.")); + } + }; + + } // namespace internal + + + template + struct is_taped_ad_number + : std::false_type + {}; + + + template + struct is_tapeless_ad_number + : std::false_type + {}; + + + template + struct is_real_valued_ad_number + : std::false_type + {}; + + + template + struct is_complex_valued_ad_number + : std::false_type + {}; + + + /** + * We use the specialization of the HasRequiredADInfo struct + * to ensure that only internally supported numbers are + * considered AD numbers. + */ + template + struct is_ad_number + : internal::HasRequiredADInfo< ADNumberTraits::type> > + {}; + + + /** + * Specialization of the struct for the case when the input template + * parameter is a (real or complex) taped auto-differentiable number. + */ + template + struct is_taped_ad_number::type>::is_taped + >::type> + : std::true_type + {}; + + + /** + * Specialization of the struct for the case when the input template + * parameter is a (real or complex) tapeless auto-differentiable number. + */ + template + struct is_tapeless_ad_number::type>::is_tapeless + >::type> + : std::true_type + {}; + + + /** + * Specialization of the struct for the case when the input template + * parameter is a (taped or tapeless) real-valued auto-differentiable number. + */ + template + struct is_real_valued_ad_number::type>::is_real_valued + >::type> + : std::true_type + {}; + + + /** + * Specialization of the struct for the case when the input template + * parameter is a (taped or tapeless) complex-valued auto-differentiable number. + */ + template + struct is_complex_valued_ad_number::type>::is_complex_valued + >::type> + : std::true_type + {}; + + + namespace internal + { + + /** + * Specialization of the selection struct which sets the type as being + * one that is the value type of the underlying complex number. + */ + template + struct RemoveComplexWrapper + { + typedef Number type; + }; + + + /** + * Specialization of the selection struct which sets the value type + * to that resulting from the recursive removal of the complex + * number wrapper. + */ + template + struct RemoveComplexWrapper > + { + typedef typename RemoveComplexWrapper::type type; + }; + + + /** + * A dummy specialization for floating point numbers. This is helpful + * for nested auto-differentiable numbers, where a recursive marking + * mechanism can be employed (e.g. Sacado types). + */ + template + struct ExtractData::value + >::type> + { + /** + * Extract the floating point value. + */ + static const NumberType & + value (const NumberType &x) + { + return x; + } + + + /** + * Extract the number of directional derivatives. + */ + static unsigned int + n_directional_derivatives (const NumberType &) + { + return 0; + } + + + /** + * Extract the directional derivative in the specified @p direction. + */ + static NumberType + directional_derivative (const NumberType &, + const unsigned int ) + { + return 0.0; + } + }; + + + + /** + * A struct specialization to help extract certain information associated + * with complex auto-differentiable numbers. + */ + template + struct ExtractData< std::complex > + { + static_assert( + Differentiation::AD::is_ad_number::value, + "Expected an auto-differentiable number." + ); + + + /** + * Extract the floating point value. + */ + static std::complex::scalar_type> + value (const std::complex &x) + { + return std::complex::scalar_type>( + ExtractData::value(x.real()), + ExtractData::value(x.imag()) ); + } + + + /** + * Extract the number of directional derivatives. + */ + static unsigned int + n_directional_derivatives (const std::complex &x) + { + return ExtractData::n_directional_derivatives(x.real()); + } + + + /** + * Extract the directional derivative in the specified @p direction. + */ + static std::complex::derivative_type> + directional_derivative (const std::complex &x, + const unsigned int direction) + { + return std::complex::derivative_type>( + ExtractData::directional_derivative(x.real(), direction), + ExtractData::directional_derivative(x.imag(), direction) ); + } + }; + + + template + struct NumberType + { + /** + * Standard number conversion + */ + template + static auto + value (const F &f, + typename std::enable_if< + !is_ad_number::value + >::type * = 0) + -> decltype (dealii::internal::NumberType::value(f)) + { + // We call the other function defined in the numbers + // header to take care of all of the usual cases. + return dealii::internal::NumberType::value(f); + } + + /** + * Conversion from an AD number to a scalar number. + * We wish to ensure that @p T is a scalar type because, + * in general, the conversion between AD numbers is either + * non-trivial or an invalid operation. + */ + template + static T + value (const F &f, + typename std::enable_if< + is_ad_number::value && + std::is_arithmetic::value + >::type * = 0) + { + // We recursively call this function in case the AD number is a + // nested one. The recursion ends when the extracted value is + // a floating point number. + return NumberType::value(ExtractData::value(f)); + } + + /** + * Conversion from an AD number another AD number. + * + * Since this is the most generic case we'll assume that + * the return type is constructible from the input type. + */ + template + static T + value (const F &f, + typename std::enable_if< + is_ad_number::value && + is_ad_number::value + >::type * = 0) + { + return T(f); + } + }; + + template + struct NumberType< std::complex > + { + /** + * Standard complex number conversion + */ + template + static auto + value (const F &f, + typename std::enable_if< + !is_ad_number::value + >::type * = 0) + -> decltype (dealii::internal::NumberType< std::complex >::value(f)) + { + // We call the other function defined in the numbers + // header to take care of all of the usual cases. + return dealii::internal::NumberType< std::complex >::value(f); + } + + + /** + * Conversion from a complex AD number to another + * complex number templated on a scalar number. + */ + template + static std::complex + value (const F &f, + typename std::enable_if< + is_ad_number::value && + std::is_arithmetic::value + >::type * = 0) + { + // We recursively call this function in case the AD number is a + // nested one. The recursion ends when the extracted value is + // a floating point number. + return std::complex(NumberType::value(ExtractData::value(f))); + } + + template + static std::complex + value (const std::complex &f) + { + // Deal with the two parts of the input complex + // number individually. + return std::complex( + NumberType::value(f.real()), + NumberType::value(f.imag())); + } + }; + + } // namespace internal + + + + /** + * Specialization of the general NumberTraits class that + * provides relevant information for auto-differentiable numbers. + * + * For each new @p ADNumberTypeCode enumeration, a data structure called + * internal::ADNumberInfoFromEnum is to be defined, from which we require + * the following basic information determine all of the required information + * and type traits for our helper classes: + * - A typedef called @p scalar_type, which defines the scalar or + * floating-point valued counterpart to the auto-differentiable number type. + * This can be real or complex valued. + * - A typedef called @p derivative_type, which defines the + * number type for directional derivatives. + * - A boolean called @p is_taped, which defines whether the auto-differentiable + * number is a taped number or not. + * + * This specific version specializes the generic case where the template + * @p ScalarType represents a floating or complex number that is templated + * on a floating point type. + */ + template + struct NumberTraits::value || + (boost::is_complex::value && + std::is_floating_point::type>::value) + >::type> + { + /** + * The type of taping used + */ + static constexpr enum NumberTypes type_code + = ADNumberTypeCode; + + // The clang compiler does not seem to like these + // variables being defined as constant expressions + // (the tests /ad_number_traits_02 will + // fail with linking errors). However, GCC complains + // about the use of non-constant expressions in + // std::conditional. +#ifdef __clang__ + + /** + * A flag to indicate whether the number is of + * the taped variety or not + */ + static const bool is_taped; + + + /** + * A flag to indicate whether the number is of + * the tapeless variety or not + */ + static const bool is_tapeless; + + + /** + * A flag to indicate whether the number represents + * a real value + */ + static const bool is_real_valued; + + + /** + * A flag to indicate whether the number represents + * a complex value + */ + static const bool is_complex_valued; + + + /** + * The number of directional derivatives that can be + * taken with this auto-differentiable number + */ + static const unsigned int n_supported_derivative_levels; + +#else + + /** + * A flag to indicate whether the number is of + * the taped variety or not + */ + static constexpr bool is_taped + = internal::ADNumberInfoFromEnum< + typename internal::RemoveComplexWrapper::type, ADNumberTypeCode + >::is_taped; + + + /** + * A flag to indicate whether the number is of + * the tapeless variety or not + */ + static constexpr bool is_tapeless + = !(NumberTraits::is_taped); + + + /** + * A flag to indicate whether the number represents + * a real value + */ + static constexpr bool is_real_valued + = (!boost::is_complex::value); + + + /** + * A flag to indicate whether the number represents + * a complex value + */ + static constexpr bool is_complex_valued + = !(NumberTraits::is_real_valued); + + + /** + * The number of directional derivatives that can be + * taken with this auto-differentiable number + */ + static const unsigned int n_supported_derivative_levels + = internal::ADNumberInfoFromEnum< + typename internal::RemoveComplexWrapper::type, ADNumberTypeCode + >::n_supported_derivative_levels; + +#endif + + + /** + * Underlying floating point value type. + * This could real-valued or complex-valued. + */ + typedef ScalarType scalar_type; + + + /** + * Type for real numbers + */ + typedef typename internal::ADNumberInfoFromEnum< + typename internal::RemoveComplexWrapper::type,ADNumberTypeCode + >::real_type real_type; + + + /** + * Type for complex numbers + */ + typedef std::complex complex_type; + + + /** + * The actual auto-differentiable number type + */ + typedef typename std::conditional< + is_real_valued,real_type,complex_type + >::type ad_type; + + /** + * The actual auto-differentiable number directional derivative type + */ + typedef typename std::conditional< + is_real_valued, + typename internal::ADNumberInfoFromEnum< + typename internal::RemoveComplexWrapper::type,ADNumberTypeCode + >::derivative_type, + std::complex::type,ADNumberTypeCode + >::derivative_type> + >::type derivative_type; + + + /** + * Extract the value of an auto-differentiable number + */ + static scalar_type + get_scalar_value(const ad_type &x) + { + // Some tricky conversion cases to consider here: + // - Nested AD numbers + // - std::complex --> std::complex + // e.g. when ScalarType = float and ADNumberTypeCode = adolc_taped + // Therefore, we use the internal casting mechanism + // provided by the internal::NumberType struct. + return internal::NumberType::value(internal::ExtractData::value(x)); + } + + + /** + * Extract the derivative value of an auto-differentiable number + */ + static derivative_type + get_directional_derivative(const ad_type &x, + const unsigned int direction) + { + return internal::ExtractData::directional_derivative(x, direction); + } + + + /** + * Extract the number of directional derivatives value tracked by + * an auto-differentiable number + */ + static unsigned int + n_directional_derivatives(const ad_type &x) + { + return internal::ExtractData::n_directional_derivatives(x); + } + + + static_assert( + (is_real_valued==true ? + std::is_same::value : + std::is_same::value), + "Incorrect template type selected for ad_type"); + + static_assert( + (is_complex_valued==true ? + boost::is_complex::value : + true), + "Expected a complex float_type"); + + static_assert( + (is_complex_valued==true ? + boost::is_complex::value : + true), + "Expected a complex ad_type"); + + }; + +#ifdef __clang__ + + template + const bool + NumberTraits::value || + (boost::is_complex::value && + std::is_floating_point::type>::value) + >::type>::is_taped + = internal::ADNumberInfoFromEnum< + typename internal::RemoveComplexWrapper::type, ADNumberTypeCode + >::is_taped; + + + template + const bool + NumberTraits::value || + (boost::is_complex::value && + std::is_floating_point::type>::value) + >::type>::is_tapeless + = !(NumberTraits::is_taped); + + + template + const bool + NumberTraits::value || + (boost::is_complex::value && + std::is_floating_point::type>::value) + >::type>::is_real_valued + = (!boost::is_complex::value); + + + template + const bool + NumberTraits::value || + (boost::is_complex::value && + std::is_floating_point::type>::value) + >::type>::is_complex_valued + = !(NumberTraits::is_real_valued); + + + template + const unsigned int + NumberTraits::value || + (boost::is_complex::value && + std::is_floating_point::type>::value) + >::type>::n_supported_derivative_levels + = internal::ADNumberInfoFromEnum< + typename internal::RemoveComplexWrapper::type, ADNumberTypeCode + >::n_supported_derivative_levels; + +#endif + + + /** + * A dummy specialization for floating point numbers. This is necessary to + * deal with the tricky case of higher-order derivative extraction from + * AD numbers. + * + * Sacado nests the directional derivatives within Sacado numbers, while Adol-C + * does not. So, starting off from a scalar function f(x), the number type resulting + * from the computation of a directional derivative f'(x) of that function is a floating + * point number for Adol-C number types and Sacado::FAD, but that of a + * Sacado::FAD> is a Sacado::FAD. + * + * For this reason, when trying to extract higher-order derivatives of a number that + * does not support them the input value to this function may be a scalar type. + */ + template + struct ADNumberTraits::value + >::type> + { + static ScalarType + get_directional_derivative(const ScalarType &x, + const unsigned int direction) + { + // If the AD drivers are correctly implemented then we should not get here. + // This is essentially a dummy for when the ADNumberTypeCode for the original + // AD number (from which one is getting a derivative >= 2) is one that specified + // Adol-C taped and tapeless numbers, or a non-nested Sacado number. + AssertThrow(false, ExcMessage("Floating point numbers have no directional derivatives.")); + return 0.0; + } + }; + + } // namespace AD +} // namespace Differentiation + +#endif // DOXYGEN + + +namespace numbers +{ + + template + bool + is_nan (const typename std::enable_if< + Differentiation::AD::is_ad_number::value, + ADNumberType>::type &x) + { + return is_nan(Differentiation::AD::ADNumberTraits::get_value(x)); + } + +} // namespace numbers + + +DEAL_II_NAMESPACE_CLOSE + +#endif diff --git a/include/deal.II/differentiation/ad/ad_number_types.h b/include/deal.II/differentiation/ad/ad_number_types.h new file mode 100644 index 0000000000..3d718f0541 --- /dev/null +++ b/include/deal.II/differentiation/ad/ad_number_types.h @@ -0,0 +1,86 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2016 - 2017 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + +#ifndef dealii_differentiation_ad_ad_number_types_h +#define dealii_differentiation_ad_ad_number_types_h + + +#include + + +DEAL_II_NAMESPACE_OPEN + +namespace Differentiation +{ + namespace AD + { + + /** + * An enumeration to indicate which type of auto-differentiable number + * is to be used for computations. If a type that is selected for use + * is not available in the library, a compile-time error will be thrown. + * + * @author Jean-Paul Pelteret, 2017 + */ + enum class NumberTypes + { + /** + * Taped forward and reverse-mode Adol-C number type (n-differentiable). + * + * First derivatives will be computed using reverse mode, while the second + * derivatives will be computed using forward mode. Even higher-order + * derivatives can be computed using Adol-C's own driver functions. + */ + adolc_taped, + + /** + * Tapeless dynamic forward-mode Adol-C number type (once differentiable). + */ + adolc_tapeless, + + /** + * Tapeless dynamic forward-mode Sacado number type (once differentiable). + */ + sacado_dfad, + + /** + * Tapeless nested dynamic forward-mode Sacado number type (twice differentiable). + * + * Both the first and second derivatives will be computed using forward mode. + */ + sacado_dfad_dfad, + + /** + * Tapeless reverse-mode Sacado number type (once differentiable). + */ + sacado_rad, + + /** + * Tapeless nested reverse-mode and dynamic forward-mode Sacado number type (twice differentiable). + * + * First derivatives will be computed using reverse mode, while the second derivatives + * will be computed using forward mode. + */ + sacado_rad_dfad + }; + + } // namespace AD +} // namespace Differentiation + + + +DEAL_II_NAMESPACE_CLOSE + +#endif -- 2.39.5