Dune::Copasi
Loading...
Searching...
No Matches
functor_factory_parser.impl.hh
Go to the documentation of this file.
1#ifndef DUNE_COPASI_MODEL_LOCAL_VALUES_PARSED_FUNCTOR_FACTORY_IMPL_HH
2#define DUNE_COPASI_MODEL_LOCAL_VALUES_PARSED_FUNCTOR_FACTORY_IMPL_HH
3
6
7#include <regex>
8
9#ifdef DUNE_COPASI_PRECOMPILED_MODE
10#warning "Including this file in pre-compiled mode may defeat the purpose of pre-compilation"
11#endif
12
13namespace Dune::Copasi {
14
15namespace Impl {
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]+)?");
19} // namespace Impl
20
21template<std::size_t dim>
23
24template<std::size_t dim>
25auto
26FunctorFactoryParser<dim>::make_scalar(std::string_view /*prefix*/,
27 const ParameterTree& config,
29 int codim) const -> ScalarFunctor
30{
31 return parse_scalar_expression(config, local_values, codim);
32}
33
34template<std::size_t dim>
35auto
36FunctorFactoryParser<dim>::make_vector(std::string_view /*prefix*/,
37 const ParameterTree& config,
39 int codim) const -> VectorFunctor
40{
41 // create one parser for each entry of the vector
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));
48 }
49 if (not is_active) {
50 return nullptr;
51 }
52
53 // move parsers into a lambda that evaluates vector components
54 return { [_vector_parser = std::move(vector_parser)]() noexcept {
55 Vector vec;
56 for (std::size_t i = 0; i != dim; ++i) {
57 vec[i] = (_vector_parser[i] ? _vector_parser[i]()[0] : 0.);
58 }
59 return vec;
60 } };
61}
62
63template<std::size_t dim>
64auto
66 const ParameterTree& config,
68 int codim) const
70{
71 // diffusion apply parser
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; };
77 }
78 return nullptr;
79 } else if (type == "tensor") {
80 // create one parser for each entry of the 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) {
86 if (config.hasSub(axis_names[i] + axis_names[j]))
87 is_active |= bool(tensor_parser[i][j] = parse_scalar_expression(
90 codim));
91 }
92 }
93 if (not is_active) {
94 return nullptr;
95 }
96
97 // move parsers into a lambda that evaluates matrix-vector product
98 return { [_tensor_parser = std::move(tensor_parser)](Vector in) noexcept {
99 Vector out;
100 for (std::size_t i = 0; i != dim; ++i) {
101 out[i] = 0.;
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.);
104 }
105 }
106 return out;
107 } };
108 } else {
109 spdlog::error("not known type 'scalar_value.{}.type = {}'", prefix, type);
110 std::terminate();
111 }
112}
113
114template<std::size_t dim>
115auto
118 int codim) const
119 -> ScalarFunctor
120{
121 auto expression = config.get("expression", std::string{});
122 if (expression.empty() or std::regex_match(expression, Impl::zero_regex)) {
123 return nullptr;
124 }
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 }; };
129 } else {
130 auto parser_type =
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]);
143 if (i < dim) {
144 parser_ptr->define_variable(pos_arg, &(local_values.position)[i]);
145 if (codim == 1)
146 parser_ptr->define_variable(norm_arg, &(local_values.normal)[i]);
147 } else {
148 parser_ptr->define_constant(pos_arg, 0.);
149 if (codim == 1)
150 parser_ptr->define_constant(norm_arg, 0.);
151 }
152 }
153
154 // bind cell keys with cell key values
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]);
157 }
158
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]);
163 if (i < dim) {
164 parser_ptr->define_variable(grad_arg, &(gradient)[i]);
165 } else {
166 parser_ptr->define_constant(grad_arg, 0.);
167 }
168 }
169 });
170
171 parser_ptr->set_expression(expression);
172 if (_parser_context)
173 _parser_context->add_context(*parser_ptr);
174 parser_ptr->compile();
175 // try to run the parser once, if compilation is wrong,
176 // this will throw outside of the functor
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) };
180 };
181 }
182}
183
184} // namespace Dune::Copasi
185
186#endif // DUNE_COPASI_MODEL_LOCAL_VALUES_PARSED_FUNCTOR_FACTORY_IMPL_HH
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
FieldVector< double, dim > Vector
Definition functor_factory_parser.hh:16
typename FunctorFactory< dim >::ScalarFunctor ScalarFunctor
Definition functor_factory_parser.hh:19
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
typename FunctorFactory< dim >::VectorFunctor VectorFunctor
Definition functor_factory_parser.hh:20
typename FunctorFactory< dim >::TensorApplyFunctor TensorApplyFunctor
Definition functor_factory_parser.hh:21
Definition functor_factory_parser.impl.hh:22
Definition axis_names.hh:7
std::unique_ptr< Parser > make_parser(ParserType parser_type=default_parser)
constexpr bool is_bitflags_v
Alias for Bitflag indicator.
Definition bit_flags.hh:24
std::vector< std::string > axis_names
Definition local_domain.hh:15