]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Implement type traits and helper classes for Adol-C numbers
authorJean-Paul Pelteret <jppelteret@gmail.com>
Fri, 3 Nov 2017 13:08:31 +0000 (14:08 +0100)
committerJean-Paul Pelteret <jppelteret@gmail.com>
Thu, 16 Nov 2017 05:30:47 +0000 (06:30 +0100)
include/deal.II/differentiation/ad.h
include/deal.II/differentiation/ad/adolc_number_types.h [new file with mode: 0644]
source/CMakeLists.txt
source/differentiation/CMakeLists.txt [new file with mode: 0644]
source/differentiation/ad/CMakeLists.txt [new file with mode: 0644]
source/differentiation/ad/adolc_number_types.cc [new file with mode: 0644]
source/differentiation/ad/adolc_number_types.inst.in [new file with mode: 0644]

index 482fbb5ccfb6b4d254be8e36e7b779923f496302..3e7b5f9c62ed35455c0a72cacbb54c008c9fb8e0 100644 (file)
@@ -23,6 +23,9 @@
 #include <deal.II/differentiation/ad/ad_number_types.h>
 #include <deal.II/differentiation/ad/ad_number_traits.h>
 
+#include <deal.II/differentiation/ad/adolc_number_types.h>
+#include <deal.II/differentiation/ad/adolc_product_types.h>
+
 DEAL_II_NAMESPACE_OPEN
 
 /**
diff --git a/include/deal.II/differentiation/ad/adolc_number_types.h b/include/deal.II/differentiation/ad/adolc_number_types.h
new file mode 100644 (file)
index 0000000..8dc56ef
--- /dev/null
@@ -0,0 +1,477 @@
+// ---------------------------------------------------------------------
+//
+// 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_adolc_number_types_h
+#define dealii_differentiation_ad_adolc_number_types_h
+
+#include <deal.II/base/config.h>
+
+#ifdef DEAL_II_WITH_ADOLC
+
+DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
+#include <adolc/internal/adolc_settings.h>
+#include <adolc/internal/adubfunc.h> // Taped double math functions
+
+#include <adolc/adouble.h> // Taped double
+#include <adolc/adtl.h>    // Tapeless double
+DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
+
+#include <deal.II/base/numbers.h>
+#include <deal.II/base/exceptions.h>
+
+#include <deal.II/differentiation/ad/ad_number_types.h>
+#include <deal.II/differentiation/ad/ad_number_traits.h>
+
+#include <complex>
+#include <type_traits>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+namespace Differentiation
+{
+  namespace AD
+  {
+    /**
+     * A struct to indicate whether a given @p NumberType is an
+     * Adol-C number or not. By default, numbers are not considered to
+     * have the necessary characteristics to fulfill this condition.
+     *
+     * @author Jean-Paul Pelteret, 2017
+     */
+    template <typename NumberType, typename = void>
+    struct is_adolc_number;
+  }
+}
+
+
+/* --------------------------- inline and template functions and specializations ------------------------- */
+
+
+#ifndef DOXYGEN
+
+
+namespace Differentiation
+{
+  namespace AD
+  {
+
+    namespace internal
+    {
+
+      /**
+       * A specialization for the information struct for taped Adol-C
+       * numbers.
+       */
+      template<typename ScalarType>
+      struct ADNumberInfoFromEnum<ScalarType, Differentiation::AD::NumberTypes::adolc_taped,
+        typename std::enable_if<std::is_floating_point<ScalarType>::value>::type
+        >
+      {
+        static const bool         is_taped = true;
+        typedef adouble           real_type;
+        typedef double            derivative_type;
+        static const unsigned int n_supported_derivative_levels
+          = std::numeric_limits<unsigned int>::max();
+      };
+
+
+      /**
+       * A specialization for the information struct for tapeless Adol-C
+       * numbers.
+       */
+      template<typename ScalarType>
+      struct ADNumberInfoFromEnum<ScalarType, Differentiation::AD::NumberTypes::adolc_tapeless,
+        typename std::enable_if<std::is_floating_point<ScalarType>::value>::type
+        >
+      {
+        static const bool         is_taped = false;
+        typedef adtl::adouble     real_type;
+        typedef double            derivative_type;
+        static const unsigned int n_supported_derivative_levels = 1;
+      };
+
+
+      template<typename ADNumberType>
+      struct Marking<ADNumberType, typename std::enable_if<
+        ADNumberTraits<ADNumberType>::type_code == NumberTypes::adolc_taped &&
+        ADNumberTraits<ADNumberType>::is_real_valued
+        >::type
+        >
+      {
+        typedef typename ADNumberTraits<ADNumberType>::scalar_type scalar_type;
+
+        /*
+         * Initialize the state of an independent variable.
+         */
+        static void
+        independent_variable(const scalar_type  &in,
+                             const unsigned int ,
+                             const unsigned int ,
+                             ADNumberType       &out)
+        {
+          out <<= in;
+        }
+
+        /*
+         * Initialize the state of a dependent variable.
+         *
+         * @note The second argument must be writable, so we
+         * simply pass a copy instead of a non-constant reference.
+         */
+        static void
+        dependent_variable(ADNumberType      &out,
+                           ADNumberType       func)
+        {
+          // Store the value only (strip it of all sensitivities)
+          out = ADNumberTraits<ADNumberType>::get_scalar_value(func);
+          // Mark as a dependent variable
+          scalar_type tmp;
+          func >>= tmp;
+        }
+      };
+
+      template<typename ADNumberType>
+      struct Marking<ADNumberType, typename std::enable_if<
+        ADNumberTraits<ADNumberType>::type_code == NumberTypes::adolc_tapeless &&
+        ADNumberTraits<ADNumberType>::is_real_valued
+        >::type>
+      {
+        typedef typename ADNumberTraits<ADNumberType>::scalar_type scalar_type;
+
+        /*
+         * Initialize the state of an independent variable.
+         */
+        static void
+        independent_variable(const scalar_type  &in,
+                             const unsigned int  index,
+                             const unsigned int  ,
+                             ADNumberType       &out)
+        {
+          // It is important that the tapeless variables have their values set
+          // before defining their directional derivative index
+          out = in;
+
+          // Violating this condition when will result in an Adol-C internal
+          // error. We could rather always throw here in order to provide a
+          // less cryptic message.
+          AssertThrow(index < adtl::getNumDir(),
+                      ExcMessage("The index number of the independent variable being "
+                                 "marked is greater than the number of independent "
+                                 "variables that have been declared."));
+          out.setADValue(index, 1 /*seed value for first derivative*/);
+        }
+
+        /*
+         * Initialize the state of a dependent variable.
+         */
+        static void
+        dependent_variable(ADNumberType       &out,
+                           const ADNumberType &func)
+        {
+          // Simply transfer value with sensitivities
+          out = 0.0;
+          out = func;
+        }
+      };
+
+
+      /**
+      * A struct to help extract certain information associated with
+      * taped Adol-C auto-differentiable numbers.
+      *
+      * @author Jean-Paul Pelteret, 2017
+      */
+      template<>
+      struct ExtractData<adouble>
+      {
+        /**
+         * Extract the real value.
+         */
+        static double
+        value (const adouble &x)
+        {
+          return x.getValue();
+        }
+
+
+        /**
+         * Extract the number of directional derivatives.
+         *
+         * This information is not available for taped numbers, and this
+         * function exists for aesthetic/compatibility reasons only.
+         */
+        static unsigned int
+        n_directional_derivatives (const adouble &)
+        {
+          return 0;
+        }
+
+
+        /**
+         * Extract the directional derivative in the specified @p direction.
+         *
+         * It is in fact not possible to perform this operation in this manner,
+         * for taped numbers, and this function exists for
+         * aesthetic/compatibility reasons only.
+         */
+        static double
+        directional_derivative (const adouble &,
+                                const unsigned int)
+        {
+          AssertThrow(false,
+                      ExcMessage("The derivative values for taped Adol-C numbers must be"
+                                 "computed through the ::gradient function."));
+          return 0.0;
+        }
+      };
+
+
+      /**
+       * A struct to help extract certain information associated with
+       * tapeless Adol-C auto-differentiable numbers.
+       *
+       * @author Jean-Paul Pelteret, 2017
+       */
+      template<>
+      struct ExtractData<adtl::adouble>
+      {
+        /**
+         * Extract the floating point value.
+         */
+        static double
+        value (const adtl::adouble &x)
+        {
+          return x.getValue();
+        }
+
+
+        /**
+         * Extract the number of directional derivatives.
+         */
+        static unsigned int
+        n_directional_derivatives (const adtl::adouble &)
+        {
+          // This is a global function call...
+          return adtl::getNumDir();
+        }
+
+
+        /**
+         * Extract the directional derivative in the specified @p direction.
+         */
+        static double
+        directional_derivative  (const adtl::adouble &x,
+                                 const unsigned int   direction)
+        {
+          Assert(direction < n_directional_derivatives(x),
+                 ExcMessage("Requested directional derivative is greater than the number "
+                            "registered by Adol-C."));
+          return x.getADValue(direction);
+        }
+      };
+
+    } // namespace internal
+
+
+
+    /**
+     * Specialization of the general AdolCWrappers::ADNumberTraits class that
+     * provides relevant information for auto-differentiable numbers.
+     * This specialization is for the case where @p ADNumberType is an
+     * taped Adol-C (real) double.
+     *
+     * @note In this case the number traits are the same as those for a taped double.
+     *
+     * @author Jean-Paul Pelteret, 2017
+     */
+    template<typename ADNumberType>
+    struct ADNumberTraits<ADNumberType,
+      typename std::enable_if<
+      std::is_same<ADNumberType, adouble>::value
+      >::type>
+      : NumberTraits<double, NumberTypes::adolc_taped>
+    {
+      static_assert(
+        std::is_same<ad_type,adouble>::value,
+        "Incorrect template type selected for taped ad_type");
+      static_assert(
+        is_taped == true,
+        "Incorrect setting for taping");
+    };
+
+
+
+    /**
+     * Specialization of the general ADNumberTraits class that
+     * provides relevant information for auto-differentiable numbers.
+     * This specialization is for the case where @p ADNumberType is an
+     * taped Adol-C complex double.
+     *
+     * @note In this case the number traits are the same as those for a taped complex
+     * double.
+     *
+     * @author Jean-Paul Pelteret, 2017
+     */
+    template<typename ADNumberType>
+    struct ADNumberTraits<ADNumberType,
+      typename std::enable_if<
+      std::is_same<ADNumberType, std::complex<adouble> >::value
+      >::type>
+      : NumberTraits<std::complex<double>, NumberTypes::adolc_taped>
+    {
+      static_assert(
+        std::is_same<ad_type,std::complex<adouble> >::value,
+        "Incorrect template type selected for taped ad_type");
+      static_assert(
+        is_taped == true,
+        "Incorrect setting for taping");
+    };
+
+
+
+    /**
+     * Specialization of the general ADNumberTraits class that
+     * provides relevant information for auto-differentiable numbers.
+     * This specialization is for the case where @p ADNumberType is an
+     * tapeless Adol-C (real) double.
+     *
+     * @note In this case the number traits are the same as those for a tapeless double.
+     *
+     * @author Jean-Paul Pelteret, 2017
+     */
+    template<typename ADNumberType>
+    struct ADNumberTraits<ADNumberType,
+      typename std::enable_if<
+      std::is_same<ADNumberType, adtl::adouble>::value
+      >::type>
+      : NumberTraits<double, NumberTypes::adolc_tapeless>
+    {
+      static_assert(
+        std::is_same<ad_type,adtl::adouble>::value,
+        "Incorrect template type selected for tapeless ad_type");
+      static_assert(
+        is_tapeless == true,
+        "Incorrect setting for taping");
+    };
+
+
+
+    /**
+     * Specialization of the general ADNumberTraits class that
+     * provides relevant information for auto-differentiable numbers.
+     * This specialization is for the case where @p ADNumberType is an
+     * tapeless Adol-C complex double.
+     *
+     * @note In this case the number traits are the same as those for a tapeless
+     * complex double.
+     *
+     * @author Jean-Paul Pelteret, 2017
+     */
+    template<typename ADNumberType>
+    struct ADNumberTraits<ADNumberType,
+      typename std::enable_if<
+      std::is_same<ADNumberType, std::complex<adtl::adouble> >::value
+      >::type>
+      : NumberTraits<std::complex<double>, NumberTypes::adolc_tapeless>
+    {
+      static_assert(
+        std::is_same<ad_type,std::complex<adtl::adouble> >::value,
+        "Incorrect template type selected for tapeless ad_type");
+      static_assert(
+        is_tapeless == true,
+        "Incorrect setting for taping");
+    };
+
+
+
+    /**
+     * Specialization of the NumberTraits struct for
+     * the (otherwise disabled) taped Adol-C number type.
+     */
+    template<>
+    struct NumberTraits<adouble,NumberTypes::adolc_taped>
+      : NumberTraits<typename ADNumberTraits<adouble>::scalar_type,NumberTypes::adolc_taped>
+    {};
+
+
+    /**
+     * Specialization of the NumberTraits struct for
+     * the (otherwise disabled) taped Adol-C complex number type.
+     */
+    template<>
+    struct NumberTraits<std::complex<adouble>,NumberTypes::adolc_taped>
+      : NumberTraits<typename ADNumberTraits<std::complex<adouble> >::scalar_type,NumberTypes::adolc_taped>
+    {};
+
+
+    /**
+     * Specialization of the NumberTraits struct for
+     * the (otherwise disabled) tapeless Adol-C number type.
+     */
+    template<>
+    struct NumberTraits<adtl::adouble,NumberTypes::adolc_tapeless>
+      : NumberTraits<typename ADNumberTraits<adtl::adouble>::scalar_type,NumberTypes::adolc_tapeless>
+    {};
+
+
+    /**
+     * Specialization of the NumberTraits struct for
+     * the (otherwise disabled) tapeless Adol-C complex number type.
+     */
+    template<>
+    struct NumberTraits<std::complex<adtl::adouble>,NumberTypes::adolc_tapeless>
+      : NumberTraits<typename ADNumberTraits<std::complex<adtl::adouble> >::scalar_type,NumberTypes::adolc_tapeless>
+    {};
+
+
+
+    /**
+     * A struct to indicate whether a given @p NumberType is an
+     * Adol-C number or not. By default, numbers are not considered to
+     * have the necessary characteristics to fulfill this condition.
+     */
+    template <typename NumberType, typename>
+    struct is_adolc_number
+      : std::false_type
+    {};
+
+
+
+    /**
+     * Specialization of the struct for the case when the input template
+     * parameter is a (real or complex; taped or tapeless) Adol-C number.
+     */
+    template <typename NumberType>
+    struct is_adolc_number<NumberType, typename std::enable_if<
+      ADNumberTraits<typename std::decay<NumberType>::type>::type_code == NumberTypes::adolc_taped ||
+      ADNumberTraits<typename std::decay<NumberType>::type>::type_code == NumberTypes::adolc_tapeless
+      >::type>
+      : std::true_type
+    {};
+
+  } // namespace AD
+} // namespace Differentiation
+
+
+#endif  // DOXYGEN
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+
+#endif // DEAL_II_WITH_ADOLC
+
+#endif
index f789a8597f1cbb2ef3634fb8d711b7fc318f3d5d..14c2e42fd1a9ecb19a239160e8049d69d8edd03b 100644 (file)
@@ -49,6 +49,7 @@ ADD_SUBDIRECTORY(matrix_free)
 ADD_SUBDIRECTORY(meshworker)
 ADD_SUBDIRECTORY(opencascade)
 ADD_SUBDIRECTORY(particles)
