Reaktoro  v2.9.2
A unified framework for modeling chemically reactive systems
Model.hpp
1 // Reaktoro is a unified framework for modeling chemically reactive systems.
2 //
3 // Copyright © 2014-2022 Allan Leal
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this library. If not, see <http://www.gnu.org/licenses/>.
17 
18 #pragma once
19 
20 // Reaktoro includes
21 #include <Reaktoro/Common/Algorithms.hpp>
22 #include <Reaktoro/Common/Memoization.hpp>
23 #include <Reaktoro/Common/TraitsUtils.hpp>
24 #include <Reaktoro/Common/Types.hpp>
25 #include <Reaktoro/Core/Data.hpp>
26 #include <Reaktoro/Core/Param.hpp>
27 
28 namespace Reaktoro {
29 
30 template<typename Signature>
31 class Model;
32 
34 template<typename ResultRef, typename... Args>
35 using ModelEvaluator = Fn<void(ResultRef res, Args... args)>;
36 
38 template<typename Result, typename... Args>
39 using ModelCalculator = Fn<Result(Args... args)>;
40 
42 using ModelSerializer = Fn<Data()>;
43 
46 template<typename Result, typename... Args>
47 class Model<Result(Args...)>
48 {
49 public:
53  using ResultRef = Ref<Result>;
54 
57  {}
58 
63  Model(const ModelEvaluator<ResultRef, Args...>& evalfn, const Vec<Param>& params = {}, const ModelSerializer& serializerfn = {})
64  : m_params(params), m_serializerfn(serializerfn)
65  {
66  assert(evalfn);
67 
68  m_evalfn = [evalfn](ResultRef res, const Args&... args, const Vec<Param>& w)
69  {
70  evalfn(res, args...);
71  };
72 
73  m_calcfn = [evalfn](const Args&... args, const Vec<Param>& w) -> Result
74  {
75  Result res;
76  evalfn(res, args...);
77  return res;
78  };
79  }
80 
85  Model(const ModelCalculator<Result, Args...>& calcfn, const Vec<Param>& params = {}, const ModelSerializer& serializerfn = {})
86  : m_params(params), m_serializerfn(serializerfn)
87  {
88  assert(calcfn);
89 
90  m_evalfn = [calcfn](ResultRef res, const Args&... args, const Vec<Param>& w)
91  {
92  res = calcfn(args...);
93  };
94 
95  m_calcfn = [calcfn](const Args&... args, const Vec<Param>& w) -> Result
96  {
97  return calcfn(args...);
98  };
99  }
100 
109  template<typename Fun, Requires<!isFunction<Fun>> = true>
110  Model(const Fun& f)
111  : Model(std::function(f))
112  // : Model(asFunction(f))
113  {}
114 
116  auto withMemoization() const -> Model
117  {
118  Model copy = *this;
119  copy.m_evalfn = memoizeLastUsingRef<Result>(copy.m_evalfn); // Here, if `m_evalfn` did not consider `const Vec<Param>&` as argument, memoization would not know when the parameters have been changed externally!
120  copy.m_calcfn = memoizeLast(copy.m_calcfn); // Here, if `m_calcfn` did not consider `const Vec<Param>&` as argument, memoization would not know when the parameters have been changed externally!
121  return copy;
122  }
123 
125  auto apply(ResultRef res, const Args&... args) const -> void
126  {
127  assert(m_evalfn);
128  m_evalfn(res, args..., m_params);
129  }
130 
132  auto operator()(const Args&... args) const -> Result
133  {
134  assert(m_calcfn);
135  return m_calcfn(args..., m_params);
136  }
137 
139  auto operator()(ResultRef res, const Args&... args) const -> void
140  {
141  apply(res, args...);
142  }
143 
145  auto initialized() const -> bool
146  {
147  return m_evalfn != nullptr;
148  }
149 
151  operator bool() const
152  {
153  return initialized();
154  }
155 
157  auto evaluatorFn() const -> const ModelEvaluator<ResultRef, Args..., const Vec<Param>&>&
158  {
159  return m_evalfn;
160  }
161 
163  auto calculatorFn() const -> const ModelCalculator<Result, Args..., const Vec<Param>&>&
164  {
165  return m_calcfn;
166  }
167 
169  auto serializerFn() const -> const ModelSerializer
170  {
171  return m_serializerfn;
172  }
173 
175  auto params() const -> const Vec<Param>&
176  {
177  return m_params;
178  }
179 
181  auto serialize() const -> Data
182  {
183  return m_serializerfn ? m_serializerfn() : Data{}; // evaluate m_serializerfn because Param objects may have changed
184  }
185 
188  static auto Constant(const Param& param) -> Model
189  {
190  auto calcfn = [param](const Args&... args) { return param; }; // no need to have `const Vec<Param>&` in the lambda function here. This is added in the constructor call below!
191  Vec<Param> params = { param };
192  return Model(calcfn, params);
193  }
194 
195 private:
212  Vec<Param> m_params;
213 
215  ModelEvaluator<ResultRef, Args..., const Vec<Param>&> m_evalfn;
216 
220  ModelCalculator<Result, Args..., const Vec<Param>&> m_calcfn;
221 
228  ModelSerializer m_serializerfn;
229 };
230 
232 template<typename Result, typename... Args>
233 auto chain(const Vec<Model<Result(Args...)>>& models) -> Model<Result(Args...)>
234 {
235  using ResultRef = Ref<Result>;
236 
237  const auto evalfns = vectorize(models, RKT_LAMBDA(model, model.evaluatorFn()));
238  const auto paramsvec = vectorize(models, RKT_LAMBDA(model, model.params()));
239  const auto serializerfns = vectorize(models, RKT_LAMBDA(model, model.serializerFn()));
240 
241  auto evalfn = [=](ResultRef res, const Args&... args)
242  {
243  for(auto i = 0; i < evalfns.size(); ++i)
244  evalfns[i](res, args..., paramsvec[i]);
245  };
246 
247  auto serializerfn = [serializerfns]() -> Data
248  {
249  Data result;
250  for(auto i = 0; i < serializerfns.size(); ++i)
251  result.add(serializerfns[i]());
252  return result;
253  };
254 
255  Vec<Param> params;
256  for(const auto& model : models)
257  for(const auto& param : model.params())
258  params.push_back(param);
259 
260  return Model<Result(Args...)>(evalfn, params);
261 }
262 
264 template<typename Signature>
266 {
267  return model;
268 }
269 
271 template<typename Result, typename... Args, typename... Models>
272 auto chain(const Model<Result(Args...)>& model, const Models&... models) -> Model<Result(Args...)>
273 {
274  Vec<Model<Result(Args...)>> vec = {model, models...};
275  return chain(vec);
276 }
277 
278 } // namespace Reaktoro
The class used to store and retrieve data for assemblying chemical systems.
Definition: Data.hpp:41
auto add(Data data) -> void
Add a Data object to this Data object, which becomes a list if not already.
Model(const Fun &f)
Construct a Model function object with either a model evaluator or a model calculator function.
Definition: Model.hpp:110
Ref< Result > ResultRef
The reference type of result type.
Definition: Model.hpp:53
auto initialized() const -> bool
Return true if this Model function object has been initialized.
Definition: Model.hpp:145
auto operator()(const Args &... args) const -> Result
Evaluate the model with given arguments and return the result of the evaluation.
Definition: Model.hpp:132
Model()
Construct a default Model function object.
Definition: Model.hpp:56
static auto Constant(const Param &param) -> Model
Return a constant Model function object.
Definition: Model.hpp:188
Model(const ModelEvaluator< ResultRef, Args... > &evalfn, const Vec< Param > &params={}, const ModelSerializer &serializerfn={})
Construct a Model function object with given model evaluator function and its parameters.
Definition: Model.hpp:63
auto params() const -> const Vec< Param > &
Return the model parameters of this Model function object.
Definition: Model.hpp:175
auto serialize() const -> Data
Return serialization of the underlying model function to a Data object.
Definition: Model.hpp:181
auto calculatorFn() const -> const ModelCalculator< Result, Args..., const Vec< Param > & > &
Return the model calculator function of this Model function object.
Definition: Model.hpp:163
auto withMemoization() const -> Model
Return a new Model function object with memoization for the model calculator.
Definition: Model.hpp:116
Model(const ModelCalculator< Result, Args... > &calcfn, const Vec< Param > &params={}, const ModelSerializer &serializerfn={})
Construct a Model function object with given direct model calculator and its parameters.
Definition: Model.hpp:85
auto evaluatorFn() const -> const ModelEvaluator< ResultRef, Args..., const Vec< Param > & > &
Return the model evaluator function of this Model function object.
Definition: Model.hpp:157
auto operator()(ResultRef res, const Args &... args) const -> void
Evaluate the model with given arguments and return the result of the evaluation.
Definition: Model.hpp:139
auto apply(ResultRef res, const Args &... args) const -> void
Evaluate the model with given arguments.
Definition: Model.hpp:125
auto serializerFn() const -> const ModelSerializer
Return the function that serializes the underlying model function to a Data object.
Definition: Model.hpp:169
Definition: Model.hpp:31
A type used to represent the value of a parameter and its lower and upper bounds.
Definition: Param.hpp:32
The namespace containing all components of the Reaktoro library.
Definition: Algorithms.hpp:28
std::vector< T > Vec
Convenient alias for std::vector<T>.
Definition: Types.hpp:66
Fn< Result(Args... args)> ModelCalculator
The functional signature of functions that calculates properties.
Definition: Model.hpp:39
auto memoizeLast(Fn< Ret(Args...)> f) -> Fn< Ret(Args...)>
Return a memoized version of given function f that caches only the arguments used in the last call.
Definition: Memoization.hpp:176
auto chain(const Vec< ActivityModelGenerator > &models) -> ActivityModelGenerator
Return an activity model resulting from chaining other activity models.
auto vectorize(const Container &c, const Function &f)
Return a vector by applying function f on every item in container c.
Definition: Algorithms.hpp:134
std::function< F > Fn
Convenient alias for std::function<R(Args...)>.
Definition: Types.hpp:110
Fn< Data()> ModelSerializer
The functional signature of functions that serialize a Model object into a Data object.
Definition: Model.hpp:42
Fn< void(ResultRef res, Args... args)> ModelEvaluator
The functional signature of functions that evaluates properties.
Definition: Model.hpp:35