Minsky: 3.17.0
minsky::RungeKutta Class Reference

#include <rungeKutta.h>

Inheritance diagram for minsky::RungeKutta:
Inheritance graph
Collaboration diagram for minsky::RungeKutta:
Collaboration graph

Public Member Functions

virtual ~RungeKutta ()=default
 
virtual bool resetIfFlagged ()
 checks whether a reset is required, and resets the simulation if so More...
 
void rkreset ()
 reset the simulation More...
 
void rkstep ()
 step the equations (by n steps, default 1) evaluate the flow equations without stepping. More...
 
void evalEquations ()
 

Public Attributes

double t {0}
 time More...
 
bool running =false
 controls whether simulation is running More...
 
bool reverse =false
 reverse direction of simulation More...
 
EvalGodley evalGodley
 
- Public Attributes inherited from minsky::Simulation
double stepMin {0}
 
double stepMax {0.01}
 
int nSteps {1}
 
double epsRel {1e-2}
 
double epsAbs {1e-3}
 
int order {4}
 
bool implicit {false}
 
int simulationDelay {0}
 
std::string timeUnit
 
double tmax {INFINITY}
 
double t0 {0}
 

Protected Member Functions

void evalEquations (double result[], double, const double vars[])
 
void evalJacobian (Matrix &, double, const double vars[])
 

Static Protected Member Functions

static int RKfunction (double, const double y[], double f[], void *)
 function to be integrated (internal use) More...
 
static int jacobian (double, const double y[], double *, double dfdt[], void *)
 compute jacobian (internal use) More...
 

Private Member Functions

 CLASSDESC_ACCESS (RungeKutta)
 

Friends

struct RKdata
 

Additional Inherited Members

- Static Public Attributes inherited from minsky::ValueVector
static std::vector< double, CIVITA_ALLOCATOR< double > > stockVars
 vector of variables that are integrated via Runge-Kutta. These variables label the columns of the Godley table More...
 
static std::vector< double, CIVITA_ALLOCATOR< double > > flowVars
 variables defined as a simple function of the stock variables, also known as lhs variables. These variables appear in the body of the Godley table More...
 

Detailed Description

Definition at line 45 of file rungeKutta.h.

Constructor & Destructor Documentation

◆ ~RungeKutta()

virtual minsky::RungeKutta::~RungeKutta ( )
virtualdefault

Member Function Documentation

◆ CLASSDESC_ACCESS()

minsky::RungeKutta::CLASSDESC_ACCESS ( RungeKutta  )
private

◆ evalEquations() [1/2]

void minsky::RungeKutta::evalEquations ( double  result[],
double  t,
const double  vars[] 
)
protected

Definition at line 248 of file rungeKutta.cc.

References minsky::Minsky::displayErrorItem(), and pyminsky::minsky.

Referenced by minsky::VariableBase::onMouseMotion().

249  {
251  const double reverseFactor=reverse? -1: 1;
252  // firstly evaluate the flow variables. Initialise to flowVars so
253  // that no input vars are correctly initialised
254  auto flow(flowVars);
255  for (size_t i=0; i<equations.size(); ++i)
256  equations[i]->eval(flow.data(), flow.size(), vars);
257 
258  // then create the result using the Godley table
259  for (size_t i=0; i<stockVars.size(); ++i) result[i]=0;
260  evalGodley.eval(result, flow.data());
261 
262  // integrations are kind of a copy
263  for (vector<Integral>::iterator i=integrals.begin(); i<integrals.end(); ++i)
264  {
265  if (i->input().idx()<0)
266  {
267  if (i->operation)
268  minsky().displayErrorItem(*i->operation);
269  throw error("integral not wired");
270  }
271  // enable element-wise integration of tensor variables. for feature 147
272  assert(i->input().size()==i->stock->size());
273  for (size_t j=0; j<i->input().size(); ++j)
274  result[i->stock->idx()+j] = reverseFactor *
275  (i->input().isFlowVar()? flow[i->input().idx()+j] : vars[i->input().idx()+j]);
276  }
277  }
EvalGodley evalGodley
Definition: rungeKutta.h:60
void displayErrorItem(const Item &op) const
indicate operation item has error, if visible, otherwise contining group
Definition: minsky.cc:1229
static std::vector< double, CIVITA_ALLOCATOR< double > > stockVars
vector of variables that are integrated via Runge-Kutta. These variables label the columns of the God...
static double t
Definition: evalOp.h:49
bool reverse
reverse direction of simulation
Definition: rungeKutta.h:59
static std::vector< double, CIVITA_ALLOCATOR< double > > flowVars
variables defined as a simple function of the stock variables, also known as lhs variables. These variables appear in the body of the Godley table
double t
time
Definition: rungeKutta.h:57
void eval(double *sv, const double *fv) const
evaluate Godley tables on sv (of type double[]) and current value of fv (of type double[]), storing result in output variable (of fv). sv is assume to be of size stockVars and fv is assumed to be of size flowVars.
Definition: evalGodley.cc:92
Minsky & minsky()
global minsky object
Definition: addon.cc:545
Here is the call graph for this function:
Here is the caller graph for this function:

