18#ifdef DEAL_II_WITH_SYMENGINE
23# include <boost/archive/text_iarchive.hpp>
24# include <boost/archive/text_oarchive.hpp>
35 template <
typename ReturnType>
39 , ready_for_value_extraction(false)
40 , has_been_serialized(false)
45 template <
typename ReturnType>
56 template <
typename ReturnType>
59 : method(other.method)
61 , independent_variables_symbols(other.independent_variables_symbols)
62 , dependent_variables_functions(other.dependent_variables_functions)
63 , dependent_variables_output(0)
64 , map_dep_expr_vec_entry(other.map_dep_expr_vec_entry)
65 , ready_for_value_extraction(false)
70 template <
typename ReturnType>
79 "Cannot call set_optimization_method() once the optimizer is finalized."));
81# ifndef HAVE_SYMENGINE_LLVM
87 method = optimization_method;
88 flags = optimization_flags;
93 template <
typename ReturnType>
102 template <
typename ReturnType>
111 template <
typename ReturnType>
120 template <
typename ReturnType>
124 if (dependent_variables_output.size() > 0)
126 Assert(dependent_variables_output.size() ==
127 dependent_variables_functions.size(),
137 template <
typename ReturnType>
141 return ready_for_value_extraction;
146 template <
typename ReturnType>
151 Assert(optimized() ==
false,
153 "Cannot register symbols once the optimizer is finalized."));
161 Assert(SymEngine::is_a<SymEngine::Symbol>(*(symbol.
get_RCP())),
162 ExcMessage(
"Key entry in map is not a symbol."));
173 template <
typename ReturnType>
184 template <
typename ReturnType>
189 Assert(optimized() ==
false,
191 "Cannot register symbols once the optimizer is finalized."));
193 for (
const auto &symbol : symbols)
195 Assert(independent_variables_symbols.find(symbol) ==
196 independent_variables_symbols.end(),
198 independent_variables_symbols.insert(
205 template <
typename ReturnType>
208 const SymEngine::vec_basic &symbols)
216 template <
typename ReturnType>
225 template <
typename ReturnType>
229 return independent_variables_symbols.size();
234 template <
typename ReturnType>
238 Assert(optimized() ==
false,
240 "Cannot register functions once the optimizer is finalized."));
242 register_scalar_function(function);
247 template <
typename ReturnType>
252 Assert(optimized() ==
false,
254 "Cannot register functions once the optimizer is finalized."));
261 template <
typename ReturnType>
272 template <
typename ReturnType>
276 return dependent_variables_functions;
281 template <
typename ReturnType>
285 if (has_been_serialized ==
false)
289 Assert(map_dep_expr_vec_entry.size() ==
290 dependent_variables_functions.size(),
293 return dependent_variables_functions.size();
298 template <
typename ReturnType>
302 Assert(optimized() ==
false,
303 ExcMessage(
"Cannot call optimize() more than once."));
306 create_optimizer(optimizer);
323 dependent_variables_functions),
324 optimization_flags());
338 dependent_variables_functions),
339 optimization_flags());
341# ifdef HAVE_SYMENGINE_LLVM
343 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
349 internal::LLVMOptimizer<ReturnType>>::
354 dependent_variables_functions),
355 optimization_flags());
370 dependent_variables_output.resize(n_dependent_variables());
375 template <
typename ReturnType>
383 "The optimizer is not configured to perform substitution. "
384 "This action can only performed after optimize() has been called."));
394 Assert(symbol_sub_vec.size() == symbol_vec.size(),
396 for (
unsigned int i = 0; i < symbol_sub_vec.size(); ++i)
400 "The input substitution map is either incomplete, or does "
401 "not match that used in the register_symbols() call."));
407 const std::vector<ReturnType>
values =
414 template <
typename ReturnType>
425 template <
typename ReturnType>
429 const std::vector<ReturnType> &
values)
const
439 template <
typename ReturnType>
442 const SymEngine::vec_basic & symbols,
443 const std::vector<ReturnType> &
values)
const
452 template <
typename ReturnType>
455 const std::vector<ReturnType> &substitution_values)
const
460 "The optimizer is not configured to perform substitution. "
461 "This action can only performed after optimize() has been called."));
463 Assert(substitution_values.size() == independent_variables_symbols.size(),
465 independent_variables_symbols.size()));
475 substitute(opt, dependent_variables_output, substitution_values);
485 substitute(opt, dependent_variables_output, substitution_values);
487# ifdef HAVE_SYMENGINE_LLVM
489 *opt =
dynamic_cast<typename internal::LLVMOptimizer<
495 internal::LLVMOptimizer<ReturnType>>
::
496 substitute(opt, dependent_variables_output, substitution_values);
504 ready_for_value_extraction =
true;
509 template <
typename ReturnType>
510 const std::vector<ReturnType> &
514 values_substituted() ==
true,
516 "The optimizer is not configured to perform evaluation. "
517 "This action can only performed after substitute() has been called."));
519 return dependent_variables_output;
524 template <
typename ReturnType>
528 const std::vector<ReturnType> &cached_evaluation)
const
531 values_substituted() ==
true,
533 "The optimizer is not configured to perform evaluation. "
534 "This action can only performed after substitute() has been called."));
543 const typename map_dependent_expression_to_vector_entry_t::const_iterator
544 it = map_dep_expr_vec_entry.find(func);
548 if (has_been_serialized && it == map_dep_expr_vec_entry.end())
562 auto serialize_and_deserialize_expression =
564 std::ostringstream oss;
566 boost::archive::text_oarchive oa(oss,
567 boost::archive::no_header);
573 std::istringstream iss(oss.str());
574 boost::archive::text_iarchive ia(iss,
575 boost::archive::no_header);
584 serialize_and_deserialize_expression(func);
591 for (
const auto &
e : map_dep_expr_vec_entry)
594 serialize_and_deserialize_expression(
e.first);
603 map_dep_expr_vec_entry[func] =
e.second;
604 return evaluate(func);
611 "Still cannot find map entry, and there's no hope to recover from this situation."));
614 Assert(it != map_dep_expr_vec_entry.end(),
615 ExcMessage(
"Function has not been registered."));
618 return cached_evaluation[it->second];
623 template <
typename ReturnType>
627 return extract(func, dependent_variables_output);
632 template <
typename ReturnType>
633 std::vector<ReturnType>
635 const std::vector<Expression> &funcs,
636 const std::vector<ReturnType> &cached_evaluation)
const
638 std::vector<ReturnType> out;
639 out.reserve(funcs.size());
641 for (
const auto &func : funcs)
642 out.emplace_back(
extract(func, cached_evaluation));
649 template <
typename ReturnType>
650 std::vector<ReturnType>
652 const std::vector<Expression> &funcs)
const
654 return extract(funcs, dependent_variables_output);
659 template <
typename ReturnType>
664 return is_valid_nonunique_dependent_variable(func.
get_RCP());
669 template <
typename ReturnType>
672 const SymEngine::RCP<const SymEngine::Basic> &func)
const
678 if (SymEngine::is_a<SymEngine::Constant>(*func))
684 if (&*func == &*SymEngine::minus_one)
686 if (&*func == &*SymEngine::I)
688 if (&*func == &*SymEngine::Inf)
690 if (&*func == &*SymEngine::NegInf)
692 if (&*func == &*SymEngine::ComplexInf)
694 if (&*func == &*SymEngine::Nan)
702 template <
typename ReturnType>
708 dependent_variables_output.size() == 0,
710 "Cannot register function as the optimizer has already been finalized."));
711 dependent_variables_output.reserve(n_dependent_variables() + 1);
712 const bool entry_registered =
713 (map_dep_expr_vec_entry.find(func) != map_dep_expr_vec_entry.end());
715 if (entry_registered ==
true &&
716 is_valid_nonunique_dependent_variable(func) ==
false)
718 ExcMessage(
"Function has already been registered."));
720 if (entry_registered ==
false)
722 dependent_variables_functions.push_back(func);
723 map_dep_expr_vec_entry[func] =
724 dependent_variables_functions.size() - 1;
730 template <
typename ReturnType>
736 dependent_variables_output.size() == 0,
738 "Cannot register function as the optimizer has already been finalized."));
739 const std::size_t n_dependents_old = n_dependent_variables();
740 dependent_variables_output.reserve(n_dependents_old + funcs.size());
741 dependent_variables_functions.reserve(n_dependents_old + funcs.size());
743 for (
const auto &func : funcs)
745 const bool entry_registered =
746 (map_dep_expr_vec_entry.find(func) != map_dep_expr_vec_entry.end());
748 if (entry_registered ==
true &&
749 is_valid_nonunique_dependent_variable(func) ==
false)
751 ExcMessage(
"Function has already been registered."));
753 if (entry_registered ==
false)
755 dependent_variables_functions.push_back(func);
756 map_dep_expr_vec_entry[func] =
757 dependent_variables_functions.size() - 1;
764 template <
typename ReturnType>
767 std::unique_ptr<SymEngine::Visitor> &optimizer)
776 optimizer.reset(
new Optimizer_t());
782 optimizer.reset(
new Optimizer_t());
786# ifdef HAVE_SYMENGINE_LLVM
787 if (internal::LLVMOptimizer<ReturnType>::supported_by_LLVM)
791 optimizer.reset(
new Optimizer_t());
812# include "symengine_optimizer.inst"
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
bool use_symbolic_CSE() const
void substitute(const types::substitution_map &substitution_map) const
void register_scalar_function(const SD::Expression &function)
const types::symbol_vector & get_dependent_functions() const
void create_optimizer(std::unique_ptr< SymEngine::Visitor > &optimizer)
enum OptimizerType optimization_method() const
const SymEngine::RCP< const SymEngine::Basic > & get_RCP() const
static ::ExceptionBase & ExcNotImplemented()
void set_optimization_method(const enum OptimizerType &optimization_method, const enum OptimizationFlags &optimization_flags=OptimizationFlags::optimize_all)
bool use_symbolic_CSE(const enum OptimizationFlags &flags)
enum OptimizationFlags optimization_flags() const
#define Assert(cond, exc)
void register_functions(const types::symbol_vector &functions)
static ::ExceptionBase & ExcSymEngineLLVMReturnTypeNotSupported()
std::size_t n_dependent_variables() const
void register_symbols(const types::substitution_map &substitution_map)
const std::vector< ReturnType > & evaluate() const
static ::ExceptionBase & ExcSymEngineLLVMNotAvailable()
static ::ExceptionBase & ExcInternalError()
void register_function(const Expression &function)
ReturnType extract(const Expression &func, const std::vector< ReturnType > &cached_evaluation) const
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcNotInitialized()
bool is_valid_nonunique_dependent_variable(const SD::Expression &function) const
void register_vector_functions(const types::symbol_vector &functions)
const SymEngine::Basic & get_value() const
void register_functions(BatchOptimizer< NumberType > &optimizer, const T &function)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::size_t n_independent_variables() const
types::symbol_vector get_independent_symbols() const
#define AssertThrow(cond, exc)
bool values_substituted() const
SD::types::symbol_vector extract_symbols(const SD::types::substitution_map &substitution_values)
SD::types::substitution_map convert_basic_map_to_expression_map(const SymEngine::map_basic_basic &substitution_map)
SD::types::symbol_vector convert_basic_vector_to_expression_vector(const SymEngine::vec_basic &symbol_vector)
SymEngine::vec_basic convert_expression_vector_to_basic_vector(const SD::types::symbol_vector &symbol_vector)
std::vector< SD::Expression > symbol_vector
std::map< SD::Expression, SD::Expression, internal::ExpressionKeyLess > substitution_map
Expression substitute(const Expression &expression, const types::substitution_map &substitution_map)
types::substitution_map make_substitution_map(const Expression &symbol, const Expression &value)
static const types::blas_int zero
static const types::blas_int one
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
constexpr ReturnType< rank, T >::value_type & extract(T &t, const ArrayType &indices)
int(&) functions(const void *v1, const void *v2)
constexpr bool values_are_equal(const Number1 &value_1, const Number2 &value_2)