Reference documentation for deal.II version GIT b6bf1e606d 2022-08-11 15:25:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
ad_drivers.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2018 - 2022 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/config.h>
17 
18 #if defined(DEAL_II_WITH_ADOLC) || defined(DEAL_II_TRILINOS_WITH_SACADO)
19 
20 # include <deal.II/base/exceptions.h>
21 # include <deal.II/base/types.h>
22 # include <deal.II/base/utilities.h>
23 
29 
30 # include <deal.II/lac/full_matrix.h>
31 # include <deal.II/lac/vector.h>
32 
33 # ifdef DEAL_II_WITH_ADOLC
34 
36 # include <adolc/adolc_fatalerror.h>
37 # include <adolc/drivers/drivers.h>
38 # include <adolc/taping.h>
40 
41 # endif // DEAL_II_WITH_ADOLC
42 
43 # include <vector>
44 
45 
47 
48 
49 namespace Differentiation
50 {
51  namespace AD
52  {
53  // ------------- TapedDrivers -------------
54 
55 
56  template <typename ADNumberType, typename ScalarType, typename T>
57  bool
59  {
61  return false;
62  }
63 
64 
65  template <typename ADNumberType, typename ScalarType, typename T>
68  {
71  }
72 
73 
74  template <typename ADNumberType, typename ScalarType, typename T>
75  bool
77  const typename Types<ADNumberType>::tape_index) const
78  {
80  return false;
81  }
82 
83 
84  template <typename ADNumberType, typename ScalarType, typename T>
85  bool
87  {
89  return false;
90  }
91 
92 
93  template <typename ADNumberType, typename ScalarType, typename T>
94  void
100  {
102  }
103 
104 
105  template <typename ADNumberType, typename ScalarType, typename T>
106  void
108  const typename Types<ADNumberType>::tape_index,
109  const bool)
110  {
112  }
113 
114 
115  template <typename ADNumberType, typename ScalarType, typename T>
116  void
118  const typename Types<ADNumberType>::tape_index,
119  const bool)
120  {
122  }
123 
124 
125  template <typename ADNumberType, typename ScalarType, typename T>
126  std::vector<typename Types<ADNumberType>::tape_index>
128  const
129  {
131  return std::vector<typename Types<ADNumberType>::tape_index>();
132  }
133 
134 
135  template <typename ADNumberType, typename ScalarType, typename T>
136  void
138  const typename Types<ADNumberType>::tape_index)
139  {
141  }
142 
143 
144  template <typename ADNumberType, typename ScalarType, typename T>
145  bool
147  const typename Types<ADNumberType>::tape_index) const
148  {
150  return false;
151  }
152 
153 
154  template <typename ADNumberType, typename ScalarType, typename T>
155  bool
157  const
158  {
160  return false;
161  }
162 
163 
164  template <typename ADNumberType, typename ScalarType, typename T>
165  void
167  const typename Types<ADNumberType>::tape_index)
168  {
170  }
171 
172 
173  template <typename ADNumberType, typename ScalarType, typename T>
174  void
176  {
178  }
179 
180 
181  template <typename ADNumberType, typename ScalarType, typename T>
182  void
184  {
186  }
187 
188 
189  template <typename ADNumberType, typename ScalarType, typename T>
190  void
192  const typename Types<ADNumberType>::tape_index,
193  std::ostream &) const
194  {
196  }
197 
198 
199  template <typename ADNumberType, typename ScalarType, typename T>
200  ScalarType
202  const typename Types<ADNumberType>::tape_index,
203  const std::vector<ScalarType> &) const
204  {
206  return ScalarType(0.0);
207  }
208 
209 
210  template <typename ADNumberType, typename ScalarType, typename T>
211  void
213  const typename Types<ADNumberType>::tape_index,
214  const std::vector<ScalarType> &,
215  Vector<ScalarType> &) const
216  {
218  }
219 
220 
221  template <typename ADNumberType, typename ScalarType, typename T>
222  void
224  const typename Types<ADNumberType>::tape_index,
225  const std::vector<ScalarType> &,
226  FullMatrix<ScalarType> &) const
227  {
229  }
230 
231 
232  template <typename ADNumberType, typename ScalarType, typename T>
233  void
235  const typename Types<ADNumberType>::tape_index,
236  const unsigned int,
237  const std::vector<ScalarType> &,
238  Vector<ScalarType> &) const
239  {
241  }
242 
243 
244  template <typename ADNumberType, typename ScalarType, typename T>
245  void
247  const typename Types<ADNumberType>::tape_index,
248  const unsigned int,
249  const std::vector<ScalarType> &,
250  FullMatrix<ScalarType> &) const
251  {
253  }
254 
255 
256 
257 # ifdef DEAL_II_WITH_ADOLC
258 
259 # ifndef DOXYGEN
260  // Specialization for taped ADOL-C auto-differentiable numbers.
261 
262  template <typename ADNumberType>
263  TapedDrivers<ADNumberType,
264  double,
265  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
267  : active_tape(Numbers<ADNumberType>::invalid_tape_index)
268  , keep_values(true)
269  , is_recording_flag(false)
270  , use_stored_taped_buffer_sizes(false)
271  , obufsize(0u)
272  , lbufsize(0u)
273  , vbufsize(0u)
274  , tbufsize(0u)
275  {}
276 # endif
277 
278 
279  template <typename ADNumberType>
280  bool
281  TapedDrivers<ADNumberType,
282  double,
283  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
284  NumberTypes::adolc_taped>>::is_recording()
285  const
286  {
287  return is_recording_flag;
288  }
289 
290 
291  template <typename ADNumberType>
293  TapedDrivers<
294  ADNumberType,
295  double,
296  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
297  NumberTypes::adolc_taped>>::active_tape_index() const
298  {
299  return active_tape;
300  }
301 
302 
303  template <typename ADNumberType>
304  bool
305  TapedDrivers<ADNumberType,
306  double,
307  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
309  keep_independent_values() const
310  {
311  return keep_values;
312  }
313 
314 
315  template <typename ADNumberType>
316  bool
317  TapedDrivers<ADNumberType,
318  double,
319  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
321  is_registered_tape(
322  const typename Types<ADNumberType>::tape_index tape_index) const
323  {
324  // Sigh... This is a mess :-/
325  // The most succinct way to get this piece of information, would be to
326  // use the getTapeInfos() function, but would come at the expense of
327  // creating an inactive tape data within ADOL-C's global store. For
328  // hints as to why this is the way it is, see the getTapeInfos()
329  // function in
330  // https://gitlab.com/adol-c/adol-c/blob/master/ADOL-C/src/tape_handling.cpp
331  // An alternative solution would be to manually access the tape data;
332  // see the removeTape() function in
333  // https://gitlab.com/adol-c/adol-c/blob/master/ADOL-C/src/tape_handling.cpp
334  // with the consideration of the #defines in
335  // https://gitlab.com/adol-c/adol-c/blob/master/ADOL-C/src/taping_p.h
336  // as to how this would be performed.
337  // Doing things "manually" (the second way) without creating the
338  // additional data object would be a lot more work...
339  //
340  // Both of the above solutions would be possible IF ADOL-C exposed
341  // this data object or a method to access it to the outside world.
342  // But they don't :-(
343  // Instead, what we'll have to do is get the statistics for this tape
344  // and make our own determination as to whether or not this tape exists.
345  // This effectively executes the first solution, with even more
346  // overhead! If the tape is in existence, we can assume that it should a
347  // non-zero number of dependent and independent variables. Those are
348  // stored in the zeroth and first entries of the statistics vector.
349  //
350  // But, oh wait... Surprise! This will trigger an error if the tape
351  // doesn't exist at all! So lets first check their tape info cache to
352  // see if the tape REALLY exists (i.e. has been touched, even if nothing
353  // has been written to it) before trying to access it. It'll only take
354  // an O(n) search, but at this point who really cares about efficiency?
355  //
356  // It has been suggested in
357  // https://gitlab.com/adol-c/adol-c/issues/11
358  // that a simply try-catch block around ::tapestats is the solution that
359  // we want here. Unfortunately this results in unwanted pollution of
360  // the terminal, of the form
361  // ADOL-C error: reading integer tape number 4!
362  // >>> File or directory not found! <<<
363  // , every time a query is made about a non-existent tape.
364  // So either way we have to guard that check with something more
365  // conservative so that we don't output useless messages for our users.
366  const std::vector<typename Types<ADNumberType>::tape_index>
367  registered_tape_indices = get_registered_tape_indices();
368  const auto it = std::find(registered_tape_indices.begin(),
369  registered_tape_indices.end(),
370  tape_index);
371  if (it == registered_tape_indices.end())
372  return false;
373 
374  // See https://gitlab.com/adol-c/adol-c/issues/11#note_108341333
375  try
376  {
377  std::vector<std::size_t> counts(STAT_SIZE);
378  ::tapestats(tape_index, counts.data());
379  return true;
380  }
381  catch (const ::FatalError &exc)
382  {
383  return false;
384  }
385  }
386 
387 
388  template <typename ADNumberType>
389  void
390  TapedDrivers<ADNumberType,
391  double,
392  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
394  set_tape_buffer_sizes(
395  const typename Types<ADNumberType>::tape_buffer_sizes in_obufsize,
396  const typename Types<ADNumberType>::tape_buffer_sizes in_lbufsize,
397  const typename Types<ADNumberType>::tape_buffer_sizes in_vbufsize,
398  const typename Types<ADNumberType>::tape_buffer_sizes in_tbufsize)
399  {
400  // When valid for the chosen AD number type, these values will be used
401  // the next time start_recording_operations() is called.
402  obufsize = in_obufsize;
403  lbufsize = in_lbufsize;
404  vbufsize = in_vbufsize;
405  tbufsize = in_tbufsize;
406  use_stored_taped_buffer_sizes = true;
407  }
408 
409 
410  template <typename ADNumberType>
411  void
412  TapedDrivers<ADNumberType,
413  double,
414  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
416  start_taping(const typename Types<ADNumberType>::tape_index tape_index,
417  const bool keep_independent_values)
418  {
419  if (use_stored_taped_buffer_sizes)
420  trace_on(tape_index,
421  keep_independent_values,
422  obufsize,
423  lbufsize,
424  vbufsize,
425  tbufsize);
426  else
427  trace_on(tape_index, keep_independent_values);
428 
429  // Set some other flags to their indicated / required values
430  keep_values = keep_independent_values;
431  is_recording_flag = true;
432  }
433 
434 
435  template <typename ADNumberType>
436  void
437  TapedDrivers<ADNumberType,
438  double,
439  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
441  stop_taping(
442  const typename Types<ADNumberType>::tape_index active_tape_index,
443  const bool write_tapes_to_file)
444  {
445  if (write_tapes_to_file)
446  trace_off(active_tape_index); // Slow
447  else
448  trace_off(); // Fast(er)
449 
450  // Now that we've turned tracing off, we've definitely
451  // stopped all tape recording.
452  is_recording_flag = false;
453 
454  // If the keep_values flag is set, then we expect the user to use this
455  // tape immediately after recording it. There is therefore no need to
456  // invalidate it. However, there is now also no way to double-check
457  // that the newly recorded tape is indeed the active tape.
458  if (keep_independent_values() == false)
460  }
461 
462 
463  template <typename ADNumberType>
464  std::vector<typename Types<ADNumberType>::tape_index>
465  TapedDrivers<ADNumberType,
466  double,
467  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
469  get_registered_tape_indices() const
470  {
471  // We've chosen to use unsigned shorts for the tape
472  // index type (a safety precaution) so we need to
473  // perform a conversion between ADOL-C's native tape
474  // index type and that chosen by us.
475  std::vector<short> registered_tape_indices_s;
476  cachedTraceTags(registered_tape_indices_s);
477 
478  return std::vector<typename Types<ADNumberType>::tape_index>(
479  registered_tape_indices_s.begin(), registered_tape_indices_s.end());
480  }
481 
482 
483  template <typename ADNumberType>
484  void
485  TapedDrivers<ADNumberType,
486  double,
487  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
489  activate_tape(const typename Types<ADNumberType>::tape_index tape_index)
490  {
491  active_tape = tape_index;
492  }
493 
494 
495  template <typename ADNumberType>
496  bool
497  TapedDrivers<ADNumberType,
498  double,
499  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
501  requires_retaping(
502  const typename Types<ADNumberType>::tape_index tape_index) const
503  {
504  Assert(
505  is_registered_tape(tape_index) == true,
506  ExcMessage(
507  "Cannot ask for the status of a tape that has not yet been recorded and used."));
508 
509  const auto it_status_tape = status.find(tape_index);
510 
511  // This tape's status has not been found in the map. This could be
512  // because a non-existent tape_index has been used as an argument, or
513  // because the tape exists but has not been used (in a way that
514  // initiated a status update). For example, on can create a tape in one
515  // section of code and then query the status of all existing tapes in a
516  // completely different section of code that knows nothing about the
517  // first tape. There is no prerequisite that the first tape is ever
518  // used, and it can therefore not have a status. So, in this case
519  // there's not much we can do other than to report that the tape does
520  // not require retaping.
521  if (it_status_tape == status.end())
522  return false;
523 
524  const auto status_tape = it_status_tape->second;
525 
526  // See ADOL-C manual section 1.7 and comments in last paragraph of
527  // section 3.1
528  Assert(
529  status_tape < 4 && status_tape >= -2,
530  ExcMessage(
531  "The tape status is not within the range specified within the ADOL-C documentation."));
532  return (status_tape < 0);
533  }
534 
535 
536  template <typename ADNumberType>
537  bool
538  TapedDrivers<ADNumberType,
539  double,
540  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
542  last_action_requires_retaping() const
543  {
544  return requires_retaping(active_tape);
545  }
546 
547 
548  template <typename ADNumberType>
549  void
550  TapedDrivers<ADNumberType,
551  double,
552  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
554  remove_tape(const typename Types<ADNumberType>::tape_index tape_index)
555  {
556  Assert(is_registered_tape(tape_index),
557  ExcMessage(
558  "This tape does not exist, and therefore cannot be cleared."));
559  removeTape(tape_index, TapeRemovalType::ADOLC_REMOVE_COMPLETELY);
560  }
561 
562 
563  template <typename ADNumberType>
564  void
565  TapedDrivers<ADNumberType,
566  double,
567  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
569  reset(const bool clear_registered_tapes)
570  {
572  is_recording_flag = false;
573  status.clear();
574  if (clear_registered_tapes)
575  {
576  const std::vector<typename Types<ADNumberType>::tape_index>
577  registered_tape_indices = get_registered_tape_indices();
578  for (const auto &tape_index : registered_tape_indices)
579  remove_tape(tape_index);
580  }
581  }
582 
583 
584  template <typename ADNumberType>
585  void
586  TapedDrivers<ADNumberType,
587  double,
588  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
589  NumberTypes::adolc_taped>>::print(std::ostream
590  &stream)
591  const
592  {
593  const std::vector<typename Types<ADNumberType>::tape_index>
594  registered_tape_indices = get_registered_tape_indices();
595  stream << "Registered tapes and their status: ";
596  auto it_registered_tape = registered_tape_indices.begin();
597  for (unsigned int i = 0; i < registered_tape_indices.size();
598  ++i, ++it_registered_tape)
599  {
600  const auto tape_index = *it_registered_tape;
601  const auto it_status_tape = status.find(tape_index);
602  Assert(it_status_tape != status.end(),
603  ExcMessage(
604  "This tape's status has not been found in the map."));
605  const auto status_tape = it_status_tape->second;
606 
607  stream << tape_index << "->" << status_tape
608  << (i < (registered_tape_indices.size() - 1) ? "," : "");
609  }
610  stream << '\n';
611 
612  stream << "Keep values? " << keep_independent_values() << '\n';
613  stream << "Use stored tape buffer sizes? "
614  << use_stored_taped_buffer_sizes << '\n';
615  }
616 
617 
618  template <typename ADNumberType>
619  void
620  TapedDrivers<ADNumberType,
621  double,
622  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
624  print_tape_stats(
625  const typename Types<ADNumberType>::tape_index tape_index,
626  std::ostream & stream) const
627  {
628  // See ADOL-C manual section 2.1
629  // and adolc/taping.h
630  std::vector<std::size_t> counts(STAT_SIZE);
631  ::tapestats(tape_index, counts.data());
632  Assert(counts.size() >= 18, ExcInternalError());
633  stream
634  << "Tape index: " << tape_index << '\n'
635  << "Number of independent variables: " << counts[0] << '\n'
636  << "Number of dependent variables: " << counts[1] << '\n'
637  << "Max number of live, active variables: " << counts[2] << '\n'
638  << "Size of taylor stack (number of overwrites): " << counts[3] << '\n'
639  << "Operations buffer size: " << counts[4] << '\n'
640  << "Total number of recorded operations: " << counts[5] << '\n'
641  << "Operations file written or not: " << counts[6] << '\n'
642  << "Overall number of locations: " << counts[7] << '\n'
643  << "Locations file written or not: " << counts[8] << '\n'
644  << "Overall number of values: " << counts[9] << '\n'
645  << "Values file written or not: " << counts[10] << '\n'
646  << "Locations buffer size: " << counts[11] << '\n'
647  << "Values buffer size: " << counts[12] << '\n'
648  << "Taylor buffer size: " << counts[13] << '\n'
649  << "Number of eq_*_prod for sparsity pattern: " << counts[14] << '\n'
650  << "Use of 'min_op', deferred to 'abs_op' for piecewise calculations: "
651  << counts[15] << '\n'
652  << "Number of 'abs' calls that can switch branch: " << counts[16]
653  << '\n'
654  << "Number of parameters (doubles) interchangeable without retaping: "
655  << counts[17] << '\n'
656  << std::flush;
657  }
658 
659 
660  template <typename ADNumberType>
661  typename TapedDrivers<
662  ADNumberType,
663  double,
664  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
665  NumberTypes::adolc_taped>>::scalar_type
666  TapedDrivers<ADNumberType,
667  double,
668  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
670  value(const typename Types<ADNumberType>::tape_index active_tape_index,
671  const std::vector<scalar_type> &independent_variables) const
672  {
673  Assert(is_registered_tape(active_tape_index),
674  ExcMessage("This tape has not yet been recorded."));
675 
676  scalar_type value = 0.0;
677 
678  status[active_tape_index] =
679  ::function(active_tape_index,
680  1, // Only one dependent variable
681  independent_variables.size(),
682  const_cast<double *>(independent_variables.data()),
683  &value);
684 
685  return value;
686  }
687 
688 
689  template <typename ADNumberType>
690  void
691  TapedDrivers<ADNumberType,
692  double,
693  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
695  gradient(const typename Types<ADNumberType>::tape_index active_tape_index,
696  const std::vector<scalar_type> &independent_variables,
697  Vector<scalar_type> & gradient) const
698  {
700  1,
703  1));
704  Assert(gradient.size() == independent_variables.size(),
705  ExcDimensionMismatch(gradient.size(),
706  independent_variables.size()));
707  Assert(is_registered_tape(active_tape_index),
708  ExcMessage("This tape has not yet been recorded."));
709 
710  // Note: ADOL-C's ::gradient function expects a *double as the last
711  // parameter. Here we take advantage of the fact that the data in the
712  // Vector class is aligned (e.g. stored as an Array)
713  status[active_tape_index] =
714  ::gradient(active_tape_index,
715  independent_variables.size(),
716  const_cast<scalar_type *>(independent_variables.data()),
717  gradient.data());
718  }
719 
720 
721  template <typename ADNumberType>
722  void
723  TapedDrivers<ADNumberType,
724  double,
725  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
727  hessian(const typename Types<ADNumberType>::tape_index active_tape_index,
728  const std::vector<scalar_type> &independent_variables,
729  FullMatrix<scalar_type> & hessian) const
730  {
732  2,
735  2));
736  Assert(hessian.m() == independent_variables.size(),
737  ExcDimensionMismatch(hessian.m(), independent_variables.size()));
738  Assert(hessian.n() == independent_variables.size(),
739  ExcDimensionMismatch(hessian.n(), independent_variables.size()));
740  Assert(is_registered_tape(active_tape_index),
741  ExcMessage("This tape has not yet been recorded."));
742 
743  const unsigned int n_independent_variables = independent_variables.size();
744  std::vector<scalar_type *> H(n_independent_variables);
745  for (unsigned int i = 0; i < n_independent_variables; ++i)
746  H[i] = &hessian[i][0];
747 
748  status[active_tape_index] =
749  ::hessian(active_tape_index,
750  n_independent_variables,
751  const_cast<scalar_type *>(independent_variables.data()),
752  H.data());
753 
754  // ADOL-C builds only the lower-triangular part of the
755  // symmetric Hessian, so we should copy the relevant
756  // entries into the upper triangular part.
757  for (unsigned int i = 0; i < n_independent_variables; ++i)
758  for (unsigned int j = 0; j < i; ++j)
759  hessian[j][i] = hessian[i][j]; // Symmetry
760  }
761 
762 
763  template <typename ADNumberType>
764  void
765  TapedDrivers<ADNumberType,
766  double,
767  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
769  values(const typename Types<ADNumberType>::tape_index active_tape_index,
770  const unsigned int n_dependent_variables,
771  const std::vector<scalar_type> &independent_variables,
772  Vector<scalar_type> & values) const
773  {
774  Assert(values.size() == n_dependent_variables,
775  ExcDimensionMismatch(values.size(), n_dependent_variables));
776  Assert(is_registered_tape(active_tape_index),
777  ExcMessage("This tape has not yet been recorded."));
778 
779  // Note: ADOL-C's ::function function expects a *double as the last
780  // parameter. Here we take advantage of the fact that the data in the
781  // Vector class is aligned (e.g. stored as an Array)
782  status[active_tape_index] =
783  ::function(active_tape_index,
784  n_dependent_variables,
785  independent_variables.size(),
786  const_cast<scalar_type *>(independent_variables.data()),
787  values.data());
788  }
789 
790 
791  template <typename ADNumberType>
792  void
793  TapedDrivers<ADNumberType,
794  double,
795  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
797  jacobian(const typename Types<ADNumberType>::tape_index active_tape_index,
798  const unsigned int n_dependent_variables,
799  const std::vector<scalar_type> &independent_variables,
800  FullMatrix<scalar_type> & jacobian) const
801  {
802  Assert(AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels >=
803  1,
805  AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels,
806  1));
807  Assert(jacobian.m() == n_dependent_variables,
808  ExcDimensionMismatch(jacobian.m(), n_dependent_variables));
809  Assert(jacobian.n() == independent_variables.size(),
810  ExcDimensionMismatch(jacobian.n(), independent_variables.size()));
811  Assert(is_registered_tape(active_tape_index),
812  ExcMessage("This tape has not yet been recorded."));
813 
814  std::vector<scalar_type *> J(n_dependent_variables);
815  for (unsigned int i = 0; i < n_dependent_variables; ++i)
816  J[i] = &jacobian[i][0];
817 
818  status[active_tape_index] = ::jacobian(active_tape_index,
819  n_dependent_variables,
820  independent_variables.size(),
821  independent_variables.data(),
822  J.data());
823  }
824 
825 # else
826 
827  // Specialization for taped ADOL-C auto-differentiable numbers.
828 
829  template <typename ADNumberType>
830  bool
831  TapedDrivers<ADNumberType,
832  double,
833  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
834  NumberTypes::adolc_taped>>::is_recording()
835  const
836  {
837  AssertThrow(false, ExcRequiresADOLC());
838  return false;
839  }
840 
841 
842  template <typename ADNumberType>
844  TapedDrivers<
845  ADNumberType,
846  double,
847  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
848  NumberTypes::adolc_taped>>::active_tape_index() const
849  {
850  AssertThrow(false, ExcRequiresADOLC());
852  }
853 
854 
855  template <typename ADNumberType>
856  bool
857  TapedDrivers<ADNumberType,
858  double,
859  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
861  keep_independent_values() const
862  {
863  AssertThrow(false, ExcRequiresADOLC());
864  return false;
865  }
866 
867 
868  template <typename ADNumberType>
869  bool
870  TapedDrivers<ADNumberType,
871  double,
872  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
874  is_registered_tape(const typename Types<ADNumberType>::tape_index) const
875  {
876  AssertThrow(false, ExcRequiresADOLC());
877  return false;
878  }
879 
880 
881  template <typename ADNumberType>
882  void
883  TapedDrivers<ADNumberType,
884  double,
885  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
887  set_tape_buffer_sizes(
892  {
893  AssertThrow(false, ExcRequiresADOLC());
894  }
895 
896 
897  template <typename ADNumberType>
898  void
899  TapedDrivers<ADNumberType,
900  double,
901  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
903  start_taping(const typename Types<ADNumberType>::tape_index, const bool)
904  {
905  AssertThrow(false, ExcRequiresADOLC());
906  }
907 
908 
909  template <typename ADNumberType>
910  void
911  TapedDrivers<ADNumberType,
912  double,
913  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
915  stop_taping(const typename Types<ADNumberType>::tape_index, const bool)
916  {
917  AssertThrow(false, ExcRequiresADOLC());
918  }
919 
920 
921  template <typename ADNumberType>
922  std::vector<typename Types<ADNumberType>::tape_index>
923  TapedDrivers<ADNumberType,
924  double,
925  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
927  get_registered_tape_indices() const
928  {
929  AssertThrow(false, ExcRequiresADOLC());
930  return std::vector<typename Types<ADNumberType>::tape_index>();
931  }
932 
933 
934  template <typename ADNumberType>
935  void
936  TapedDrivers<ADNumberType,
937  double,
938  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
940  activate_tape(const typename Types<ADNumberType>::tape_index)
941  {
942  AssertThrow(false, ExcRequiresADOLC());
943  }
944 
945 
946  template <typename ADNumberType>
947  bool
948  TapedDrivers<ADNumberType,
949  double,
950  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
952  requires_retaping(const typename Types<ADNumberType>::tape_index) const
953  {
954  AssertThrow(false, ExcRequiresADOLC());
955  return false;
956  }
957 
958 
959  template <typename ADNumberType>
960  bool
961  TapedDrivers<ADNumberType,
962  double,
963  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
965  last_action_requires_retaping() const
966  {
967  AssertThrow(false, ExcRequiresADOLC());
968  return false;
969  }
970 
971 
972  template <typename ADNumberType>
973  void
974  TapedDrivers<ADNumberType,
975  double,
976  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
978  remove_tape(const typename Types<ADNumberType>::tape_index)
979  {
980  AssertThrow(false, ExcRequiresADOLC());
981  }
982 
983 
984  template <typename ADNumberType>
985  void
986  TapedDrivers<ADNumberType,
987  double,
988  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
989  NumberTypes::adolc_taped>>::reset(const bool)
990  {
991  AssertThrow(false, ExcRequiresADOLC());
992  }
993 
994 
995  template <typename ADNumberType>
996  void
997  TapedDrivers<ADNumberType,
998  double,
999  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1000  NumberTypes::adolc_taped>>::print(std::ostream
1001  &) const
1002  {
1003  AssertThrow(false, ExcRequiresADOLC());
1004  }
1005 
1006 
1007  template <typename ADNumberType>
1008  void
1009  TapedDrivers<ADNumberType,
1010  double,
1011  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1013  print_tape_stats(const typename Types<ADNumberType>::tape_index,
1014  std::ostream &) const
1015  {
1016  AssertThrow(false, ExcRequiresADOLC());
1017  }
1018 
1019 
1020  template <typename ADNumberType>
1021  typename TapedDrivers<
1022  ADNumberType,
1023  double,
1024  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1025  NumberTypes::adolc_taped>>::scalar_type
1026  TapedDrivers<ADNumberType,
1027  double,
1028  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1030  value(const typename Types<ADNumberType>::tape_index,
1031  const std::vector<scalar_type> &) const
1032  {
1033  AssertThrow(false, ExcRequiresADOLC());
1034  return 0.0;
1035  }
1036 
1037 
1038  template <typename ADNumberType>
1039  void
1040  TapedDrivers<ADNumberType,
1041  double,
1042  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1044  gradient(const typename Types<ADNumberType>::tape_index,
1045  const std::vector<scalar_type> &,
1046  Vector<scalar_type> &) const
1047  {
1048  AssertThrow(false, ExcRequiresADOLC());
1049  }
1050 
1051 
1052  template <typename ADNumberType>
1053  void
1054  TapedDrivers<ADNumberType,
1055  double,
1056  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1058  hessian(const typename Types<ADNumberType>::tape_index,
1059  const std::vector<scalar_type> &,
1060  FullMatrix<scalar_type> &) const
1061  {
1062  AssertThrow(false, ExcRequiresADOLC());
1063  }
1064 
1065 
1066  template <typename ADNumberType>
1067  void
1068  TapedDrivers<ADNumberType,
1069  double,
1070  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1073  const unsigned int,
1074  const std::vector<scalar_type> &,
1075  Vector<scalar_type> &) const
1076  {
1077  AssertThrow(false, ExcRequiresADOLC());
1078  }
1079 
1080 
1081  template <typename ADNumberType>
1082  void
1083  TapedDrivers<ADNumberType,
1084  double,
1085  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1087  jacobian(const typename Types<ADNumberType>::tape_index,
1088  const unsigned int,
1089  const std::vector<scalar_type> &,
1090  FullMatrix<scalar_type> &) const
1091  {
1092  AssertThrow(false, ExcRequiresADOLC());
1093  }
1094 
1095 # endif // DEAL_II_WITH_ADOLC
1096 
1097 
1098  // Specialization for ADOL-C taped numbers. It is expected that the
1099  // scalar return type for this class is a float.
1100 
1101  template <typename ADNumberType>
1102  bool
1103  TapedDrivers<ADNumberType,
1104  float,
1105  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1106  NumberTypes::adolc_taped>>::is_recording()
1107  const
1108  {
1109  // ADOL-C only supports 'double', not 'float', so we can forward to
1110  // the 'double' implementation of this function
1111  return taped_driver.is_recording();
1112  }
1113 
1114 
1115  template <typename ADNumberType>
1117  TapedDrivers<
1118  ADNumberType,
1119  float,
1120  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1121  NumberTypes::adolc_taped>>::active_tape_index() const
1122  {
1123  // ADOL-C only supports 'double', not 'float', so we can forward to
1124  // the 'double' implementation of this function
1125  return taped_driver.active_tape_index();
1126  }
1127 
1128 
1129  template <typename ADNumberType>
1130  bool
1131  TapedDrivers<ADNumberType,
1132  float,
1133  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1135  keep_independent_values() const
1136  {
1137  return taped_driver.keep_independent_values();
1138  }
1139 
1140 
1141  template <typename ADNumberType>
1142  bool
1143  TapedDrivers<ADNumberType,
1144  float,
1145  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1147  is_registered_tape(
1148  const typename Types<ADNumberType>::tape_index tape_index) const
1149  {
1150  // ADOL-C only supports 'double', not 'float', so we can forward to
1151  // the 'double' implementation of this function
1152  return taped_driver.is_registered_tape(tape_index);
1153  }
1154 
1155 
1156  template <typename ADNumberType>
1157  void
1158  TapedDrivers<ADNumberType,
1159  float,
1160  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1162  set_tape_buffer_sizes(
1163  const typename Types<ADNumberType>::tape_buffer_sizes obufsize,
1164  const typename Types<ADNumberType>::tape_buffer_sizes lbufsize,
1165  const typename Types<ADNumberType>::tape_buffer_sizes vbufsize,
1166  const typename Types<ADNumberType>::tape_buffer_sizes tbufsize)
1167  {
1168  // ADOL-C only supports 'double', not 'float', so we can forward to
1169  // the 'double' implementation of this function
1170  taped_driver.set_tape_buffer_sizes(obufsize,
1171  lbufsize,
1172  vbufsize,
1173  tbufsize);
1174  }
1175 
1176 
1177  template <typename ADNumberType>
1178  void
1179  TapedDrivers<ADNumberType,
1180  float,
1181  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1183  start_taping(const typename Types<ADNumberType>::tape_index tape_index,
1184  const bool keep_independent_values)
1185  {
1186  // ADOL-C only supports 'double', not 'float', so we can forward to
1187  // the 'double' implementation of this function
1188  taped_driver.start_taping(tape_index, keep_independent_values);
1189  }
1190 
1191 
1192  template <typename ADNumberType>
1193  void
1194  TapedDrivers<ADNumberType,
1195  float,
1196  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1198  stop_taping(
1199  const typename Types<ADNumberType>::tape_index active_tape_index,
1200  const bool write_tapes_to_file)
1201  {
1202  // ADOL-C only supports 'double', not 'float', so we can forward to
1203  // the 'double' implementation of this function
1204  taped_driver.stop_taping(active_tape_index, write_tapes_to_file);
1205  }
1206 
1207 
1208  template <typename ADNumberType>
1209  std::vector<typename Types<ADNumberType>::tape_index>
1210  TapedDrivers<ADNumberType,
1211  float,
1212  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1214  get_registered_tape_indices() const
1215  {
1216  return taped_driver.get_registered_tape_indices();
1217  }
1218 
1219 
1220  template <typename ADNumberType>
1221  void
1222  TapedDrivers<ADNumberType,
1223  float,
1224  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1226  activate_tape(const typename Types<ADNumberType>::tape_index tape_index)
1227  {
1228  taped_driver.activate_tape(tape_index);
1229  }
1230 
1231 
1232  template <typename ADNumberType>
1233  bool
1234  TapedDrivers<ADNumberType,
1235  float,
1236  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1238  requires_retaping(
1239  const typename Types<ADNumberType>::tape_index tape_index) const
1240  {
1241  return taped_driver.requires_retaping(tape_index);
1242  }
1243 
1244 
1245  template <typename ADNumberType>
1246  bool
1247  TapedDrivers<ADNumberType,
1248  float,
1249  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1251  last_action_requires_retaping() const
1252  {
1253  return taped_driver.last_action_requires_retaping();
1254  }
1255 
1256 
1257  template <typename ADNumberType>
1258  void
1259  TapedDrivers<ADNumberType,
1260  float,
1261  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1263  remove_tape(const typename Types<ADNumberType>::tape_index tape_index)
1264  {
1265  taped_driver.remove_tape(tape_index);
1266  }
1267 
1268 
1269  template <typename ADNumberType>
1270  void
1271  TapedDrivers<ADNumberType,
1272  float,
1273  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1275  reset(const bool clear_registered_tapes)
1276  {
1277  taped_driver.reset(clear_registered_tapes);
1278  }
1279 
1280 
1281  template <typename ADNumberType>
1282  void
1283  TapedDrivers<ADNumberType,
1284  float,
1285  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1286  NumberTypes::adolc_taped>>::print(std::ostream
1287  &stream)
1288  const
1289  {
1290  taped_driver.print(stream);
1291  }
1292 
1293 
1294  template <typename ADNumberType>
1295  void
1296  TapedDrivers<ADNumberType,
1297  float,
1298  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1300  print_tape_stats(
1301  const typename Types<ADNumberType>::tape_index tape_index,
1302  std::ostream & stream) const
1303  {
1304  // ADOL-C only supports 'double', not 'float', so we can forward to
1305  // the 'double' implementation of this function
1306  taped_driver.print_tape_stats(tape_index, stream);
1307  }
1308 
1309 
1310  template <typename ADNumberType>
1311  typename TapedDrivers<
1312  ADNumberType,
1313  float,
1314  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1315  NumberTypes::adolc_taped>>::scalar_type
1316  TapedDrivers<ADNumberType,
1317  float,
1318  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1320  value(const typename Types<ADNumberType>::tape_index active_tape_index,
1321  const std::vector<scalar_type> &independent_variables) const
1322  {
1323  // ADOL-C only supports 'double', not 'float', so we can forward to
1324  // the 'double' implementation of this function
1325  return taped_driver.value(active_tape_index,
1326  vector_float_to_double(independent_variables));
1327  }
1328 
1329 
1330  template <typename ADNumberType>
1331  void
1332  TapedDrivers<ADNumberType,
1333  float,
1334  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1336  gradient(const typename Types<ADNumberType>::tape_index active_tape_index,
1337  const std::vector<scalar_type> &independent_variables,
1338  Vector<scalar_type> & gradient) const
1339  {
1340  Vector<double> gradient_double(gradient.size());
1341  // ADOL-C only supports 'double', not 'float', so we can forward to
1342  // the 'double' implementation of this function
1343  taped_driver.gradient(active_tape_index,
1344  vector_float_to_double(independent_variables),
1345  gradient_double);
1346  gradient = gradient_double;
1347  }
1348 
1349 
1350  template <typename ADNumberType>
1351  void
1352  TapedDrivers<ADNumberType,
1353  float,
1354  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1356  hessian(const typename Types<ADNumberType>::tape_index active_tape_index,
1357  const std::vector<scalar_type> &independent_variables,
1358  FullMatrix<scalar_type> & hessian) const
1359  {
1360  FullMatrix<double> hessian_double(hessian.m(), hessian.n());
1361  // ADOL-C only supports 'double', not 'float', so we can forward to
1362  // the 'double' implementation of this function
1363  taped_driver.hessian(active_tape_index,
1364  vector_float_to_double(independent_variables),
1365  hessian_double);
1366  hessian = hessian_double;
1367  }
1368 
1369 
1370  template <typename ADNumberType>
1371  void
1372  TapedDrivers<ADNumberType,
1373  float,
1374  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1376  values(const typename Types<ADNumberType>::tape_index active_tape_index,
1377  const unsigned int n_dependent_variables,
1378  const std::vector<scalar_type> &independent_variables,
1379  Vector<scalar_type> & values) const
1380  {
1381  Vector<double> values_double(values.size());
1382  // ADOL-C only supports 'double', not 'float', so we can forward to
1383  // the 'double' implementation of this function
1384  taped_driver.values(active_tape_index,
1385  n_dependent_variables,
1386  vector_float_to_double(independent_variables),
1387  values_double);
1388  values = values_double;
1389  }
1390 
1391 
1392  template <typename ADNumberType>
1393  void
1394  TapedDrivers<ADNumberType,
1395  float,
1396  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1398  jacobian(const typename Types<ADNumberType>::tape_index active_tape_index,
1399  const unsigned int n_dependent_variables,
1400  const std::vector<scalar_type> &independent_variables,
1401  FullMatrix<scalar_type> & jacobian) const
1402  {
1403  FullMatrix<double> jacobian_double(jacobian.m(), jacobian.n());
1404  // ADOL-C only supports 'double', not 'float', so we can forward to
1405  // the 'double' implementation of this function
1406  taped_driver.jacobian(active_tape_index,
1407  n_dependent_variables,
1408  vector_float_to_double(independent_variables),
1409  jacobian_double);
1410  jacobian = jacobian_double;
1411  }
1412 
1413 
1414 # ifndef DOXYGEN
1415  template <typename ADNumberType>
1416  std::vector<double>
1417  TapedDrivers<ADNumberType,
1418  float,
1419  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1421  vector_float_to_double(const std::vector<float> &in) const
1422  {
1423  std::vector<double> out(in.size());
1424  std::copy(in.begin(), in.end(), out.begin());
1425  return out;
1426  }
1427 # endif
1428 
1429 
1430  // ------------- TapelessDrivers -------------
1431 
1432 
1433  template <typename ADNumberType, typename ScalarType, typename T>
1434  void
1436  const unsigned int)
1437  {
1439  }
1440 
1441  template <typename ADNumberType, typename ScalarType, typename T>
1442  void
1445  {
1447  }
1448 
1449  template <typename ADNumberType, typename ScalarType, typename T>
1450  void
1453  {
1455  }
1456 
1457  template <typename ADNumberType, typename ScalarType, typename T>
1458  bool
1461  {
1463  return false;
1464  }
1465 
1466 
1467  template <typename ADNumberType, typename ScalarType, typename T>
1468  ScalarType
1470  const std::vector<ADNumberType> &) const
1471  {
1473  return ScalarType(0.0);
1474  }
1475 
1476 
1477  template <typename ADNumberType, typename ScalarType, typename T>
1478  void
1480  const std::vector<ADNumberType> &,
1481  const std::vector<ADNumberType> &,
1482  Vector<ScalarType> &) const
1483  {
1485  }
1486 
1487 
1488  template <typename ADNumberType, typename ScalarType, typename T>
1489  void
1491  const std::vector<ADNumberType> &,
1492  const std::vector<ADNumberType> &,
1493  FullMatrix<ScalarType> &) const
1494  {
1496  }
1497 
1498 
1499  template <typename ADNumberType, typename ScalarType, typename T>
1500  void
1502  const std::vector<ADNumberType> &,
1503  Vector<ScalarType> &) const
1504  {
1506  }
1507 
1508 
1509  template <typename ADNumberType, typename ScalarType, typename T>
1510  void
1512  const std::vector<ADNumberType> &,
1513  const std::vector<ADNumberType> &,
1514  FullMatrix<ScalarType> &) const
1515  {
1517  }
1518 
1519 
1520  namespace internal
1521  {
1526  template <typename ADNumberType>
1527  std::enable_if_t<!(ADNumberTraits<ADNumberType>::type_code ==
1532  {}
1533 
1534 # ifdef DEAL_II_TRILINOS_WITH_SACADO
1535 
1536 
1545  template <typename ADNumberType>
1546  std::enable_if_t<
1550  ADNumberType &dependent_variable)
1551  {
1552  // Compute all gradients (adjoints) for this
1553  // reverse-mode Sacado dependent variable.
1554  // For reverse-mode Sacado numbers it is necessary to broadcast to
1555  // all independent variables that it is time to compute gradients.
1556  // For one dependent variable one would just need to call
1557  // ADNumberType::Gradcomp(), but since we have a more
1558  // generic implementation for vectors of dependent variables
1559  // (vector mode) we default to the complex case.
1560  ADNumberType::Outvar_Gradcomp(dependent_variable);
1561  }
1562 
1563 # endif
1564 
1565 
1570  template <typename ADNumberType>
1571  std::enable_if_t<!(ADNumberTraits<ADNumberType>::type_code ==
1573  configure_tapeless_mode(const unsigned int)
1574  {}
1575 
1576 
1577 # ifdef DEAL_II_WITH_ADOLC
1578 
1579 
1587  template <typename ADNumberType>
1588  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1590  configure_tapeless_mode(const unsigned int n_directional_derivatives)
1591  {
1592 # ifdef DEAL_II_ADOLC_WITH_TAPELESS_REFCOUNTING
1593  // See ADOL-C manual section 7.1
1594  //
1595  // NOTE: It is critical that this is done for tapeless mode BEFORE
1596  // any adtl::adouble are created. If this is not done, then we see
1597  // this scary warning:
1598  //
1599  // "
1600  // ADOL-C Warning: Tapeless: Setting numDir could change memory
1601  // allocation of derivatives in existing adoubles and may lead to
1602  // erroneous results or memory corruption
1603  // "
1604  //
1605  // So we use this dummy function to configure this setting before
1606  // we create and initialize our class data
1607  const std::size_t n_live_variables = adtl::refcounter::getNumLiveVar();
1608  if (n_live_variables == 0)
1609  {
1610  adtl::setNumDir(n_directional_derivatives);
1611  }
1612  else
1613  {
1614  // So there are some live active variables floating around. Here we
1615  // check if we ask to increase the number of computable
1616  // directional derivatives. If this really is necessary then it's
1617  // absolutely vital that there exist no live variables before doing
1618  // so.
1619  const std::size_t n_set_directional_derivatives = adtl::getNumDir();
1620  if (n_directional_derivatives > n_set_directional_derivatives)
1621  AssertThrow(
1622  n_live_variables == 0,
1623  ExcMessage(
1624  "There are currently " + std::to_string(n_live_variables) +
1625  " live "
1626  "adtl::adouble variables in existence. They currently "
1627  "assume " +
1628  std::to_string(n_set_directional_derivatives) +
1629  " directional derivatives "
1630  "but you wish to increase this to " +
1631  std::to_string(n_directional_derivatives) +
1632  ". \n"
1633  "To safely change (or more specifically in this case, "
1634  "increase) the number of directional derivatives, there "
1635  "must be no tapeless doubles in local/global scope."));
1636  }
1637 # else
1638  // If ADOL-C is not configured with tapeless number reference counting
1639  // then there is no way that we can guarantee that the following call
1640  // is safe. No comment... :-/
1641  adtl::setNumDir(n_directional_derivatives);
1642 # endif
1643  }
1644 
1645 # else // DEAL_II_WITH_ADOLC
1646 
1647  template <typename ADNumberType>
1648  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1650  configure_tapeless_mode(const unsigned int /*n_directional_derivatives*/)
1651  {
1652  AssertThrow(false, ExcRequiresADOLC());
1653  }
1654 
1655 # endif
1656 
1657  } // namespace internal
1658 
1659 
1660 
1661  // Specialization for auto-differentiable numbers that use
1662  // reverse mode to compute the first derivatives (and, if supported,
1663  // forward mode for the second).
1664 
1665 # ifndef DOXYGEN
1666  template <typename ADNumberType, typename ScalarType>
1667  TapelessDrivers<
1668  ADNumberType,
1669  ScalarType,
1670  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1672  ADNumberTraits<ADNumberType>::type_code ==
1673  NumberTypes::sacado_rad_dfad>>::TapelessDrivers()
1674  : dependent_variable_marking_safe(false)
1675  {}
1676 # endif
1677 
1678 
1679  template <typename ADNumberType, typename ScalarType>
1680  void
1681  TapelessDrivers<ADNumberType,
1682  ScalarType,
1683  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1685  ADNumberTraits<ADNumberType>::type_code ==
1687  initialize_global_environment(const unsigned int n_independent_variables)
1688  {
1689  internal::configure_tapeless_mode<ADNumberType>(n_independent_variables);
1690  }
1691 
1692 
1693  template <typename ADNumberType, typename ScalarType>
1694  void
1695  TapelessDrivers<
1696  ADNumberType,
1697  ScalarType,
1698  std::enable_if_t<
1699  ADNumberTraits<ADNumberType>::type_code == NumberTypes::sacado_rad ||
1700  ADNumberTraits<ADNumberType>::type_code ==
1701  NumberTypes::sacado_rad_dfad>>::allow_dependent_variable_marking()
1702  {
1703  dependent_variable_marking_safe = true;
1704  }
1705 
1706 
1707  template <typename ADNumberType, typename ScalarType>
1708  void
1709  TapelessDrivers<
1710  ADNumberType,
1711  ScalarType,
1712  std::enable_if_t<
1713  ADNumberTraits<ADNumberType>::type_code == NumberTypes::sacado_rad ||
1714  ADNumberTraits<ADNumberType>::type_code ==
1715  NumberTypes::sacado_rad_dfad>>::prevent_dependent_variable_marking()
1716  {
1717  dependent_variable_marking_safe = false;
1718  }
1719 
1720 
1721  template <typename ADNumberType, typename ScalarType>
1722  bool
1723  TapelessDrivers<ADNumberType,
1724  ScalarType,
1725  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1727  ADNumberTraits<ADNumberType>::type_code ==
1729  is_dependent_variable_marking_allowed() const
1730  {
1731  return dependent_variable_marking_safe;
1732  }
1733 
1734 
1735  template <typename ADNumberType, typename ScalarType>
1736  ScalarType
1737  TapelessDrivers<ADNumberType,
1738  ScalarType,
1739  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1741  ADNumberTraits<ADNumberType>::type_code ==
1743  value(const std::vector<ADNumberType> &dependent_variables) const
1744  {
1745  Assert(dependent_variables.size() == 1,
1746  ExcDimensionMismatch(dependent_variables.size(), 1));
1747  return ADNumberTraits<ADNumberType>::get_scalar_value(
1748  dependent_variables[0]);
1749  }
1750 
1751 
1752  template <typename ADNumberType, typename ScalarType>
1753  void
1754  TapelessDrivers<ADNumberType,
1755  ScalarType,
1756  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1758  ADNumberTraits<ADNumberType>::type_code ==
1760  gradient(const std::vector<ADNumberType> &independent_variables,
1761  const std::vector<ADNumberType> &dependent_variables,
1762  Vector<ScalarType> & gradient) const
1763  {
1764  Assert(AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels >=
1765  1,
1767  AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels,
1768  1));
1769  Assert(dependent_variables.size() == 1,
1770  ExcDimensionMismatch(dependent_variables.size(), 1));
1771  Assert(gradient.size() == independent_variables.size(),
1773  independent_variables.size()));
1774 
1775  // In reverse mode, the gradients are computed from the
1776  // independent variables (i.e. the adjoint)
1778  const_cast<ADNumberType &>(dependent_variables[0]));
1779  const std::size_t n_independent_variables = independent_variables.size();
1780  for (unsigned int i = 0; i < n_independent_variables; ++i)
1782  ADNumberTraits<ADNumberType>::get_directional_derivative(
1783  independent_variables[i], 0 /*This number doesn't really matter*/));
1784  }
1785 
1786 
1787  template <typename ADNumberType, typename ScalarType>
1788  void
1789  TapelessDrivers<ADNumberType,
1790  ScalarType,
1791  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1793  ADNumberTraits<ADNumberType>::type_code ==
1795  hessian(const std::vector<ADNumberType> &independent_variables,
1796  const std::vector<ADNumberType> &dependent_variables,
1797  FullMatrix<ScalarType> & hessian) const
1798  {
1799  Assert(AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels >=
1800  2,
1802  AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels,
1803  2));
1804  Assert(dependent_variables.size() == 1,
1805  ExcDimensionMismatch(dependent_variables.size(), 1));
1806  Assert(hessian.m() == independent_variables.size(),
1807  ExcDimensionMismatch(hessian.m(), independent_variables.size()));
1808  Assert(hessian.n() == independent_variables.size(),
1809  ExcDimensionMismatch(hessian.n(), independent_variables.size()));
1810 
1811  // In reverse mode, the gradients are computed from the
1812  // independent variables (i.e. the adjoint)
1814  const_cast<ADNumberType &>(dependent_variables[0]));
1815  const std::size_t n_independent_variables = independent_variables.size();
1816  for (unsigned int i = 0; i < n_independent_variables; ++i)
1817  {
1818  using derivative_type =
1819  typename ADNumberTraits<ADNumberType>::derivative_type;
1820  const derivative_type gradient_i =
1821  ADNumberTraits<ADNumberType>::get_directional_derivative(
1822  independent_variables[i], i);
1823 
1824  for (unsigned int j = 0; j <= i; ++j) // Symmetry
1825  {
1826  // Extract higher-order directional derivatives. Depending on
1827  // the AD number type, the result may be another AD number or a
1828  // floating point value.
1829  const ScalarType hessian_ij =
1831  ADNumberTraits<derivative_type>::get_directional_derivative(
1832  gradient_i, j));
1833  hessian[i][j] = hessian_ij;
1834  if (i != j)
1835  hessian[j][i] = hessian_ij; // Symmetry
1836  }
1837  }
1838  }
1839 
1840 
1841  template <typename ADNumberType, typename ScalarType>
1842  void
1843  TapelessDrivers<ADNumberType,
1844  ScalarType,
1845  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1847  ADNumberTraits<ADNumberType>::type_code ==
1849  values(const std::vector<ADNumberType> &dependent_variables,
1850  Vector<ScalarType> & values) const
1851  {
1852  Assert(values.size() == dependent_variables.size(),
1853  ExcDimensionMismatch(values.size(), dependent_variables.size()));
1854 
1855  const std::size_t n_dependent_variables = dependent_variables.size();
1856  for (unsigned int i = 0; i < n_dependent_variables; ++i)
1857  values[i] = ADNumberTraits<ADNumberType>::get_scalar_value(
1858  dependent_variables[i]);
1859  }
1860 
1861 
1862  template <typename ADNumberType, typename ScalarType>
1863  void
1864  TapelessDrivers<ADNumberType,
1865  ScalarType,
1866  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1868  ADNumberTraits<ADNumberType>::type_code ==
1870  jacobian(const std::vector<ADNumberType> &independent_variables,
1871  const std::vector<ADNumberType> &dependent_variables,
1872  FullMatrix<ScalarType> & jacobian) const
1873  {
1874  Assert(AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels >=
1875  1,
1877  AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels,
1878  1));
1879  Assert(jacobian.m() == dependent_variables.size(),
1880  ExcDimensionMismatch(jacobian.m(), dependent_variables.size()));
1881  Assert(jacobian.n() == independent_variables.size(),
1882  ExcDimensionMismatch(jacobian.n(), independent_variables.size()));
1883 
1884  const std::size_t n_independent_variables = independent_variables.size();
1885  const std::size_t n_dependent_variables = dependent_variables.size();
1886 
1887  // In reverse mode, the gradients are computed from the
1888  // independent variables (i.e. the adjoint).
1889  // For a demonstration of why this accumulation process is
1890  // required, see the unit tests
1891  // sacado/basic_01b.cc and sacado/basic_02b.cc
1892  // Here we also take into consideration the derivative type:
1893  // The Sacado number may be of the nested variety, in which
1894  // case the effect of the accumulation process on the
1895  // sensitivities of the nested number need to be accounted for.
1896  using accumulation_type =
1897  typename ADNumberTraits<ADNumberType>::derivative_type;
1898  std::vector<accumulation_type> rad_accumulation(
1899  n_independent_variables,
1901 
1902  for (unsigned int i = 0; i < n_dependent_variables; ++i)
1903  {
1905  const_cast<ADNumberType &>(dependent_variables[i]));
1906  for (unsigned int j = 0; j < n_independent_variables; ++j)
1907  {
1908  const accumulation_type df_i_dx_j =
1909  ADNumberTraits<ADNumberType>::get_directional_derivative(
1910  independent_variables[j],
1911  i /*This number doesn't really matter*/) -
1912  rad_accumulation[j];
1913  jacobian[i][j] =
1915  rad_accumulation[j] += df_i_dx_j;
1916  }
1917  }
1918  }
1919 
1920 
1921 
1922  // Specialization for auto-differentiable numbers that use
1923  // forward mode to compute the first (and, if supported, second)
1924  // derivatives.
1925 
1926 # ifndef DOXYGEN
1927  template <typename ADNumberType, typename ScalarType>
1928  TapelessDrivers<
1929  ADNumberType,
1930  ScalarType,
1931  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1933  ADNumberTraits<ADNumberType>::type_code ==
1935  ADNumberTraits<ADNumberType>::type_code ==
1936  NumberTypes::sacado_dfad_dfad>>::TapelessDrivers()
1937  : dependent_variable_marking_safe(false)
1938  {}
1939 # endif
1940 
1941 
1942  template <typename ADNumberType, typename ScalarType>
1943  void
1944  TapelessDrivers<ADNumberType,
1945  ScalarType,
1946  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1948  ADNumberTraits<ADNumberType>::type_code ==
1950  ADNumberTraits<ADNumberType>::type_code ==
1952  initialize_global_environment(const unsigned int n_independent_variables)
1953  {
1954  internal::configure_tapeless_mode<ADNumberType>(n_independent_variables);
1955  }
1956 
1957 
1958  template <typename ADNumberType, typename ScalarType>
1959  void
1960  TapelessDrivers<
1961  ADNumberType,
1962  ScalarType,
1963  std::enable_if_t<
1964  ADNumberTraits<ADNumberType>::type_code ==
1966  ADNumberTraits<ADNumberType>::type_code == NumberTypes::sacado_dfad ||
1967  ADNumberTraits<ADNumberType>::type_code ==
1968  NumberTypes::sacado_dfad_dfad>>::allow_dependent_variable_marking()
1969  {
1970  dependent_variable_marking_safe = true;
1971  }
1972 
1973 
1974  template <typename ADNumberType, typename ScalarType>
1975  void
1976  TapelessDrivers<
1977  ADNumberType,
1978  ScalarType,
1979  std::enable_if_t<
1980  ADNumberTraits<ADNumberType>::type_code ==
1982  ADNumberTraits<ADNumberType>::type_code == NumberTypes::sacado_dfad ||
1983  ADNumberTraits<ADNumberType>::type_code ==
1984  NumberTypes::sacado_dfad_dfad>>::prevent_dependent_variable_marking()
1985  {
1986  dependent_variable_marking_safe = false;
1987  }
1988 
1989 
1990  template <typename ADNumberType, typename ScalarType>
1991  bool
1992  TapelessDrivers<ADNumberType,
1993  ScalarType,
1994  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
1996  ADNumberTraits<ADNumberType>::type_code ==
1998  ADNumberTraits<ADNumberType>::type_code ==
2000  is_dependent_variable_marking_allowed() const
2001  {
2002  return dependent_variable_marking_safe;
2003  }
2004 
2005 
2006  template <typename ADNumberType, typename ScalarType>
2007  ScalarType
2008  TapelessDrivers<ADNumberType,
2009  ScalarType,
2010  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
2012  ADNumberTraits<ADNumberType>::type_code ==
2014  ADNumberTraits<ADNumberType>::type_code ==
2016  value(const std::vector<ADNumberType> &dependent_variables) const
2017  {
2018  Assert(dependent_variables.size() == 1,
2019  ExcDimensionMismatch(dependent_variables.size(), 1));
2020  return ADNumberTraits<ADNumberType>::get_scalar_value(
2021  dependent_variables[0]);
2022  }
2023 
2024 
2025  template <typename ADNumberType, typename ScalarType>
2026  void
2027  TapelessDrivers<ADNumberType,
2028  ScalarType,
2029  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
2031  ADNumberTraits<ADNumberType>::type_code ==
2033  ADNumberTraits<ADNumberType>::type_code ==
2035  gradient(const std::vector<ADNumberType> &independent_variables,
2036  const std::vector<ADNumberType> &dependent_variables,
2037  Vector<ScalarType> & gradient) const
2038  {
2039  Assert(AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels >=
2040  1,
2042  AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels,
2043  1));
2044  Assert(dependent_variables.size() == 1,
2045  ExcDimensionMismatch(dependent_variables.size(), 1));
2046  Assert(gradient.size() == independent_variables.size(),
2048  independent_variables.size()));
2049 
2050  // In forward mode, the gradients are computed from the
2051  // dependent variables
2052  const std::size_t n_independent_variables = independent_variables.size();
2053  for (unsigned int i = 0; i < n_independent_variables; ++i)
2055  ADNumberTraits<ADNumberType>::get_directional_derivative(
2056  dependent_variables[0], i));
2057  }
2058 
2059 
2060  template <typename ADNumberType, typename ScalarType>
2061  void
2062  TapelessDrivers<ADNumberType,
2063  ScalarType,
2064  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
2066  ADNumberTraits<ADNumberType>::type_code ==
2068  ADNumberTraits<ADNumberType>::type_code ==
2070  hessian(const std::vector<ADNumberType> &independent_variables,
2071  const std::vector<ADNumberType> &dependent_variables,
2072  FullMatrix<ScalarType> & hessian) const
2073  {
2074  Assert(AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels >=
2075  2,
2077  AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels,
2078  2));
2079  Assert(dependent_variables.size() == 1,
2080  ExcDimensionMismatch(dependent_variables.size(), 1));
2081  Assert(hessian.m() == independent_variables.size(),
2082  ExcDimensionMismatch(hessian.m(), independent_variables.size()));
2083  Assert(hessian.n() == independent_variables.size(),
2084  ExcDimensionMismatch(hessian.n(), independent_variables.size()));
2085 
2086  // In forward mode, the gradients are computed from the
2087  // dependent variables
2088  const std::size_t n_independent_variables = independent_variables.size();
2089  for (unsigned int i = 0; i < n_independent_variables; ++i)
2090  {
2091  using derivative_type =
2092  typename ADNumberTraits<ADNumberType>::derivative_type;
2093  const derivative_type gradient_i =
2094  ADNumberTraits<ADNumberType>::get_directional_derivative(
2095  dependent_variables[0], i);
2096 
2097  for (unsigned int j = 0; j <= i; ++j) // Symmetry
2098  {
2099  // Extract higher-order directional derivatives. Depending on
2100  // the AD number type, the result may be another AD number or a
2101  // floating point value.
2102  const ScalarType hessian_ij =
2104  ADNumberTraits<derivative_type>::get_directional_derivative(
2105  gradient_i, j));
2106  hessian[i][j] = hessian_ij;
2107  if (i != j)
2108  hessian[j][i] = hessian_ij; // Symmetry
2109  }
2110  }
2111  }
2112 
2113 
2114  template <typename ADNumberType, typename ScalarType>
2115  void
2116  TapelessDrivers<ADNumberType,
2117  ScalarType,
2118  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
2120  ADNumberTraits<ADNumberType>::type_code ==
2122  ADNumberTraits<ADNumberType>::type_code ==
2124  values(const std::vector<ADNumberType> &dependent_variables,
2125  Vector<ScalarType> & values) const
2126  {
2127  Assert(values.size() == dependent_variables.size(),
2128  ExcDimensionMismatch(values.size(), dependent_variables.size()));
2129 
2130  const std::size_t n_dependent_variables = dependent_variables.size();
2131  for (unsigned int i = 0; i < n_dependent_variables; ++i)
2132  values[i] = ADNumberTraits<ADNumberType>::get_scalar_value(
2133  dependent_variables[i]);
2134  }
2135 
2136 
2137  template <typename ADNumberType, typename ScalarType>
2138  void
2139  TapelessDrivers<ADNumberType,
2140  ScalarType,
2141  std::enable_if_t<ADNumberTraits<ADNumberType>::type_code ==
2143  ADNumberTraits<ADNumberType>::type_code ==
2145  ADNumberTraits<ADNumberType>::type_code ==
2147  jacobian(const std::vector<ADNumberType> &independent_variables,
2148  const std::vector<ADNumberType> &dependent_variables,
2149  FullMatrix<ScalarType> & jacobian) const
2150  {
2151  Assert(AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels >=
2152  1,
2154  AD::ADNumberTraits<ADNumberType>::n_supported_derivative_levels,
2155  1));
2156  Assert(jacobian.m() == dependent_variables.size(),
2157  ExcDimensionMismatch(jacobian.m(), dependent_variables.size()));
2158  Assert(jacobian.n() == independent_variables.size(),
2159  ExcDimensionMismatch(jacobian.n(), independent_variables.size()));
2160 
2161  const std::size_t n_independent_variables = independent_variables.size();
2162  const std::size_t n_dependent_variables = dependent_variables.size();
2163 
2164  // In forward mode, the gradients are computed from the
2165  // dependent variables
2166  for (unsigned int i = 0; i < n_dependent_variables; ++i)
2167  for (unsigned int j = 0; j < n_independent_variables; ++j)
2168  jacobian[i][j] = internal::NumberType<ScalarType>::value(
2169  ADNumberTraits<ADNumberType>::get_directional_derivative(
2170  dependent_variables[i], j));
2171  }
2172 
2173 
2174  } // namespace AD
2175 } // namespace Differentiation
2176 
2177 
2178 /* --- Explicit instantiations --- */
2179 # include "ad_drivers.inst"
2180 # ifdef DEAL_II_WITH_ADOLC
2181 # include "ad_drivers.inst1"
2182 # endif
2183 # ifdef DEAL_II_TRILINOS_WITH_SACADO
2184 # include "ad_drivers.inst2"
2185 # endif
2186 
2187 
2189 
2190 
2191 #endif // defined(DEAL_II_WITH_ADOLC) || defined(DEAL_II_TRILINOS_WITH_SACADO)
size_type n() const
size_type m() const
Definition: vector.h:110
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:442
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition: config.h:456
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:443
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition: config.h:495
static ::ExceptionBase & ExcRequiresADOLC()
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define Assert(cond, exc)
Definition: exceptions.h:1473
static ::ExceptionBase & ExcSupportedDerivativeLevels(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcRequiresADNumberSpecialization()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1583
std::enable_if_t<!(ADNumberTraits< ADNumberType >::type_code==NumberTypes::sacado_rad||ADNumberTraits< ADNumberType >::type_code==NumberTypes::sacado_rad_dfad)> reverse_mode_dependent_variable_activation(ADNumberType &)
Definition: ad_drivers.cc:1531
std::enable_if_t<!(ADNumberTraits< ADNumberType >::type_code==NumberTypes::adolc_tapeless)> configure_tapeless_mode(const unsigned int)
Definition: ad_drivers.cc:1573
std::string to_string(const T &t)
Definition: patterns.h:2393
void copy(const T *begin, const T *end, U *dest)
static const Types< ADNumberType >::tape_index invalid_tape_index
Definition: ad_drivers.h:121
void gradient(const typename Types< ADNumberType >::tape_index active_tape_index, const std::vector< ScalarType > &independent_variables, Vector< ScalarType > &gradient) const
Definition: ad_drivers.cc:212
bool is_registered_tape(const typename Types< ADNumberType >::tape_index tape_index) const
Definition: ad_drivers.cc:76
void stop_taping(const typename Types< ADNumberType >::tape_index active_tape_index, const bool write_tapes_to_file)
Definition: ad_drivers.cc:117
void remove_tape(const typename Types< ADNumberType >::tape_index tape_index)
Definition: ad_drivers.cc:166
void start_taping(const typename Types< ADNumberType >::tape_index tape_index, const bool keep_independent_values)
Definition: ad_drivers.cc:107
void hessian(const typename Types< ADNumberType >::tape_index active_tape_index, const std::vector< ScalarType > &independent_variables, FullMatrix< ScalarType > &hessian) const
Definition: ad_drivers.cc:223
void set_tape_buffer_sizes(const typename Types< ADNumberType >::tape_buffer_sizes obufsize=64 *1024 *1024, const typename Types< ADNumberType >::tape_buffer_sizes lbufsize=64 *1024 *1024, const typename Types< ADNumberType >::tape_buffer_sizes vbufsize=64 *1024 *1024, const typename Types< ADNumberType >::tape_buffer_sizes tbufsize=64 *1024 *1024)
Definition: ad_drivers.cc:95
void activate_tape(const typename Types< ADNumberType >::tape_index tape_index)
Definition: ad_drivers.cc:137
bool last_action_requires_retaping() const
Definition: ad_drivers.cc:156
bool requires_retaping(const typename Types< ADNumberType >::tape_index tape_index) const
Definition: ad_drivers.cc:146
void print(std::ostream &stream) const
Definition: ad_drivers.cc:183
void print_tape_stats(const typename Types< ADNumberType >::tape_index tape_index, std::ostream &stream) const
Definition: ad_drivers.cc:191
ScalarType value(const typename Types< ADNumberType >::tape_index active_tape_index, const std::vector< ScalarType > &independent_variables) const
Definition: ad_drivers.cc:201
Types< ADNumberType >::tape_index active_tape_index() const
Definition: ad_drivers.cc:67
void reset(const bool clear_registered_tapes)
Definition: ad_drivers.cc:175
std::vector< typename Types< ADNumberType >::tape_index > get_registered_tape_indices() const
Definition: ad_drivers.cc:127
void values(const typename Types< ADNumberType >::tape_index active_tape_index, const unsigned int n_dependent_variables, const std::vector< ScalarType > &independent_variables, Vector< ScalarType > &values) const
Definition: ad_drivers.cc:234
void jacobian(const typename Types< ADNumberType >::tape_index active_tape_index, const unsigned int n_dependent_variables, const std::vector< ScalarType > &independent_variables, FullMatrix< ScalarType > &jacobian) const
Definition: ad_drivers.cc:246
void gradient(const std::vector< ADNumberType > &independent_variables, const std::vector< ADNumberType > &dependent_variables, Vector< ScalarType > &gradient) const
Definition: ad_drivers.cc:1479
void hessian(const std::vector< ADNumberType > &independent_variables, const std::vector< ADNumberType > &dependent_variables, FullMatrix< ScalarType > &hessian) const
Definition: ad_drivers.cc:1490
void values(const std::vector< ADNumberType > &dependent_variables, Vector< ScalarType > &values) const
Definition: ad_drivers.cc:1501
void jacobian(const std::vector< ADNumberType > &independent_variables, const std::vector< ADNumberType > &dependent_variables, FullMatrix< ScalarType > &jacobian) const
Definition: ad_drivers.cc:1511
static void initialize_global_environment(const unsigned int n_independent_variables)
Definition: ad_drivers.cc:1435
bool is_dependent_variable_marking_allowed() const
Definition: ad_drivers.cc:1460
ScalarType value(const std::vector< ADNumberType > &dependent_variables) const
Definition: ad_drivers.cc:1469
unsigned int tape_buffer_sizes
Definition: ad_drivers.h:104
static constexpr const T & value(const T &t)
Definition: numbers.h:733