◆ evalEquations() [2/2]

void minsky::RungeKutta::evalEquations ( )
inline

Definition at line 70 of file rungeKutta.h.

70  {
71  for (auto& eq: equations)
73  }
static std::vector< double, CIVITA_ALLOCATOR< double > > stockVars
vector of variables that are integrated via Runge-Kutta. These variables label the columns of the God...
static std::vector< double, CIVITA_ALLOCATOR< double > > flowVars
variables defined as a simple function of the stock variables, also known as lhs variables. These variables appear in the body of the Godley table

◆ evalJacobian()

void minsky::RungeKutta::evalJacobian ( Matrix jac,
double  t,
const double  vars[] 
)
protected

Definition at line 216 of file rungeKutta.cc.

217  {
219  const double reverseFactor=reverse? -1: 1;
220  // firstly evaluate the flow variables. Initialise to flowVars so
221  // that no input vars are correctly initialised
222  auto flow=flowVars;
223  for (size_t i=0; i<equations.size(); ++i)
224  equations[i]->eval(flow.data(), flow.size(), sv);
225 
226  // then determine the derivatives with respect to variable j
227  for (size_t j=0; j<stockVars.size(); ++j)
228  {
229  vector<double> ds(stockVars.size()), df(flowVars.size());
230  ds[j]=1;
231  for (size_t i=0; i<equations.size(); ++i)
232  equations[i]->deriv(df.data(), df.size(), ds.data(), sv, flow.data());
233  vector<double> d(stockVars.size());
234  evalGodley.eval(d.data(), df.data());
235  for (vector<Integral>::iterator i=integrals.begin();
236  i!=integrals.end(); ++i)
237  {
238  assert(i->stock->idx()>=0 && i->input().idx()>=0);
239  d[i->stock->idx()] =
240  i->input().isFlowVar()? df[i->input().idx()]: ds[i->input().idx()];
241  }
242  for (size_t i=0; i<stockVars.size(); i++)
243  jac(i,j)=reverseFactor*d[i];
244  }
245 
246  }
EvalGodley evalGodley
Definition: rungeKutta.h:60
static std::vector< double, CIVITA_ALLOCATOR< double > > stockVars
vector of variables that are integrated via Runge-Kutta. These variables label the columns of the God...
static double t
Definition: evalOp.h:49
bool reverse
reverse direction of simulation
Definition: rungeKutta.h:59
static std::vector< double, CIVITA_ALLOCATOR< double > > flowVars
variables defined as a simple function of the stock variables, also known as lhs variables. These variables appear in the body of the Godley table
double t
time
Definition: rungeKutta.h:57
void eval(double *sv, const double *fv) const
evaluate Godley tables on sv (of type double[]) and current value of fv (of type double[]), storing result in output variable (of fv). sv is assume to be of size stockVars and fv is assumed to be of size flowVars.
Definition: evalGodley.cc:92

◆ jacobian()

int minsky::RungeKutta::jacobian ( double  t,
const double  y[],
double *  dfdy,
double  dfdt[],
void *  params 
)
staticprotected

compute jacobian (internal use)

Definition at line 65 of file rungeKutta.cc.

66  {
67  if (params==NULL) return GSL_EBADFUNC;
68  Matrix jac(stockVars.size(), dfdy);
69  try
70  {
71  ((RungeKutta*)params)->evalJacobian(jac,t,y);
72  }
73  catch (std::exception& e)
74  {
75  ((RungeKutta*)params)->threadErrMsg=e.what();
76  return GSL_EBADFUNC;
77  }
78  return GSL_SUCCESS;
79  }
static std::vector< double, CIVITA_ALLOCATOR< double > > stockVars
vector of variables that are integrated via Runge-Kutta. These variables label the columns of the God...
double t
time
Definition: rungeKutta.h:57

◆ resetIfFlagged()

virtual bool minsky::RungeKutta::resetIfFlagged ( )
inlinevirtual

checks whether a reset is required, and resets the simulation if so

Returns
whether simulation was reset

Reimplemented in minsky::Minsky.

Definition at line 65 of file rungeKutta.h.

65 {return false;}

◆ RKfunction()

int minsky::RungeKutta::RKfunction ( double  t,
const double  y[],
double  f[],
void *  params 
)
staticprotected

function to be integrated (internal use)

checks if any GUI events are waiting, and proces an event if so TODO - make this a virtual method of RungeKutta?

Definition at line 50 of file rungeKutta.cc.

References f.

51  {
52  if (params==NULL) return GSL_EBADFUNC;
53  try
54  {
55  ((RungeKutta*)params)->evalEquations(f,t,y);
56  }
57  catch (std::exception& e)
58  {
59  ((RungeKutta*)params)->threadErrMsg=e.what();
60  return GSL_EBADFUNC;
61  }
62  return GSL_SUCCESS;
63  }
function f
Definition: canvas.m:1
double t
time
Definition: rungeKutta.h:57