+ADD_SUBDIRECTORY(differentiation)
 ADD_SUBDIRECTORY(physics)
 ADD_SUBDIRECTORY(optimization/rol)
 ADD_SUBDIRECTORY(non_matching)
diff --git a/source/differentiation/CMakeLists.txt b/source/differentiation/CMakeLists.txt
new file mode 100644 (file)
index 0000000..77bb11c
--- /dev/null
@@ -0,0 +1,16 @@
+## ---------------------------------------------------------------------
+##
+## Copyright (C) 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.
+##
+## ---------------------------------------------------------------------
+
+ADD_SUBDIRECTORY(ad)
diff --git a/source/differentiation/ad/CMakeLists.txt b/source/differentiation/ad/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d445d49
--- /dev/null
@@ -0,0 +1,31 @@
+## ---------------------------------------------------------------------
+##
+## Copyright (C) 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.
+##
+## ---------------------------------------------------------------------
+
+INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
+
+SET(_src
+  adolc_number_types.cc
+  )
+
+SET(_inst
+  adolc_number_types.inst.in
+  )
+
+FILE(GLOB _header
+  ${CMAKE_SOURCE_DIR}/include/deal.II/differentiation/ad/*.h
+  )
+
+DEAL_II_ADD_LIBRARY(obj_differentiation_ad OBJECT ${_src} ${_header} ${_inst})
+EXPAND_INSTANTIATIONS(obj_differentiation_ad "${_inst}")
diff --git a/source/differentiation/ad/adolc_number_types.cc b/source/differentiation/ad/adolc_number_types.cc
new file mode 100644 (file)
index 0000000..073e421
--- /dev/null
@@ -0,0 +1,31 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/base/config.h>
+
+#ifdef DEAL_II_WITH_ADOLC
+
+#include <deal.II/differentiation/ad/adolc_number_types.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+/*---------------------- Explicit Instantiations ----------------------*/
+
+#include "adolc_number_types.inst"
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
diff --git a/source/differentiation/ad/adolc_number_types.inst.in b/source/differentiation/ad/adolc_number_types.inst.in
new file mode 100644 (file)
index 0000000..1f57953
--- /dev/null
@@ -0,0 +1,51 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 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.
+//
+// ---------------------------------------------------------------------
+
+for (Number : DIFFERENTIABLE_ADOLC_REAL_SCALARS)
+{
+    namespace Differentiation
+    \{
+    namespace AD
+    \{
+    template struct ADNumberTraits<Number>;
+    \}
+    \}
+}
+
+
+for (Number : REAL_SCALARS)
+{
+    namespace Differentiation
+    \{
+    namespace AD
+    \{
+    template struct NumberTraits<Number,NumberTypes::adolc_taped>;
+    template struct NumberTraits<Number,NumberTypes::adolc_tapeless>;
+    \}
+    \}
+}
+
+
+for (Number : COMPLEX_SCALARS)
+{
+    namespace Differentiation
+    \{
+    namespace AD
+    \{
+    template struct NumberTraits<Number,NumberTypes::adolc_taped>;
+    template struct NumberTraits<Number,NumberTypes::adolc_tapeless>;
+    \}
+    \}
+}

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.