16 #ifndef dealii_differentiation_ad_ad_drivers_h 17 #define dealii_differentiation_ad_ad_drivers_h 19 #include <deal.II/base/config.h> 21 #include <deal.II/base/exceptions.h> 22 #include <deal.II/base/types.h> 23 #include <deal.II/base/utilities.h> 25 #include <deal.II/differentiation/ad/ad_number_traits.h> 26 #include <deal.II/differentiation/ad/ad_number_types.h> 27 #include <deal.II/differentiation/ad/adolc_number_types.h> 28 #include <deal.II/differentiation/ad/sacado_number_types.h> 30 #include <deal.II/lac/full_matrix.h> 31 #include <deal.II/lac/vector.h> 33 #ifdef DEAL_II_WITH_ADOLC 35 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
36 # include <adolc/drivers/drivers.h> 37 # include <adolc/internal/usrparms.h> 38 # include <adolc/taping.h> 39 DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
41 #endif // DEAL_II_WITH_ADOLC 46 DEAL_II_NAMESPACE_OPEN
64 "This function is called in a class that is expected to be specialized " 65 "for auto-differentiable numbers.");
72 "This function is only available if deal.II is compiled with ADOL-C.");
86 <<
"The number of derivative levels that this auto-differentiable number type supports is " 88 <<
", but to perform the intended operation the number must support at least " 89 << arg2 <<
" levels.");
125 #ifdef DEAL_II_WITH_ADOLC 134 std::numeric_limits<types::tape_index>::max();
135 #endif // DEAL_II_WITH_ADOLC 155 template <
typename ADNumberType,
typename ScalarType,
typename T =
void>
177 const bool keep_independent_values);
194 const bool keep_independent_values,
210 const bool write_tapes_to_file);
220 print_tape_stats(std::ostream & stream,
242 const std::vector<ScalarType> &independent_variables);
259 const std::vector<ScalarType> &independent_variables,
260 Vector<ScalarType> & gradient);
277 const std::vector<ScalarType> &independent_variables,
301 const unsigned int n_dependent_variables,
302 const std::vector<ScalarType> &independent_variables,
303 Vector<ScalarType> & values);
325 const unsigned int n_dependent_variables,
326 const std::vector<ScalarType> &independent_variables,
351 template <
typename ADNumberType,
typename ScalarType,
typename T =
void>
381 initialize_global_environment(
const unsigned int n_independent_variables);
399 value(
const std::vector<ADNumberType> &dependent_variables);
415 gradient(
const std::vector<ADNumberType> &independent_variables,
416 const std::vector<ADNumberType> &dependent_variables,
417 Vector<ScalarType> & gradient);
433 hessian(
const std::vector<ADNumberType> &independent_variables,
434 const std::vector<ADNumberType> &dependent_variables,
454 values(
const std::vector<ADNumberType> &dependent_variables,
455 Vector<ScalarType> & values);
475 jacobian(
const std::vector<ADNumberType> &independent_variables,
476 const std::vector<ADNumberType> &dependent_variables,
499 template <
typename ADNumberType,
typename ScalarType,
typename T>
509 template <
typename ADNumberType,
typename ScalarType,
typename T>
523 template <
typename ADNumberType,
typename ScalarType,
typename T>
533 template <
typename ADNumberType,
typename ScalarType,
typename T>
543 template <
typename ADNumberType,
typename ScalarType,
typename T>
547 const std::vector<ScalarType> &)
550 return ScalarType(0.0);
554 template <
typename ADNumberType,
typename ScalarType,
typename T>
558 const std::vector<ScalarType> &,
559 Vector<ScalarType> &)
565 template <
typename ADNumberType,
typename ScalarType,
typename T>
569 const std::vector<ScalarType> &,
576 template <
typename ADNumberType,
typename ScalarType,
typename T>
581 const std::vector<ScalarType> &,
582 Vector<ScalarType> &)
588 template <
typename ADNumberType,
typename ScalarType,
typename T>
593 const std::vector<ScalarType> &,
600 # ifdef DEAL_II_WITH_ADOLC 609 template <
typename ADNumberType>
613 typename std::enable_if<ADNumberTraits<ADNumberType>::type_code ==
614 NumberTypes::adolc_taped>::type>
616 using scalar_type = double;
622 const bool keep_independent_values)
624 trace_on(tape_index, keep_independent_values);
629 const bool keep_independent_values,
636 keep_independent_values,
645 const bool write_tapes_to_file)
647 if (write_tapes_to_file)
648 trace_off(active_tape_index);
658 std::vector<std::size_t> counts(STAT_SIZE);
659 ::tapestats(tape_index, counts.data());
662 <<
"Tape index: " << tape_index <<
"\n" 663 <<
"Number of independent variables: " << counts[0] <<
"\n" 664 <<
"Number of dependent variables: " << counts[1] <<
"\n" 665 <<
"Max number of live, active variables: " << counts[2] <<
"\n" 666 <<
"Size of taylor stack (number of overwrites): " << counts[3]
668 <<
"Operations buffer size: " << counts[4] <<
"\n" 669 <<
"Total number of recorded operations: " << counts[5] <<
"\n" 670 <<
"Operations file written or not: " << counts[6] <<
"\n" 671 <<
"Overall number of locations: " << counts[7] <<
"\n" 672 <<
"Locations file written or not: " << counts[8] <<
"\n" 673 <<
"Overall number of values: " << counts[9] <<
"\n" 674 <<
"Values file written or not: " << counts[10] <<
"\n" 675 <<
"Locations buffer size: " << counts[11] <<
"\n" 676 <<
"Values buffer size: " << counts[12] <<
"\n" 677 <<
"Taylor buffer size: " << counts[13] <<
"\n" 678 <<
"Number of eq_*_prod for sparsity pattern: " << counts[14] <<
"\n" 679 <<
"Use of 'min_op', deferred to 'abs_op' for piecewise calculations: " 680 << counts[15] <<
"\n" 681 <<
"Number of 'abs' calls that can switch branch: " << counts[16]
683 <<
"Number of parameters (doubles) interchangable without retaping: " 684 << counts[17] <<
"\n" 693 const std::vector<scalar_type> &independent_variables)
695 scalar_type value = 0.0;
697 ::function(active_tape_index,
699 independent_variables.size(),
700 const_cast<double *
>(independent_variables.data()),
708 const std::vector<scalar_type> &independent_variables,
709 Vector<scalar_type> & gradient)
716 Assert(gradient.size() == independent_variables.size(),
718 independent_variables.size()));
723 ::gradient(active_tape_index,
724 independent_variables.size(),
725 const_cast<scalar_type *
>(independent_variables.data()),
731 const std::vector<scalar_type> &independent_variables,
739 Assert(hessian.
m() == independent_variables.size(),
741 Assert(hessian.
n() == independent_variables.size(),
744 const unsigned int n_independent_variables =
745 independent_variables.size();
746 std::vector<scalar_type *> H(n_independent_variables);
747 for (
unsigned int i = 0; i < n_independent_variables; ++i)
748 H[i] = &(hessian[i][0]);
750 ::hessian(active_tape_index,
751 n_independent_variables,
752 const_cast<scalar_type *>(independent_variables.data()),
758 for (
unsigned int i = 0; i < n_independent_variables; i++)
759 for (
unsigned int j = 0; j < i; j++)
760 hessian[j][i] = hessian[i][j];
767 const unsigned int n_dependent_variables,
768 const std::vector<scalar_type> &independent_variables,
769 Vector<scalar_type> & values)
771 Assert(values.size() == n_dependent_variables,
777 ::function(active_tape_index,
778 n_dependent_variables,
779 independent_variables.size(),
780 const_cast<scalar_type *
>(independent_variables.data()),
786 const unsigned int n_dependent_variables,
787 const std::vector<scalar_type> &independent_variables,
795 Assert(jacobian.
m() == n_dependent_variables,
797 Assert(jacobian.
n() == independent_variables.size(),
799 independent_variables.size()));
801 std::vector<scalar_type *> J(n_dependent_variables);
802 for (
unsigned int i = 0; i < n_dependent_variables; ++i)
803 J[i] = &(jacobian[i][0]);
805 ::jacobian(active_tape_index,
806 n_dependent_variables,
807 independent_variables.size(),
808 independent_variables.data(),
813 # else // DEAL_II_WITH_ADOLC 823 template <
typename ADNumberType>
827 typename std::enable_if<ADNumberTraits<ADNumberType>::type_code ==
828 NumberTypes::adolc_taped>::type>
830 using scalar_type = double;
875 const std::vector<scalar_type> &,
876 Vector<scalar_type> &)
883 const std::vector<scalar_type> &,
894 const std::vector<scalar_type> &,
895 Vector<scalar_type> &)
903 const std::vector<scalar_type> &,
910 # endif // DEAL_II_WITH_ADOLC 921 template <
typename ADNumberType>
925 typename std::enable_if<ADNumberTraits<ADNumberType>::type_code ==
926 NumberTypes::adolc_taped>::type>
928 using scalar_type = float;
934 const bool keep_independent_values)
939 tape_index, keep_independent_values);
944 const bool keep_independent_values,
954 keep_independent_values,
963 const bool write_tapes_to_file)
968 write_tapes_to_file);
984 const std::vector<scalar_type> &independent_variables)
989 active_tape_index, vector_float_to_double(independent_variables));
994 const std::vector<scalar_type> &independent_variables,
995 Vector<scalar_type> & gradient)
1001 vector_float_to_double(
1002 independent_variables),
1004 gradient = gradient_double;
1009 const std::vector<scalar_type> &independent_variables,
1016 vector_float_to_double(
1017 independent_variables),
1019 hessian = hessian_double;
1026 const unsigned int n_dependent_variables,
1027 const std::vector<scalar_type> &independent_variables,
1028 Vector<scalar_type> & values)
1034 n_dependent_variables,
1035 vector_float_to_double(
1036 independent_variables),
1038 values = values_double;
1043 const unsigned int n_dependent_variables,
1044 const std::vector<scalar_type> &independent_variables,
1051 n_dependent_variables,
1052 vector_float_to_double(
1053 independent_variables),
1055 jacobian = jacobian_double;
1062 static std::vector<double>
1063 vector_float_to_double(
const std::vector<float> &in)
1065 std::vector<double> out(in.size());
1066 std::copy(in.begin(), in.end(), out.begin());
1075 template <
typename ADNumberType,
typename ScalarType,
typename T>
1084 template <
typename ADNumberType,
typename ScalarType,
typename T>
1087 const std::vector<ADNumberType> &)
1090 return ScalarType(0.0);
1094 template <
typename ADNumberType,
typename ScalarType,
typename T>
1097 const std::vector<ADNumberType> &,
1098 const std::vector<ADNumberType> &,
1099 Vector<ScalarType> &)
1105 template <
typename ADNumberType,
typename ScalarType,
typename T>
1108 const std::vector<ADNumberType> &,
1109 const std::vector<ADNumberType> &,
1116 template <
typename ADNumberType,
typename ScalarType,
typename T>
1119 const std::vector<ADNumberType> &,
1120 Vector<ScalarType> &)
1126 template <
typename ADNumberType,
typename ScalarType,
typename T>
1129 const std::vector<ADNumberType> &,
1130 const std::vector<ADNumberType> &,
1143 template <
typename ADNumberType>
1145 typename std::enable_if<!(ADNumberTraits<ADNumberType>::type_code ==
1149 reverse_mode_dependent_variable_activation(ADNumberType &)
1152 # ifdef DEAL_II_TRILINOS_WITH_SACADO 1163 template <
typename ADNumberType>
1164 static typename std::enable_if<ADNumberTraits<ADNumberType>::type_code ==
1168 reverse_mode_dependent_variable_activation(
1169 ADNumberType &dependent_variable)
1179 ADNumberType::Outvar_Gradcomp(dependent_variable);
1189 template <
typename ADNumberType>
1191 typename std::enable_if<!(ADNumberTraits<ADNumberType>::type_code ==
1193 configure_tapeless_mode(
const unsigned int)
1197 # ifdef DEAL_II_WITH_ADOLC 1207 template <
typename ADNumberType>
1208 static typename std::enable_if<ADNumberTraits<ADNumberType>::type_code ==
1210 configure_tapeless_mode(
const unsigned int n_directional_derivatives)
1212 # ifdef DEAL_II_ADOLC_WITH_TAPELESS_REFCOUNTING 1227 const std::size_t n_live_variables = adtl::refcounter::getNumLiveVar();
1228 if (n_live_variables == 0)
1230 adtl::setNumDir(n_directional_derivatives);
1239 const std::size_t n_set_directional_derivatives = adtl::getNumDir();
1240 if (n_directional_derivatives > n_set_directional_derivatives)
1242 n_live_variables == 0,
1244 "There are currently " +
1247 "adtl::adouble variables in existence. They currently " 1250 " directional derivatives " 1251 "but you wish to increase this to " +
1254 "To safely change (or more specifically in this case, " 1255 "increase) the number of directional derivatives, there " 1256 "must be no tapeless doubles in local/global scope."));
1262 adtl::setNumDir(n_directional_derivatives);
1266 # else // DEAL_II_WITH_ADOLC 1268 template <
typename ADNumberType>
1269 static typename std::enable_if<ADNumberTraits<ADNumberType>::type_code ==
1271 configure_tapeless_mode(
const unsigned int n_directional_derivatives)
1286 template <
typename ADNumberType,
typename ScalarType>
1290 typename std::enable_if<ADNumberTraits<ADNumberType>::type_code ==
1291 NumberTypes::sacado_rad ||
1292 ADNumberTraits<ADNumberType>::type_code ==
1293 NumberTypes::sacado_rad_dfad>::type>
1298 initialize_global_environment(
const unsigned int n_independent_variables)
1300 internal::configure_tapeless_mode<ADNumberType>(
1301 n_independent_variables);
1307 value(
const std::vector<ADNumberType> &dependent_variables)
1309 Assert(dependent_variables.size() == 1,
1312 dependent_variables[0]);
1316 gradient(
const std::vector<ADNumberType> &independent_variables,
1317 const std::vector<ADNumberType> &dependent_variables,
1318 Vector<ScalarType> & gradient)
1325 Assert(dependent_variables.size() == 1,
1327 Assert(gradient.size() == independent_variables.size(),
1329 independent_variables.size()));
1333 internal::reverse_mode_dependent_variable_activation(
1334 const_cast<ADNumberType &>(dependent_variables[0]));
1335 const std::size_t n_independent_variables =
1336 independent_variables.size();
1337 for (
unsigned int i = 0; i < n_independent_variables; i++)
1340 independent_variables[i],
1345 hessian(
const std::vector<ADNumberType> &independent_variables,
1346 const std::vector<ADNumberType> &dependent_variables,
1354 Assert(dependent_variables.size() == 1,
1356 Assert(hessian.
m() == independent_variables.size(),
1358 Assert(hessian.
n() == independent_variables.size(),
1363 internal::reverse_mode_dependent_variable_activation(
1364 const_cast<ADNumberType &>(dependent_variables[0]));
1365 const std::size_t n_independent_variables =
1366 independent_variables.size();
1367 for (
unsigned int i = 0; i < n_independent_variables; i++)
1369 using derivative_type =
1371 const derivative_type gradient_i =
1373 independent_variables[i], i);
1375 for (
unsigned int j = 0; j <= i; ++j)
1380 const ScalarType hessian_ij =
1384 hessian[i][j] = hessian_ij;
1386 hessian[j][i] = hessian_ij;
1394 values(
const std::vector<ADNumberType> &dependent_variables,
1395 Vector<ScalarType> & values)
1397 Assert(values.size() == dependent_variables.size(),
1400 const std::size_t n_dependent_variables = dependent_variables.size();
1401 for (
unsigned int i = 0; i < n_dependent_variables; i++)
1403 dependent_variables[i]);
1407 jacobian(
const std::vector<ADNumberType> &independent_variables,
1408 const std::vector<ADNumberType> &dependent_variables,
1416 Assert(jacobian.
m() == dependent_variables.size(),
1418 Assert(jacobian.
n() == independent_variables.size(),
1420 independent_variables.size()));
1422 const std::size_t n_independent_variables =
1423 independent_variables.size();
1424 const std::size_t n_dependent_variables = dependent_variables.size();
1435 using accumulation_type =
1437 std::vector<accumulation_type> rad_accumulation(
1438 n_independent_variables,
1441 for (
unsigned int i = 0; i < n_dependent_variables; i++)
1443 internal::reverse_mode_dependent_variable_activation(
1444 const_cast<ADNumberType &>(dependent_variables[i]));
1445 for (
unsigned int j = 0; j < n_independent_variables; j++)
1447 const accumulation_type df_i_dx_j =
1449 independent_variables[j],
1451 rad_accumulation[j];
1454 rad_accumulation[j] += df_i_dx_j;
1466 template <
typename ADNumberType,
typename ScalarType>
1470 typename std::enable_if<ADNumberTraits<ADNumberType>::type_code ==
1471 NumberTypes::adolc_tapeless ||
1472 ADNumberTraits<ADNumberType>::type_code ==
1473 NumberTypes::sacado_dfad ||
1474 ADNumberTraits<ADNumberType>::type_code ==
1475 NumberTypes::sacado_dfad_dfad>::type>
1480 initialize_global_environment(
const unsigned int n_independent_variables)
1482 internal::configure_tapeless_mode<ADNumberType>(
1483 n_independent_variables);
1489 value(
const std::vector<ADNumberType> &dependent_variables)
1491 Assert(dependent_variables.size() == 1,
1494 dependent_variables[0]);
1498 gradient(
const std::vector<ADNumberType> &independent_variables,
1499 const std::vector<ADNumberType> &dependent_variables,
1500 Vector<ScalarType> & gradient)
1507 Assert(dependent_variables.size() == 1,
1509 Assert(gradient.size() == independent_variables.size(),
1511 independent_variables.size()));
1515 const std::size_t n_independent_variables =
1516 independent_variables.size();
1517 for (
unsigned int i = 0; i < n_independent_variables; i++)
1520 dependent_variables[0], i));
1524 hessian(
const std::vector<ADNumberType> &independent_variables,
1525 const std::vector<ADNumberType> &dependent_variables,
1533 Assert(dependent_variables.size() == 1,
1535 Assert(hessian.
m() == independent_variables.size(),
1537 Assert(hessian.
n() == independent_variables.size(),
1542 const std::size_t n_independent_variables =
1543 independent_variables.size();
1544 for (
unsigned int i = 0; i < n_independent_variables; i++)
1546 using derivative_type =
1548 const derivative_type gradient_i =
1550 dependent_variables[0], i);
1552 for (
unsigned int j = 0; j <= i; ++j)
1557 const ScalarType hessian_ij =
1561 hessian[i][j] = hessian_ij;
1563 hessian[j][i] = hessian_ij;
1571 values(
const std::vector<ADNumberType> &dependent_variables,
1572 Vector<ScalarType> & values)
1574 Assert(values.size() == dependent_variables.size(),
1577 const std::size_t n_dependent_variables = dependent_variables.size();
1578 for (
unsigned int i = 0; i < n_dependent_variables; i++)
1580 dependent_variables[i]);
1584 jacobian(
const std::vector<ADNumberType> &independent_variables,
1585 const std::vector<ADNumberType> &dependent_variables,
1593 Assert(jacobian.
m() == dependent_variables.size(),
1595 Assert(jacobian.
n() == independent_variables.size(),
1597 independent_variables.size()));
1599 const std::size_t n_independent_variables =
1600 independent_variables.size();
1601 const std::size_t n_dependent_variables = dependent_variables.size();
1605 for (
unsigned int i = 0; i < n_dependent_variables; i++)
1606 for (
unsigned int j = 0; j < n_independent_variables; j++)
1609 dependent_variables[i], j));
1619 DEAL_II_NAMESPACE_CLOSE
static::ExceptionBase & ExcRequiresADNumberSpecialization()
#define DeclException2(Exception2, type1, type2, outsequence)
static ScalarType value(const std::vector< ADNumberType > &dependent_variables)
static::ExceptionBase & ExcSupportedDerivativeLevels(std::size_t arg1, std::size_t arg2)
static void enable_taping(const types::tape_index tape_index, const bool keep_independent_values)
static void jacobian(const types::tape_index active_tape_index, const unsigned int n_dependent_variables, const std::vector< ScalarType > &independent_variables, FullMatrix< ScalarType > &jacobian)
#define AssertThrow(cond, exc)
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
static void print_tape_stats(std::ostream &stream, const types::tape_index tape_index)
static::ExceptionBase & ExcMessage(std::string arg1)
static void hessian(const std::vector< ADNumberType > &independent_variables, const std::vector< ADNumberType > &dependent_variables, FullMatrix< ScalarType > &hessian)
#define Assert(cond, exc)
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define DeclExceptionMsg(Exception, defaulttext)
static void hessian(const types::tape_index active_tape_index, const std::vector< ScalarType > &independent_variables, FullMatrix< ScalarType > &hessian)
static void jacobian(const std::vector< ADNumberType > &independent_variables, const std::vector< ADNumberType > &dependent_variables, FullMatrix< ScalarType > &jacobian)
static void initialize_global_environment(const unsigned int n_independent_variables)
static::ExceptionBase & ExcRequiresAdolC()
static const types::tape_index max_tape_index
static void values(const std::vector< ADNumberType > &dependent_variables, Vector< ScalarType > &values)
static ScalarType value(const types::tape_index active_tape_index, const std::vector< ScalarType > &independent_variables)
static void values(const types::tape_index active_tape_index, const unsigned int n_dependent_variables, const std::vector< ScalarType > &independent_variables, Vector< ScalarType > &values)
static const types::tape_index invalid_tape_index
static void disable_taping(const types::tape_index active_tape_index, const bool write_tapes_to_file)
unsigned short tape_index
static void gradient(const std::vector< ADNumberType > &independent_variables, const std::vector< ADNumberType > &dependent_variables, Vector< ScalarType > &gradient)
unsigned int tape_buffer_sizes
static::ExceptionBase & ExcInternalError()
static void gradient(const types::tape_index active_tape_index, const std::vector< ScalarType > &independent_variables, Vector< ScalarType > &gradient)