Reference documentation for deal.II version 9.2.0
\(\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\}}\)
symengine_optimizer.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2020 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 #ifndef dealii_differentiation_sd_symengine_optimizer_h
17 #define dealii_differentiation_sd_symengine_optimizer_h
18 
19 #include <deal.II/base/config.h>
20 
21 #ifdef DEAL_II_WITH_SYMENGINE
22 
24 // Low level
25 # include <symengine/basic.h>
26 # include <symengine/dict.h>
27 # include <symengine/symengine_exception.h>
28 # include <symengine/symengine_rcp.h>
29 
30 // Optimization
31 # include <symengine/lambda_double.h>
32 # include <symengine/visitor.h>
33 # ifdef HAVE_SYMENGINE_LLVM
34 # include <symengine/llvm_double.h>
35 # endif
37 
38 # include <deal.II/base/exceptions.h>
39 # include <deal.II/base/logstream.h>
40 # include <deal.II/base/utilities.h>
41 
47 
48 # include <boost/serialization/split_member.hpp>
49 # include <boost/type_traits.hpp>
50 
51 # include <algorithm>
52 # include <map>
53 # include <memory>
54 # include <type_traits>
55 # include <utility>
56 # include <vector>
57 
58 
60 
61 
62 namespace Differentiation
63 {
64  namespace SD
65  {
76  "SymEngine has not been built with LLVM support.");
77 
83  "The SymEngine LLVM optimizer does not (yet) support the "
84  "selected return type.");
85 
87 
88 
89  // Forward declarations
90  template <typename ReturnType>
92 
93 
99  enum class OptimizerType
100  {
104  dictionary,
109  lambda,
114  llvm
115  };
116 
117 
121  template <class StreamType>
122  inline StreamType &
123  operator<<(StreamType &s, OptimizerType o)
124  {
125  if (o == OptimizerType::dictionary)
126  s << "dictionary";
127  else if (o == OptimizerType::lambda)
128  s << "lambda";
129  else if (o == OptimizerType::llvm)
130  s << "llvm";
131  else
132  {
133  Assert(false, ExcMessage("Unknown optimization method."));
134  }
135 
136  return s;
137  }
138 
139 
145  enum class OptimizationFlags : unsigned char
146  {
150  optimize_default = 0,
154  optimize_cse = 0x0001,
159  optimize_aggressive = 0x0002,
164  };
165 
166 
175  // This operator exists since if it did not then the result of the bit-or
176  // <tt>operator |</tt> would be an integer which would in turn trigger a
177  // compiler warning when we tried to assign it to an object of type
178  // OptimizationFlags.
179  inline OptimizationFlags
181  {
182  return static_cast<OptimizationFlags>(static_cast<unsigned int>(f1) |
183  static_cast<unsigned int>(f2));
184  }
185 
186 
191  inline OptimizationFlags &
193  {
194  f1 = f1 | f2;
195  return f1;
196  }
197 
198 
207  // This operator exists since if it did not then the result of the bit-or
208  // <tt>operator |</tt> would be an integer which would in turn trigger a
209  // compiler warning when we tried to assign it to an object of type
210  // OptimizationFlags.
212  const OptimizationFlags f2)
213  {
214  return static_cast<OptimizationFlags>(static_cast<unsigned int>(f1) &
215  static_cast<unsigned int>(f2));
216  }
217 
218 
223  inline OptimizationFlags &
225  {
226  f1 = f1 & f2;
227  return f1;
228  }
229 
230 
231  namespace internal
232  {
237  inline bool
239  {
240  return static_cast<int>(flags & OptimizationFlags::optimize_cse);
241  }
242 
247  inline int
249  {
250  // With the LLVM compiler there exists the opportunity to tune
251  // the level of optimizations performed during compilation.
252  // By default SymEngine sets this at "opt_level=2", which one
253  // presumes targets -O2. Here we are a bit more specific about
254  // want we want it to do:
255  // - Normal compilation: -02 (default settings)
256  // - Aggressive mode: -03 (the whole lot!)
257  // In theory we could also target
258  // - Debug mode: -O0 (no optimizations)
259  // but this doesn't make much sense since SymEngine is a
260  // tested external library.
261  const bool use_agg_opt =
262  static_cast<int>(flags & OptimizationFlags::optimize_aggressive);
263  const int opt_level = (use_agg_opt ? 3 : 2);
264  return opt_level;
265  }
266  } // namespace internal
267 
268 
273  template <class StreamType>
274  inline StreamType &
275  operator<<(StreamType &s, OptimizationFlags o)
276  {
277  s << " OptimizationFlags|";
278  if (static_cast<unsigned int>(o & OptimizationFlags::optimize_cse))
279  s << "cse|";
280 
281  // LLVM optimization level
282  s << "-O" +
285  "|";
286 
287  return s;
288  }
289 
290 
291  namespace internal
292  {
302  template <typename ReturnType, typename T = void>
304 
305 
315  template <typename ReturnType, typename T = void>
317 
318 
319 # ifdef HAVE_SYMENGINE_LLVM
320 
329  template <typename ReturnType, typename T = void>
330  struct LLVMOptimizer;
331 # endif // HAVE_SYMENGINE_LLVM
332 
333 
349  template <typename ReturnType, typename Optimizer, typename T = void>
351 
352 
353 # ifndef DOXYGEN
354 
355 
356  /* ----------- Specializations for the Optimizers ----------- */
357 
358 
359  // A helper struct to type trait detection for the optimizers that
360  // will be defined next.
361  template <typename ReturnType_, typename T = void>
362  struct SupportedOptimizerTypeTraits
363  {
364  static const bool is_supported = false;
365 
366  using ReturnType = void;
367  };
368 
369 
370 
371  // Specialization for arithmetic types
372  template <typename ReturnType_>
373  struct SupportedOptimizerTypeTraits<
374  ReturnType_,
375  typename std::enable_if<std::is_arithmetic<ReturnType_>::value>::type>
376  {
377  static const bool is_supported = true;
378 
379  using ReturnType =
381  float,
382  double>::type;
383  };
384 
385 
386 
387  // Specialization for complex arithmetic types
388  template <typename ReturnType_>
389  struct SupportedOptimizerTypeTraits<
390  ReturnType_,
391  typename std::enable_if<
392  boost::is_complex<ReturnType_>::value &&
393  std::is_arithmetic<typename ReturnType_::value_type>::value>::type>
394  {
395  static const bool is_supported = true;
396 
397  using ReturnType = typename std::conditional<
398  std::is_same<ReturnType_, std::complex<float>>::value,
399  std::complex<float>,
400  std::complex<double>>::type;
401  };
402 
403 
404 
405  template <typename ReturnType_>
406  struct DictionaryOptimizer<
407  ReturnType_,
408  typename std::enable_if<
409  SupportedOptimizerTypeTraits<ReturnType_>::is_supported>::type>
410  {
411  using ReturnType =
412  typename SupportedOptimizerTypeTraits<ReturnType_>::ReturnType;
413  using OptimizerType =
414  internal::DictionarySubstitutionVisitor<ReturnType, SD::Expression>;
415 
416 
425  static void
426  initialize(OptimizerType & optimizer,
427  const SymEngine::vec_basic & independent_symbols,
428  const SymEngine::vec_basic & dependent_functions,
429  const enum OptimizationFlags &optimization_flags)
430  {
431  const bool use_symbolic_cse = use_symbolic_CSE(optimization_flags);
432  optimizer.init(independent_symbols,
433  dependent_functions,
434  use_symbolic_cse);
435  }
436 
437 
438 
443  template <class Archive>
444  static void
445  save(Archive & archive,
446  const unsigned int version,
447  OptimizerType & optimizer)
448  {
449  optimizer.save(archive, version);
450  }
451 
452 
453 
458  template <class Archive>
459  static void
460  load(Archive & archive,
461  const unsigned int version,
462  OptimizerType & optimizer,
463  const SymEngine::vec_basic & /*independent_symbols*/,
464  const SymEngine::vec_basic & /*dependent_functions*/,
465  const enum OptimizationFlags & /*optimization_flags*/)
466  {
467  optimizer.load(archive, version);
468  }
469 
470 
471 
487  template <typename Stream>
488  static void
489  print(Stream & stream,
490  const OptimizerType &optimizer,
491  const bool print_independent_symbols = false,
492  const bool print_dependent_functions = false,
493  const bool print_cse_reductions = true)
494  {
495  optimizer.print(stream,
496  print_independent_symbols,
497  print_dependent_functions,
498  print_cse_reductions);
499  }
500  };
501 
502 
503 
504  template <typename ReturnType_>
505  struct LambdaOptimizer<
506  ReturnType_,
507  typename std::enable_if<
508  SupportedOptimizerTypeTraits<ReturnType_>::is_supported>::type>
509  {
510  using ReturnType =
512  double,
513  std::complex<double>>::type;
514  using OptimizerType = typename std::conditional<
516  SymEngine::LambdaRealDoubleVisitor,
517  SymEngine::LambdaComplexDoubleVisitor>::type;
518 
519 
528  static void
529  initialize(OptimizerType & optimizer,
530  const SymEngine::vec_basic & independent_symbols,
531  const SymEngine::vec_basic & dependent_functions,
532  const enum OptimizationFlags &optimization_flags)
533  {
534  const bool use_symbolic_cse = use_symbolic_CSE(optimization_flags);
535  optimizer.init(independent_symbols,
536  dependent_functions,
537  use_symbolic_cse);
538  }
539 
540 
541 
546  template <class Archive>
547  static void
548  save(Archive & /*archive*/,
549  const unsigned int /*version*/,
550  OptimizerType & /*optimizer*/)
551  {}
552 
553 
558  template <class Archive>
559  static void
560  load(Archive & /*archive*/,
561  const unsigned int /*version*/,
562  OptimizerType & optimizer,
563  const SymEngine::vec_basic & independent_symbols,
564  const SymEngine::vec_basic & dependent_functions,
565  const enum OptimizationFlags &optimization_flags)
566  {
567  initialize(optimizer,
568  independent_symbols,
569  dependent_functions,
570  optimization_flags);
571  }
572 
573 
574 
590  template <typename StreamType>
591  static void
592  print(StreamType & /*stream*/,
593  const OptimizerType & /*optimizer*/,
594  const bool /*print_independent_symbols*/ = false,
595  const bool /*print_dependent_functions*/ = false,
596  const bool /*print_cse_reductions*/ = true)
597  {
598  // No built-in print function
599  }
600  };
601 
602 
603 
604 # ifdef HAVE_SYMENGINE_LLVM
605  template <typename ReturnType_>
606  struct LLVMOptimizer<
607  ReturnType_,
608  typename std::enable_if<std::is_arithmetic<ReturnType_>::value>::type>
609  {
610  using ReturnType =
612  float,
613  double>::type;
614  using OptimizerType =
616  SymEngine::LLVMFloatVisitor,
617  SymEngine::LLVMDoubleVisitor>::type;
618 
623  static const bool supported_by_LLVM = true;
624 
625 
634  static void
635  initialize(OptimizerType & optimizer,
636  const SymEngine::vec_basic & independent_symbols,
637  const SymEngine::vec_basic & dependent_functions,
638  const enum OptimizationFlags &optimization_flags)
639  {
640  const int opt_level = get_LLVM_optimization_level(optimization_flags);
641  const bool use_symbolic_cse = use_symbolic_CSE(optimization_flags);
642  optimizer.init(independent_symbols,
643  dependent_functions,
644  use_symbolic_cse,
645  opt_level);
646  }
647 
648 
649 
654  template <class Archive>
655  static void
656  save(Archive &archive,
657  const unsigned int /*version*/,
658  OptimizerType &optimizer)
659  {
660  const std::string llvm_compiled_function = optimizer.dumps();
661  archive & llvm_compiled_function;
662  }
663 
664 
665 
670  template <class Archive>
671  static void
672  load(Archive &archive,
673  const unsigned int /*version*/,
674  OptimizerType &optimizer,
675  const SymEngine::vec_basic & /*independent_symbols*/,
676  const SymEngine::vec_basic & /*dependent_functions*/,
677  const enum OptimizationFlags & /*optimization_flags*/)
678  {
679  std::string llvm_compiled_function;
680  archive & llvm_compiled_function;
681  optimizer.loads(llvm_compiled_function);
682  }
683 
684 
685 
701  template <typename StreamType>
702  static void
703  print(StreamType & /*stream*/,
704  const OptimizerType & /*optimizer*/,
705  const bool /*print_independent_symbols*/ = false,
706  const bool /*print_dependent_functions*/ = false,
707  const bool /*print_cse_reductions*/ = true)
708  {
709  // No built-in print function
710  }
711  };
712 
713 
714  // There is no LLVM optimizer built with complex number support.
715  // So we fall back to the LambdaDouble case as a type (required
716  // at compile time), but offer no implementation. We expect that
717  // the calling class does not create this type: This can be done by
718  // checking the `supported_by_LLVM` flag.
719  template <typename ReturnType_>
720  struct LLVMOptimizer<
721  ReturnType_,
722  typename std::enable_if<
723  boost::is_complex<ReturnType_>::value &&
724  std::is_arithmetic<typename ReturnType_::value_type>::value>::type>
725  {
726  // Since there is no working implementation, these are dummy types
727  // that help with templating in the calling function.
728  using ReturnType = typename LambdaOptimizer<ReturnType_>::ReturnType;
729  using OptimizerType =
731 
736  static const bool supported_by_LLVM = false;
737 
738 
747  static void
748  initialize(OptimizerType & /*optimizer*/,
749  const SymEngine::vec_basic & /*independent_symbols*/,
750  const SymEngine::vec_basic & /*dependent_functions*/,
751  const enum OptimizationFlags & /*optimization_flags*/)
752  {
753  AssertThrow(false, ExcNotImplemented());
754  }
755 
756 
757 
762  template <class Archive>
763  static void
764  save(Archive & /*archive*/,
765  const unsigned int /*version*/,
766  OptimizerType & /*optimizer*/)
767  {
768  AssertThrow(false, ExcNotImplemented());
769  }
770 
771 
772 
777  template <class Archive>
778  static void
779  load(Archive & /*archive*/,
780  const unsigned int /*version*/,
781  OptimizerType & /*optimizer*/,
782  const SymEngine::vec_basic & /*independent_symbols*/,
783  const SymEngine::vec_basic & /*dependent_functions*/,
784  const enum OptimizationFlags & /*optimization_flags*/)
785  {
786  AssertThrow(false, ExcNotImplemented());
787  }
788 
789 
790 
806  template <typename StreamType>
807  static void
808  print(StreamType & /*stream*/,
809  const OptimizerType & /*optimizer*/,
810  const bool /*print_independent_symbols*/ = false,
811  const bool /*print_dependent_functions*/ = false,
812  const bool /*print_cse_reductions*/ = true)
813  {
814  AssertThrow(false, ExcNotImplemented());
815  }
816  };
817 # endif // HAVE_SYMENGINE_LLVM
818 
819 
820  /* ----------- Specializations for OptimizerHelper ----------- */
821 
822 
823  template <typename ReturnType, typename Optimizer>
824  struct OptimizerHelper<ReturnType,
825  Optimizer,
826  typename std::enable_if<std::is_same<
827  ReturnType,
828  typename Optimizer::ReturnType>::value>::type>
829  {
838  static void
839  initialize(typename Optimizer::OptimizerType *optimizer,
840  const SymEngine::vec_basic & independent_symbols,
841  const SymEngine::vec_basic & dependent_functions,
842  const enum OptimizationFlags & optimization_flags)
843  {
844  Assert(optimizer, ExcNotInitialized());
845 
846  // Some optimizers don't have the same interface for
847  // initialization, we filter them out through the specializations
848  // of the Optimizer class
849  Optimizer::initialize(*optimizer,
850  independent_symbols,
851  dependent_functions,
852  optimization_flags);
853  }
854 
855 
856 
870  static void
871  substitute(typename Optimizer::OptimizerType *optimizer,
872  std::vector<ReturnType> & output_values,
873  const std::vector<ReturnType> & substitution_values)
874  {
875  Assert(optimizer, ExcNotInitialized());
876  optimizer->call(output_values.data(), substitution_values.data());
877  }
878 
879 
880 
885  template <class Archive>
886  static void
887  save(Archive & archive,
888  const unsigned int version,
889  typename Optimizer::OptimizerType *optimizer)
890  {
891  Assert(optimizer, ExcNotInitialized());
892 
893  // Some optimizers don't have the same interface for
894  // serialization, we filter them out through the specializations
895  // of the Optimizer class
896  Optimizer::save(archive, version, *optimizer);
897  }
898 
899 
900 
905  template <class Archive>
906  static void
907  load(Archive & archive,
908  const unsigned int version,
909  typename Optimizer::OptimizerType *optimizer,
910  const SymEngine::vec_basic & independent_symbols,
911  const SymEngine::vec_basic & dependent_functions,
912  const enum OptimizationFlags & optimization_flags)
913  {
914  Assert(optimizer, ExcNotInitialized());
915 
916  // Some optimizers don't have the same interface for
917  // serialization, we filter them out through the specializations
918  // of the Optimizer class
919  Optimizer::load(archive,
920  version,
921  *optimizer,
922  independent_symbols,
923  dependent_functions,
924  optimization_flags);
925  }
926 
927 
928 
944  template <typename Stream>
945  static void
946  print(Stream & stream,
947  typename Optimizer::OptimizerType *optimizer,
948  const bool print_independent_symbols = false,
949  const bool print_dependent_functions = false,
950  const bool print_cse_reductions = true)
951  {
952  Assert(optimizer, ExcNotInitialized());
953 
954  // Some optimizers don't have a print function, so
955  // we filter them out through the specializations of
956  // the Optimizer class
957  Optimizer::print(stream,
958  *optimizer,
959  print_independent_symbols,
960  print_dependent_functions,
961  print_cse_reductions);
962  }
963  };
964 
965  template <typename ReturnType, typename Optimizer>
966  struct OptimizerHelper<ReturnType,
967  Optimizer,
968  typename std::enable_if<!std::is_same<
969  ReturnType,
970  typename Optimizer::ReturnType>::value>::type>
971  {
980  static void
981  initialize(typename Optimizer::OptimizerType *optimizer,
982  const SymEngine::vec_basic & independent_symbols,
983  const SymEngine::vec_basic & dependent_functions,
984  const enum OptimizationFlags & optimization_flags)
985  {
986  Assert(optimizer, ExcNotInitialized());
987 
988  const bool use_symbolic_cse = use_symbolic_CSE(optimization_flags);
989  optimizer->init(independent_symbols,
990  dependent_functions,
991  use_symbolic_cse);
992  }
993 
994 
995 
1009  static void
1010  substitute(typename Optimizer::OptimizerType *optimizer,
1011  std::vector<ReturnType> & output_values,
1012  const std::vector<ReturnType> & substitution_values)
1013  {
1014  Assert(optimizer, ExcNotInitialized());
1015 
1016  // Intermediate values to accommodate the difference in
1017  // value types.
1018  std::vector<typename Optimizer::ReturnType> int_outputs(
1019  output_values.size());
1020  std::vector<typename Optimizer::ReturnType> int_inputs(
1021  substitution_values.size());
1022 
1023  std::copy(substitution_values.begin(),
1024  substitution_values.end(),
1025  int_inputs.begin());
1026  optimizer->call(int_outputs.data(), int_inputs.data());
1027  std::copy(int_outputs.begin(),
1028  int_outputs.end(),
1029  output_values.begin());
1030  }
1031 
1032 
1033 
1038  template <class Archive>
1039  static void
1040  save(Archive & archive,
1041  const unsigned int version,
1042  typename Optimizer::OptimizerType *optimizer)
1043  {
1044  Assert(optimizer, ExcNotInitialized());
1045  Optimizer::save(archive, version, *optimizer);
1046  }
1047 
1048 
1049 
1054  template <class Archive>
1055  static void
1056  load(Archive & archive,
1057  const unsigned int version,
1058  typename Optimizer::OptimizerType *optimizer,
1059  const SymEngine::vec_basic & independent_symbols,
1060  const SymEngine::vec_basic & dependent_functions,
1061  const enum OptimizationFlags & optimization_flags)
1062  {
1063  Assert(optimizer, ExcNotInitialized());
1064 
1065  // Some optimizers don't have the same interface for
1066  // serialization, we filter them out through the specializations
1067  // of the Optimizer class
1068  Optimizer::load(archive,
1069  version,
1070  *optimizer,
1071  independent_symbols,
1072  dependent_functions,
1073  optimization_flags);
1074  }
1075 
1076 
1077 
1093  template <typename Stream>
1094  static void
1095  print(Stream & stream,
1096  typename Optimizer::OptimizerType *optimizer,
1097  const bool print_cse_reductions = true,
1098  const bool print_independent_symbols = false,
1099  const bool print_dependent_functions = false)
1100  {
1101  Assert(optimizer, ExcNotInitialized());
1102 
1103  optimizer->print(stream,
1104  print_independent_symbols,
1105  print_dependent_functions,
1106  print_cse_reductions);
1107  }
1108  };
1109 
1110 # endif // DOXYGEN
1111 
1112 
1113  /* -------------------- Utility functions ---------------------- */
1114 
1115 
1132  template <typename NumberType,
1133  int rank,
1134  int dim,
1135  template <int, int, typename> class TensorType>
1136  TensorType<rank, dim, NumberType>
1138  const TensorType<rank, dim, Expression> &symbol_tensor,
1139  const BatchOptimizer<NumberType> & optimizer)
1140  {
1141  TensorType<rank, dim, NumberType> out;
1142  for (unsigned int i = 0; i < out.n_independent_components; ++i)
1143  {
1144  const TableIndices<rank> indices(
1145  out.unrolled_to_component_indices(i));
1146  out[indices] = optimizer.evaluate(symbol_tensor[indices]);
1147  }
1148  return out;
1149  }
1150 
1151 
1169  template <typename NumberType, int dim>
1172  const SymmetricTensor<4, dim, Expression> &symbol_tensor,
1173  const BatchOptimizer<NumberType> & optimizer)
1174  {
1176  for (unsigned int i = 0;
1177  i < SymmetricTensor<2, dim>::n_independent_components;
1178  ++i)
1179  for (unsigned int j = 0;
1180  j < SymmetricTensor<2, dim>::n_independent_components;
1181  ++j)
1182  {
1183  const TableIndices<4> indices =
1184  make_rank_4_tensor_indices<dim>(i, j);
1185  out[indices] = optimizer.evaluate(symbol_tensor[indices]);
1186  }
1187  return out;
1188  }
1189 
1190 
1208  template <typename NumberType, typename T>
1209  void
1211  const T & function)
1212  {
1213  optimizer.register_function(function);
1214  }
1215 
1216 
1234  template <typename NumberType, typename T>
1235  void
1237  const std::vector<T> & functions)
1238  {
1239  for (const auto &function : functions)
1240  register_functions(optimizer, function);
1241  }
1242 
1243 
1263  template <typename NumberType, typename T, typename... Args>
1264  void
1266  const T & function,
1267  const Args &... other_functions)
1268  {
1269  register_functions(optimizer, function);
1270  register_functions(optimizer, other_functions...);
1271  }
1272 
1273 
1285  template <int rank,
1286  int dim,
1287  template <int, int, typename> class TensorType>
1290  const TensorType<rank, dim, Expression> &symbol_tensor)
1291  {
1293  out.reserve(symbol_tensor.n_independent_components);
1294  for (unsigned int i = 0; i < symbol_tensor.n_independent_components;
1295  ++i)
1296  {
1297  const TableIndices<rank> indices(
1298  symbol_tensor.unrolled_to_component_indices(i));
1299  out.push_back(symbol_tensor[indices].get_RCP());
1300  }
1301  return out;
1302  }
1303 
1304 
1314  template <int dim>
1317  const SymmetricTensor<4, dim, Expression> &symbol_tensor)
1318  {
1320  out.reserve(symbol_tensor.n_independent_components);
1321  for (unsigned int i = 0;
1322  i < SymmetricTensor<2, dim>::n_independent_components;
1323  ++i)
1324  for (unsigned int j = 0;
1325  j < SymmetricTensor<2, dim>::n_independent_components;
1326  ++j)
1327  {
1328  const TableIndices<4> indices =
1329  make_rank_4_tensor_indices<dim>(i, j);
1330  out.push_back(symbol_tensor[indices].get_RCP());
1331  }
1332  return out;
1333  }
1334 
1335  } // namespace internal
1336 
1337 
1338 
1431  template <typename ReturnType>
1432  class BatchOptimizer
1433  {
1434  public:
1442  BatchOptimizer();
1443 
1464 
1474  BatchOptimizer(const BatchOptimizer &other/*,
1475  const bool copy_initialized = true*/);
1476 
1480  BatchOptimizer(BatchOptimizer &&) = default;
1481 
1485  ~BatchOptimizer() = default;
1486 
1496  template <typename Stream>
1497  void
1498  print(Stream &stream, const bool print_cse = false) const;
1499 
1507  template <class Archive>
1508  void
1509  save(Archive &archive, const unsigned int version) const;
1510 
1523  template <class Archive>
1524  void
1525  load(Archive &archive, const unsigned int version);
1526 
1527 # ifdef DOXYGEN
1528 
1548  template <class Archive>
1549  void
1550  serialize(Archive &archive, const unsigned int version);
1551 # else
1552  // This macro defines the serialize() method that is compatible with
1553  // the templated save() and load() method that have been implemented.
1554  BOOST_SERIALIZATION_SPLIT_MEMBER()
1555 # endif
1556 
1561 
1567  void
1569 
1575  void
1576  register_symbols(const SymEngine::map_basic_basic &substitution_map);
1577 
1588  void
1589  register_symbols(const types::symbol_vector &symbols);
1590 
1601  void
1602  register_symbols(const SymEngine::vec_basic &symbols);
1603 
1609  get_independent_symbols() const;
1610 
1616  std::size_t
1617  n_independent_variables() const;
1618 
1620 
1625 
1630  void
1631  register_function(const Expression &function);
1632 
1637  template <int rank, int dim>
1638  void
1639  register_function(const Tensor<rank, dim, Expression> &function_tensor);
1640 
1645  template <int rank, int dim>
1646  void
1648  const SymmetricTensor<rank, dim, Expression> &function_tensor);
1649 
1654  void
1656 
1661  void
1662  register_functions(const SymEngine::vec_basic &functions);
1663 
1673  template <typename T>
1674  void
1675  register_functions(const std::vector<T> &functions);
1676 
1690  template <typename T, typename... Args>
1691  void
1692  register_functions(const T &functions, const Args &... other_functions);
1693 
1698  const types::symbol_vector &
1699  get_dependent_functions() const;
1700 
1707  std::size_t
1708  n_dependent_variables() const;
1709 
1711 
1716 
1728  void
1732 
1737  enum OptimizerType
1738  optimization_method() const;
1739 
1744  enum OptimizationFlags
1745  optimization_flags() const;
1746 
1752  bool
1753  use_symbolic_CSE() const;
1754 
1770  void
1771  optimize();
1772 
1777  bool
1778  optimized() const;
1779 
1781 
1786 
1796  void
1798 
1808  void
1809  substitute(const SymEngine::map_basic_basic &substitution_map) const;
1810 
1821  void
1822  substitute(const types::symbol_vector & symbols,
1823  const std::vector<ReturnType> &values) const;
1824 
1835  void
1836  substitute(const SymEngine::vec_basic & symbols,
1837  const std::vector<ReturnType> &values) const;
1838 
1844  bool
1845  values_substituted() const;
1846 
1848 
1853 
1874  const std::vector<ReturnType> &
1875  evaluate() const;
1876 
1884  ReturnType
1885  evaluate(const Expression &func) const;
1886 
1895  std::vector<ReturnType>
1896  evaluate(const std::vector<Expression> &funcs) const;
1897 
1906  template <int rank, int dim>
1908  evaluate(const Tensor<rank, dim, Expression> &funcs) const;
1909 
1910 
1919  template <int rank, int dim>
1922 
1924 
1925  private:
1930 
1936 
1947 
1954 
1959  bool
1961  const SD::Expression &function) const;
1962 
1967  bool
1969  const SymEngine::RCP<const SymEngine::Basic> &function) const;
1970 
1985  mutable std::vector<ReturnType> dependent_variables_output;
1986 
1996  std::map<SD::Expression,
1997  std::size_t,
1999 
2005 
2012  mutable std::unique_ptr<SymEngine::Visitor> optimizer;
2013 
2023 
2028  mutable bool has_been_serialized;
2029 
2033  void
2034  register_scalar_function(const SD::Expression &function);
2035 
2040  void
2042 
2046  void
2047  create_optimizer(std::unique_ptr<SymEngine::Visitor> &optimizer);
2048 
2065  void
2066  substitute(const std::vector<ReturnType> &substitution_values) const;
2067  };
2068 
2069 
2070 
2071  /* -------------------- inline and template functions ------------------ */
2072 
2073 
2074 # ifndef DOXYGEN
2075 
2076 
2077  template <typename ReturnType>
2078  template <typename Stream>
2079  void
2080  BatchOptimizer<ReturnType>::print(Stream &stream,
2081  const bool /*print_cse*/) const
2082  {
2083  // Settings
2084  stream << "Method? " << optimization_method() << "\n";
2085  stream << "Flags: " << optimization_flags() << "\n";
2086  stream << "Optimized? " << (optimized() ? "Yes" : "No") << "\n";
2087  stream << "Values substituted? " << values_substituted() << "\n\n";
2088 
2089  // Independent variables
2090  stream << "Symbols (" << n_independent_variables()
2091  << " independent variables):"
2092  << "\n";
2093  int cntr = 0;
2094  for (SD::types::substitution_map::const_iterator it =
2095  independent_variables_symbols.begin();
2096  it != independent_variables_symbols.end();
2097  ++it, ++cntr)
2098  {
2099  stream << cntr << ": " << it->first << "\n";
2100  }
2101  stream << "\n" << std::flush;
2102 
2103  // Dependent functions
2104  stream << "Functions (" << n_dependent_variables()
2105  << " dependent variables):"
2106  << "\n";
2107  cntr = 0;
2108  for (typename SD::types::symbol_vector::const_iterator it =
2109  dependent_variables_functions.begin();
2110  it != dependent_variables_functions.end();
2111  ++it, ++cntr)
2112  {
2113  stream << cntr << ": " << (*it) << "\n";
2114  }
2115  stream << "\n" << std::flush;
2116 
2117  // Common subexpression
2118  if (optimized() == true && use_symbolic_CSE() == true)
2119  {
2120  Assert(optimizer, ExcNotInitialized());
2121  const bool print_cse_reductions = true;
2122  const bool print_independent_symbols = false;
2123  const bool print_dependent_functions = false;
2124 
2125  if (optimization_method() == OptimizerType::dictionary)
2126  {
2127  Assert(dynamic_cast<typename internal::DictionaryOptimizer<
2128  ReturnType>::OptimizerType *>(optimizer.get()),
2129  ExcMessage("Cannot cast optimizer to Dictionary type."));
2130 
2131  internal::OptimizerHelper<
2132  ReturnType,
2133  internal::DictionaryOptimizer<ReturnType>>::
2134  print(stream,
2135  dynamic_cast<typename internal::DictionaryOptimizer<
2136  ReturnType>::OptimizerType *>(optimizer.get()),
2137  print_independent_symbols,
2138  print_dependent_functions,
2139  print_cse_reductions);
2140 
2141  stream << "\n" << std::flush;
2142  }
2143  else if (optimization_method() == OptimizerType::lambda)
2144  {
2145  Assert(dynamic_cast<typename internal::LambdaOptimizer<
2146  ReturnType>::OptimizerType *>(optimizer.get()),
2147  ExcMessage("Cannot cast optimizer to Lambda type."));
2148 
2149  internal::OptimizerHelper<ReturnType,
2150  internal::LambdaOptimizer<ReturnType>>::
2151  print(stream,
2152  dynamic_cast<typename internal::LambdaOptimizer<
2153  ReturnType>::OptimizerType *>(optimizer.get()),
2154  print_independent_symbols,
2155  print_dependent_functions,
2156  print_cse_reductions);
2157  }
2158 # ifdef HAVE_SYMENGINE_LLVM
2159  else if (optimization_method() == OptimizerType::llvm)
2160  {
2161  Assert(dynamic_cast<typename internal::LLVMOptimizer<
2162  ReturnType>::OptimizerType *>(optimizer.get()),
2163  ExcMessage("Cannot cast optimizer to LLVM type."));
2164 
2165  internal::OptimizerHelper<ReturnType,
2166  internal::LLVMOptimizer<ReturnType>>::
2167  print(stream,
2168  dynamic_cast<typename internal::LLVMOptimizer<
2169  ReturnType>::OptimizerType *>(optimizer.get()),
2170  print_independent_symbols,
2171  print_dependent_functions,
2172  print_cse_reductions);
2173  }
2174 # endif // HAVE_SYMENGINE_LLVM
2175  else
2176  {
2177  AssertThrow(false, ExcMessage("Unknown optimizer type."));
2178  }
2179  }
2180 
2181  if (values_substituted())
2182  {
2183  stream << "Evaluated functions:"
2184  << "\n";
2185  stream << std::flush;
2186  cntr = 0;
2187  for (typename std::vector<ReturnType>::const_iterator it =
2188  dependent_variables_output.begin();
2189  it != dependent_variables_output.end();
2190  ++it, ++cntr)
2191  {
2192  stream << cntr << ": " << (*it) << "\n";
2193  }
2194  stream << "\n" << std::flush;
2195  }
2196  }
2197 
2198 
2199 
2200  template <typename ReturnType>
2201  template <class Archive>
2202  void
2203  BatchOptimizer<ReturnType>::save(Archive & ar,
2204  const unsigned int version) const
2205  {
2206  // Serialize enum classes...
2207  {
2208  const auto m =
2209  static_cast<typename std::underlying_type<OptimizerType>::type>(
2210  method);
2211  ar &m;
2212  }
2213  {
2214  const auto f =
2215  static_cast<typename std::underlying_type<OptimizationFlags>::type>(
2216  flags);
2217  ar &f;
2218  }
2219 
2220  // Important: Independent variables must always be
2221  // serialized before the dependent variables.
2222  ar &independent_variables_symbols;
2223  ar &dependent_variables_functions;
2224 
2225  ar &dependent_variables_output;
2226  ar &map_dep_expr_vec_entry;
2227  ar &ready_for_value_extraction;
2228 
2229  // Mark that we've saved this class at some point.
2230  has_been_serialized = true;
2231  ar &has_been_serialized;
2232 
2233  // When we serialize the optimizer itself, we have to (unfortunately)
2234  // provide it with sufficient information to rebuild itself from scratch.
2235  // This is because only two of the three optimization classes support
2236  // real serialization (i.e. have save/load capability).
2237  const SD::types::symbol_vector symbol_vec =
2238  Utilities::extract_symbols(independent_variables_symbols);
2240  *opt = dynamic_cast<typename internal::DictionaryOptimizer<
2241  ReturnType>::OptimizerType *>(optimizer.get()))
2242  {
2243  Assert(optimization_method() == OptimizerType::dictionary,
2244  ExcInternalError());
2245  internal::OptimizerHelper<
2246  ReturnType,
2247  internal::DictionaryOptimizer<ReturnType>>::save(ar, version, opt);
2248  }
2250  *opt = dynamic_cast<typename internal::LambdaOptimizer<
2251  ReturnType>::OptimizerType *>(optimizer.get()))
2252  {
2253  Assert(optimization_method() == OptimizerType::lambda,
2254  ExcInternalError());
2255  internal::OptimizerHelper<
2256  ReturnType,
2257  internal::LambdaOptimizer<ReturnType>>::save(ar, version, opt);
2258  }
2259 # ifdef HAVE_SYMENGINE_LLVM
2261  *opt = dynamic_cast<typename internal::LLVMOptimizer<
2262  ReturnType>::OptimizerType *>(optimizer.get()))
2263  {
2264  Assert(optimization_method() == OptimizerType::llvm,
2265  ExcInternalError());
2266  internal::OptimizerHelper<
2267  ReturnType,
2268  internal::LLVMOptimizer<ReturnType>>::save(ar, version, opt);
2269  }
2270 # endif
2271  else
2272  {
2273  AssertThrow(false, ExcMessage("Unknown optimizer type."));
2274  }
2275  }
2276 
2277 
2278 
2279  template <typename ReturnType>
2280  template <class Archive>
2281  void
2282  BatchOptimizer<ReturnType>::load(Archive &ar, const unsigned int version)
2283  {
2284  Assert(independent_variables_symbols.empty(), ExcInternalError());
2285  Assert(dependent_variables_functions.empty(), ExcInternalError());
2286  Assert(dependent_variables_output.empty(), ExcInternalError());
2287  Assert(map_dep_expr_vec_entry.empty(), ExcInternalError());
2288  Assert(ready_for_value_extraction == false, ExcInternalError());
2289 
2290  // Deserialize enum classes...
2291  {
2292  typename std::underlying_type<OptimizerType>::type m;
2293  ar & m;
2294  method = static_cast<OptimizerType>(m);
2295  }
2296  {
2297  typename std::underlying_type<OptimizationFlags>::type f;
2298  ar & f;
2299  flags = static_cast<OptimizationFlags>(f);
2300  }
2301 
2302  // Important: Independent variables must always be
2303  // deserialized before the dependent variables.
2304  ar &independent_variables_symbols;
2305  ar &dependent_variables_functions;
2306 
2307  ar &dependent_variables_output;
2308  ar &map_dep_expr_vec_entry;
2309  ar &ready_for_value_extraction;
2310 
2311  ar &has_been_serialized;
2312 
2313  // If we're reading in data, then create the optimizer
2314  // and then deserialize it.
2315  Assert(!optimizer, ExcInternalError());
2316 
2317  // Create and configure the optimizer
2318  create_optimizer(optimizer);
2319  Assert(optimizer, ExcNotInitialized());
2320 
2321  // When we deserialize the optimizer itself, we have to (unfortunately)
2322  // provide it with sufficient information to rebuild itself from scratch.
2323  // This is because only two of the three optimization classes support
2324  // real serialization (i.e. have save/load capability).
2325  const SD::types::symbol_vector symbol_vec =
2326  Utilities::extract_symbols(independent_variables_symbols);
2328  *opt = dynamic_cast<typename internal::DictionaryOptimizer<
2329  ReturnType>::OptimizerType *>(optimizer.get()))
2330  {
2331  Assert(optimization_method() == OptimizerType::dictionary,
2332  ExcInternalError());
2333  internal::OptimizerHelper<ReturnType,
2334  internal::DictionaryOptimizer<ReturnType>>::
2335  load(ar,
2336  version,
2337  opt,
2339  symbol_vec),
2341  dependent_variables_functions),
2342  optimization_flags());
2343  }
2345  *opt = dynamic_cast<typename internal::LambdaOptimizer<
2346  ReturnType>::OptimizerType *>(optimizer.get()))
2347  {
2348  Assert(optimization_method() == OptimizerType::lambda,
2349  ExcInternalError());
2350  internal::OptimizerHelper<ReturnType,
2351  internal::LambdaOptimizer<ReturnType>>::
2352  load(ar,
2353  version,
2354  opt,
2356  symbol_vec),
2358  dependent_variables_functions),
2359  optimization_flags());
2360  }
2361 # ifdef HAVE_SYMENGINE_LLVM
2363  *opt = dynamic_cast<typename internal::LLVMOptimizer<
2364  ReturnType>::OptimizerType *>(optimizer.get()))
2365  {
2366  Assert(optimization_method() == OptimizerType::llvm,
2367  ExcInternalError());
2368  internal::OptimizerHelper<ReturnType,
2369  internal::LLVMOptimizer<ReturnType>>::
2370  load(ar,
2371  version,
2372  opt,
2374  symbol_vec),
2376  dependent_variables_functions),
2377  optimization_flags());
2378  }
2379 # endif
2380  else
2381  {
2382  AssertThrow(false, ExcMessage("Unknown optimizer type."));
2383  }
2384  }
2385 
2386 
2387 
2388  template <typename ReturnType>
2389  template <int rank, int dim>
2390  void
2392  const Tensor<rank, dim, Expression> &function_tensor)
2393  {
2394  Assert(optimized() == false,
2395  ExcMessage(
2396  "Cannot register functions once the optimizer is finalised."));
2397 
2398  register_vector_functions(
2399  internal::unroll_to_expression_vector(function_tensor));
2400  }
2401 
2402 
2403 
2404  template <typename ReturnType>
2405  template <int rank, int dim>
2406  void
2408  const SymmetricTensor<rank, dim, Expression> &function_tensor)
2409  {
2410  Assert(optimized() == false,
2411  ExcMessage(
2412  "Cannot register functions once the optimizer is finalised."));
2413 
2414  register_vector_functions(
2415  internal::unroll_to_expression_vector(function_tensor));
2416  }
2417 
2418 
2419 
2420  template <typename ReturnType>
2421  template <typename T, typename... Args>
2422  void
2424  const T &functions,
2425  const Args &... other_functions)
2426  {
2428  internal::register_functions(*this, other_functions...);
2429  }
2430 
2431 
2432 
2433  template <typename ReturnType>
2434  template <typename T>
2435  void
2437  const std::vector<T> &functions)
2438  {
2440  }
2441 
2442 
2443 
2444  template <typename ReturnType>
2445  template <int rank, int dim>
2448  const Tensor<rank, dim, Expression> &funcs) const
2449  {
2450  Assert(
2451  values_substituted() == true,
2452  ExcMessage(
2453  "The optimizer is not configured to perform evaluation. "
2454  "This action can only performed after substitute() has been called."));
2455 
2456  return internal::tensor_evaluate_optimized(funcs, *this);
2457  }
2458 
2459 
2460 
2461  template <typename ReturnType>
2462  template <int rank, int dim>
2465  const SymmetricTensor<rank, dim, Expression> &funcs) const
2466  {
2467  Assert(
2468  values_substituted() == true,
2469  ExcMessage(
2470  "The optimizer is not configured to perform evaluation. "
2471  "This action can only performed after substitute() has been called."));
2472 
2473  return internal::tensor_evaluate_optimized(funcs, *this);
2474  }
2475 
2476 # endif // DOXYGEN
2477 
2478  } // namespace SD
2479 } // namespace Differentiation
2480 
2481 
2483 
2484 #endif // DEAL_II_WITH_SYMENGINE
2485 
2486 #endif
Differentiation::SD::BatchOptimizer::register_symbols
void register_symbols(const types::substitution_map &substitution_map)
Definition: symengine_optimizer.cc:148
DeclExceptionMsg
#define DeclExceptionMsg(Exception, defaulttext)
Definition: exceptions.h:496
Differentiation::SD::BatchOptimizer::register_functions
void register_functions(const types::symbol_vector &functions)
symengine_scalar_operations.h
Differentiation::SD::Utilities::extract_symbols
SD::types::symbol_vector extract_symbols(const SD::types::substitution_map &substitution_values)
Differentiation::SD::BatchOptimizer::evaluate
const std::vector< ReturnType > & evaluate() const
Definition: symengine_optimizer.cc:511
Differentiation::SD::OptimizationFlags::optimize_default
@ optimize_default
Differentiation::SD::internal::register_functions
void register_functions(BatchOptimizer< NumberType > &optimizer, const T &function)
Definition: symengine_optimizer.h:1210
Differentiation::SD::Utilities::convert_expression_vector_to_basic_vector
SymEngine::vec_basic convert_expression_vector_to_basic_vector(const SD::types::symbol_vector &symbol_vector)
Differentiation::SD::OptimizationFlags::optimize_all
@ optimize_all
TableIndices< rank >
SymmetricTensor
Definition: symmetric_tensor.h:611
Differentiation::SD::BatchOptimizer::optimizer
std::unique_ptr< SymEngine::Visitor > optimizer
Definition: symengine_optimizer.h:2012
Differentiation::SD::BatchOptimizer::has_been_serialized
bool has_been_serialized
Definition: symengine_optimizer.h:2028
Differentiation::SD::internal::unroll_to_expression_vector
types::symbol_vector unroll_to_expression_vector(const TensorType< rank, dim, Expression > &symbol_tensor)
Definition: symengine_optimizer.h:1289
Differentiation::SD::OptimizerType::lambda
@ lambda
StandardExceptions::ExcNotImplemented
static ::ExceptionBase & ExcNotImplemented()
Differentiation::SD::BatchOptimizer::save
void save(Archive &archive, const unsigned int version) const
Differentiation::SD::BatchOptimizer::map_dependent_expression_to_vector_entry_t
std::map< SD::Expression, std::size_t, SD::types::internal::ExpressionKeyLess > map_dependent_expression_to_vector_entry_t
Definition: symengine_optimizer.h:1998
Differentiation::SD::internal::get_LLVM_optimization_level
int get_LLVM_optimization_level(const enum OptimizationFlags &flags)
Definition: symengine_optimizer.h:248
utilities.h
Differentiation::SD::ExcSymEngineLLVMReturnTypeNotSupported
static ::ExceptionBase & ExcSymEngineLLVMReturnTypeNotSupported()
Differentiation::SD::operator|
Expression operator|(const Expression &lhs, const Expression &rhs)
Definition: symengine_number_types.cc:467
Differentiation::SD::internal::use_symbolic_CSE
bool use_symbolic_CSE(const enum OptimizationFlags &flags)
Definition: symengine_optimizer.h:238
Differentiation::SD::BatchOptimizer::set_optimization_method
void set_optimization_method(const enum OptimizerType &optimization_method, const enum OptimizationFlags &optimization_flags=OptimizationFlags::optimize_all)
Definition: symengine_optimizer.cc:72
Differentiation::SD::BatchOptimizer::use_symbolic_CSE
bool use_symbolic_CSE() const
Definition: symengine_optimizer.cc:113
Patterns::Tools::to_string
std::string to_string(const T &t)
Definition: patterns.h:2360
Differentiation::SD::BatchOptimizer::substitute
void substitute(const types::substitution_map &substitution_map) const
Definition: symengine_optimizer.cc:377
Differentiation::SD::BatchOptimizer::get_independent_symbols
types::symbol_vector get_independent_symbols() const
Definition: symengine_optimizer.cc:218
Differentiation::SD::types::symbol_vector
std::vector< SD::Expression > symbol_vector
Definition: symengine_types.h:71
Differentiation::SD::BatchOptimizer::optimization_flags
enum OptimizationFlags optimization_flags() const
Definition: symengine_optimizer.cc:104
Differentiation::SD::operator<<
std::ostream & operator<<(std::ostream &stream, const Expression &expression)
Definition: symengine_number_types.cc:379
Differentiation::SD::internal::DictionaryOptimizer
Definition: symengine_optimizer.h:303
Differentiation::SD::types::substitution_map
std::map< SD::Expression, SD::Expression, internal::ExpressionKeyLess > substitution_map
Definition: symengine_types.h:62
Differentiation::SD::BatchOptimizer::values_substituted
bool values_substituted() const
Definition: symengine_optimizer.cc:139
symengine_number_types.h
internal::p4est::functions
int(&) functions(const void *v1, const void *v2)
Definition: p4est_wrappers.cc:339
Differentiation::SD::BatchOptimizer::create_optimizer
void create_optimizer(std::unique_ptr< SymEngine::Visitor > &optimizer)
Definition: symengine_optimizer.cc:744
Differentiation::SD::BatchOptimizer::get_dependent_functions
const types::symbol_vector & get_dependent_functions() const
Definition: symengine_optimizer.cc:274
Differentiation::SD::BatchOptimizer::n_independent_variables
std::size_t n_independent_variables() const
Definition: symengine_optimizer.cc:227
Differentiation::SD::BatchOptimizer::n_dependent_variables
std::size_t n_dependent_variables() const
Definition: symengine_optimizer.cc:283
Differentiation::SD::operator&=
OptimizationFlags & operator&=(OptimizationFlags &f1, const OptimizationFlags f2)
Definition: symengine_optimizer.h:224
Differentiation::SD::BatchOptimizer::register_vector_functions
void register_vector_functions(const types::symbol_vector &functions)
Definition: symengine_optimizer.cc:710
Differentiation::SD::BatchOptimizer::map_dep_expr_vec_entry
map_dependent_expression_to_vector_entry_t map_dep_expr_vec_entry
Definition: symengine_optimizer.h:2004
symengine_tensor_operations.h
Differentiation::SD::OptimizerType
OptimizerType
Definition: symengine_optimizer.h:99
DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition: config.h:409
Differentiation::SD::BatchOptimizer::is_valid_nonunique_dependent_variable
bool is_valid_nonunique_dependent_variable(const SD::Expression &function) const
Definition: symengine_optimizer.cc:639
LAPACKSupport::T
static const char T
Definition: lapack_support.h:163
Differentiation::SD::BatchOptimizer::flags
enum OptimizationFlags flags
Definition: symengine_optimizer.h:1935
StandardExceptions::ExcMessage
static ::ExceptionBase & ExcMessage(std::string arg1)
double
Tensor
Definition: tensor.h:450
Differentiation::SD::internal::OptimizerHelper
Definition: symengine_optimizer.h:350
DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:358
Differentiation::SD::BatchOptimizer::optimize
void optimize()
Definition: symengine_optimizer.cc:300
Differentiation
Definition: numbers.h:645
Differentiation::SD::operator|=
OptimizationFlags & operator|=(OptimizationFlags &f1, const OptimizationFlags f2)
Definition: symengine_optimizer.h:192
Differentiation::SD::internal::tensor_evaluate_optimized
TensorType< rank, dim, NumberType > tensor_evaluate_optimized(const TensorType< rank, dim, Expression > &symbol_tensor, const BatchOptimizer< NumberType > &optimizer)
Definition: symengine_optimizer.h:1137
Differentiation::SD::BatchOptimizer::serialize
void serialize(Archive &archive, const unsigned int version)
Differentiation::SD::BatchOptimizer::ready_for_value_extraction
bool ready_for_value_extraction
Definition: symengine_optimizer.h:2022
Differentiation::SD::BatchOptimizer::dependent_variables_functions
types::symbol_vector dependent_variables_functions
Definition: symengine_optimizer.h:1953
StandardExceptions::ExcNotInitialized
static ::ExceptionBase & ExcNotInitialized()
Differentiation::SD::substitute
Expression substitute(const Expression &expression, const types::substitution_map &substitution_map)
Differentiation::SD::ExcSymEngineLLVMNotAvailable
static ::ExceptionBase & ExcSymEngineLLVMNotAvailable()
Differentiation::SD::OptimizerType::dictionary
@ dictionary
exceptions.h
Differentiation::SD::BatchOptimizer::optimization_method
enum OptimizerType optimization_method() const
Definition: symengine_optimizer.cc:95
Differentiation::SD::Expression
Definition: symengine_number_types.h:179
Differentiation::SD::BatchOptimizer::dependent_variables_output
std::vector< ReturnType > dependent_variables_output
Definition: symengine_optimizer.h:1985
value
static const bool value
Definition: dof_tools_constraints.cc:433
StandardExceptions::ExcInternalError
static ::ExceptionBase & ExcInternalError()
Assert
#define Assert(cond, exc)
Definition: exceptions.h:1419
Differentiation::SD::BatchOptimizer::register_scalar_function
void register_scalar_function(const SD::Expression &function)
Definition: symengine_optimizer.cc:682
Differentiation::SD::BatchOptimizer::method
enum OptimizerType method
Definition: symengine_optimizer.h:1929
Differentiation::SD::BatchOptimizer::print
void print(Stream &stream, const bool print_cse=false) const
Differentiation::SD::OptimizationFlags::optimize_aggressive
@ optimize_aggressive
Differentiation::SD::OptimizationFlags::optimize_cse
@ optimize_cse
Differentiation::SD::operator&
Expression operator&(const Expression &lhs, const Expression &rhs)
Definition: symengine_number_types.cc:450
config.h
internal
Definition: aligned_vector.h:369
Differentiation::SD::BatchOptimizer::register_function
void register_function(const Expression &function)
Definition: symengine_optimizer.cc:236
DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:359
Differentiation::SD::BatchOptimizer::independent_variables_symbols
types::substitution_map independent_variables_symbols
Definition: symengine_optimizer.h:1946
Differentiation::SD::OptimizerType::llvm
@ llvm
Differentiation::SD::BatchOptimizer::~BatchOptimizer
~BatchOptimizer()=default
logstream.h
Differentiation::SD::OptimizationFlags
OptimizationFlags
Definition: symengine_optimizer.h:145
Differentiation::SD::types::internal::ExpressionKeyLess
Definition: symengine_types.h:45
symengine_number_visitor_internal.h
AssertThrow
#define AssertThrow(cond, exc)
Definition: exceptions.h:1531
symengine_utilities.h
Differentiation::SD::BatchOptimizer::load
void load(Archive &archive, const unsigned int version)
SymmetricTensor::n_independent_components
static constexpr unsigned int n_independent_components
Definition: symmetric_tensor.h:636
Differentiation::SD::internal::LambdaOptimizer
Definition: symengine_optimizer.h:316
internal::VectorOperations::copy
void copy(const T *begin, const T *end, U *dest)
Definition: vector_operations_internal.h:67
Differentiation::SD::BatchOptimizer::BatchOptimizer
BatchOptimizer()
Definition: symengine_optimizer.cc:36
Differentiation::SD::BatchOptimizer::optimized
bool optimized() const
Definition: symengine_optimizer.cc:122
DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition: config.h:372
Differentiation::SD::BatchOptimizer
Definition: symengine_optimizer.h:91