COPASI API  4.16.103
CMathModel.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010 - 2014 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 // Copyright (C) 2009 by Pedro Mendes, Virginia Tech Intellectual
7 // Properties, Inc., EML Research, gGmbH, University of Heidelberg,
8 // and The University of Manchester.
9 // All rights reserved.
10 
11 #include <cmath>
12 
13 #include "copasi.h"
14 
15 #include "CMathModel.h"
16 #include "CModel.h"
17 
18 #include "lapack/blaswrap.h"
19 #include "lapack/lapackwrap.h"
20 
22  CCopasiContainer("MathModel", pParent, "CMathModel"),
23  mpModel(NULL),
24  mProcessQueue(),
25  mEvents("ListOfMathEvents", this),
26  mRootValues(),
27  mRootDiscrete(),
28  mRootRefreshes(),
29  mRootIndex2Event(),
30  mRootIndex2RootFinder()
31 {}
32 
34  const CCopasiContainer * pParent) :
35  CCopasiContainer(src, pParent),
36  mpModel(src.mpModel),
37  mProcessQueue(src.mProcessQueue),
38  mEvents("ListOfMathEvents", this),
39  mRootValues(),
40  mRootDiscrete(),
41  mRootRefreshes(),
42  mRootIndex2Event(),
43  mRootIndex2RootFinder()
44 {
45  // Compile the math model.
47 
48  // TODO
49  // The problem is that the pointers to events in the process queue point
50  // to events in the source model. We can construct a mapping of source event pointers
51  // to event pointers and update each process queue entry.
52 }
53 
54 // virtual
56 {}
57 
59 {
60  // For each CEvent we need to create a CMathEvent
61  mEvents.clear();
62 
63  // We clear the sequence of root refreshes to avoid accessing invalid pointers.
64  mRootRefreshes.clear();
65 
66  // We clear the map to avoid accessing no longer existing events.
68 
69  // We clear the map to avoid accessing no longer existing root finders.
71 
72  mpModel = pModel;
73 
74  if (mpModel == NULL)
75  return false;
76 
77  // Now we are ready to start the compilations.
78  bool success = true;
79 
80  // The context in which this model is compiled.
81  // TODO When the math model is the only thing required for simulation this should be changed
82  // to this.
83  std::vector< CCopasiContainer * > Context;
84  Context.push_back(mpModel);
85 
88 
89  size_t RootFinderCount = 0;
90 
91  for (; itEvent != endEvent; ++itEvent)
92  {
93  CMathEvent * pEvent = new CMathEvent();
94  mEvents.add(pEvent, true);
95  success &= pEvent->compile(*itEvent, Context);
96 
97  RootFinderCount += pEvent->getMathTrigger().getRootFinders().size();
98  }
99 
100  // We need to create a CVector of pointers to the current root finder values
101  mRootValues.resize(RootFinderCount);
102  C_FLOAT64 ** ppRootValue = mRootValues.array();
103 
104  // We need to create a CVector indicating whether the roots only change
105  // during discrete events.
106  mRootDiscrete.resize(RootFinderCount);
107  bool * pRootDiscrete = mRootDiscrete.array();
108 
109  // We need create a map of root indexes to events.
110  mRootIndex2Event.resize(RootFinderCount);
111  CMathEvent ** ppEvent = mRootIndex2Event.array();
112 
113  // We need create a map of root indexes to root finders.
114  mRootIndex2RootFinder.resize(RootFinderCount);
116 
117  // We need to list all state variables to find out whether the roots
118  // only change during discrete events.
119  std::set< const CCopasiObject * > StateVariables;
120  CModelEntity *const*ppEntity = mpModel->getStateTemplate().getEntities();
121  CModelEntity *const*ppEntityEnd = mpModel->getStateTemplate().endDependent();
122 
123  for (; ppEntity != ppEntityEnd; ++ppEntity)
124  {
125  StateVariables.insert((*ppEntity)->getValueReference());
126  }
127 
128  std::set< const CCopasiObject * > RootValuesDependencies;
129 
132 
133  // for each event
134  for (; itMathEvent != endMathEvent; ++itMathEvent)
135  {
137  (*itMathEvent)->getMathTrigger().getRootFinders().begin();
139  (*itMathEvent)->getMathTrigger().getRootFinders().end();
140 
141  // for each root finder
142  for (; itRootFinder != endRootFinder;
143  ++itRootFinder, ++ppRootValue, ++pRootDiscrete, ++ppEvent, ++ppRootFinder)
144  {
145  // Update the vector of pointers to current root values.
146  *ppRootValue = (*itRootFinder)->getRootValuePtr();
147 
148  // Store whether a root changes only during discrete events.
149  (*itRootFinder)->determineDiscrete(StateVariables);
150  *pRootDiscrete = (*itRootFinder)->isDiscrete();
151 
152  // Build the mapping from root values indexes to CMathEvents
153  *ppEvent = *itMathEvent;
154 
155  // Build the mapping from root values indexes to root finders
156  *ppRootFinder = *itRootFinder;
157 
158  // The root finder needs to be up to date
159  RootValuesDependencies.insert(*itRootFinder);
160  }
161  }
162 
163  // We need to compile a refresh sequence which calculates all root values.
164  mRootRefreshes = buildRequiredRefreshList(RootValuesDependencies);
165 
166  return success;
167 }
168 
170  const bool & ignoreDiscrete)
171 {
172  // Apply all needed refresh calls to calculate the current root values.
173  std::vector< Refresh * >::const_iterator itRefresh = mRootRefreshes.begin();
174  std::vector< Refresh * >::const_iterator endRefresh = mRootRefreshes.end();
175 
176  while (itRefresh != endRefresh)
177  (**itRefresh++)();
178 
179  // Copy the current values to the output vector.
180  assert(rootValues.size() == mRootValues.size());
181 
182  C_FLOAT64 *pTarget = rootValues.array();
183  C_FLOAT64 **pSrc = mRootValues.array();
184  C_FLOAT64 **pSrcEnd = pSrc + mRootValues.size();
185 
186  if (ignoreDiscrete)
187  {
188  bool *pDiscrete = mRootDiscrete.array();
189 
190  for (; pSrc != pSrcEnd; ++pSrc, ++pDiscrete, ++pTarget)
191  {
192  *pTarget = (*pDiscrete) ? 1.0 : **pSrc;
193  }
194  }
195  else
196  {
197  for (; pSrc != pSrcEnd; ++pSrc, ++pTarget)
198  {
199  *pTarget = **pSrc;
200  }
201  }
202 
203  return;
204 }
205 
207 {
208  return mpModel->getInitialTime();
209 }
210 
212  const bool & equality,
213  CProcessQueue::resolveSimultaneousAssignments pResolveSimultaneousAssignments)
214 {
215  return mProcessQueue.process(time, equality, pResolveSimultaneousAssignments);
216 }
217 
219  const bool & equality,
220  const bool & correct,
221  const CVector< C_INT > & foundRoots)
222 {
223  // Apply all needed refresh calls to calculate the current root values.
224  std::vector< Refresh * >::const_iterator itRefresh = mRootRefreshes.begin();
225  std::vector< Refresh * >::const_iterator endRefresh = mRootRefreshes.end();
226 
227  while (itRefresh != endRefresh)
228  (**itRefresh++)();
229 
230  assert(foundRoots.size() == mRootIndex2Event.size());
231 
232  // All events associated with the found roots need to be evaluated whether they fire.
233  // In case one fires the corresponding event needs to be scheduled in the process queue.
234 
235  const C_INT *pFoundRoot = foundRoots.array();
236  const C_INT *pFoundRootEnd = pFoundRoot + foundRoots.size();
237 
238  CMathEvent ** ppEvent = mRootIndex2Event.array();
239  CMathEvent * pProcessEvent = NULL;
240 
242 
243  if (correct)
244  {
245  while (pFoundRoot != pFoundRootEnd)
246  {
247  // We reevaluate the state of the non found roots, which should be save.
248  if (*pFoundRoot < 1 && (*ppRootFinder)->isEquality() == equality)
249  {
250  (*ppRootFinder)->calculateTrueValue();
251  }
252 
253  ++pFoundRoot; ++ppRootFinder;
254  }
255  }
256 
257  pFoundRoot = foundRoots.array();
258  ppRootFinder = mRootIndex2RootFinder.array();
259 
260  // We go through the list of roots and process the events
261  // which need to be checked whether they fire.
262  bool TriggerBefore = true;
263 
264  while (pFoundRoot != pFoundRootEnd)
265  {
266  pProcessEvent = *ppEvent;
267  TriggerBefore = pProcessEvent->getMathTrigger().calculate();
268 
269  // Process the events for which we have found a root.
270  // A found root is indicated by roots[i] = 1 or 0 otherwise.
271  while (pFoundRoot != pFoundRootEnd &&
272  *ppEvent == pProcessEvent)
273  {
274  // We must only toggle the roots which are marked.
275  if (*pFoundRoot > 0)
276  {
277  (*ppRootFinder)->toggle(time, equality, correct);
278  }
279 
280  ++pFoundRoot; ++ppEvent; ++ppRootFinder;
281  }
282 
283  bool TriggerAfter = pProcessEvent->getMathTrigger().calculate();
284 
285  // Check whether the event fires
286  if (TriggerAfter == true &&
287  TriggerBefore == false)
288  {
289  pProcessEvent->fire(time, equality, mProcessQueue);
290  }
291  }
292 
293  return;
294 }
295 
297  const CVector< C_INT > & foundRoots)
298 {
299  // Apply all needed refresh calls to calculate the current root values.
300  std::vector< Refresh * >::const_iterator itRefresh = mRootRefreshes.begin();
301  std::vector< Refresh * >::const_iterator endRefresh = mRootRefreshes.end();
302 
303  while (itRefresh != endRefresh)
304  (**itRefresh++)();
305 
306  assert(foundRoots.size() == mRootIndex2Event.size());
307 
308  // All events associated with the found roots need to be evaluated whether they fire.
309  // In case one fires the corresponding event needs to be scheduled in the process queue.
310 
311  const C_INT *pFoundRoot = foundRoots.array();
312  const C_INT *pFoundRootEnd = pFoundRoot + foundRoots.size();
313 
314  CMathEvent ** ppEvent = mRootIndex2Event.array();
315  CMathEvent * pProcessEvent = NULL;
316 
318 
319  // We go through the list of roots and process the events
320  // which need to be checked whether they fire.
321  bool TriggerBefore = true;
322 
323  while (pFoundRoot != pFoundRootEnd)
324  {
325  pProcessEvent = *ppEvent;
326  TriggerBefore = pProcessEvent->getMathTrigger().calculate();
327 
328  // Process the events for which we have found a root.
329  // A found root is indicated by roots[i] = 1 or 0 otherwise.
330  while (pFoundRoot != pFoundRootEnd &&
331  *ppEvent == pProcessEvent)
332  {
333  // We must only toggle the roots which are marked.
334  if (*pFoundRoot > 0)
335  {
336  (*ppRootFinder)->toggle(time);
337  }
338 
339  ++pFoundRoot; ++ppEvent; ++ppRootFinder;
340  }
341 
342  bool TriggerAfter = pProcessEvent->getMathTrigger().calculate();
343 
344  // Check whether the event fires
345  if (TriggerAfter == true &&
346  TriggerBefore == false)
347  {
348  // We are dealing with discrete root processing and can not distinguish
349  // between equality and inequality. Thus we just pick equality = true
350  pProcessEvent->fire(time, true, mProcessQueue);
351  }
352  }
353 
354  return;
355 }
356 
358 {
360 }
361 
363 {
364  return mProcessQueue;
365 }
366 
368 {
369  return mProcessQueue;
370 }
371 
373 {
374  // Clear the process queue.
376 
377  // Prepare the roots, i.e., evaluate them
378  // Apply all needed refresh calls to calculate the current root values.
379  std::vector< Refresh * >::const_iterator itRefresh = mRootRefreshes.begin();
380  std::vector< Refresh * >::const_iterator endRefresh = mRootRefreshes.end();
381 
382  while (itRefresh != endRefresh)
383  (**itRefresh++)();
384 
385  // Now calculate the current root activities
388 
389  // for each event
390  for (; itMathEvent != endMathEvent; ++itMathEvent)
391  {
392  (*itMathEvent)->getMathTrigger().applyInitialValues();
393  }
394 
395  // We need to schedule events which fire at t > t_0
396 
397  // The roots which are checked for inequality with a current root value
398  // zero are the candidates. We should toggle them if their time derivative
399  // is positive.
400 
401  // The time derivative of the roots can be calculated as:
402  // Dr_i/Dt = sum_j (dr_i/dx_j dx_j/dt) + dr_i/dt
403  // dx_j/dt are the rates of the state variables
404  CVector< C_INT > InitialRoots;
405 
406  if (determineInitialRoots(InitialRoots))
407  {
408  processRoots(mpModel->getInitialTime(), false, false, InitialRoots);
409  }
410 }
411 
413 {
414  return mRootValues.size();
415 }
416 
418 {
419  size_t NumCols =
421 
422  CVector< C_FLOAT64 > Rates(NumCols);
423  C_FLOAT64 * pRate = Rates.array();
424  *pRate = 1.0; // for time
425 
427  mpModel->calculateDerivatives(pRate + 1);
428 
429  CMatrix< C_FLOAT64 > Jacobian;
430  calculateRootJacobian(Jacobian, Rates);
431 
432  rootDerivatives.resize(mRootValues.size());
433  C_FLOAT64 * pDerivative = rootDerivatives.array();
434 
435  // Now calculate derivatives of all metabolites determined by reactions
436  char T = 'N';
437  C_INT M = 1;
438  C_INT N = (C_INT) mRootValues.size();
439  C_INT K = (C_INT) NumCols;
440  C_FLOAT64 Alpha = 1.0;
441  C_FLOAT64 Beta = 0.0;
442 
443  dgemm_(&T, &T, &M, &N, &K, &Alpha, Rates.array(), &M,
444  Jacobian.array(), &K, &Beta, pDerivative, &M);
445 }
446 
448 {
449  return mRootIndex2RootFinder;
450 }
451 
452 std::vector< Refresh * > CMathModel::buildRequiredRefreshList(const std::set< const CCopasiObject * > & requiredObjects) const
453 {
454  // We assume that all values determined by ODEs and reactions are current.
455  // This means for reduced models moieties must have been applied.
456  std::set< const CCopasiObject * > UpToDate;
457 
458  return CCopasiObject::buildUpdateSequence(requiredObjects, UpToDate);
459 }
460 
461 std::vector< Refresh * > CMathModel::buildDependendRefreshList(const std::set< const CCopasiObject * > & changedObjects) const
462 {
463  if (mpModel == NULL)
464  return std::vector< Refresh * >();
465 
466  // We cannot use the default dependencies for a species which concentration was changed
467  // by an event as the concentration is the dependent value. This must not be done for
468  // species which where not changed by the event, i.e., the solution must be context specific.
469  // This implies that the methods getDirectDependencies and its callers must be aware of the species
470  // concentrations in the list of the changed objects.
471 
472  // CCopasiObject::mDependencies is private this means the only place where can be accessed is
473  // CCopasiObject itself. We need to replace all read access the mDirectDependencies with
474  // getDirectDependencies in CCopasiObject and than make this method context sensitive. This new
475  // method will be virtual and must be overloaded for the concentration and particle number in species.
476 
477  // We build a list of all simulated objects which depend on the changed values.
478  std::set< const CCopasiObject * > RequiredObjects;
479 
480  // The values which need to be updated are all values needed for simulation.
481  // These are all objects which are required to calculate the reaction rates and
482  // the right hand side of ODEs in other words all rates of entities of type reaction
483  // or ODE.
484 
485  // Due to the context sensitivity, i.e., the changed concentration is no longer dependent
486  // on the particle number and compartment volume, we will miss all particle numbers of changed
487  // species which do not directly appear in any calculation.
488 
489  CModelEntity *const* ppEntity = mpModel->getStateTemplate().getEntities();
490  CModelEntity *const* ppEndEntity = ppEntity + mpModel->getStateTemplate().size();
491 
492  const CMetab * pSpecies;
493 
494  for (; ppEntity != ppEndEntity; ++ppEntity)
495  {
496  switch ((*ppEntity)->getStatus())
497  {
498  // First rates of all entities depending on ODEs and species depending on reactions.
499  case CModelEntity::ODE:
501 
502  if ((*ppEntity)->getRateReference()->dependsOn(changedObjects, changedObjects))
503  {
504  RequiredObjects.insert((*ppEntity)->getRateReference());
505  }
506 
507  // The break statement is intentionally missing since we need to check
508  // the particle values of species for the above and for fixed.
509  case CModelEntity::FIXED:
510  pSpecies = dynamic_cast< const CMetab * >(*ppEntity);
511 
512  if (pSpecies != NULL &&
513  pSpecies->getValueReference()->dependsOn(changedObjects, changedObjects))
514  {
515  RequiredObjects.insert(pSpecies->getValueReference());
516  }
517 
518  break;
519 
521  // Assignments may have to be recalculated but only if an ODE or a
522  // reaction flux depends on it.
523  break;
524 
525  case CModelEntity::TIME:
526  // The model time will not advance during an event. For discrete time
527  // simulation the users should add a global quantity representing the time.
528  break;
529  }
530  }
531 
532  // Since we have discontinuous change we have to evaluate the total amount of the moieties
533  // which participant changed concentration.
534 
537 
538  for (; itMoiety != endMoiety; ++itMoiety)
539  {
540  if ((*itMoiety)->getValueReference()->dependsOn(changedObjects, changedObjects))
541  {
542  RequiredObjects.insert((*itMoiety)->getValueReference());
543  }
544  }
545 
546  std::set< const CCopasiObject * > UpToDate;
547  return CCopasiObject::buildUpdateSequence(RequiredObjects, UpToDate, changedObjects);
548 }
549 
551 {
552  bool Found = false;
553 
554  CVector< C_FLOAT64 > RootDerivatives;
555  calculateRootDerivatives(RootDerivatives);
556 
557  foundRoots.resize(mRootValues.size());
558  C_INT * pFoundRoot = foundRoots.array();
559  C_FLOAT64 ** pRootValue = mRootValues.array();
560  C_FLOAT64 * pDerivative = RootDerivatives.array();
562  CMathTrigger::CRootFinder ** ppEndRootFinder = ppRootFinder + mRootIndex2RootFinder.size();
563 
564  for (; ppRootFinder != ppEndRootFinder;
565  ++ppRootFinder, ++pRootValue, ++pDerivative, ++pFoundRoot)
566  {
567  if (**pRootValue == 0.0)
568  {
569  if (!(*ppRootFinder)->isEquality() &&
570  *pDerivative > 0.0)
571  {
572  *pFoundRoot = 1;
573  Found = true;
574 
575  continue;
576  }
577 
578  if ((*ppRootFinder)->isEquality() &&
579  *pDerivative < 0.0)
580  {
581  (*ppRootFinder)->toggle(std::numeric_limits< C_FLOAT64 >::quiet_NaN(), true, false);
582  }
583  }
584 
585  *pFoundRoot = 0;
586  }
587 
588  return Found;
589 }
590 
592  const CVector< C_FLOAT64 > & rates)
593 {
594  CState State = mpModel->getState();
595 
596  size_t NumRows = mRootValues.size();
597 
598  // Partial derivatives with respect to time and all variables determined by ODEs and reactions.
599  size_t NumCols =
601 
602  size_t Col = 0;
603 
604  jacobian.resize(NumRows, NumCols);
605 
606  C_FLOAT64 X1 = 0.0;
607  C_FLOAT64 X2 = 0.0;
608  C_FLOAT64 InvDelta = 0.0;
609 
610  CVector< C_FLOAT64 > Y1(NumRows);
611  CVector< C_FLOAT64 > Y2(NumRows);
612 
613  C_FLOAT64 * pX = State.beginIndependent() - 1;
614  C_FLOAT64 * pXEnd = pX + NumCols;
615 
616  C_FLOAT64 * pJacobian = jacobian.array();
617  C_FLOAT64 * pJacobianEnd = pJacobian + jacobian.size();
618 
619  const C_FLOAT64 * pRate = rates.array();
620 
621  for (; pX != pXEnd; ++pX, ++Col, ++pRate)
622  {
623  C_FLOAT64 Store = *pX;
624 
625  if (fabs(*pRate) < 1e4 * std::numeric_limits< C_FLOAT64 >::epsilon() * fabs(Store) ||
626  fabs(*pRate) < 1e4 * std::numeric_limits< C_FLOAT64 >::min())
627  {
628  if (fabs(Store) < 100.0 * std::numeric_limits< C_FLOAT64 >::min())
629  {
630  X1 = 0.0;
631 
632  if (Store < 0.0)
634  else
636 
637  InvDelta = X2;
638  }
639  else
640  {
641  X1 = 0.999 * Store;
642  X2 = 1.001 * Store;
643  InvDelta = 500.0 / Store;
644  }
645  }
646  else
647  {
648  X1 = Store - 0.001 * *pRate;
649  X2 = Store + 0.001 * *pRate;
650  InvDelta = 500.0 / *pRate;
651  }
652 
653  *pX = X1;
654  mpModel->setState(State);
655  evaluateRoots(Y1, true);
656 
657  *pX = X2;
658  mpModel->setState(State);
659  evaluateRoots(Y2, true);
660 
661  *pX = Store;
662 
663  pJacobian = jacobian.array() + Col;
664  C_FLOAT64 * pY1 = Y1.array();
665  C_FLOAT64 * pY2 = Y2.array();
666 
667  for (; pJacobian < pJacobianEnd; pJacobian += NumCols, ++pY1, ++pY2)
668  * pJacobian = (*pY2 - *pY1) * InvDelta;
669  }
670 
671  // Undo the changes from evaluateRoots.
672  mpModel->setState(State);
673  evaluateRoots(Y2, true);
674 }
void initialize(CMathModel *pMathModel)
#define C_INT
Definition: copasi.h:115
const C_FLOAT64 & getProcessQueueExecutionTime() const
Definition: CMathModel.cpp:357
CCopasiVectorN< CEvent > & getEvents()
Definition: CModel.cpp:1110
#define K
bool compile(const CEvent *pEvent, std::vector< CCopasiContainer * > listOfContainer)
size_t getNumIndependent() const
Definition: CState.cpp:222
CVector< C_FLOAT64 * > mRootValues
Definition: CMathModel.h:192
const C_FLOAT64 & getProcessQueueExecutionTime() const
void calculateRootJacobian(CMatrix< C_FLOAT64 > &jacobian, const CVector< C_FLOAT64 > &rates)
Definition: CMathModel.cpp:591
iterator begin()
void updateSimulatedValues(const bool &updateMoieties)
Definition: CModel.cpp:1851
std::vector< Refresh * > buildRequiredRefreshList(const std::set< const CCopasiObject * > &requiredObjects) const
Definition: CMathModel.cpp:452
void fire(const C_FLOAT64 &time, const bool &equality, CProcessQueue &processQueue)
void evaluateRoots(CVectorCore< C_FLOAT64 > &rootValues, const bool &ignoreDiscrete)
Definition: CMathModel.cpp:169
Definition: CState.h:305
void resize(size_t size, const bool &copy=false)
Definition: CVector.h:301
void applyInitialValues()
Definition: CMathModel.cpp:372
std::vector< Refresh * > buildDependendRefreshList(const std::set< const CCopasiObject * > &changedObjects) const
Definition: CMathModel.cpp:461
CModelEntity ** endDependent()
Definition: CState.cpp:211
Definition: CMetab.h:178
const C_FLOAT64 & getInitialTime() const
Definition: CMathModel.cpp:206
const size_t & size() const
Definition: CState.cpp:242
CProcessQueue mProcessQueue
Definition: CMathModel.h:182
virtual ~CMathModel()
Definition: CMathModel.cpp:55
const CCopasiVector< CMoiety > & getMoieties() const
Definition: CModel.cpp:1163
CModel * mpModel
Definition: CMathModel.h:177
CMathTrigger & getMathTrigger()
iterator end()
size_t getNumDependentReactionMetabs() const
Definition: CModel.cpp:1133
void setState(const CState &state)
Definition: CModel.cpp:1785
CMathModel(const CCopasiContainer *pParent=NULL)
Definition: CMathModel.cpp:21
virtual bool add(const CType &src)
const C_FLOAT64 & getInitialTime() const
Definition: CModel.cpp:1184
size_t getNumIndependent() const
Definition: CState.cpp:342
int dgemm_(char *transa, char *transb, integer *m, integer *n, integer *k, doublereal *alpha, doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *beta, doublereal *c, integer *ldc)
virtual void resize(size_t rows, size_t cols, const bool &copy=false)
Definition: CMatrix.h:151
bool process(const C_FLOAT64 &time, const bool &priorToOutput, resolveSimultaneousAssignments pResolveSimultaneousAssignments)
bool dependsOn(DataObjectSet candidates, const DataObjectSet &context=DataObjectSet()) const
size_t size() const
Definition: CVector.h:100
std::vector< Refresh * > mRootRefreshes
Definition: CMathModel.h:204
iterator(* resolveSimultaneousAssignments)(const std::multimap< CKey, CAction > &, const C_FLOAT64 &, const bool &, const size_t &)
CVector< bool > mRootDiscrete
Definition: CMathModel.h:198
#define C_FLOAT64
Definition: copasi.h:92
CType * array()
Definition: CVector.h:139
const CStateTemplate & getStateTemplate() const
Definition: CModel.cpp:1172
virtual size_t size() const
Definition: CMatrix.h:132
static std::vector< Refresh * > buildUpdateSequence(const DataObjectSet &objects, const DataObjectSet &uptoDateObjects, const DataObjectSet &context=DataObjectSet())
virtual void clear()
void calculateDerivatives(C_FLOAT64 *derivatives)
Definition: CModel.cpp:1903
Definition: CModel.h:50
CVector< CMathTrigger::CRootFinder * > mRootIndex2RootFinder
Definition: CMathModel.h:214
CCopasiVector< CMathEvent > mEvents
Definition: CMathModel.h:187
const CState & getState() const
Definition: CModel.cpp:1771
void calculateRootDerivatives(CVector< C_FLOAT64 > &rootDerivatives)
Definition: CMathModel.cpp:417
const CProcessQueue & getProcessQueue() const
Definition: CMathModel.cpp:362
CVector< CMathEvent * > mRootIndex2Event
Definition: CMathModel.h:209
size_t getNumRoots() const
Definition: CMathModel.cpp:412
bool determineInitialRoots(CVector< C_INT > &foundRoots)
Definition: CMathModel.cpp:550
const CVector< CMathTrigger::CRootFinder * > & getRootFinders() const
Definition: CMathModel.cpp:447
virtual CType * array()
Definition: CMatrix.h:337
#define min(a, b)
Definition: f2c.h:175
void processRoots(const C_FLOAT64 &time, const bool &equality, const bool &correct, const CVector< C_INT > &roots)
Definition: CMathModel.cpp:218
bool compile(CModel *pModel)
Definition: CMathModel.cpp:58
C_FLOAT64 * beginIndependent()
Definition: CState.cpp:328
CModelEntity ** getEntities()
Definition: CState.cpp:204
CCopasiVector< CRootFinder > & getRootFinders()
bool processQueue(const C_FLOAT64 &time, const bool &equality, CProcessQueue::resolveSimultaneousAssignments pResolveSimultaneousAssignments)
Definition: CMathModel.cpp:211
CCopasiObject * getValueReference() const