10#include <range/v3/algorithm/contains.hpp>
11#include <range/v3/algorithm/find.hpp>
12#include <range/v3/algorithm/find_if.hpp>
13#include <range/v3/range/conversion.hpp>
14#include <range/v3/view/filter.hpp>
15#include <range/v3/view/transform.hpp>
16#include <unordered_set>
39 :
src_offset{reinterpret_cast<char const*>(dst) -
40 reinterpret_cast<char const*>(&base)},
48 double const val = *
reinterpret_cast<double const*
>(
49 reinterpret_cast<char const*
>(&src) +
src_offset);
53 "Function property: Scalar variable '{:s}' is not "
67 std::vector<std::string>
const& expression_symbol_names,
68 bool const spatial_position_is_required,
69 std::vector<std::string>
const& used_curve_names,
71 std::unique_ptr<MathLib::PiecewiseLinearInterpolation>>
const&
74 std::map<std::string, ParameterLib::CurveWrapper>& curve_wrappers)
79 std::unordered_set<std::string> curve_name_set(used_curve_names.begin(),
80 used_curve_names.end());
82 for (
auto const& v : expression_symbol_names)
89 auto add_scalar = [&v, &symbol_table](
double& value)
90 { symbol_table.add_variable(v, value); };
93 [&v, &symbol_table](
double* ptr, std::size_t
const size)
94 { symbol_table.add_vector(v, ptr, size); };
98 { add_scalar(*address); },
101 auto constexpr size =
104 address->template emplace<Eigen::Matrix<double, size, 1>>();
105 add_vector(result.data(), size);
111 address->template emplace<Eigen::Matrix<double, size, 1>>();
112 add_vector(result.data(), size);
144 std::vector<exprtk::expression<double>>
expressions)
164 std::integral_constant<int, D> ,
165 std::vector<std::string>
const& expression_symbol_names,
166 bool spatial_position_is_required,
167 std::vector<std::string>
const& used_curve_names,
168 std::map<std::string,
169 std::unique_ptr<MathLib::PiecewiseLinearInterpolation>>
const&
171 std::vector<Variable>
const& variables_enum,
172 std::vector<Variable>* non_scalar_out,
173 std::vector<std::string>
const& value_string_expressions,
174 std::vector<std::pair<std::string, std::vector<std::string>>>
const&
175 dvalue_string_expressions,
176 std::vector<D2ValueConfig>
const& d2value_string_expressions)
178 expression_symbol_names, spatial_position_is_required,
184 d2value_string_expressions);
190 "MPL's Function property: The internal PerThreadData is not "
191 "move-constructible.");
232 std::vector<std::pair<Variable, std::vector<exprtk::expression<double>>>>
259 std::vector<Variable>
const& non_scalar_variables,
272 std::vector<Variable>
const& non_scalar_variables,
275 std::vector<exprtk::expression<double>>
const& expressions);
282 std::vector<Variable>* non_scalar_out)
284 for (
auto const variable : variables_enum)
286 auto const add_non_scalar = [&]()
290 non_scalar_out->push_back(variable);
301 { add_non_scalar(); },
303 { add_non_scalar(); }},
315 std::vector<std::string>
const& value_string_expressions,
316 std::vector<std::pair<std::string, std::vector<std::string>>>
const&
317 dvalue_string_expressions,
318 std::vector<D2ValueConfig>
const& d2value_string_expressions)
323 for (
auto const& [variable_name, string_expressions] :
324 dvalue_string_expressions)
326 if (string_expressions.size() != value_string_expressions.size())
329 "The number of dValue expressions ({:d}) for variable "
330 "'{:s}' does not match the number of value expressions "
332 string_expressions.size(), variable_name,
333 value_string_expressions.size());
338 string_expressions));
343 for (
auto const& [variable_name1, variable_name2, string_expressions] :
344 d2value_string_expressions)
350 string_expressions));
362 std::vector<std::string>
const& expression_symbol_names,
363 std::vector<Variable>
const& variables_enum,
364 std::vector<std::string>
const& value_string_expressions,
365 std::vector<std::pair<std::string, std::vector<std::string>>>
const&
366 dvalue_string_expressions,
367 std::vector<D2ValueConfig>
const& d2value_string_expressions,
368 std::map<std::string,
369 std::unique_ptr<MathLib::PiecewiseLinearInterpolation>>
const&
385 std::vector<std::string>
const& expression_symbol_names,
386 std::vector<Variable>
const& variables_enum,
387 std::vector<std::string>
const& value_string_expressions,
388 std::vector<std::pair<std::string, std::vector<std::string>>>
const&
389 dvalue_string_expressions,
390 std::vector<D2ValueConfig>
const& d2value_string_expressions,
391 std::map<std::string,
392 std::unique_ptr<MathLib::PiecewiseLinearInterpolation>>
const&
402 auto const used_curve_names =
406 for (
int thread_id = 0; thread_id < num_threads; ++thread_id)
409 std::integral_constant<int, D>{}, expression_symbol_names,
412 value_string_expressions, dvalue_string_expressions,
413 d2value_string_expressions);
418 std::vector<Variable>
const& non_scalar_variables,
421 for (
auto const& variable : non_scalar_variables)
423 auto assign_kelvin_vector = [&variable, &new_variable_array](
426 auto assign_value = [&destination = *address,
427 &variable]<
typename S>(S
const& source)
429 if constexpr (std::is_same_v<S, std::monostate>)
432 "Function property: Kelvin vector variable '{:s}' is "
438 if (std::holds_alternative<S>(destination))
446 "Function property: Mismatch of Kelvin vector "
447 "sizes for variable {:s}.",
453 std::visit(assign_value,
454 *std::get<VariableArray::KelvinVector const*>(
457 auto assign_deformation_gradient =
461 auto assign_value = [&destination = *address,
462 &variable]<
typename S>(S
const& source)
464 if constexpr (std::is_same_v<S, std::monostate>)
467 "Function property: Vectorized tensor variable '{:s}' "
468 "is not initialized.",
473 if (std::holds_alternative<S>(destination))
475 std::get<S>(destination) = source;
480 "Function property: Mismatch of vectorized tensor "
481 "sizes for variable {:s}.",
487 std::visit(assign_value,
488 *std::get<VariableArray::DeformationGradient const*>(
497 "Function property: updateNonScalarVariables called "
498 "with a scalar variable.");
500 assign_kelvin_vector, assign_deformation_gradient},
507template <std::
size_t N>
509 std::vector<exprtk::expression<double>>
const& expressions)
511 std::array<double, N> result{};
512 for (std::size_t i = 0; i < N; ++i)
514 result[i] = expressions[i].value();
520 std::vector<Variable>
const& non_scalar_variables,
523 std::vector<exprtk::expression<double>>
const& expressions)
528 op.apply(new_variable_array);
539 auto const n = expressions.size();
556 "Cannot convert a vector of size {} to a PropertyDataType", n);
562 std::vector<std::string>
const& value_string_expressions,
563 std::vector<std::pair<std::string, std::vector<std::string>>>
const&
564 dvalue_string_expressions,
565 std::vector<D2ValueConfig>
const& d2value_string_expressions,
566 std::map<std::string,
567 std::unique_ptr<MathLib::PiecewiseLinearInterpolation>>
const&
576 std::vector<VariablePair> seen_pairs;
577 for (
auto const& [vname1, vname2, exprs] : d2value_string_expressions)
581 if (ranges::contains(seen_pairs, pair))
584 "Function property '{}': duplicate d2value block for "
585 "variable pair '{}'/'{}'. Each unordered pair may "
586 "appear at most once.",
587 name_, vname1, vname2);
589 seen_pairs.push_back(pair);
591 if (exprs.size() != value_string_expressions.size())
594 "Function property '{}': the number of d2Value expressions "
595 "({:d}) for variables '{:s}'/'{:s}' does not match the "
596 "number of value expressions ({:d}).",
597 name_, exprs.size(), vname1, vname2,
598 value_string_expressions.size());
606 auto all_exprs = value_string_expressions;
607 for (
auto const& [_, exprs] : dvalue_string_expressions)
609 all_exprs.insert(all_exprs.end(), exprs.begin(), exprs.end());
611 for (
auto const& [_1, _2, exprs] : d2value_string_expressions)
613 all_exprs.insert(all_exprs.end(), exprs.begin(), exprs.end());
615 auto const expression_symbol_names =
619 expression_symbol_names |
620 ranges::views::filter(
621 [&curves](std::string
const& s)
625 ranges::views::transform([](std::string
const& s)
627 ranges::to<std::vector>;
631 impl2_ = std::make_unique<Implementation<2>>(
633 value_string_expressions, dvalue_string_expressions,
634 d2value_string_expressions, curves);
635 impl3_ = std::make_unique<Implementation<3>>(
637 value_string_expressions, dvalue_string_expressions,
638 d2value_string_expressions, curves);
645 if (variable_array.
is2D())
649 if (variable_array.
is3D())
655 "Variable array has vectors for 2 and 3 dimensions simultaneously. "
656 "Mixed dimensions cannot be dealt within Function evaluation.");
662 std::size_t
const num_slots)
665 int const thread_id = omp_get_thread_num();
667 int const thread_id = 0;
669 if (thread_id >=
static_cast<int>(num_slots))
672 "In Function-type property '{:s}' evaluation the OMP-thread with "
673 "id {:d} exceeds the number of allocated threads {:d}.",
674 property_name, thread_id, num_slots);
681 double const t,
double const )
const
687 name_, impl_ptr->per_thread_data.size())];
688 return thread_data.evaluate(impl_ptr->non_scalar_variables,
689 variable_array, pos, t,
690 thread_data.value_expressions);
698 double const t,
double const )
const
704 name_, impl_ptr->per_thread_data.size())];
705 auto const it = ranges::find_if(thread_data.dvalue_expressions,
706 [&variable](
auto const& v)
707 { return v.first == variable; });
709 if (it == end(thread_data.dvalue_expressions))
712 "Requested derivative with respect to the variable {:s} "
713 "not provided for Function-type property {:s}.",
717 return thread_data.evaluate(impl_ptr->non_scalar_variables,
718 variable_array, pos, t, it->second);
727 double const t,
double const )
const
733 name_, impl_ptr->per_thread_data.size())];
734 auto const it = ranges::find(thread_data.d2value_expressions,
738 if (it == thread_data.d2value_expressions.end())
741 "Requested second derivative with respect to variables "
742 "'{:s}'/'{:s}' not provided for Function-type property "
749 return thread_data.evaluate(impl_ptr->non_scalar_variables,
750 variable_array, pos, t,
std::unique_ptr< Implementation< 3 > > impl3_
std::variant< Function::Implementation< 2 > *, Function::Implementation< 3 > * > getImplementationForDimensionOfVariableArray(VariableArray const &variable_array) const
std::vector< Variable > required_variables_enum_
Variables used in the exprtk expressions.
Function(std::string name, std::vector< std::string > const &value_string_expressions, std::vector< std::pair< std::string, std::vector< std::string > > > const &dvalue_string_expressions, std::vector< D2ValueConfig > const &d2value_string_expressions, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves)
PropertyDataType dValue(VariableArray const &variable_array, Variable const variable, ParameterLib::SpatialPosition const &pos, double const t, double const dt) const override
std::unique_ptr< Implementation< 2 > > impl2_
PropertyDataType d2Value(VariableArray const &variable_array, Variable const variable1, Variable const variable2, ParameterLib::SpatialPosition const &pos, double const t, double const dt) const override
Default implementation: 2nd derivative of any constant property is zero.
virtual PropertyDataType value() const
std::variant< std::monostate, Eigen::Vector< double, 5 >, Eigen::Vector< double, 9 > > DeformationGradient
std::variant< std::monostate, Eigen::Vector< double, 4 >, Eigen::Vector< double, 6 > > KelvinVector
VariablePointerConst address_of(Variable const v) const
auto visitVariable(Visitor &&visitor, Variable const variable)
static std::array< double, N > evaluateToArray(std::vector< exprtk::expression< double > > const &expressions)
static int currentThreadId(std::string const &property_name, std::size_t const num_slots)
static exprtk::symbol_table< double > createSymbolTable(std::vector< std::string > const &expression_symbol_names, bool const spatial_position_is_required, std::vector< std::string > const &used_curve_names, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves, VariableArray &variable_array, std::map< std::string, ParameterLib::CurveWrapper > &curve_wrappers)
PropertyDataType fromArray(std::array< double, N > const &values)
static const std::array< std::string, static_cast< int >(Variable::number_of_variables)> variable_enum_to_string
Variable convertStringToVariable(std::string const &string)
std::variant< double, Eigen::Matrix< double, 2, 1 >, Eigen::Matrix< double, 3, 1 >, Eigen::Matrix< double, 2, 2 >, Eigen::Matrix< double, 3, 3 >, Eigen::Matrix< double, 4, 1 >, Eigen::Matrix< double, 6, 1 >, Eigen::MatrixXd > PropertyDataType
Eigen::Matrix< double, 4, 1 > kelvinVectorToSymmetricTensor(Eigen::Matrix< double, 4, 1, Eigen::ColMajor, 4, 1 > const &v)
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
constexpr int size(int const displacement_dim)
Vectorized tensor size for given displacement dimension.
std::vector< exprtk::expression< T > > compileExpressions(exprtk::symbol_table< T > &symbol_table, std::vector< std::string > const &string_expressions)
bool isBuiltinSymbol(std::string_view const name)
exprtk::symbol_table< double > createBaseSymbolTable(bool spatial_position_is_required)
void registerCurveWrappers(exprtk::symbol_table< double > &symbol_table, std::vector< std::string > const &curve_names, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves, std::map< std::string, CurveWrapper > &curve_wrappers)
std::vector< std::string > collectVariables(std::vector< std::string > const &expression_strings)
std::vector< std::string > collectUsedCurveNames(std::vector< std::string > const &expression_symbol_names, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves)
Returns the subset of expression_symbol_names that are keys in curves.
bool hasSpatialVariables(std::vector< std::string > const &variables)
std::vector< exprtk::expression< double > > expressions
D2ValueExpression(Variable const variable1, Variable const variable2, std::vector< exprtk::expression< double > > expressions)
Implementation(int num_threads, std::vector< std::string > const &expression_symbol_names, std::vector< Variable > const &variables_enum, std::vector< std::string > const &value_string_expressions, std::vector< std::pair< std::string, std::vector< std::string > > > const &dvalue_string_expressions, std::vector< D2ValueConfig > const &d2value_string_expressions, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves)
std::vector< PerThreadData > per_thread_data
Per-thread data; indexed by omp_get_thread_num().
bool spatial_position_is_required
std::vector< Variable > non_scalar_variables
exprtk::expression< double > Expression
VariableArray variable_array
std::vector< ScalarCopyOp > scalar_copy_ops
Scalar copy operations into this thread's symbol table.
PerThreadData(PerThreadData &&)
PerThreadData & operator=(PerThreadData const &)=delete
PropertyDataType evaluate(std::vector< Variable > const &non_scalar_variables, VariableArray const &new_variable_array, ParameterLib::SpatialPosition const &pos, double t, std::vector< exprtk::expression< double > > const &expressions)
PerThreadData(std::integral_constant< int, D >, std::vector< std::string > const &expression_symbol_names, bool spatial_position_is_required, std::vector< std::string > const &used_curve_names, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation > > const &curves, std::vector< Variable > const &variables_enum, std::vector< Variable > *non_scalar_out, std::vector< std::string > const &value_string_expressions, std::vector< std::pair< std::string, std::vector< std::string > > > const &dvalue_string_expressions, std::vector< D2ValueConfig > const &d2value_string_expressions)
std::map< std::string, ParameterLib::CurveWrapper > curve_wrappers
Curve wrappers owned by this thread; must outlive the symbol table.
std::vector< std::pair< Variable, std::vector< exprtk::expression< double > > > > dvalue_expressions
std::vector< exprtk::expression< double > > value_expressions
void buildCopyOps(std::vector< Variable > const &variables_enum, std::vector< Variable > *non_scalar_out)
std::vector< D2ValueExpression > d2value_expressions
PerThreadData(PerThreadData const &)=delete
ParameterLib::SymbolTableCache symbol_table_cache
Cached pointers to symbol table variables (t, x, y, z).
void compileExpressions(std::vector< std::string > const &value_string_expressions, std::vector< std::pair< std::string, std::vector< std::string > > > const &dvalue_string_expressions, std::vector< D2ValueConfig > const &d2value_string_expressions)
void updateNonScalarVariables(std::vector< Variable > const &non_scalar_variables, VariableArray const &new_variable_array)
PerThreadData & operator=(PerThreadData &&other) noexcept=delete
exprtk::symbol_table< double > symbol_table
Variable variable
for error messages
ScalarCopyOp(VariableArray const &base, VariableArray::Scalar *dst, Variable var)
std::ptrdiff_t src_offset
byte offset from VariableArray start
double * dst_ptr
pointer into this thread's symbol table
void apply(VariableArray const &src) const
friend bool operator==(VariablePair const &p, VariablePair const &q)
Order-independent equality: {a, b} equals {b, a}.