libRoadRunner C++ API  1.3
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
EulerIntegrator.h
1 /*
2  * EulerIntegrator.h
3  *
4  * Created on: Dec 17, 2014
5  * Author: andy
6  */
7 
8 #ifndef EULERINTEGRATOR_H_
9 #define EULERINTEGRATOR_H_
10 
11 #include "Integrator.h"
12 #include "rrExecutableModel.h"
13 #include "rrRoadRunnerOptions.h"
14 #include <string>
15 #include <stdexcept>
16 #include <sstream>
17 
18 namespace rr
19 {
20  using std::string;
21  using std::invalid_argument;
22  using std::stringstream;
23 
24  /**
25  * An example class intended to show how to create
26  * an Integrator. This class implements the most
27  * basic possible integration algorithm: the forward Euler method.
28  *
29  * This integrator should not really be used in practice as the
30  * forward Euler algorithm is highly unstable and will seldomly
31  * yield numerically correct values.
32  *
33  * This class also has two dummy variables, exampleParameter1 and
34  * exampleParameter2. These serve as examples of how to use the Dictionary
35  * interface to get/set various tuning paramters that an Integrator
36  * might have. These values will be displayed when the toString method
37  * is called, typically by Python.
38  *
39  * An example of calling simulate in Python, and the results of specifying
40  * the parameters as keyword arguments is
41  *
42  * @code
43  * r.simulate(integrator='euler', exampleParameter1=123456, exampleParameter2='some value');
44  *
45  * print(r.integrator)
46  * < roadrunner.EulerIntegrator()
47  * { 'this' : 0x101f28350
48  * 'exampleParameter1' : 123456
49  * 'exampleParameter2' : some value
50  * }>
51  * @endcode
52  *
53  */
54  class EulerIntegrator: public Integrator
55  {
56  public:
57 
58  /**
59  * Creates a new EulerIntegrator.
60  *
61  * The IntegratorFactory is the ONLY object that creates integrators.
62  *
63  * Integrators are created when the IntegratorFactory::New method is called,
64  * typically by the top level RoadRunner object.
65  *
66  * The integrator will hold onto the ExecutableModel pointer, m, and when the
67  * integrate method is called, will advance the model object forward in time.
68  *
69  * @param m: a borrowed reference to an existing ExecutableModel object.
70  * @param o: a reference to a SimulatOptions object where the configuration
71  * parameters will be read from.
72  */
74  model = m;
75  exampleParameter1 = 3.14;
76  exampleParameter2 = "hello";
77 
78  if(model) {
79  // calling the getStateVector with a NULL argument returns
80  // the size of teh state vector.
81  stateVectorSize = model->getStateVector(NULL);
82  rateBuffer = new double[stateVectorSize];
83  stateBuffer1 = new double[stateVectorSize];
84  stateBuffer2 = new double[stateVectorSize];
85  } else {
86  rateBuffer = NULL;
87  stateBuffer1 = NULL;
88  stateBuffer2 = NULL;
89  }
90  }
91 
92  /**
93  * delete any memory we allocated
94  */
95  virtual ~EulerIntegrator() {
96  delete[] rateBuffer;
97  delete[] stateBuffer1;
98  delete[] stateBuffer2;
99  };
100 
101  /**
102  * integrates the model from t0 to t0 + hstep
103  *
104  * In this implementation, this performs a basic forward Euler step.
105  * This method also demonstrates how to notify the listener
106  * that a timestep has completed.
107  *
108  * @return the end time.
109  */
110  virtual double integrate(double t0, double h) {
111  if(model) {
112  // evaluate and copy the rate of change of the state vector
113  // rate into the local buffer. If the 2nd argument is NULL,
114  // the current model state is used to evaluate the
115  // state vector rate.
116  model->getStateVectorRate(t0, NULL, rateBuffer);
117 
118  // copy the current state vector into a local buffer
119  model->getStateVector(stateBuffer1);
120 
121  // perform the Euler integration step, i.e.
122  // y_{n+1} = y_{n} + h * y'_{n}
123  for (int i = 0; i < stateVectorSize; ++i) {
124  stateBuffer2[i] = stateBuffer1[i] + h * rateBuffer[i];
125  }
126 
127  // set the model state to the newly calculated state
128  model->setStateVector(stateBuffer2);
129 
130  // update the model time to the new time
131  model->setTime(t0 + h);
132 
133  // if we have a client, notify them that we have taken
134  // a time step
135  if (listener)
136  {
137  listener->onTimeStep(this, model, t0 + h);
138  }
139  }
140  return t0 + h;
141  }
142 
143  /**
144  * This simple integrator has nothing to reset, so do nothing here
145  */
146  virtual void restart(double t0) {}
147 
148  /**
149  * Clients may register a listener to listen for
150  * sbml events and time step events.
151  */
152  virtual void setListener(IntegratorListenerPtr p) {
153  listener = p;
154  }
155 
156  /**
157  * get the integrator listener
158  */
159  virtual IntegratorListenerPtr getListener() {
160  return listener;
161  }
162 
163  /**
164  * get a description of this object, compatable with python __str__
165  */
166  virtual std::string toString() const {
167  std::stringstream ss;
168  ss << "< roadrunner.EulerIntegrator() " << std::endl;
169  ss << "{ 'this' : " << (void*)this << std::endl;
170  ss << "'exampleParameter1' : " << exampleParameter1 << std::endl;
171  ss << "'exampleParameter2' : " << exampleParameter2 << std::endl;
172  ss << "}>";
173  return ss.str();
174  }
175 
176  /**
177  * get a short descriptions of this object, compatable with python __repr__.
178  */
179  virtual std::string toRepr() const {
180  std::stringstream ss;
181  ss << "< roadrunner.EulerIntegrator() { 'this' : "
182  << (void*)this << " }>";
183  return ss.str();
184  }
185 
186  /**
187  * get the name of this integrator
188  */
189  virtual std::string getName() const {
190  return getEulerName();
191  }
192 
193  /**
194  * @author JKM
195  * @brief Get the name for this integrator
196  */
197  static std::string getEulerName() {
198  return "euler";
199  }
200 
201  /**
202  * @author JKM
203  * @brief Get the description for this integrator
204  * @note Delegates to @ref getDescription
205  */
206  std::string getDescription() const {
207  return getEulerDescription();
208  }
209 
210  /**
211  * @author JKM
212  * @brief Get the description for this integrator
213  */
214  static std::string getEulerDescription() {
215  return "The Euler method is one of the simplest approaches to "
216  "solving a first order ODE. Given the rate of change of "
217  "function f at time t, it computes the new value of f as "
218  "f(t+h) = f(t) + h*f'(t), where h is the time step. "
219  "Euler's method is rarely used in practice due to poor "
220  "numerical robustness.";
221  }
222 
223  /**
224  * @author JKM
225  * @brief Get the hint for this integrator
226  * @note Delegates to @ref getHint
227  */
228  std::string getHint() const {
229  return getEulerHint();
230  }
231 
232  /**
233  * @author JKM
234  * @brief Get the hint for this integrator
235  */
236  static std::string getEulerHint() {
237 // return "An elementary (my dear Watson) Euler integrator";
238  return "A simple Euler integrator";
239  }
240 
241  /**
242  * @author JKM
243  * @brief Reset all integrator settings to their respective default values
244  */
246  {
248 
249  // Euler integrator has no settings
250  }
251 
252  /**
253  * @author JKM
254  * @brief Always deterministic for Euler
255  */
256  IntegrationMethod getIntegrationMethod() const {
257  return Integrator::Deterministic;
258  }
259 
260  /**
261  * sets the value for a key.
262  *
263  * This integrator only supports 2 values, so those are the
264  * only two valid items to set.
265  */
266  virtual void setItem(const std::string& key, const rr::Variant& value) {
267  if (key == "exampleParameter1") {
268  exampleParameter1 = value;
269  return;
270  }
271 
272  if(key == "exampleParameter2") {
273  exampleParameter2 = (string)value;
274  }
275 
276  // they did not give a valid key, so throw an exception.
277  throw invalid_argument("Error, attempt to set invalid key: " + key);
278  }
279 
280  /**
281  * Get a value.
282  *
283  * This integrator only supports two parameters, those are the
284  * only valid ones to get.
285  */
286  virtual Variant getItem(const std::string& key) const {
287  if (key == "exampleParameter1") {
288  return exampleParameter1;
289  }
290 
291  if(key == "exampleParameter2") {
292  return exampleParameter2;
293  }
294 
295  // they did not give a valid key, so throw an exception.
296  throw invalid_argument("Error, attempt to read invalid key: " + key);
297  }
298 
299  /**
300  * is there a key matching this name.
301  */
302  virtual bool hasKey(const std::string& key) const {
303  if (key == "exampleParameter1" || key == "exampleParameter2") {
304  return true;
305  } else {
306  return false;
307  }
308  }
309 
310  /**
311  * remove a value, this example class does not support deleting
312  * keys, so just raise an exception if someone tries to do so.
313  */
314  virtual int deleteItem(const std::string& key) {
315  throw invalid_argument(
316  "Error, the EulerIntegrator does not support deleting keys");
317  }
318 
319  /**
320  * list of keys in this object.
321  */
322  virtual std::vector<std::string> getKeys() const {
323  std::vector<std::string> keys;
324  keys.push_back("exampleParameter1");
325  keys.push_back("exampleParameter2");
326  return keys;
327  }
328 
329  /**
330  * list of keys that this integrator supports.
331  *
332  * This method is called by the IntegratorFactory to build a list of
333  * all the options that all the integrators support.
334  */
336  static BasicDictionary dict;
337 
338  // fill out the required options for defining this integrator
339  dict.setItem("integrator", "euler");
340  dict.setItem("integrator.description",
341  "Forward Euler Integrator: an example of creating an integrator");
342  dict.setItem("integrator.hint", "Forward Euler Integrator");
343 
344  // this uses two example parameters, add them here
345  dict.setItem("exampleParameter1", 3.14);
346  dict.setItem("exampleParameter1.description",
347  "an example parameter that does nothing");
348  dict.setItem("exampleParameter1.hint", "a hint for the example parameter");
349 
350  dict.setItem("exampleParameter2", string("hello"));
351  dict.setItem("exampleParameter2.description",
352  "another parameter which does nothing");
353  dict.setItem("exampleParameter2.hint", "a hint for the other parameter");
354 
355  return &dict;
356  }
357 
358  private:
359  /**
360  * a parameter which does nothing
361  */
362  double exampleParameter1;
363 
364  /**
365  * another parameter which does nothing
366  */
367  string exampleParameter2;
368 
369  /**
370  * a stolen reference to an existing model object.
371  */
372  ExecutableModel *model;
373 
374  /**
375  * two buffers to store the state vector rate, and
376  * new state vector
377  */
378  double *rateBuffer, *stateBuffer1, *stateBuffer2;
379 
380  /**
381  * size of state vector
382  */
383  int stateVectorSize;
384 
385  /**
386  * Clients may register a listener to listen for time steps, or
387  * sbml events. Time step events are much more usefull for variable
388  * time step integrators where they may take long time steps and
389  * clients may be notified when these occur.
390  *
391  * This is a smart pointer to a object which implements the
392  * IntegratorListener interface.
393  */
394  IntegratorListenerPtr listener;
395  };
396 
397 
398  // ** Registration *********************************************************
399 
400 
401  class EulerIntegratorRegistrar : public IntegratorRegistrar {
402  public:
403  /**
404  * @author JKM
405  * @brief Gets the name associated with this integrator type
406  */
407  virtual std::string getName() const {
409  }
410 
411  /**
412  * @author JKM
413  * @brief Gets the description associated with this integrator type
414  */
415  virtual std::string getDescription() const {
417  }
418 
419  /**
420  * @author JKM
421  * @brief Gets the hint associated with this integrator type
422  */
423  virtual std::string getHint() const {
425  }
426 
427  /**
428  * @author JKM
429  * @brief Constructs a new integrator of a given type
430  */
431  virtual Integrator* construct(ExecutableModel *model) const {
432  return new EulerIntegrator(model);
433  }
434  };
435 
436 } /* namespace rr */
437 
438 #endif /* EULERINTEGRATOR_H_ */
virtual ~EulerIntegrator()
Definition: EulerIntegrator.h:95
virtual void resetSettings()
Reset all settings to their respective default values.
Definition: Solver.cpp:46
virtual double integrate(double t0, double h)
Definition: EulerIntegrator.h:110
Base class for all code generators in RoadRunner.
static std::string getEulerHint()
Get the hint for this integrator.
Definition: EulerIntegrator.h:236
virtual std::vector< std::string > getKeys() const
Definition: EulerIntegrator.h:322
Contains the base class for RoadRunner integrators.
static std::string getEulerDescription()
Get the description for this integrator.
Definition: EulerIntegrator.h:214
Definition: CVODEIntegrator.cpp:26
Definition: EulerIntegrator.h:54
virtual std::string getName() const
Definition: EulerIntegrator.h:189
virtual bool hasKey(const std::string &key) const
Definition: EulerIntegrator.h:302
static const Dictionary * getIntegratorOptions()
Definition: EulerIntegrator.h:335
virtual std::string toRepr() const
Definition: EulerIntegrator.h:179
virtual void restart(double t0)
Definition: EulerIntegrator.h:146
std::string getDescription() const
Get the description for this integrator.
Definition: EulerIntegrator.h:206
virtual void getStateVectorRate(double time, const double *y, double *dydt=0)=0
virtual int setStateVector(const double *stateVector)=0
virtual IntegratorListenerPtr getListener()
Definition: EulerIntegrator.h:159
Base class for all code generation systems; allows compiling and evaluating the model.
Definition: rrExecutableModel.h:127
virtual Variant getItem(const std::string &key) const
Definition: EulerIntegrator.h:286
EulerIntegrator(ExecutableModel *m)
Definition: EulerIntegrator.h:73
virtual void setItem(const std::string &key, const rr::Variant &value)
Definition: Dictionary.cpp:12
IntegrationMethod getIntegrationMethod() const
Always deterministic for Euler.
Definition: EulerIntegrator.h:256
virtual void setItem(const std::string &key, const rr::Variant &value)
Definition: EulerIntegrator.h:266
virtual void setListener(IntegratorListenerPtr p)
Definition: EulerIntegrator.h:152
This class is frozen, no new features A dictionary interface that objects can implement. These are automatically mapped to python dictionaries.
Definition: Dictionary.h:30
Definition: Variant.h:73
static std::string getEulerName()
Get the name for this integrator.
Definition: EulerIntegrator.h:197
This class is frozen, no new features Basic implementation of the Dictionary interface which uses a s...
Definition: Dictionary.h:140
void resetSettings()
Reset all integrator settings to their respective default values.
Definition: EulerIntegrator.h:245
virtual int getStateVector(double *stateVector)=0
virtual int deleteItem(const std::string &key)
Definition: EulerIntegrator.h:314
std::string getHint() const
Get the hint for this integrator.
Definition: EulerIntegrator.h:228
virtual std::string toString() const
Definition: EulerIntegrator.h:166