◆ rkreset()

void minsky::RungeKutta::rkreset ( )

reset the simulation

Definition at line 122 of file rungeKutta.cc.

123  {
124  if (order==1 && !implicit)
125  ode.reset(); // do explicit Euler
126  else
127  ode.reset(new RKdata(this)); // set up GSL ODE routines
128  }
friend struct RKdata
Definition: rungeKutta.h:55

◆ rkstep()

void minsky::RungeKutta::rkstep ( )

step the equations (by n steps, default 1) evaluate the flow equations without stepping.

Exceptions
ecolab::errorif equations are illdefined

Definition at line 130 of file rungeKutta.cc.

References minsky::doOneEvent().

131  {
132  if (nSteps<1) return;
133  running=true; // this ensure reset flag is cleared
134  resetIfFlagged();
135  running=true;
136 
137  // create a private copy for worker thread use
138  auto stockVarsCopy(stockVars);
139  RKThreadRunning=true;
140  int err=GSL_SUCCESS;
141  // run RK algorithm on a separate worker thread so as to not block UI. See ticket #6
142  boost::thread rkThread([&]() {
143  try
144  {
145  double tp=reverse? -t: t;
146  if (ode)
147  {
148  gsl_odeiv2_driver_set_nmax(ode->driver, nSteps);
149  // we need to update Minsky's t synchronously to support the t operator
150  // potentially means t and stockVars out of sync on GUI, but should still be thread safe
151  err=gsl_odeiv2_driver_apply(ode->driver, &tp, numeric_limits<double>::max(),
152  stockVarsCopy.data());
153  }
154  else // do explicit Euler method
155  {
156  vector<double> d(stockVarsCopy.size());
157  for (int i=0; i<nSteps; ++i, tp+=stepMax)
158  {
159  evalEquations(d.data(), tp, stockVarsCopy.data());
160  for (size_t j=0; j<d.size(); ++j)
161  stockVarsCopy[j]+=d[j];
162  }
163  }
164  t=reverse? -tp:tp;
165  }
166  catch (const std::exception& ex)
167  {
168  // catch any thrown exception, and report back to GUI thread
169  threadErrMsg=ex.what();
170  }
171  catch (...)
172  {
173  threadErrMsg="Unknown exception thrown on ODE solver thread";
174  }
175  RKThreadRunning=false;
176  });
177 
178  while (RKThreadRunning)
179  {
180  // while waiting for thread to finish, check and process any UI events
181  usleep(1000);
182  doOneEvent(false);
183  }
184  rkThread.join();
185 
186  if (!threadErrMsg.empty())
187  {
188  auto msg=std::move(threadErrMsg);
189  threadErrMsg.clear(); // to be sure, to be sure
190  // rethrow exception so message gets displayed to user
191  throw runtime_error(msg);
192  }
193 
194  if (resetIfFlagged())
195  return; // in case reset() was called during the step evaluation
196 
197  switch (err)
198  {
199  case GSL_SUCCESS: case GSL_EMAXITER: break;
200  case GSL_FAILURE:
201  throw error("unspecified error GSL_FAILURE returned");
202  case GSL_EBADFUNC:
203  gsl_odeiv2_driver_reset(ode->driver);
204  throw error("Invalid arithmetic operation detected");
205  default:
206  throw error("gsl error: %s",gsl_strerror(err));
207  }
208 
209  stockVars.swap(stockVarsCopy);
210 
211  // update flow variables
212  evalEquations();
213 
214  }
void doOneEvent(bool idleTasksOnly)
checks if any GUI events are waiting, and proces an event if so
Definition: addon.cc:550
static std::vector< double, CIVITA_ALLOCATOR< double > > stockVars
vector of variables that are integrated via Runge-Kutta. These variables label the columns of the God...
bool reverse
reverse direction of simulation
Definition: rungeKutta.h:59
double t
time
Definition: rungeKutta.h:57
virtual bool resetIfFlagged()
checks whether a reset is required, and resets the simulation if so
Definition: rungeKutta.h:65
void evalEquations()
Definition: rungeKutta.h:70
bool running
controls whether simulation is running
Definition: rungeKutta.h:58
Here is the call graph for this function:

Friends And Related Function Documentation

◆ RKdata

friend struct RKdata
friend

Definition at line 55 of file rungeKutta.h.

Member Data Documentation

◆ evalGodley

EvalGodley minsky::RungeKutta::evalGodley

Definition at line 60 of file rungeKutta.h.

◆ reverse

bool minsky::RungeKutta::reverse =false

reverse direction of simulation

Definition at line 59 of file rungeKutta.h.

◆ running

bool minsky::RungeKutta::running =false

controls whether simulation is running

Definition at line 58 of file rungeKutta.h.

◆ t

double minsky::RungeKutta::t {0}

time

Definition at line 57 of file rungeKutta.h.

Referenced by minsky::VariableBase::draw().


The documentation for this class was generated from the following files: