1#ifndef DUNE_COPASI_MODEL_LOCAL_VALUES_PARSED_FUNCTOR_FACTORY_IMPL_HH
2#define DUNE_COPASI_MODEL_LOCAL_VALUES_PARSED_FUNCTOR_FACTORY_IMPL_HH
9#ifdef DUNE_COPASI_PRECOMPILED_MODE
10#warning "Including this file in pre-compiled mode may defeat the purpose of pre-compilation"
16static inline const std::regex scientific_notation_regex(
"/[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+\\-]?\\d+)?/");
17static inline const std::regex float_regex(
"-?([0-9]+)?([\\.]?)([0-9]+)?");
18static inline const std::regex zero_regex(
"-?([0]+)?([\\.]?)([0]+)?");
21template<std::
size_t dim>
24template<std::
size_t dim>
27 const ParameterTree& config,
31 return parse_scalar_expression(config, local_values, codim);
34template<std::
size_t dim>
37 const ParameterTree& config,
42 std::array<ScalarFunctor, dim> vector_parser;
43 const std::size_t max_axis = std::min<std::size_t>({
axis_names.size(), dim});
44 bool is_active =
false;
45 for (std::size_t i = 0; i != max_axis; ++i) {
46 is_active |= bool(vector_parser[i] = parse_scalar_expression(
47 config.sub(
axis_names[i],
true), local_values, codim));
54 return { [_vector_parser = std::move(vector_parser)]()
noexcept {
56 for (std::size_t i = 0; i != dim; ++i) {
57 vec[i] = (_vector_parser[i] ? _vector_parser[i]()[0] : 0.);
63template<std::
size_t dim>
66 const ParameterTree& config,
72 std::string type = config.get(
"type",
"scalar");
73 if (type ==
"scalar") {
74 if (
auto parser = parse_scalar_expression(config, local_values, codim)) {
75 return [parser = std::move(parser)](
Vector vec)
76 noexcept {
return parser()[0] * vec; };
79 }
else if (type ==
"tensor") {
81 std::array<std::array<ScalarFunctor, dim>, dim> tensor_parser;
82 const std::size_t max_axis = std::min<std::size_t>({
axis_names.size(), dim});
83 bool is_active =
false;
84 for (std::size_t i = 0; i != max_axis; ++i) {
85 for (std::size_t j = 0; j != max_axis; ++j) {
87 is_active |= bool(tensor_parser[i][j] = parse_scalar_expression(
98 return { [_tensor_parser = std::move(tensor_parser)](
Vector in)
noexcept {
100 for (std::size_t i = 0; i != dim; ++i) {
102 for (std::size_t j = 0; j != dim; ++j) {
103 out[i] += in[j] * (_tensor_parser[i][j] ? _tensor_parser[i][j]()[0] : 0.);
109 spdlog::error(
"not known type 'scalar_value.{}.type = {}'", prefix, type);
114template<std::
size_t dim>
121 auto expression = config.get(
"expression", std::string{});
122 if (expression.empty() or std::regex_match(expression, Impl::zero_regex)) {
125 if (std::regex_match(expression, Impl::float_regex)
126 or std::regex_match(expression, Impl::scientific_notation_regex)) {
127 double value = std::stod(expression);
128 return [_value = value]()
noexcept {
return Scalar{ _value }; };
131 string2parser.at(config.get(
"parser_type", std::string{ parser2string.at(_parser_type) }));
133 parser_ptr->define_variable(
"time", &(local_values.time));
134 parser_ptr->define_variable(
"integration_factor", &(local_values.integration_factor));
135 parser_ptr->define_variable(
"entity_volume", &(local_values.entity_volume));
136 parser_ptr->define_variable(
"in_volume", &(local_values.in_volume));
137 parser_ptr->define_variable(
"in_boundary", &(local_values.in_boundary));
138 parser_ptr->define_variable(
"in_skeleton", &(local_values.in_skeleton));
139 parser_ptr->define_constant(
"no_value", std::numeric_limits<double>::max());
140 for (std::size_t i = 0; i !=
axis_names.size(); ++i) {
141 auto pos_arg = fmt::format(
"position_{}",
axis_names[i]);
142 auto norm_arg = fmt::format(
"normal_{}",
axis_names[i]);
144 parser_ptr->define_variable(pos_arg, &(local_values.position)[i]);
146 parser_ptr->define_variable(norm_arg, &(local_values.normal)[i]);
148 parser_ptr->define_constant(pos_arg, 0.);
150 parser_ptr->define_constant(norm_arg, 0.);
155 for (std::size_t j = 0; j < local_values.cell_keys.size(); ++j) {
156 parser_ptr->define_variable(local_values.cell_keys[j], &local_values.cell_values[j]);
159 local_values.forEachValue(Codim<0>{}, [&](
auto name,
const auto& value,
const auto& gradient){
160 parser_ptr->define_variable(std::string{name}, &(value[0]));
161 for (std::size_t i = 0; i !=
axis_names.size(); ++i) {
162 auto grad_arg = fmt::format(
"grad_{}_{}", name,
axis_names[i]);
164 parser_ptr->define_variable(grad_arg, &(gradient)[i]);
166 parser_ptr->define_constant(grad_arg, 0.);
171 parser_ptr->set_expression(expression);
173 _parser_context->add_context(*parser_ptr);
174 parser_ptr->compile();
177 [[maybe_unused]]
auto dummy = std::invoke(*parser_ptr);
178 return [_parser_ptr = std::move(parser_ptr)]()
noexcept {
179 return Scalar{ std::invoke(*_parser_ptr) };
Definition: functor_factory_parser.hh:13
ScalarFunctor make_scalar(std::string_view, const ParameterTree &, const LocalDomain< dim > &, int=0) const override
Definition: functor_factory_parser.impl.hh:26
VectorFunctor make_vector(std::string_view, const ParameterTree &, const LocalDomain< dim > &, int=0) const override
Definition: functor_factory_parser.impl.hh:36
TensorApplyFunctor make_tensor_apply(std::string_view, const ParameterTree &, const LocalDomain< dim > &, int=0) const override
Definition: functor_factory_parser.impl.hh:65
FieldVector< double, dim > Vector
Definition: functor_factory.hh:27
fu2::unique_function< Vector(Vector) const noexcept > TensorApplyFunctor
Definition: functor_factory.hh:32
fu2::unique_function< Vector() const noexcept > VectorFunctor
Definition: functor_factory.hh:31
fu2::unique_function< Scalar() const noexcept > ScalarFunctor
Definition: functor_factory.hh:30
Definition: functor_factory_parser.impl.hh:22
Definition: axis_names.hh:7
std::unique_ptr< Parser > make_parser(ParserType parser_type=default_parser)
std::vector< std::string > axis_names
Definition: local_domain.hh:15