From 9ea7ae78d50be994d962277baaba9d62495e5e36 Mon Sep 17 00:00:00 2001 From: Jean-Paul Pelteret Date: Mon, 18 Jan 2021 22:17:03 +0100 Subject: [PATCH] SD BatchOptimizer: Implement cached evaluation --- .../changes/minor/20210313Jean-PaulPelteret-4 | 8 ++ .../differentiation/sd/symengine_optimizer.h | 112 ++++++++++++++++-- .../differentiation/sd/symengine_optimizer.cc | 32 ++++- 3 files changed, 138 insertions(+), 14 deletions(-) create mode 100644 doc/news/changes/minor/20210313Jean-PaulPelteret-4 diff --git a/doc/news/changes/minor/20210313Jean-PaulPelteret-4 b/doc/news/changes/minor/20210313Jean-PaulPelteret-4 new file mode 100644 index 0000000000..94b846cb62 --- /dev/null +++ b/doc/news/changes/minor/20210313Jean-PaulPelteret-4 @@ -0,0 +1,8 @@ +New: The new method Differentiation::SD::BatchOptimizer::extract() allows one to +extract results from previous evaluation of the symbolic expressions. +This means that one can safely use a single instance of a batch optimizer to +pre-compute a set of results, cache them, and then later extract some results +from the cached data without re-evaluating any symbolic expressions. +
+(Jean-Paul Pelteret, 2021/03/13) + diff --git a/include/deal.II/differentiation/sd/symengine_optimizer.h b/include/deal.II/differentiation/sd/symengine_optimizer.h index 440f15761b..55dff430ad 100644 --- a/include/deal.II/differentiation/sd/symengine_optimizer.h +++ b/include/deal.II/differentiation/sd/symengine_optimizer.h @@ -1124,6 +1124,11 @@ namespace Differentiation * @tparam TensorType The type of tensor to be evaluated and returned * (i.e. Tensor or SymmetricTensor). * @param[in] symbol_tensor The symbolic tensor that is to be evaluated. + * @param[in] cached_evaluation A vector that stores the numerical + * values of all dependent variables referenced by the + * @p optimizer. This vector is, most typically, first attained + * by a call to the BatchOptimizer::evaluate() variant that + * takes no arguments. * @param[in] optimizer The optimizer that can evaluate the input * @p symbol_tensor. * @return TensorType The numeric result that the @@ -1136,6 +1141,7 @@ namespace Differentiation TensorType tensor_evaluate_optimized( const TensorType &symbol_tensor, + const std::vector & cached_evaluation, const BatchOptimizer & optimizer) { TensorType out; @@ -1143,7 +1149,8 @@ namespace Differentiation { const TableIndices indices( out.unrolled_to_component_indices(i)); - out[indices] = optimizer.evaluate(symbol_tensor[indices]); + out[indices] = + optimizer.extract(symbol_tensor[indices], cached_evaluation); } return out; } @@ -1161,6 +1168,11 @@ namespace Differentiation * @tparam TensorType The type of tensor to be evaluated and returned * (i.e. Tensor or SymmetricTensor). * @param[in] symbol_tensor The symbolic tensor that is to be evaluated. + * @param[in] cached_evaluation A vector that stores the numerical + * values of all dependent variables referenced by the + * @p optimizer. This vector is, most typically, first attained + * by a call to the BatchOptimizer::evaluate() variant that + * takes no arguments. * @param[in] optimizer The optimizer that can evaluate the input * @p symbol_tensor. * @return TensorType The numeric result that the @@ -1170,6 +1182,7 @@ namespace Differentiation SymmetricTensor<4, dim, NumberType> tensor_evaluate_optimized( const SymmetricTensor<4, dim, Expression> &symbol_tensor, + const std::vector & cached_evaluation, const BatchOptimizer & optimizer) { SymmetricTensor<4, dim, NumberType> out; @@ -1182,7 +1195,8 @@ namespace Differentiation { const TableIndices<4> indices = make_rank_4_tensor_indices(i, j); - out[indices] = optimizer.evaluate(symbol_tensor[indices]); + out[indices] = + optimizer.extract(symbol_tensor[indices], cached_evaluation); } return out; } @@ -1855,7 +1869,9 @@ namespace Differentiation /** * Returns the result of a value substitution into the optimized * counterpart of all dependent functions. This function fetches all of - * those cached values. + * those cached values. If these results are stored elsewhere, and you + * want to use this optimizer to extract components of the cached results + * then you can make use of the extract() functions listed below. * * These values were computed by substituting a @p substitution_values map * during substitute() call. @@ -1921,6 +1937,56 @@ namespace Differentiation SymmetricTensor evaluate(const SymmetricTensor &funcs) const; + + /** + * Returns the result of a value substitution into the optimized + * counterpart of @p func. This function fetches that one value + * stored in the @p cached_evaluation vector. This vector is, most + * typically, first attained by a call to the evaluate() variant that + * takes no arguments. + */ + ReturnType + extract(const Expression & func, + const std::vector &cached_evaluation) const; + + + /** + * Returns the result of a value substitution into the optimized + * counterpart of @p funcs. This function fetches that subset of + * values stored in the @p cached_evaluation vector. This vector is, most + * typically, first attained by a call to the evaluate() variant that + * takes no arguments. + */ + std::vector + extract(const std::vector &funcs, + const std::vector &cached_evaluation) const; + + + /** + * Returns the result of a tensor value substitution into the optimized + * counterpart of @p funcs. This function fetches those tensor components + * stored in the @p cached_evaluation vector. This vector is, most + * typically, first attained by a call to the evaluate() variant that + * takes no arguments. + */ + template + Tensor + extract(const Tensor &funcs, + const std::vector & cached_evaluation) const; + + + /** + * Returns the result of a tensor value substitution into the optimized + * counterpart of @p funcs. This function fetches those symmetric + * tensor components stored in the @p cached_evaluation vector. This vector + * is, most typically, first attained by a call to the evaluate() variant + * that takes no arguments. + */ + template + SymmetricTensor + extract(const SymmetricTensor &funcs, + const std::vector &cached_evaluation) const; + //@} private: @@ -2445,8 +2511,9 @@ namespace Differentiation template template Tensor - BatchOptimizer::evaluate( - const Tensor &funcs) const + BatchOptimizer::extract( + const Tensor &funcs, + const std::vector & cached_evaluation) const { Assert( values_substituted() == true, @@ -2454,16 +2521,30 @@ namespace Differentiation "The optimizer is not configured to perform evaluation. " "This action can only performed after substitute() has been called.")); - return internal::tensor_evaluate_optimized(funcs, *this); + return internal::tensor_evaluate_optimized(funcs, + cached_evaluation, + *this); } template template - SymmetricTensor + Tensor BatchOptimizer::evaluate( - const SymmetricTensor &funcs) const + const Tensor &funcs) const + { + return extract(funcs, dependent_variables_output); + } + + + + template + template + SymmetricTensor + BatchOptimizer::extract( + const SymmetricTensor &funcs, + const std::vector & cached_evaluation) const { Assert( values_substituted() == true, @@ -2471,7 +2552,20 @@ namespace Differentiation "The optimizer is not configured to perform evaluation. " "This action can only performed after substitute() has been called.")); - return internal::tensor_evaluate_optimized(funcs, *this); + return internal::tensor_evaluate_optimized(funcs, + cached_evaluation, + *this); + } + + + + template + template + SymmetricTensor + BatchOptimizer::evaluate( + const SymmetricTensor &funcs) const + { + return extract(funcs, dependent_variables_output); } # endif // DOXYGEN diff --git a/source/differentiation/sd/symengine_optimizer.cc b/source/differentiation/sd/symengine_optimizer.cc index e90516e928..09b2c2b74c 100644 --- a/source/differentiation/sd/symengine_optimizer.cc +++ b/source/differentiation/sd/symengine_optimizer.cc @@ -523,7 +523,9 @@ namespace Differentiation template ReturnType - BatchOptimizer::evaluate(const Expression &func) const + BatchOptimizer::extract( + const Expression & func, + const std::vector &cached_evaluation) const { Assert( values_substituted() == true, @@ -613,27 +615,47 @@ namespace Differentiation ExcMessage("Function has not been registered.")); Assert(it->second < n_dependent_variables(), ExcInternalError()); - return dependent_variables_output[it->second]; + return cached_evaluation[it->second]; + } + + + + template + ReturnType + BatchOptimizer::evaluate(const Expression &func) const + { + return extract(func, dependent_variables_output); } template std::vector - BatchOptimizer::evaluate( - const std::vector &funcs) const + BatchOptimizer::extract( + const std::vector &funcs, + const std::vector &cached_evaluation) const { std::vector out; out.reserve(funcs.size()); for (const auto &func : funcs) - out.emplace_back(evaluate(func)); + out.emplace_back(extract(func, cached_evaluation)); return out; } + template + std::vector + BatchOptimizer::evaluate( + const std::vector &funcs) const + { + return extract(funcs, dependent_variables_output); + } + + + template bool BatchOptimizer::is_valid_nonunique_dependent_variable( -- 2.39.5