COPASI API  4.16.103
CMathEvent.cpp
Go to the documentation of this file.
1 // Copyright (C) 2011 - 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 #include <limits>
7 
8 #include "copasi.h"
9 
10 #include "CMathEvent.h"
11 #include "CMathContainer.h"
12 #include "CMathExpression.h"
13 
14 #include "model/CMathModel.h"
15 #include "model/CEvent.h"
16 
17 #include "function/CFunction.h"
20 
22  mpTarget(NULL),
23  mpAssignment(NULL)
24 {}
25 
27 {}
28 
30 {
31  // Initialize the assignment object
32  mpAssignment = pointers.pEventAssignmentsObject;
35  false, false, NULL);
36 }
37 
39  CMathContainer & /* container */,
40  const size_t & /* valueOffset */,
41  const size_t & objectOffset)
42 {
43  mpTarget = src.mpTarget + objectOffset;
44  mpAssignment = src.mpAssignment + objectOffset;
45 }
46 
48  CMathContainer & container)
49 {
50  // A compiled pDataAssignment is prerequisite.
51  bool success = true;
52 
53  // Determine the target object
54  mpTarget = container.getMathObject(pDataAssignment->getTargetObject());
55 
56  if (mpTarget != NULL &&
57  mpTarget->getSimulationType() == CMath::Fixed)
58  {
60  }
61 
62  std::vector< CCopasiContainer * > ListOfContainer;
63 
64  // Compile the assignment object in the model context
65  CExpression AssignmentExpression("AssignmentExpression", &container);
66  success &= AssignmentExpression.setInfix(pDataAssignment->getExpression());
67  success &= AssignmentExpression.compile(ListOfContainer);
68  success &= mpAssignment->setExpression(AssignmentExpression, container);
69 
70  return success;
71 }
72 
74 {
75  mpTarget = pTarget;
76 }
77 
79 {
80  mpAssignment = pExpression;
81 }
82 
84  mpRoot(NULL),
85  mpRootState(NULL),
86  mEquality(false),
87  mDiscrete(false)
88 {}
89 
91 {}
92 
94 {
95  // Initialize the root object!
96  mpRoot = pointers.pEventRootsObject;
97  *pointers.pEventRoots = 1.0;
100  false, false, NULL);
101 
102  // Initialize the root state object!
103  mpRootState = pointers.pEventRootStatesObject;
104  *pointers.pEventRootStates = 1.0;
107  false, false, NULL);
108 }
109 
111  CMathContainer & /* container */,
112  const size_t & /* valueOffset */,
113  const size_t & objectOffset)
114 {
115  mpRoot = src.mpRoot + objectOffset;
116  mpRootState = src.mpRootState + objectOffset;
117  mEquality = src.mEquality;
118  mDiscrete = src.mDiscrete;
119 }
120 
122  const bool & equality,
123  CMathContainer & container)
124 {
125  mEquality = equality;
126 
127  std::vector< CCopasiContainer * > ListOfContainer;
128  ListOfContainer.push_back(const_cast< CMathContainer * >(&container));
129 
130  CMathExpression * pExpression = new CMathExpression("RootExpression", container);
131  bool success = static_cast< CEvaluationTree * >(pExpression)->setRoot(pRootNode);
132  success &= mpRoot->setExpressionPtr(pExpression);
133 
134  // Compile the root state object
135  CMathExpression * pStateExpression = new CMathExpression("RootStateExpression", container);
136 
137  CEvaluationNode * pStateExpressionNode = new CEvaluationNodeLogical(CEvaluationNodeLogical::GT, "GT");
138  pStateExpressionNode->addChild(new CEvaluationNodeObject((C_FLOAT64 *) mpRoot->getValuePointer()));
139  pStateExpressionNode->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "0.5"));
140 
141  success &= static_cast< CEvaluationTree * >(pStateExpression)->setRoot(pStateExpressionNode);
142  success &= mpRootState->setExpressionPtr(pStateExpression);
143 
144  return success;
145 }
146 
147 // static
149 {
150  return new CEvaluationNodeObject((C_FLOAT64 *) mpRootState->getValuePointer());
151 }
152 
154  mpTrigger(NULL),
155  mpInitialTrigger(NULL),
156  mRoots(),
157  mDualAction(false)
158 {}
159 
161 {}
162 
163 void CMathEventN::CTrigger::allocate(const CEvent * pDataEvent,
164  const CMathContainer & container)
165 {
166  // Determine the number of roots.
167  CMath::Variables< size_t > Variables;
168 
169  std::vector< CCopasiContainer * > Container;
170  Container.push_back(const_cast< CMathContainer * >(&container));
171 
172  CExpression Trigger("EventTrigger", &container);
173  Trigger.setIsBoolean(true);
174 
175  if (Trigger.setInfix(pDataEvent->getTriggerExpression()))
176  {
177  Trigger.compile(Container);
178  mRoots.resize(countRoots(Trigger.getRoot(), Variables));
179  }
180  else
181  {
182  CFunction TriggerFunction("EventTrigger", &container);
183 
184  if (TriggerFunction.setInfix(pDataEvent->getTriggerExpression()))
185  {
186  TriggerFunction.compile();
187  mRoots.resize(countRoots(TriggerFunction.getRoot(), Variables));
188  }
189  }
190 
191  return;
192 }
193 
195  const CMathContainer & /* container */)
196 {
197  mRoots.resize(nRoots);
198 }
199 
201 {
202  // Initialize trigger object.
203  mpTrigger = pointers.pEventTriggersObject;
204  *pointers.pEventTriggers = 1.0;
207  false, false, NULL);
208 
209  // Initialize initial trigger object.
210  mpInitialTrigger = pointers.pInitialEventTriggersObject;
211  *pointers.pInitialEventTriggers = 1.0;
214  false, true, NULL);
215 
216  // Initialize root object.
217  CRoot * pRoot = mRoots.array();
218  CRoot * pRootEnd = pRoot + mRoots.size();
219 
220  for (; pRoot != pRootEnd; ++pRoot)
221  {
222  pRoot->initialize(pointers);
223  }
224 }
225 
227  CMathContainer & container,
228  const size_t & valueOffset,
229  const size_t & objectOffset)
230 {
231  mpTrigger = src.mpTrigger + objectOffset;
232  mpInitialTrigger = src.mpInitialTrigger + objectOffset;
233 
234  mRoots.resize(src.mRoots.size());
235  CRoot * pRoot = mRoots.array();
236  CRoot * pRootEnd = pRoot + mRoots.size();
237  const CRoot * pRootSrc = src.mRoots.array();
238 
239  for (; pRoot != pRootEnd; ++pRoot, ++pRootSrc)
240  {
241  pRoot->copy(*pRootSrc, container, valueOffset, objectOffset);
242  }
243 
244  mDualAction = src.mDualAction;
245 }
246 
248  CMathContainer & container)
249 {
250  bool success = true;
251 
253 
254  std::vector< CCopasiContainer * > ListOfContainer;
255  ListOfContainer.push_back(&container);
256 
257  CExpression DataTrigger("DataTrigger", &container);
258  DataTrigger.setIsBoolean(true);
259 
260  if (pDataEvent != NULL)
261  {
262  DataTrigger.setInfix(pDataEvent->getTriggerExpression());
263  mDualAction = false;
264  }
265  else
266  {
267  DataTrigger.setInfix(mpTrigger->getExpressionPtr()->getInfix());
268  }
269 
270  success &= DataTrigger.compile();
271 
272  CEvaluationNode * pTriggerRoot = NULL;
273  CRoot * pRoot = mRoots.array();
274 
275  pTriggerRoot = compile(DataTrigger.getRoot(), Variables, pRoot, container);
276 
277  assert(pRoot == mRoots.array() + mRoots.size());
278 
279  CMathExpression * pTrigger = new CMathExpression("EventTrigger", container);
280  success &= static_cast< CEvaluationTree * >(pTrigger)->setRoot(pTriggerRoot);
281 
282  success &= mpTrigger->setExpressionPtr(pTrigger);
283 
284  return success;
285 }
286 
288 {
289  return mRoots;
290 }
291 
292 void CMathEventN::CTrigger::setExpression(const std::string & infix,
293  CMathContainer & container)
294 {
295  assert(mpTrigger != NULL);
296 
297  mpTrigger->setExpression(infix, true, container);
298 
299  compile(NULL, container);
300 
301  std::cout << *mpTrigger;
302  std::cout << *mpInitialTrigger;
303 
304  CRoot * pRoot = mRoots.array();
305  CRoot * pRootEnd = pRoot + mRoots.size();
306 
307  for (; pRoot != pRootEnd; ++pRoot)
308  {
309  std::cout << *pRoot->mpRoot;
310  std::cout << *pRoot->mpRootState;
311  }
312 }
313 
314 // static
316  const CMath::Variables< size_t > & variables)
317 {
318  size_t RootCount = 0;
319 
320  // TODO CRITICAL We only need to count in boolean functions see compile for details.
323 
324  while (itNode.next() != itNode.end())
325  {
326  if (*itNode == NULL)
327  {
328  continue;
329  }
330 
331  switch (itNode.processingMode())
332  {
334 
335  // Variables return always false we need to dig deeper.
337  itNode->isBoolean())
338  {
339  continue;
340  }
341 
342  // We found a non boolean node which does not create a root.
343  itNode.skipChildren();
344  RootCount = 0;
345 
346  break;
347 
349  {
350  // We do not need to check whether the root is boolean as non boolean nodes are
351  // already processed
352  const CEvaluationNode::Type & Type = itNode->getType();
353 
354  switch (CEvaluationNode::type(Type))
355  {
357 
358  switch ((int) CEvaluationNode::subType(Type))
359  {
362  RootCount = countRootsEQ(*itNode, itNode.context());
363  break;
364 
369  RootCount = 1;
370  break;
371 
372  default:
373  RootCount = countRootsDefault(itNode.context());
374  break;
375  }
376 
377  break;
378 
380 
381  switch ((int) CEvaluationNode::subType(Type))
382  {
385  RootCount = countRootsFUNCTION(*itNode, itNode.context());
386  break;
387 
388  default:
389  RootCount = countRootsDefault(itNode.context());
390  break;
391  }
392 
393  break;
394 
396 
397  switch ((int) CEvaluationNode::subType(Type))
398  {
400  RootCount = countRootsVARIABLE(*itNode, variables);
401  break;
402 
403  default:
404  RootCount = countRootsDefault(itNode.context());
405  break;
406  }
407 
408  break;
409 
410  default:
411  RootCount = countRootsDefault(itNode.context());
412  break;
413  }
414  }
415  break;
416 
417  default:
418  break;
419  }
420 
421  if (itNode.parentContextPtr() != NULL)
422  {
423  itNode.parentContextPtr()->push_back(RootCount);
424  }
425  }
426 
427  return RootCount;
428 }
429 
430 // static
431 size_t CMathEventN::CTrigger::countRootsDefault(const std::vector< size_t > & children)
432 {
433  size_t RootCount = 0;
434 
435  std::vector< size_t >::const_iterator it = children.begin();
436  std::vector< size_t >::const_iterator end = children.end();
437 
438  for (; it != end; ++it)
439  {
440  RootCount += *it;
441  }
442 
443  return RootCount;
444 }
445 
446 // static
448  const std::vector< size_t > & children)
449 {
450  size_t nRoots = children[0] + children[1];
451 
452  // Equality can be determined between Boolean and double values.
453  if (static_cast<const CEvaluationNode *>(pNode->getChild())->isBoolean())
454  {
455  nRoots = children[0] + children[1];
456  }
457  else
458  {
459  nRoots = 2;
460  }
461 
462  return nRoots;
463 }
464 
465 // static
467  const std::vector< size_t > & children)
468 {
469  const CEvaluationNode * pTreeRoot =
470  static_cast< const CEvaluationNodeCall * >(pNode)->getCalledTree()->getRoot();
471 
472  size_t nRoots = countRoots(pTreeRoot, children);
473 
474  return nRoots;
475 }
476 
477 // static
479  const CMath::Variables< size_t > & variables)
480 {
481  size_t Index =
482  static_cast< const CEvaluationNodeVariable * >(pNode)->getIndex();
483 
484  if (Index == C_INVALID_INDEX)
485  {
486  return 0;
487  }
488 
489  return variables[Index];
490 }
491 
492 // static
494  const CMath::Variables< CEvaluationNode * > & variables,
496  CMathContainer & container)
497 {
498  CEvaluationNode * pNode = NULL;
499 
502 
503  while (itNode.next() != itNode.end())
504  {
505  if (*itNode == NULL)
506  {
507  continue;
508  }
509 
510  switch (itNode.processingMode())
511  {
513 
514  // Variables return always false we need to dig deeper.
516  {
517  size_t Index =
518  static_cast< const CEvaluationNodeVariable * >(*itNode)->getIndex();
519 
520  if (Index != C_INVALID_INDEX &&
521  Index < variables.size() &&
522  variables[Index]->isBoolean())
523  {
524  continue;
525  }
526 
527  // We found a non boolean node which we simply copy.
528  itNode.skipChildren();
529 
530  // Since a variable may be referred to multiple times we need to copy it.
531  if (Index != C_INVALID_INDEX)
532  {
533  pNode = variables[Index]->copyBranch();
534  }
535  else
536  {
537  // Variables must not appear in mathematical expressions.
538  // We create an constant node with the variable name and value NaN.
540  }
541  }
542  else if (!itNode->isBoolean())
543  {
544  // We found a non boolean node which we simply copy.
545  itNode.skipChildren();
546  pNode = container.copyBranch(*itNode, variables, true);
547  }
548  else
549  {
550  continue;
551  }
552 
553  break;
554 
556 
557  // We do not need to check whether the root is boolean as non boolean nodes are
558  // already processed
559  switch ((int) itNode->getType())
560  {
564  pNode = compileAND(*itNode, itNode.context(), variables, pRoot, container);
565  break;
566 
568  pNode = compileEQ(*itNode, itNode.context(), variables, pRoot, container);
569  break;
570 
572  pNode = compileNE(*itNode, itNode.context(), variables, pRoot, container);
573  break;
574 
579  pNode = compileLE(*itNode, itNode.context(), variables, pRoot, container);
580  break;
581 
583  pNode = compileNOT(*itNode, itNode.context(), variables, pRoot, container);
584  break;
585 
588  pNode = compileFUNCTION(*itNode, itNode.context(), variables, pRoot, container);
589  break;
590 
592  pNode = compileVARIABLE(*itNode, itNode.context(), variables, pRoot, container);
593  break;
594 
597  default:
598  pNode = itNode->copyNode(itNode.context());
599  break;
600  }
601 
602  break;
603 
604  default:
605  // This will never happen
606  break;
607  }
608 
609  if (itNode.parentContextPtr() != NULL)
610  {
611  itNode.parentContextPtr()->push_back(pNode);
612  }
613  }
614 
615  return pNode;
616 }
617 
618 // static
620  const std::vector< CEvaluationNode * > & children,
621  const CMath::Variables< CEvaluationNode * > & /* variables */,
622  CMathEventN::CTrigger::CRoot *& /* pRoot */,
623  CMathContainer & /* container */)
624 {
625  CEvaluationNode * pNode = NULL;
626 
627  switch ((int) CEvaluationNode::subType(pTriggerNode->getType()))
628  {
631  break;
632 
635  break;
636 
639  break;
640 
641  default:
642  break;
643  }
644 
645  if (pNode != NULL)
646  {
647  pNode->addChild(children[0]);
648  pNode->addChild(children[1]);
649  }
650 
651  return pNode;
652 }
653 
654 // static
656  const std::vector< CEvaluationNode * > & children,
657  const CMath::Variables< CEvaluationNode * > & variables,
659  CMathContainer & container)
660 {
661  CEvaluationNode * pNode = NULL;
662 
663  // Equality can be determined between Boolean and double values.
664  if (!static_cast< const CEvaluationNode * >(pTriggerNode->getChild())->isBoolean())
665  {
666  // We treat x EQ y as (x GE y) AND (y GE x)
668 
670  CEvaluationNode * pGELeft = compileLE(&GELeft, children, variables, pRoot, container);
671  pNode->addChild(pGELeft);
672 
673  // We need to duplicate and reverse the order for the right
674  std::vector< CEvaluationNode * > RightChildren;
675  RightChildren.push_back(children[1]->copyBranch());
676  RightChildren.push_back(children[0]->copyBranch());
677 
679  CEvaluationNode * pGERight = compileLE(&GERight, RightChildren, variables, pRoot, container);
680  pNode->addChild(pGERight);
681  }
682  else
683  {
685  pNode->addChild(children[0]);
686  pNode->addChild(children[1]);
687  }
688 
689  return pNode;
690 }
691 
692 // static
694  const std::vector< CEvaluationNode * > & children,
695  const CMath::Variables< CEvaluationNode * > & variables,
697  CMathContainer & container)
698 {
699  CEvaluationNode * pNode = NULL;
700 
701  // We treat this as NOT and EQ.
702  // For this we create a modified copy of the current node.
703 
705 
707 
708  EqNode.addChild(children[0]);
709  EqNode.addChild(children[1]);
710 
711  CEvaluationNode * pEqNode = compileEQ(&EqNode, children, variables, pRoot, container);
712  pNotNode->addChild(pEqNode);
713 
714  // We need to remove the children since the ownership has been transferred to pEqNode.
715  EqNode.removeChild(children[0]);
716  EqNode.removeChild(children[1]);
717 
718  return pNode;
719 }
720 
721 // static
723  const std::vector< CEvaluationNode * > & children,
724  const CMath::Variables< CEvaluationNode * > & /* variables */,
726  CMathContainer & container)
727 {
728  CEvaluationNode * pNode = NULL;
729 
730  // We need to compile the root finding structure
731  // Create a root expression
733 
734  bool Equality = false;
735 
736  // We need to create a copy the left and right data nodes with the variables being replaced.
737  switch ((int) CEvaluationNode::subType(pTriggerNode->getType()))
738  {
740  pRootNode->addChild(children[1]);
741  pRootNode->addChild(children[0]);
742  Equality = true;
743  break;
744 
746  pRootNode->addChild(children[1]);
747  pRootNode->addChild(children[0]);
748  Equality = false;
749  break;
750 
752  pRootNode->addChild(children[0]);
753  pRootNode->addChild(children[1]);
754  Equality = true;
755  break;
756 
758  pRootNode->addChild(children[0]);
759  pRootNode->addChild(children[1]);
760  Equality = false;
761  break;
762  }
763 
764  pRoot->compile(pRootNode, Equality, container);
765  pNode = pRoot->createTriggerExpressionNode();
766  pRoot++;
767 
768  // We do not need to delete pRootNode as CRoot::compile takes car of it.
769 
770  return pNode;
771 }
772 
773 // static
775  const std::vector< CEvaluationNode * > & children,
776  const CMath::Variables< CEvaluationNode * > & /* variables */,
777  CMathEventN::CTrigger::CRoot *& /* pRoot */,
778  CMathContainer & /* container */)
779 {
780  CEvaluationNode * pNode = NULL;
781 
783  pNode->addChild(children[0]);
784 
785  return pNode;
786 }
787 
788 // static
790  const std::vector< CEvaluationNode * > & children,
791  const CMath::Variables< CEvaluationNode * > & /* variables */,
793  CMathContainer & container)
794 {
795  const CEvaluationNode * pCalledNode =
796  static_cast< const CEvaluationNodeCall * >(pTriggerNode)->getCalledTree()->getRoot();
797 
798  CEvaluationNode * pNode = compile(pCalledNode, children, pRoot, container);
799 
800  // We need to delete the children as the variables have been copied in place.
801  std::vector< CEvaluationNode * >::const_iterator it = children.begin();
802  std::vector< CEvaluationNode * >::const_iterator end = children.end();
803 
804  for (; it != end; ++it)
805  {
806  delete *it;
807  }
808 
809  return pNode;
810 }
811 
812 // static
814  const std::vector< CEvaluationNode * > & /* children */,
815  const CMath::Variables< CEvaluationNode * > & variables,
816  CMathEventN::CTrigger::CRoot *& /* pRoot */,
817  CMathContainer & /* container */)
818 {
819  // We need to mimic the process in CMathContainer::copyBranch;
820  size_t Index =
821  static_cast< const CEvaluationNodeVariable * >(pTriggerNode)->getIndex();
822 
823  if (Index != C_INVALID_INDEX &&
824  Index < variables.size())
825  {
826  // Since a variable may be referred to multiple times we need to copy it.
827  return variables[Index]->copyBranch();
828  }
829  else
830  {
831  // Variables must not appear in mathematical expressions.
832  // We create a constant node with the variable name and value NaN.
834  }
835 }
836 
837 // static
839  const CEvent * pDataEvent,
840  const CMathContainer & container)
841 {
842  pEvent->mTrigger.allocate(pDataEvent, container);
843  pEvent->mAssignments.resize(pDataEvent->getAssignments().size());
844 }
845 
847  mType(CEvent::Assignment),
848  mTrigger(),
849  mAssignments(),
850  mpDelay(NULL),
851  mpPriority(NULL),
852  mFireAtInitialTime(false),
853  mPersistentTrigger(false),
854  mDelayAssignment(true)
855 {}
856 
857 /**
858  * Destructor
859  */
861 {}
862 
864 {
865  return mTrigger;
866 }
867 
869 {
870  mTrigger.initialize(pointers);
871 
872  CAssignment * pAssignment = mAssignments.array();
873  CAssignment * pAssignmentEnd = pAssignment + mAssignments.size();
874 
875  // Initialize assignments.
876  for (; pAssignment != pAssignmentEnd; ++pAssignment)
877  {
878  pAssignment->initialize(pointers);
879  }
880 
881  // Initialize delay object.
882  mpDelay = pointers.pEventDelaysObject;
885  false, false, NULL);
886 
887  // Initialize priority object.
888  mpPriority = pointers.pEventDelaysObject;
891  false, false, NULL);
892 }
893 
894 void CMathEventN::copy(const CMathEventN & src, CMathContainer & container, const size_t & valueOffset, const size_t & objectOffset)
895 {
896  mType = src.mType;
897  mTrigger.copy(src.mTrigger, container, valueOffset, objectOffset);
898 
899  mAssignments.resize(src.mAssignments.size());
900  CAssignment * pAssignment = mAssignments.array();
901  CAssignment * pAssignmentEnd = pAssignment + mAssignments.size();
902  const CAssignment * pAssignmentSrc = src.mAssignments.array();
903 
904  for (; pAssignment != pAssignmentEnd; ++pAssignment, ++pAssignmentSrc)
905  {
906  pAssignment->copy(*pAssignmentSrc, container, valueOffset, objectOffset);
907  }
908 
909  mpDelay = src.mpDelay + objectOffset;
910  mpPriority = src.mpPriority + objectOffset;
914 }
915 
916 bool CMathEventN::compile(CEvent * pDataEvent,
917  CMathContainer & container)
918 {
919  bool success = true;
920 
923  mDelayAssignment = pDataEvent->getDelayAssignment();
924 
925  // Compile Trigger
926  success &= mTrigger.compile(pDataEvent, container);
927 
928  CAssignment * pAssignment = mAssignments.array();
929  CAssignment * pAssignmentEnd = pAssignment + mAssignments.size();
931 
932  // Compile assignments.
933  for (; pAssignment != pAssignmentEnd; ++pAssignment, ++itAssignment)
934  {
935  success &= pAssignment->compile(*itAssignment, container);
936  }
937 
938  std::vector< CCopasiContainer * > ListOfContainer;
939  // ListOfContainer.push_back(const_cast< CMathContainer * >(&container));
940 
941  // Compile the delay object.
942  CExpression DelayExpression("DelayExpression", &container);
943  success &= DelayExpression.setInfix(pDataEvent->getDelayExpression());
944  success &= DelayExpression.compile(ListOfContainer);
945  success &= mpDelay->setExpression(DelayExpression, container);
946 
947  // Compile the priority object.
948  CExpression PriorityExpression("PriorityExpression", &container);
949  success &= PriorityExpression.setInfix(pDataEvent->getPriorityExpression());
950  success &= PriorityExpression.compile(ListOfContainer);
951  success &= mpPriority->setExpression(PriorityExpression, container);
952 
953  return success;
954 }
955 
957 {
958  bool success = true;
959 
960  // Compile Trigger
961  success &= mTrigger.compile(NULL, container);
962 
963  // Compile assignments.
964  // Nothing to do since the target and expression objects are already compiled
965 
966  // The delay object is already compiled.
967  // The priority object is already compiled.
968 
969  return success;
970 }
971 
972 void CMathEventN::setTriggerExpression(const std::string & infix, CMathContainer & container)
973 {
974  mTrigger.setExpression(infix, container);
975 }
976 
977 void CMathEventN::setDelayExpression(const std::string & infix, CMathContainer & container)
978 {
979  assert(mpDelay != NULL);
980 
981  mpDelay->setExpression(infix, false, container);
982 }
983 
984 void CMathEventN::setPriorityExpression(const std::string & infix, CMathContainer & container)
985 {
986  assert(mpPriority != NULL);
987 
988  mpPriority->setExpression(infix, false, container);
989 }
990 
991 void CMathEventN::addAssignment(CMathObject * pTarget, CMathObject * pExpression)
992 {
993  size_t OldSize = mAssignments.size();
994  mAssignments.resize(OldSize + 1, true);
995 
996  CAssignment & Assignment = mAssignments[OldSize];
997  Assignment.setTarget(pTarget);
998  Assignment.setExpression(pExpression);
999 }
1000 
1002 {
1003  return mAssignments;
1004 }
1005 
1007  CCopasiContainer("MathEventAssignment", pParent),
1008  mpTarget(NULL),
1009  mExpression("Expression", this)
1010 {}
1011 
1013  const CCopasiContainer * pParent) :
1014  CCopasiContainer(src, pParent),
1015  mpTarget(src.mpTarget),
1016  mExpression(src.mExpression, this)
1017 {}
1018 
1020 {}
1021 
1023  std::vector< CCopasiContainer * > listOfContainer)
1024 {
1025  if (pAssignment == NULL)
1026  return false;
1027 
1028  bool success = true;
1029 
1030  mpTarget = NULL;
1031 
1032  if (pAssignment->getTargetObject() != NULL)
1033  {
1034  mpTarget = (C_FLOAT64 *) pAssignment->getTargetObject()->getValuePointer();
1035  }
1036 
1037  if (mpTarget == NULL)
1038  success = false;
1039 
1040  success &= mExpression.setInfix(pAssignment->getExpression());
1041  success &= mExpression.compile(listOfContainer);
1042 
1043  setDirectDependencies(mExpression.getDirectDependencies());
1044 
1045  return success;
1046 }
1047 
1049  CCopasiContainer("MathEvent", pParent, "MathEvent"),
1050  mTrigger(this),
1051  mOrder(false),
1052  mHaveDelay(false),
1053  mDelay("DelayExpression", this),
1054  mDelayAssignment(true),
1055  mAssignments("ListOfMathEventAssignment", this),
1059  mType(CEvent::Assignment)
1060 {}
1061 
1063  const CCopasiContainer * pParent) :
1064  CCopasiContainer(src, pParent),
1065  mTrigger(src.mTrigger, this),
1066  mOrder(src.mOrder),
1067  mHaveDelay(src.mHaveDelay),
1068  mDelay(src.mDelay, this),
1069  mDelayAssignment(src.mDelayAssignment),
1070  mAssignments(src.mAssignments, this),
1071  mDelayValueRefreshes(src.mDelayValueRefreshes),
1072  mAssignmentValueRefreshes(src.mAssignmentValueRefreshes),
1073  mDependentValueRefreshes(src.mDependentValueRefreshes),
1074  mType(src.mType)
1075 {}
1076 
1078 {}
1079 
1080 bool CMathEvent::compile(const CEvent * pEvent,
1081  std::vector< CCopasiContainer * > listOfContainer)
1082 {
1083  // A CMathEvent must be part of CMathModel to be compiled.
1084  CMathModel * pMathModel = dynamic_cast< CMathModel *>(getObjectAncestor("CMathModel"));
1085 
1086  if (pMathModel == NULL)
1087  return false;
1088 
1089  bool success = true;
1090 
1091  success &= mTrigger.compile(pEvent->getTriggerExpressionPtr(), listOfContainer);
1092 
1093  success &= mDelay.setInfix(pEvent->getDelayExpression());
1094  success &= mDelay.compile(listOfContainer);
1095 
1096  mHaveDelay = (mDelay.getInfix() != "");
1097 
1098  mType = pEvent->getType();
1099 
1100  // Build the list of refresh calls needed to assure that the delay expression
1101  // can be calculated.
1102 
1104 
1106 
1107  mAssignments.clear();
1108 
1111 
1112  std::set< const CCopasiObject * > Assignments;
1113  std::set< const CCopasiObject * > Targets;
1114 
1115  for (; it != end; ++it)
1116  {
1117  CAssignment * pAssignment = new CAssignment();
1118 
1119  mAssignments.add(pAssignment, true);
1120  success &= pAssignment->compile(*it, listOfContainer);
1121 
1122  Assignments.insert(pAssignment);
1123  Targets.insert((*it)->getTargetObject());
1124  }
1125 
1126  // Build the list of refresh calls needed to assure that the assignment expressions
1127  // can be calculated.
1128  mAssignmentValueRefreshes = pMathModel->buildRequiredRefreshList(Assignments);
1129 
1130  // Build the list of refresh calls needed to assure that all dependent model values
1131  // are updated after the assignments are executed.
1132  mDependentValueRefreshes = pMathModel->buildDependendRefreshList(Targets);
1133 
1134  return success;
1135 }
1136 
1137 void CMathEvent::fire(const C_FLOAT64 & time,
1138  const bool & equality,
1139  CProcessQueue & processQueue)
1140 {
1141  if (mDelayAssignment)
1142  {
1143  processQueue.addAssignment(getAssignmentTime(time), equality, getTargetValues(), this);
1144  }
1145  else
1146  {
1147  processQueue.addCalculation(getCalculationTime(time), equality, this);
1148  }
1149 }
1150 
1152 {
1154 
1155  CVector< C_FLOAT64 > Values(mAssignments.size());
1156  C_FLOAT64 * pValue = Values.array();
1159 
1160  for (; itAssignment != endAssignment; ++itAssignment, ++pValue)
1161  {
1162  *pValue = (*itAssignment)->mExpression.calcValue();
1163  }
1164 
1165  return Values;
1166 }
1167 
1169 {
1170  bool StateChanged = false;
1171 
1172  const C_FLOAT64 * pValue = values.array();
1175 
1176  for (; itAssignment != endAssignment; ++itAssignment, ++pValue)
1177  {
1178  if (*(*itAssignment)->mpTarget != *pValue)
1179  {
1180  StateChanged = true;
1181  *(*itAssignment)->mpTarget = *pValue;
1182  }
1183  }
1184 
1185  if (StateChanged)
1186  {
1188  }
1189 
1190  return StateChanged;
1191 }
1192 
1194 {
1195  return setTargetValues(getTargetValues());
1196 }
1197 
1199 {
1200  std::vector< Refresh * >::const_iterator itRefresh = mDelayValueRefreshes.begin();
1201  std::vector< Refresh * >::const_iterator endRefresh = mDelayValueRefreshes.end();
1202 
1203  while (itRefresh != endRefresh)
1204  (**itRefresh++)();
1205 
1206  return;
1207 }
1208 
1210 {
1211  std::vector< Refresh * >::const_iterator itRefresh = mAssignmentValueRefreshes.begin();
1212  std::vector< Refresh * >::const_iterator endRefresh = mAssignmentValueRefreshes.end();
1213 
1214  while (itRefresh != endRefresh)
1215  (**itRefresh++)();
1216 
1217  return;
1218 }
1219 
1221 {
1222  std::vector< Refresh * >::const_iterator itRefresh = mDependentValueRefreshes.begin();
1223  std::vector< Refresh * >::const_iterator endRefresh = mDependentValueRefreshes.end();
1224 
1225  while (itRefresh != endRefresh)
1226  (**itRefresh++)();
1227 
1228  return;
1229 }
1230 
1232 {
1233  return mTrigger;
1234 }
1235 
1236 const size_t & CMathEvent::getOrder() const
1237 {
1238  return mOrder;
1239 }
1240 
1241 const bool & CMathEvent::delayAssignment() const
1242 {
1243  return mDelayAssignment;
1244 }
1245 
1247 {
1248  if (mDelayAssignment)
1249  {
1250  return currentTime;
1251  }
1252 
1253  return calculateDelayedTime(currentTime);
1254 }
1255 
1257 {
1258  if (!mDelayAssignment)
1259  {
1260  return currentTime;
1261  }
1262 
1263  return calculateDelayedTime(currentTime);
1264 }
1265 
1267 {
1268  if (mDelay.getInfix() == "")
1269  {
1270  return currentTime;
1271  }
1272 
1273  // We make sure everything is up to date.
1275 
1276  C_FLOAT64 DelayedTime = currentTime + mDelay.calcValue();
1277 
1278  // Events are only allowed in forward integration. Thus the ExecutionTime
1279  // must not be less than the time.
1280  if (DelayedTime - currentTime < 0.0)
1281  {
1282  // We allow small numerical errors.
1283  C_FLOAT64 Scale =
1284  (fabs(DelayedTime) + fabs(currentTime)) * 50.0 * std::numeric_limits< C_FLOAT64 >::epsilon();
1285 
1286  // Both are approximately zero
1287  if (Scale < 100.0 * std::numeric_limits< C_FLOAT64 >::min())
1288  {
1289  DelayedTime = currentTime;
1290  }
1291  // The difference is small compared to the scale
1292  else if (fabs(DelayedTime - currentTime) < Scale)
1293  {
1294  DelayedTime = currentTime;
1295  }
1296  // The execution time is definitely in the past
1297  else
1298  {
1299  // Create an error message and throw an exception.
1300  CCopasiMessage(CCopasiMessage::EXCEPTION, MCMathModel + 2, DelayedTime, currentTime);
1301  }
1302  }
1303 
1304  return DelayedTime;
1305 }
1306 
1308 {
1309  return mType;
1310 }
Definition: CEvent.h:152
void setExpression(const std::string &infix, CMathContainer &container)
Definition: CMathEvent.cpp:292
static CEvaluationNode * compileVARIABLE(const CEvaluationNode *pNode, const std::vector< CEvaluationNode * > &children, const CMath::Variables< CEvaluationNode * > &variables, CMathEventN::CTrigger::CRoot *&pRoot, CMathContainer &container)
Definition: CMathEvent.cpp:813
CCopasiContainer * getObjectAncestor(const std::string &type) const
const size_t & getOrder() const
bool compile(CEventAssignment *pDataAssignment, CMathContainer &container)
Definition: CMathEvent.cpp:47
CMathObject * pEventRootsObject
Definition: CMathEnum.h:137
static size_t countRoots(const CEvaluationNode *pNode, const CMath::Variables< size_t > &variables)
Definition: CMathEvent.cpp:315
std::vector< Refresh * > mDependentValueRefreshes
Definition: CMathEvent.h:501
void setSimulationType(const CMath::SimulationType &simulationType)
const CCopasiVectorN< CEventAssignment > & getAssignments() const
Definition: CEvent.cpp:678
bool mPersistentTrigger
Definition: CMathEvent.h:275
void setExpression(CMathObject *pExpression)
Definition: CMathEvent.cpp:78
virtual bool setInfix(const std::string &infix)
Definition: CExpression.cpp:63
const bool & getDelayAssignment() const
Definition: CEvent.cpp:419
static size_t countRootsVARIABLE(const CEvaluationNode *pNode, const CMath::Variables< size_t > &variables)
Definition: CMathEvent.cpp:478
CMathObject * mpTarget
Definition: CMathEvent.h:55
bool compile(CEvent *pDataEvent, CMathContainer &container)
Definition: CMathEvent.cpp:916
C_FLOAT64 * pEventRoots
Definition: CMathEnum.h:110
CMathTrigger mTrigger
Definition: CMathEvent.h:457
const CVector< CRoot > & getRoots() const
Definition: CMathEvent.cpp:287
CMathObject * getMathObject(const CObjectInterface *pObject) const
void copy(const CMathEventN &src, CMathContainer &container, const size_t &valueOffset, const size_t &objectOffset)
Definition: CMathEvent.cpp:894
void setTriggerExpression(const std::string &infix, CMathContainer &container)
Definition: CMathEvent.cpp:972
bool compile(const CEvent *pEvent, std::vector< CCopasiContainer * > listOfContainer)
CEvaluationNode * copyNode(CEvaluationNode *child1, CEvaluationNode *child2) const
static CEvaluationNode * compileNE(const CEvaluationNode *pNode, const std::vector< CEvaluationNode * > &children, const CMath::Variables< CEvaluationNode * > &variables, CMathEventN::CTrigger::CRoot *&pRoot, CMathContainer &container)
Definition: CMathEvent.cpp:693
virtual size_t size() const
C_FLOAT64 * pEventDelays
Definition: CMathEnum.h:107
CMathObject * mpAssignment
Definition: CMathEvent.h:56
void applyValueRefreshes()
C_FLOAT64 * pEventRootStates
Definition: CMathEnum.h:111
const bool & delayAssignment() const
bool compile(CEvent *pDataEvent, CMathContainer &container)
Definition: CMathEvent.cpp:247
void setDelayExpression(const std::string &infix, CMathContainer &container)
Definition: CMathEvent.cpp:977
bool setTargetValues(const CVector< C_FLOAT64 > &targetValues)
iterator begin()
bool executeAssignment()
std::vector< Refresh * > buildRequiredRefreshList(const std::set< const CCopasiObject * > &requiredObjects) const
Definition: CMathModel.cpp:452
void initialize(CMath::sPointers &pointers)
Definition: CMathEvent.cpp:200
const Type & getType() const
void fire(const C_FLOAT64 &time, const bool &equality, CProcessQueue &processQueue)
void setDirectDependencies(const DataObjectSet &directDependencies)
static CEvaluationNode * compileAND(const CEvaluationNode *pNode, const std::vector< CEvaluationNode * > &children, const CMath::Variables< CEvaluationNode * > &variables, CMathEventN::CTrigger::CRoot *&pRoot, CMathContainer &container)
Definition: CMathEvent.cpp:619
Type
Definition: CEvent.h:155
std::vector< Refresh * > mDelayValueRefreshes
Definition: CMathEvent.h:489
bool addAssignment(const C_FLOAT64 &executionTime, const bool &equality, const CVector< C_FLOAT64 > &values, CMathEvent *pEvent)
#define C_INVALID_INDEX
Definition: copasi.h:222
std::string getTriggerExpression() const
Definition: CEvent.cpp:524
static CEvaluationNode * compileEQ(const CEvaluationNode *pNode, const std::vector< CEvaluationNode * > &children, const CMath::Variables< CEvaluationNode * > &variables, CMathEventN::CTrigger::CRoot *&pRoot, CMathContainer &container)
Definition: CMathEvent.cpp:655
CMathObject * pEventRootStatesObject
Definition: CMathEnum.h:138
virtual bool compile(std::vector< CCopasiContainer * > listOfContainer=CCopasiContainer::EmptyList)
Definition: CExpression.cpp:97
CEvaluationNode * copyBranch(const CEvaluationNode *pSrc, const bool &replaceDiscontinuousNodes)
std::vector< Refresh * > buildDependendRefreshList(const std::set< const CCopasiObject * > &changedObjects) const
Definition: CMathModel.cpp:461
CVector< CRoot > mRoots
Definition: CMathEvent.h:202
const CNodeIteratorMode::State & next()
bool mFireAtInitialTime
Definition: CMathEvent.h:274
void setIsBoolean(const bool &booleanRequired)
Definition: CExpression.cpp:58
static size_t countRootsFUNCTION(const CEvaluationNode *pNode, const std::vector< size_t > &children)
Definition: CMathEvent.cpp:466
const CEvent::Type & getType() const
void setPriorityExpression(const std::string &infix, CMathContainer &container)
Definition: CMathEvent.cpp:984
virtual bool setInfix(const std::string &infix)
Definition: CFunction.cpp:73
CTrigger mTrigger
Definition: CMathEvent.h:270
void copy(const CTrigger &src, CMathContainer &container, const size_t &valueOffset, const size_t &objectOffset)
Definition: CMathEvent.cpp:226
CMathObject * mpPriority
Definition: CMathEvent.h:273
#define MCMathModel
CExpression mDelay
Definition: CMathEvent.h:473
const Type & getType() const
Definition: CEvent.cpp:699
void addAssignment(CMathObject *pTarget, CMathObject *pExpression)
Definition: CMathEvent.cpp:991
CMathObject * mpInitialTrigger
Definition: CMathEvent.h:201
C_FLOAT64 * pInitialEventTriggers
Definition: CMathEnum.h:96
void setTarget(CMathObject *pTarget)
Definition: CMathEvent.cpp:73
const bool & getPersistentTrigger() const
Definition: CEvent.cpp:439
static Type type(const Type &type)
CMathTrigger & getMathTrigger()
iterator end()
virtual const C_FLOAT64 & calcValue()
bool mHaveDelay
Definition: CMathEvent.h:468
C_FLOAT64 * pEventPriorities
Definition: CMathEnum.h:108
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
void initialize(CMath::sPointers &pointers)
Definition: CMathEvent.cpp:868
void initialize(CMath::sPointers &pointers)
Definition: CMathEvent.cpp:29
CVector< C_FLOAT64 > getTargetValues()
const CNodeIteratorMode::State & skipChildren()
Context * parentContextPtr()
C_FLOAT64 getAssignmentTime(const C_FLOAT64 &currentTime)
C_FLOAT64 * pEventAssignments
Definition: CMathEnum.h:109
bool setExpression(const std::string &infix, const bool &isBoolean, CMathContainer &container)
static CEvaluationNode * compileLE(const CEvaluationNode *pNode, const std::vector< CEvaluationNode * > &children, const CMath::Variables< CEvaluationNode * > &variables, CMathEventN::CTrigger::CRoot *&pRoot, CMathContainer &container)
Definition: CMathEvent.cpp:722
void allocateDiscontinuous(const size_t &nRoots, const CMathContainer &container)
Definition: CMathEvent.cpp:194
CMathObject * mpDelay
Definition: CMathEvent.h:272
bool compile(CEvaluationNode *pRootNode, const bool &equality, CMathContainer &container)
Definition: CMathEvent.cpp:121
CMathObject * pEventTriggersObject
Definition: CMathEnum.h:132
static size_t countRootsDefault(const std::vector< size_t > &children)
Definition: CMathEvent.cpp:431
std::string getDelayExpression() const
Definition: CEvent.cpp:591
static CEvaluationNode * compileFUNCTION(const CEvaluationNode *pNode, const std::vector< CEvaluationNode * > &children, const CMath::Variables< CEvaluationNode * > &variables, CMathEventN::CTrigger::CRoot *&pRoot, CMathContainer &container)
Definition: CMathEvent.cpp:789
size_t mOrder
Definition: CMathEvent.h:463
CMathObject * pInitialEventTriggersObject
Definition: CMathEnum.h:123
const CVector< CAssignment > & getAssignments() const
CAssignment(const CCopasiContainer *pParent=NULL)
bool mDelayAssignment
Definition: CMathEvent.h:478
CMathObject * pEventAssignmentsObject
Definition: CMathEnum.h:136
CVector< CAssignment > mAssignments
Definition: CMathEvent.h:271
virtual const DataObjectSet & getDirectDependencies(const DataObjectSet &context=DataObjectSet()) const
static Type subType(const Type &type)
const CExpression * getTriggerExpressionPtr() const
Definition: CEvent.cpp:534
CEvent::Type mType
Definition: CMathEvent.h:506
CMathObject * mpTrigger
Definition: CMathEvent.h:200
void setProcessingModes(const CNodeIteratorMode::Flag &processingModes)
void allocate(const CEvent *pDataEvent, const CMathContainer &container)
Definition: CMathEvent.cpp:163
C_FLOAT64 getCalculationTime(const C_FLOAT64 &currentTime)
CMathObject * pEventDelaysObject
Definition: CMathEnum.h:134
CEvaluationNode * createTriggerExpressionNode() const
Definition: CMathEvent.cpp:148
bool mDelayAssignment
Definition: CMathEvent.h:276
#define C_FLOAT64
Definition: copasi.h:92
static void initialize(CMathObject *&pObject, C_FLOAT64 *&pValue, const CMath::ValueType &valueType, const CMath::EntityType &entityType, const CMath::SimulationType &simulationType, const bool &isIntensiveProperty, const bool &isInitialValue, const CCopasiObject *pDataObject)
Definition: CMathObject.cpp:23
void applyDelayRefreshes()
virtual bool isBoolean() const
CType * array()
Definition: CVector.h:139
bool compile(const CEventAssignment *pAssignment, std::vector< CCopasiContainer * > listOfContainer)
static size_t countRootsEQ(const CEvaluationNode *pNode, const std::vector< size_t > &children)
Definition: CMathEvent.cpp:447
bool addCalculation(const C_FLOAT64 &executionTime, const bool &equality, CMathEvent *pEvent)
const CNodeIteratorMode::State & processingMode() const
CCopasiVector< CAssignment > mAssignments
Definition: CMathEvent.h:483
std::vector< CType * >::iterator iterator
Definition: CCopasiVector.h:56
std::vector< Refresh * > mAssignmentValueRefreshes
Definition: CMathEvent.h:495
virtual bool compile()
The class for handling a chemical kinetic function.
Definition: CFunction.h:29
static void allocate(CMathEventN *pEvent, const CEvent *pDataEvent, const CMathContainer &container)
Definition: CMathEvent.cpp:838
C_FLOAT64 calculateDelayedTime(const C_FLOAT64 &currentTime)
void copy(const CRoot &src, CMathContainer &container, const size_t &valueOffset, const size_t &objectOffset)
Definition: CMathEvent.cpp:110
CMathEvent(const CCopasiContainer *pParent=NULL)
virtual void * getValuePointer() const
const CTrigger & getTrigger() const
Definition: CMathEvent.cpp:863
virtual bool removeChild(CCopasiNode< Data > *pChild)
Definition: CCopasiNode.h:181
const bool & getFireAtInitialTime() const
Definition: CEvent.cpp:429
Header file of class CEvent.
CMathObject * pEventPrioritiesObject
Definition: CMathEnum.h:135
C_FLOAT64 * pEventTriggers
Definition: CMathEnum.h:105
virtual const Data & getData() const
Definition: CCopasiNode.h:118
CNodeIteratorMode::State end() const
static CEvaluationNode * compileNOT(const CEvaluationNode *pNode, const std::vector< CEvaluationNode * > &children, const CMath::Variables< CEvaluationNode * > &variables, CMathEventN::CTrigger::CRoot *&pRoot, CMathContainer &container)
Definition: CMathEvent.cpp:774
const CCopasiObject * getTargetObject() const
Definition: CEvent.cpp:146
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
CEvent::Type mType
Definition: CMathEvent.h:269
std::string getPriorityExpression() const
Definition: CEvent.cpp:658
void applyDependentRefreshes()
void initialize(CMath::sPointers &pointers)
Definition: CMathEvent.cpp:93
#define min(a, b)
Definition: f2c.h:175
CEvaluationNode * getRoot()
const std::string & getInfix() const
bool compile(const CExpression *pTriggerExpression, std::vector< CCopasiContainer * > listOfContainer)
std::string getExpression() const
Definition: CEvent.cpp:216
void copy(const CAssignment &src, CMathContainer &container, const size_t &valueOffset, const size_t &objectOffset)
Definition: CMathEvent.cpp:38