MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Stoich.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 ** This program is part of 'MOOSE', the
3 ** Messaging Object Oriented Simulation Environment.
4 ** Copyright (C) 2003-2010 Upinder S. Bhalla. and NCBS
5 ** It is made available under the terms of the
6 ** GNU Lesser General Public License version 2.1
7 ** See the file COPYING.LIB for the full notice.
8 **********************************************************************/
9 
10 #include "header.h"
11 #include "ElementValueFinfo.h"
12 #include "PoolBase.h"
13 #include "ReacBase.h"
14 #include "EnzBase.h"
15 #include "CplxEnzBase.h"
16 #include "FuncTerm.h"
17 #include "RateTerm.h"
18 #include "FuncRateTerm.h"
19 #include "SparseMatrix.h"
20 #include "KinSparseMatrix.h"
21 #include "VoxelPoolsBase.h"
22 #include "../mesh/VoxelJunction.h"
23 #include "XferInfo.h"
24 #include "ZombiePoolInterface.h"
25 #include "../builtins/Variable.h"
26 #include "../builtins/Function.h"
27 #include "ZombieFunction.h"
28 #include "Stoich.h"
29 #include "lookupVolumeFromMesh.h"
30 #include "../scheduling/Clock.h"
31 #include "../shell/Shell.h"
32 #include "../shell/Wildcard.h"
33 
35 {
37  // Field Definitions
40  "path",
41  "Wildcard path for reaction system handled by Stoich",
44  );
45 
46  static ValueFinfo< Stoich, Id > ksolve(
47  "ksolve",
48  "Id of Kinetic reaction solver class that works with this "
49  "Stoich. "
50  " Must be of class Ksolve, or Gsolve (at present) "
51  " Must be assigned before the path is set.",
54  );
55 
56  static ValueFinfo< Stoich, Id > dsolve(
57  "dsolve",
58  "Id of Diffusion solver class that works with this Stoich."
59  " Must be of class Dsolve "
60  " If left unset then the system will be assumed to work in a"
61  " non-diffusive, well-stirred cell. If it is going to be "
62  " used it must be assigned before the path is set.",
65  );
66 
67  static ValueFinfo< Stoich, Id > compartment(
68  "compartment",
69  "Id of chemical compartment class that works with this Stoich."
70  " Must be derived from class ChemCompt."
71  " If left unset then the system will be assumed to work in a"
72  " non-diffusive, well-stirred cell. If it is going to be "
73  " used it must be assigned before the path is set.",
76  );
77 
78  static ValueFinfo< Stoich, bool > allowNegative(
79  "allowNegative",
80  "Flag: allow negative values if true. Default is false."
81  " This is used to protect the chemical system from going unstable"
82  " in cases where the numerical integration gives a negative value."
83  " Typically it is a small negative value but is obviously"
84  " physically impossible. In some cases we want to use the "
85  " solvers to handle general systems of equations (not purely "
86  " chemical ones), so we have this flag to allow it.",
89  );
90 
92  "numVarPools",
93  "Number of time-varying pools to be computed by the "
94  "numerical engine",
96  );
97 
99  "numBufPools",
100  "Number of buffered pools to be computed by the "
101  "numerical engine. Includes pools controlled by functions.",
103  );
104 
106  "numAllPools",
107  "Total number of pools handled by the numerical engine. "
108  "This includes variable ones, buffered ones, and functions. "
109  "It includes local pools as well as cross-solver proxy pools.",
111  );
112 
113  static ReadOnlyValueFinfo< Stoich, unsigned int > numProxyPools(
114  "numProxyPools",
115  "Number of pools here by proxy as substrates of a cross-"
116  "compartment reaction.",
118  );
119 
121  poolIdMap(
122  "poolIdMap",
123  "Map to look up the index of the pool from its Id."
124  "poolIndex = poolIdMap[ Id::value() - poolOffset ] "
125  "where the poolOffset is the smallest Id::value. "
126  "poolOffset is passed back as the last entry of this vector."
127  " Any Ids that are not pools return EMPTY=~0. ",
129  );
130 
132  "numRates",
133  "Total number of rate terms in the reaction system.",
135  );
136 
137  // Stuff here for getting Stoichiometry matrix to manipulate in
138  // Python.
140  matrixEntry(
141  "matrixEntry",
142  "The non-zero matrix entries in the sparse matrix. Their"
143  "column indices are in a separate vector and the row"
144  "information in a third",
146  );
147  // Stuff here for getting Stoichiometry matrix to manipulate in
148  // Python.
150  columnIndex(
151  "columnIndex",
152  "Column Index of each matrix entry",
154  );
155  // Stuff here for getting Stoichiometry matrix to manipulate in
156  // Python.
158  rowStart(
159  "rowStart",
160  "Row start for each block of entries and column indices",
162  );
163 
164  // Proxy pool information
166  proxyPools(
167  "proxyPools",
168  "Return vector of proxy pools for X-compt reactions between "
169  "current stoich, and the argument, which is a StoichId. "
170  "The returned pools belong to the compartment handling the "
171  "Stoich specified in the argument. "
172  "If no pools are found, return an empty vector.",
174  );
175 
176  static ReadOnlyValueFinfo< Stoich, int > status(
177  "status",
178  "Status of Stoich in the model building process. Values are: "
179  "-1: Reaction path not yet assigned.\n "
180  "0: Successfully built stoichiometry matrix.\n "
181  "1: Warning: Missing a reactant in a Reac or Enz.\n "
182  "2: Warning: Missing a substrate in an MMenz.\n "
183  "3: Warning: Missing substrates as well as reactants.\n "
184  "4: Warning: Compartment not defined.\n "
185  "8: Warning: Neither Ksolve nor Dsolve defined.\n "
186  "16: Warning: No objects found on path.\n "
187  "",
189  );
190 
192  // MsgDest Definitions
194  static DestFinfo unzombify( "unzombify",
195  "Restore all zombies to their native state",
197  );
198  static DestFinfo scaleBufsAndRates( "scaleBufsAndRates",
199  "Args: voxel#, volRatio\n"
200  "Handles requests for runtime volume changes in the specified "
201  "voxel#, Used in adaptors changing spine vols.",
204  );
205 
207  // SrcFinfo Definitions
209 
211  // SharedMsg Definitions
213 
214  static Finfo* stoichFinfos[] =
215  {
216  &path, // ElementValue
217  &ksolve, // Value
218  &dsolve, // Value
219  &compartment, // Value
220  &allowNegative, // Value
221  &numVarPools, // ReadOnlyValue
222  &numBufPools, // ReadOnlyValue
223  &numAllPools, // ReadOnlyValue
224  &numProxyPools, // ReadOnlyValue
225  &poolIdMap, // ReadOnlyValue
226  &numRates, // ReadOnlyValue
227  &matrixEntry, // ReadOnlyValue
228  &columnIndex, // ReadOnlyValue
229  &rowStart, // ReadOnlyValue
230  &proxyPools, // ReadOnlyLookupValue
231  &status, // ReadOnlyLookupValue
232  &unzombify, // DestFinfo
233  &scaleBufsAndRates, // DestFinfo
234  };
235 
236  static Dinfo< Stoich > dinfo;
237  static Cinfo stoichCinfo (
238  "Stoich",
240  stoichFinfos,
241  sizeof( stoichFinfos ) / sizeof ( Finfo* ),
242  &dinfo
243  );
244 
245  return &stoichCinfo;
246 }
247 
249 // Class definitions
252 
254 
256  :
257  useOneWay_( false ),
258  allowNegative_( false ),
259  path_( "" ),
260  ksolve_(), // Must be reassigned to build stoich system.
261  dsolve_(), // Must be assigned if diffusion is planned.
262  compartment_(), // Must be assigned if diffusion is planned.
263  kinterface_( 0 ),
264  dinterface_( 0 ),
265  rates_( 0 ), // No RateTerms yet.
266  // uniqueVols_( 1, 1.0 ),
267  numVoxels_( 1 ),
268  status_( -1 )
269 {
270  ;
271 }
272 
274 {
275  unZombifyModel();
276  // Note that we cannot do the unZombify here, because it is too
277  // prone to problems with the ordering of the delete operations
278  // relative to the zombies.
279  for ( vector< RateTerm* >::iterator j = rates_.begin();
280  j != rates_.end(); ++j )
281  delete *j;
282 
283  for ( vector< FuncTerm* >::iterator j = funcs_.begin();
284  j != funcs_.end(); ++j )
285  delete *j;
286 
287  /*
288  * Do NOT delete FuncTerms, they are just pointers stolen from
289  * the non-zombified objects.
290  for ( vector< FuncTerm* >::iterator i = funcs_.begin();
291  i != funcs_.end(); ++i )
292  delete *i;
293  */
294 }
295 
297 // Field Definitions
299 
300 void Stoich::setOneWay( bool v )
301 {
302  useOneWay_ = v;
303 }
304 
305 bool Stoich::getOneWay() const
306 {
307  return useOneWay_;
308 }
309 
311 {
312  allowNegative_ = v;
313 }
314 
316 {
317  return allowNegative_;
318 }
319 
320 void Stoich::setPath( const Eref& e, string v )
321 {
322  if ( path_ != "" && path_ != v )
323  {
324  // unzombify( path_ );
325  cout << "Stoich::setPath: need to clear old path.\n";
326  status_ = -1;
327  return;
328  }
329  if ( ksolve_ == Id() )
330  {
331  cout << "Stoich::setPath: need to first set ksolve.\n";
332  status_ = -1;
333  return;
334  }
335  vector< ObjId > elist;
336  path_ = v;
337  wildcardFind( path_, elist );
338  setElist( e, elist );
339 }
340 
341 void convWildcards( vector< Id >& ret, const vector< ObjId >& elist )
342 {
343  ret.resize( elist.size() );
344  for ( unsigned int i = 0; i < elist.size(); ++i )
345  ret[i] = elist[i].id;
346 }
347 
348 void filterWildcards( vector< Id >& ret, const vector< ObjId >& elist )
349 {
350  ret.clear();
351  ret.reserve( elist.size() );
352  for ( vector< ObjId >::const_iterator
353  i = elist.begin(); i != elist.end(); ++i )
354  {
355  if ( i->element()->cinfo()->isA( "PoolBase" ) ||
356  i->element()->cinfo()->isA( "ReacBase" ) ||
357  i->element()->cinfo()->isA( "EnzBase" ) ||
358  i->element()->cinfo()->isA( "Function" ) )
359  ret.push_back( i->id );
360  }
361 }
362 
363 void Stoich::setElist( const Eref& e, const vector< ObjId >& elist )
364 {
365  if ( compartment_ == Id() )
366  {
367  cout << "Warning: Stoich::setElist/setPath: Compartment not set. Aborting.\n";
368  status_ = 4;
369  return;
370  }
371  if ( !( kinterface_ || dinterface_ ) )
372  {
373  cout << "Warning: Stoich::setElist/setPath: Neither solver has been set. Aborting.\n";
374  status_ = 8;
375  return;
376  }
377  status_ = 0;
378  if ( kinterface_ )
380  if ( dinterface_ )
382  vector< Id > temp;
383  filterWildcards( temp, elist );
384  if( temp.size() == 0 )
385  {
386  cout << "Warning: Stoich::setElist/setPath: No kinetics objects found on path. Aborting.\n";
387  status_ = 16;
388  return;
389  }
390 
391  // allocateObjMap( temp );
392  allocateModel( temp );
393  if ( kinterface_ )
394  {
395  // kinterface_->setNumPools( n );
396  kinterface_->setStoich( e.id() );
397  Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() );
398  shell->doAddMsg( "Single",
399  compartment_, "voxelVolOut", ksolve_, "voxelVol" );
400  }
401  if ( dinterface_ )
402  {
403  // dinterface_->setNumPools( n );
404  dinterface_->setStoich( e.id() );
405  }
406  zombifyModel( e, temp );
407  if ( kinterface_ )
408  {
411  }
412 }
413 
415 
416 string Stoich::getPath( const Eref& e ) const
417 {
418  return path_;
419 }
420 
421 void Stoich::setKsolve( Id ksolve )
422 {
423  ksolve_ = Id();
424  kinterface_ = 0;
425  if ( ! (
426  ksolve.element()->cinfo()->isA( "Ksolve" ) ||
427  ksolve.element()->cinfo()->isA( "Gsolve" )
428  )
429  )
430  {
431  cout << "Error: Stoich::setKsolve: invalid class assigned,"
432  " should be either Ksolve or Gsolve\n";
433  return;
434  }
435  ksolve_ = ksolve;
436  kinterface_ = reinterpret_cast< ZombiePoolInterface* >(
437  ksolve.eref().data() );
438 
439  if ( ksolve.element()->cinfo()->isA( "Gsolve" ) )
440  setOneWay( true );
441  else
442  setOneWay( false );
443 
444 }
445 
447 {
448  return ksolve_;
449 }
450 
451 void Stoich::setDsolve( Id dsolve )
452 {
453  dsolve_ = Id();
454  dinterface_ = 0;
455  if ( ! (
456  dsolve.element()->cinfo()->isA( "Dsolve" )
457  )
458  )
459  {
460  cout << "Error: Stoich::setDsolve: invalid class assigned,"
461  " should be Dsolve\n";
462  return;
463  }
464  dsolve_ = dsolve;
465  dinterface_ = reinterpret_cast< ZombiePoolInterface* >(
466  dsolve.eref().data() );
467 }
468 
470 {
471  return dsolve_;
472 }
473 
474 void Stoich::setCompartment( Id compartment )
475 {
476  if ( ! (
477  compartment.element()->cinfo()->isA( "ChemCompt" )
478  )
479  )
480  {
481  cout << "Error: Stoich::setCompartment: invalid class assigned,"
482  " should be ChemCompt or derived class\n";
483  return;
484  }
485  compartment_ = compartment;
486  vector< double > temp;
487  vector< double > vols =
488  Field< vector < double > >::get( compartment, "voxelVolume" );
489  if ( vols.size() > 0 )
490  {
491  numVoxels_ = vols.size();
492  sort( vols.begin(), vols.end() );
493  double bigVol = vols.back();
494  assert( bigVol > 0.0 );
495  temp.push_back( vols[0] / bigVol );
496  for ( vector< double >::iterator
497  i = vols.begin(); i != vols.end(); ++i )
498  {
499  if ( !doubleEq( temp.back(), *i / bigVol ) )
500  temp.push_back( *i / bigVol );
501  }
502  }
503 }
504 
506 {
507  return compartment_;
508 }
509 
510 unsigned int Stoich::getNumVarPools() const
511 {
512  return varPoolVec_.size();
513 }
514 
515 unsigned int Stoich::getNumBufPools() const
516 {
517  return bufPoolVec_.size();
518 }
519 
520 unsigned int Stoich::getNumAllPools() const
521 {
522  return varPoolVec_.size() + offSolverPoolVec_.size() + bufPoolVec_.size();
523 }
524 
525 unsigned int Stoich::getNumProxyPools() const
526 {
527  return offSolverPoolVec_.size();
528 }
529 
530 vector< unsigned int > Stoich::getPoolIdMap() const
531 {
532  if ( poolLookup_.size() == 0 )
533  return vector< unsigned int >( 1, 0 );
534 
535  unsigned int minId = 1000000;
536  unsigned int maxId = 0;
537  unsigned int maxIndex = 0;
538  map< Id, unsigned int >::const_iterator i;
539  for ( i = poolLookup_.begin(); i != poolLookup_.end(); ++i )
540  {
541  unsigned int j = i->first.value();
542  if ( j < minId ) minId = j;
543  if ( j > maxId ) maxId = j;
544  if ( maxIndex < i->second ) maxIndex = i->second;
545  }
546  vector< unsigned int > ret( maxId - minId + 2, ~0U );
547  for ( i = poolLookup_.begin(); i != poolLookup_.end(); ++i )
548  {
549  unsigned int j = i->first.value() - minId;
550  ret[j] = i->second;
551  }
552  ret[ ret.size() -1 ] = minId;
553 
554  return ret;
555 }
556 
557 Id Stoich::getPoolByIndex( unsigned int index ) const
558 {
559  map< Id, unsigned int >::const_iterator i;
560  for ( i = poolLookup_.begin(); i != poolLookup_.end(); ++i )
561  {
562  if( i->second == index )
563  return i->first;
564  }
565  return Id();
566 }
567 
568 unsigned int Stoich::getNumRates() const
569 {
570  return rates_.size();
571 }
572 
574 unsigned int Stoich::getNumCoreRates() const
575 {
576  return
577  reacVec_.size() * (1 + useOneWay_) +
578  enzVec_.size() * (2 + useOneWay_ ) +
579  mmEnzVec_.size() + incrementFuncVec_.size();
580 }
581 
582 
583 const RateTerm* Stoich::rates( unsigned int i ) const
584 {
585  assert( i < rates_.size() );
586  return rates_[i];
587 }
588 
589 const vector< RateTerm* >& Stoich::getRateTerms() const
590 {
591  return rates_;
592 }
593 
594 unsigned int Stoich::getNumFuncs() const
595 {
596  return funcs_.size();
597 }
598 
599 const FuncTerm* Stoich::funcs( unsigned int i ) const
600 {
601  assert( i < funcs_.size() );
602  assert( funcs_[i]);
603  return funcs_[i];
604 }
605 
606 bool Stoich::isFuncTarget( unsigned int poolIndex ) const
607 {
608  assert( poolIndex < funcTarget_.size() );
609  return ( funcTarget_[poolIndex] != ~0U );
610 }
611 
612 vector< int > Stoich::getMatrixEntry() const
613 {
614  return N_.matrixEntry();
615 }
616 
617 vector< unsigned int > Stoich::getColIndex() const
618 {
619  return N_.colIndex();
620 }
621 
622 vector< unsigned int > Stoich::getRowStart() const
623 {
624  return N_.rowStart();
625 }
626 
627 vector< Id > Stoich::getProxyPools( Id i ) const
628 {
629  static vector< Id > dummy;
630  if ( !i.element()->cinfo()->isA( "Stoich" ) )
631  {
632  cout << "Warning: Stoich::getProxyPools: argument " << i <<
633  " is not a Stoich\n";
634  return dummy;
635  }
636  Id compt = Field< Id >::get( i, "compartment" );
637  map< Id, vector< Id > >::const_iterator j =
638  offSolverPoolMap_.find( compt );
639  if ( j != offSolverPoolMap_.end() )
640  return j->second;
641  return dummy;
642 }
643 
644 int Stoich::getStatus() const
645 {
646  return status_;
647 }
648 
650 // Model setup functions
652 
658 static bool isOffSolverReac( const Element* e, Id myCompt,
659  // vector< Id >& offSolverPools,
660  vector< Id >& poolCompts,
661  map< Id, Id >& poolComptMap )
662 {
663  assert( myCompt != Id() );
664  assert( myCompt.element()->cinfo()->isA( "ChemCompt" ) );
665  bool ret = false;
666  vector< Id > neighbors;
667  e->getNeighbors( neighbors, e->cinfo()->findFinfo( "subOut" ));
668  vector< Id > n2;
669  e->getNeighbors( n2, e->cinfo()->findFinfo( "prdOut" ));
670  neighbors.insert( neighbors.end(), n2.begin(), n2.end() );
671  for ( vector< Id >::const_iterator
672  j = neighbors.begin(); j != neighbors.end(); ++j )
673  {
674  Id otherCompt = getCompt( *j );
675  if ( myCompt != otherCompt )
676  {
677  // offSolverPools.push_back( *j );
678  poolCompts.push_back( otherCompt );
679  poolComptMap[ *j ] = otherCompt; // Avoids duplication of pools
680  ret = true;
681  if ( j->element()->cinfo()->isA( "BufPool" ) )
682  {
683  cout << "Warning: Avoid BufPool: " << j->path() <<
684  "\n as reactant in cross-compartment reactions\n";
685  }
686  }
687  }
688  return ret;
689 }
690 
694 pair< Id, Id > extractCompts( const vector< Id >& compts )
695 {
696  pair< Id, Id > ret;
697  for ( vector< Id >::const_iterator i = compts.begin();
698  i != compts.end(); ++i )
699  {
700  if ( ret.first == Id() )
701  {
702  ret.first = *i;
703  }
704  else if ( ret.first != *i )
705  {
706  if ( ret.second == Id() )
707  ret.second = *i;
708  else
709  {
710  cout << "Error: Stoich::extractCompts: more than 2 compartments\n";
711  assert( 0 );
712  }
713  }
714  }
715  if ( ( ret.second != Id() ) && ret.second < ret.first )
716  {
717  Id temp = ret.first;
718  ret.first = ret.second;
719  ret.second = ret.first;
720  }
721 
722  return ret;
723 }
724 
725 void Stoich::locateOffSolverReacs( Id myCompt, vector< Id >& elist )
726 {
727  offSolverPoolVec_.clear();
728  offSolverReacVec_.clear();
729  offSolverEnzVec_.clear();
730  offSolverMMenzVec_.clear();
731  offSolverReacCompts_.clear();
732  offSolverEnzCompts_.clear();
733  offSolverMMenzCompts_.clear();
734  map< Id, Id > poolComptMap; // < pool, compt >
735 
736  vector< Id > temp;
737  temp.reserve( elist.size() );
738  for ( vector< Id >::const_iterator
739  i = elist.begin(); i != elist.end(); ++i )
740  {
741  const Element* e = i->element();
742  if ( e->cinfo()->isA( "ReacBase" ) || e->cinfo()->isA( "EnzBase" ) )
743  {
744  vector< Id > compts;
745  if ( isOffSolverReac( e, myCompt, compts, poolComptMap ) )
746  {
747  if ( e->cinfo()->isA( "ReacBase" ) )
748  {
749  offSolverReacVec_.push_back( *i );
750  offSolverReacCompts_.push_back( extractCompts(compts));
751  }
752  else if ( e->cinfo()->isA( "CplxEnzBase" ) )
753  {
754  offSolverEnzVec_.push_back( *i );
755  offSolverEnzCompts_.push_back( extractCompts(compts));
756  }
757  else if ( e->cinfo()->isA( "EnzBase" ) )
758  {
759  offSolverMMenzVec_.push_back( *i );
760  offSolverMMenzCompts_.push_back(extractCompts(compts));
761  }
762  }
763  else
764  {
765  temp.push_back( *i );
766  }
767  }
768  else
769  {
770  temp.push_back( *i );
771  }
772  }
773 
774  offSolverPoolMap_.clear();
775  for ( map< Id, Id >::iterator
776  i = poolComptMap.begin(); i != poolComptMap.end(); ++i )
777  {
778  // fill in the map for activeOffSolverPools.
779  offSolverPoolMap_[i->second].push_back( i->first );
780  }
781 
782  // Ensure we don't have repeats, and the pools are ordered by compt
783  offSolverPoolVec_.clear();
784  for ( map< Id, vector< Id > >::iterator
785  i = offSolverPoolMap_.begin(); i != offSolverPoolMap_.end(); ++i )
786  {
787  if ( i->first != myCompt )
788  {
789  offSolverPoolVec_.insert( offSolverPoolVec_.end(),
790  i->second.begin(), i->second.end() );
791  }
792  }
793 
794  elist = temp;
795 }
796 
798 // Model allocation stuff here
800 
801 /*
802 void Stoich::allocateObjMap( const vector< Id >& elist )
803 {
804  vector< Id > temp( elist );
805  temp.insert( temp.end(), offSolverPoolVec_.begin(),
806  offSolverPoolVec_.end() );
807  temp.insert( temp.end(), offSolverReacs_.begin(),
808  offSolverReacs_.end() );
809  if ( temp.size() == 0 )
810  return;
811  objMapStart_ = ~0;
812  unsigned int maxId = 0;
813  for ( vector< Id >::const_iterator
814  i = temp.begin(); i != temp.end(); ++i ) {
815  if ( objMapStart_ > i->value() )
816  objMapStart_ = i->value();
817  if ( maxId < i->value() )
818  maxId = i->value();
819  }
820  objMap_.clear();
821  objMap_.resize( 1 + maxId - objMapStart_, 0 );
822  */
837 /*
838  assert( objMap_.size() >= temp.size() );
839 }
840 */
841 
842 
845 {
846  static const Cinfo* poolCinfo = Cinfo::find( "Pool" );
847  static const Cinfo* bufPoolCinfo = Cinfo::find( "BufPool" );
848  static const Cinfo* reacCinfo = Cinfo::find( "Reac" );
849  static const Cinfo* enzCinfo = Cinfo::find( "Enz" );
850  static const Cinfo* mmEnzCinfo = Cinfo::find( "MMenz" );
851  static const Cinfo* functionCinfo = Cinfo::find( "Function" );
852  static const Finfo* f1 = functionCinfo->findFinfo( "valueOut" );
853  static const SrcFinfo* sf = dynamic_cast< const SrcFinfo* >( f1 );
854  assert( sf );
855 
856  Element* ei = id.element();
857  if ( ei->cinfo() == poolCinfo )
858  {
859  // objMap_[ id.value() - objMapStart_ ] = numVarPools_;
860  varPoolVec_.push_back( id );
861  // ++numVarPools_;
862  }
863  else if ( ei->cinfo() == bufPoolCinfo )
864  {
865  bufPoolVec_.push_back( id );
866  }
867  else if ( ei->cinfo() == mmEnzCinfo )
868  {
869  mmEnzVec_.push_back( ei->id() );
870  // objMap_[ id.value() - objMapStart_ ] = numReac_;
871  // ++numReac_;
872  }
873  else if ( ei->cinfo() == reacCinfo )
874  {
875  reacVec_.push_back( ei->id() );
876  /*
877  if ( useOneWay_ ) {
878  objMap_[ id.value() - objMapStart_ ] = numReac_;
879  numReac_ += 2;
880  } else {
881  objMap_[ id.value() - objMapStart_ ] = numReac_;
882  ++numReac_;
883  }
884  */
885  }
886  else if ( ei->cinfo() == enzCinfo )
887  {
888  enzVec_.push_back( ei->id() );
889  /*
890  if ( useOneWay_ ) {
891  objMap_[ id.value() - objMapStart_ ] = numReac_;
892  numReac_ += 3;
893  } else {
894  objMap_[ id.value() - objMapStart_ ] = numReac_;
895  numReac_ += 2;
896  }
897  */
898  }
899  else if ( ei->cinfo() == functionCinfo )
900  {
901  vector< ObjId > tgt;
902  vector< string > func;
903  ei->getMsgTargetAndFunctions( 0, sf, tgt, func );
904  if ( func.size() > 0 && func[0] == "increment" )
905  {
906  incrementFuncVec_.push_back( ei->id() );
907  // objMap_[ id.value() - objMapStart_ ] = numReac_;
908  // numReac_++;
909  }
910  else if ( func.size() > 0 && func[0] == "setNumKf" )
911  {
912  reacFuncVec_.push_back( ei->id() );
913  }
914  else // Assume it controls the N of a pool.
915  {
916  poolFuncVec_.push_back( ei->id() );
917  // objMap_[ id.value() - objMapStart_ ] = numFunctions_;
918  // ++numFunctions_;
919  }
920  }
921 }
922 
923 // Sorts, unique, erase any extras.
924 void myUnique( vector< Id >& v )
925 {
926  sort( v.begin(), v.end() );
927  vector< Id >::iterator last = unique( v.begin(), v.end() );
928  v.erase( last, v.end() );
929 }
930 
933 {
937  myUnique( reacVec_ );
939  myUnique( enzVec_ );
941  myUnique( mmEnzVec_ );
943 
944  unsigned int totNumPools = varPoolVec_.size() + bufPoolVec_.size() +
945  + offSolverPoolVec_.size();
946 
947  species_.resize( totNumPools, 0 );
948 
949  funcTarget_.clear();
950  // Only the pools controlled by a func (targets) have positive indices.
951  funcTarget_.resize( totNumPools, ~0 );
952 
953  unsigned int totNumRates =
954  ( reacVec_.size() + offSolverReacVec_.size() ) * (1+useOneWay_) +
955  ( enzVec_.size() + offSolverEnzVec_.size() ) * (2 + useOneWay_ ) +
956  mmEnzVec_.size() + offSolverMMenzVec_.size() +
957  incrementFuncVec_.size();
958  rates_.resize( totNumRates, 0 );
959  funcs_.resize( poolFuncVec_.size(), 0 );
960  N_.setSize( totNumPools, totNumRates );
961  if ( kinterface_ )
962  kinterface_->setNumPools( totNumPools );
963  if ( dinterface_ ) // Only set up var pools managed locally.
965 }
966 
968 void Stoich::allocateModel( const vector< Id >& elist )
969 {
970  // numVarPools_ = 0;
971  // numReac_ = 0;
972  // numFunctions_ = 0;
973  // vector< Id > bufPools;
974  varPoolVec_.clear();
975  bufPoolVec_.clear();
976  // offSolverPoolVec is filled up by the locateOffSolverReacs function
977  reacVec_.clear();
978  enzVec_.clear();
979  mmEnzVec_.clear();
980  poolFuncVec_.clear();
981  incrementFuncVec_.clear();
982  reacFuncVec_.clear();
983 
984  for ( vector< Id >::const_iterator i = elist.begin();
985  i != elist.end(); ++i )
986  allocateModelObject( *i );
987  resizeArrays();
988 
989  buildPoolLookup();
991  buildFuncLookup();
992 }
993 
995 // Build the lookup maps for conversion of Ids to internal indices.
998 {
999  // The order of pools is: varPools, offSolverVarPools, bufPools.
1000  poolLookup_.clear();
1001  int poolNum = 0;
1002  vector< Id >::iterator i;
1003  for ( i = varPoolVec_.begin(); i != varPoolVec_.end(); ++i )
1004  poolLookup_[ *i ] = poolNum++;
1005  for ( i = offSolverPoolVec_.begin(); i != offSolverPoolVec_.end(); ++i)
1006  poolLookup_[ *i ] = poolNum++;
1007  for ( i = bufPoolVec_.begin(); i != bufPoolVec_.end(); ++i )
1008  poolLookup_[ *i ] = poolNum++;
1009 }
1010 
1012 {
1013  // The order of pools is: varPools, offSolverVarPools, bufPools.
1014  rateTermLookup_.clear();
1015  int termNum = 0;
1016  vector< Id >::iterator i;
1017  for ( i = reacVec_.begin(); i != reacVec_.end(); ++i )
1018  {
1019  rateTermLookup_[ *i ] = termNum;
1020  termNum += 1 + useOneWay_;
1021  }
1022  for ( i = enzVec_.begin(); i != enzVec_.end(); ++i )
1023  {
1024  rateTermLookup_[ *i ] = termNum;
1025  termNum += 2 + useOneWay_;
1026  }
1027  for ( i = mmEnzVec_.begin(); i != mmEnzVec_.end(); ++i )
1028  {
1029  rateTermLookup_[ *i ] = termNum;
1030  termNum += 1;
1031  }
1032  for ( i=incrementFuncVec_.begin(); i != incrementFuncVec_.end(); ++i )
1033  {
1034  rateTermLookup_[ *i ] = termNum;
1035  termNum += 1;
1036  }
1037  for ( i = offSolverReacVec_.begin(); i != offSolverReacVec_.end(); ++i)
1038  {
1039  rateTermLookup_[ *i ] = termNum;
1040  termNum += 1 + useOneWay_;
1041  }
1042  for ( i = offSolverEnzVec_.begin(); i != offSolverEnzVec_.end(); ++i )
1043  {
1044  rateTermLookup_[ *i ] = termNum;
1045  termNum += 2 + useOneWay_;
1046  }
1047  for ( i=offSolverMMenzVec_.begin(); i != offSolverMMenzVec_.end(); ++i)
1048  {
1049  rateTermLookup_[ *i ] = termNum;
1050  termNum += 1;
1051  }
1052 }
1053 
1055 {
1056  funcLookup_.clear();
1057  int funcNum = 0;
1058  vector< Id >::iterator i;
1059  for ( i = poolFuncVec_.begin(); i != poolFuncVec_.end(); ++i )
1060  funcLookup_[ *i ] = funcNum++;
1061 }
1062 
1064 // Stoich building stuff here for installing model components.
1066 
1067 void Stoich::installAndUnschedFunc( Id func, Id pool, double volScale )
1068 {
1069  static const Cinfo* varCinfo = Cinfo::find( "Variable" );
1070  static const Finfo* funcInputFinfo = varCinfo->findFinfo( "input" );
1071  static const DestFinfo* df = dynamic_cast< const DestFinfo* >( funcInputFinfo );
1072  assert( df );
1073  // Unsched Func
1074  func.element()->setTick( -2 ); // Disable with option to resurrect.
1075 
1076  // Install the FuncTerm
1077  FuncTerm* ft = new FuncTerm();
1078 
1079  Id ei( func.value() + 1 );
1080 
1081  unsigned int numSrc = Field< unsigned int >::get( func, "numVars" );
1082  vector< pair< Id, unsigned int> > srcPools;
1083 #ifndef NDEBUG
1084  unsigned int n =
1085 #endif
1086  ei.element()->getInputsWithTgtIndex( srcPools, df );
1087  assert( numSrc == n );
1088  vector< unsigned int > poolIndex( numSrc, 0 );
1089  for ( unsigned int i = 0; i < numSrc; ++i )
1090  {
1091  unsigned int j = srcPools[i].second;
1092  if ( j >= numSrc )
1093  {
1094  cout << "Warning: Stoich::installAndUnschedFunc: tgt index not allocated, " << j << ", " << numSrc << endl;
1095  continue;
1096  }
1097  poolIndex[j] = convertIdToPoolIndex( srcPools[i].first );
1098  }
1099  ft->setReactantIndex( poolIndex );
1100  string expr = Field< string >::get( func, "expr" );
1101  ft->setExpr( expr );
1102  // Tie the output of the FuncTerm to the pool it controls.
1103  unsigned int targetIndex = convertIdToPoolIndex( pool );
1104  ft->setTarget( targetIndex );
1105  ft->setVolScale( volScale );
1106  unsigned int funcIndex = convertIdToFuncIndex( func );
1107  assert( funcIndex != ~0U );
1108  // funcTarget_ vector tracks which pools are controlled by which func.
1109  funcTarget_[targetIndex] = funcIndex;
1110  funcs_[ funcIndex ] = ft;
1111 }
1112 
1114 {
1115  static const Cinfo* varCinfo = Cinfo::find( "Variable" );
1116  static const Finfo* funcInputFinfo = varCinfo->findFinfo( "input" );
1117  static const DestFinfo* df = dynamic_cast< const DestFinfo* >( funcInputFinfo );
1118  assert( df );
1119  // Unsched Func
1120  func.element()->setTick( -2 ); // Disable with option to resurrect.
1121 
1122  // Note that we set aside this index during allocateModelObject
1123  unsigned int rateIndex = convertIdToReacIndex( func );
1124  unsigned int tempIndex = convertIdToPoolIndex( pool );
1125  assert( rateIndex != ~0U );
1126  assert( tempIndex != ~0U );
1127  // Install the FuncReac
1128  FuncRate* fr = new FuncRate( 1.0, tempIndex );
1129  rates_[rateIndex] = fr;
1130  int stoichEntry = N_.get( tempIndex, rateIndex );
1131  N_.set( tempIndex, rateIndex, stoichEntry + 1 );
1132 
1133  Id ei( func.value() + 1 );
1134 
1135  unsigned int numSrc = Field< unsigned int >::get( func, "numVars" );
1136  vector< pair< Id, unsigned int > > srcPools;
1137 #ifndef NDEBUG
1138  unsigned int n =
1139 #endif
1140  ei.element()->getInputsWithTgtIndex( srcPools, df );
1141  assert( numSrc == n );
1142  vector< unsigned int > poolIndex( numSrc, 0 );
1143  for ( unsigned int i = 0; i < numSrc; ++i )
1144  {
1145  unsigned int j = srcPools[i].second;
1146  if ( j >= numSrc )
1147  {
1148  cout << "Warning: Stoich::installAndUnschedFuncRate: tgt index not allocated, " << j << ", " << numSrc << endl;
1149  continue;
1150  }
1151  poolIndex[j] = convertIdToPoolIndex( srcPools[i].first );
1152  }
1153  fr->setFuncArgIndex( poolIndex );
1154  string expr = Field< string >::get( func, "expr" );
1155  fr->setExpr( expr );
1156 }
1157 
1159 {
1160  static const Cinfo* varCinfo = Cinfo::find( "Variable" );
1161  // static const Finfo* funcSrcFinfo = varCinfo->findFinfo( "input" );
1162  static const Finfo* funcSrcFinfo = varCinfo->findFinfo( "input" );
1163  assert( funcSrcFinfo );
1164  // Unsched Func
1165  func.element()->setTick( -2 ); // Disable with option to resurrect.
1166 
1167  unsigned int rateIndex = convertIdToReacIndex( reac );
1168  assert( rateIndex != ~0U );
1169  // Install the FuncReac
1170  double k = rates_[rateIndex]->getR1();
1171  vector< unsigned int > reactants;
1172  unsigned int numForward = rates_[rateIndex]->getReactants( reactants );
1173  // The reactants vector has both substrates and products.
1174  reactants.resize( numForward );
1175  FuncReac* fr = new FuncReac( k, reactants );
1176  delete rates_[rateIndex];
1177  rates_[rateIndex] = fr;
1178 
1179  Id ei( func.value() + 1 );
1180 
1181  unsigned int numSrc = Field< unsigned int >::get( func, "numVars" );
1182  vector< Id > srcPools;
1183 #ifndef NDEBUG
1184  unsigned int n =
1185 #endif
1186  ei.element()->getNeighbors( srcPools, funcSrcFinfo);
1187  assert( numSrc == n );
1188  vector< unsigned int > poolIndex( numSrc, 0 );
1189  for ( unsigned int i = 0; i < numSrc; ++i )
1190  poolIndex[i] = convertIdToPoolIndex( srcPools[i] );
1191  fr->setFuncArgIndex( poolIndex );
1192  string expr = Field< string >::get( func, "expr" );
1193  fr->setExpr( expr );
1194 }
1195 
1197 {
1198  for ( unsigned int i = 0; i < rates_.size(); ++i )
1199  {
1200  vector< unsigned int > molIndex;
1201  if ( rates_[i]->getReactants( molIndex ) > 1 )
1202  {
1203  if ( molIndex.size() == 2 && molIndex[0] == molIndex[1] )
1204  {
1205  RateTerm* oldRate = rates_[i];
1207  oldRate->getR1(), molIndex[ 0 ]
1208  );
1209  delete oldRate;
1210  }
1211  else if ( molIndex.size() > 2 )
1212  {
1213  RateTerm* oldRate = rates_[ i ];
1214  rates_[i] = new StochNOrder( oldRate->getR1(), molIndex );
1215  delete oldRate;
1216  }
1217  }
1218  }
1219 }
1220 
1222 {
1223  return N_;
1224 }
1225 
1227 // Model zombification functions
1229 
1231 static Id findFuncMsgSrc( Id pa, const string& msg )
1232 {
1233  const Finfo *finfo = pa.element()->cinfo()->findFinfo( msg );
1234  if ( !finfo ) return Id();
1235  vector< Id > ret;
1236  if ( pa.element()->getNeighbors( ret, finfo ) > 0 )
1237  {
1238  if ( ret[0].element()->cinfo()->isA( "Function" ) )
1239  return ret[0];
1240  }
1241  return Id(); // failure
1242 }
1243 
1245 {
1246  static const Cinfo* zfCinfo = Cinfo::find( "ZombieFunction" );
1247  Id funcId = findFuncMsgSrc( pool, "setN" );
1248  if ( funcId != Id() )
1249  {
1250  Element* fe = funcId.element();
1251  installAndUnschedFunc( funcId, pool, 1.0 );
1252  ZombieFunction::zombify( fe, zfCinfo,ksolve_,dsolve_);
1253  }
1254  else
1255  {
1256  funcId = findFuncMsgSrc( pool, "setConc" );
1257  if ( funcId != Id() )
1258  {
1259  // cout << "Warning: Stoich::zombifyModel: Prefer to use setN rather than setConc:" << pool.path() << endl;
1260  Element* fe = funcId.element();
1261  double vol = Field< double >::get( pool, "volume" );
1262  installAndUnschedFunc( funcId, pool, vol * NA );
1263  ZombieFunction::zombify( fe, zfCinfo,ksolve_,dsolve_);
1264  }
1265  }
1266  return funcId;
1267 }
1268 
1269 // e is the stoich Eref, elist is list of all Ids to zombify.
1270 void Stoich::zombifyModel( const Eref& e, const vector< Id >& elist )
1271 {
1272  static const Cinfo* poolCinfo = Cinfo::find( "Pool" );
1273  static const Cinfo* bufPoolCinfo = Cinfo::find( "BufPool" );
1274  static const Cinfo* reacCinfo = Cinfo::find( "Reac" );
1275  static const Cinfo* enzCinfo = Cinfo::find( "Enz" );
1276  static const Cinfo* mmEnzCinfo = Cinfo::find( "MMenz" );
1277  static const Cinfo* zombiePoolCinfo = Cinfo::find( "ZombiePool" );
1278  static const Cinfo* zombieBufPoolCinfo = Cinfo::find( "ZombieBufPool");
1279  static const Cinfo* zombieReacCinfo = Cinfo::find( "ZombieReac");
1280  static const Cinfo* zombieMMenzCinfo = Cinfo::find( "ZombieMMenz");
1281  static const Cinfo* zombieEnzCinfo = Cinfo::find( "ZombieEnz");
1282  static const Cinfo* zfCinfo = Cinfo::find( "ZombieFunction" );
1283  // static const Finfo* funcSrcFinfo = Cinfo::find( "Function")->findFinfo( "valueOut" );
1284  // vector< Id > meshEntries;
1285  vector< Id > temp = elist;
1286 
1287  temp.insert( temp.end(), offSolverReacVec_.begin(), offSolverReacVec_.end() );
1288  temp.insert( temp.end(), offSolverEnzVec_.begin(), offSolverEnzVec_.end() );
1289  temp.insert( temp.end(), offSolverMMenzVec_.begin(), offSolverMMenzVec_.end() );
1290 
1291  for ( vector< Id >::const_iterator i = temp.begin(); i != temp.end(); ++i )
1292  {
1293  Element* ei = i->element();
1294  if ( ei->cinfo() == poolCinfo )
1295  {
1296  // We need to check the increment message before we zombify the
1297  // pool, because ZombiePool doesn't have this message.
1298  Id funcId = findFuncMsgSrc( *i, "increment" );
1299  double concInit =
1300  Field< double >::get( ObjId( ei->id(), 0 ), "concInit" );
1301  // Look for func setting rate of change of pool
1302  // Id funcId = Neutral::child( i->eref(), "func" );
1303  if ( funcId != Id() )
1304  {
1305  // cout << "Found Msg src for increment at " << funcId.path() << endl;
1306  Element* fe = funcId.element();
1307  installAndUnschedFuncRate( funcId, (*i) );
1308  ZombieFunction::zombify( fe, zfCinfo,ksolve_,dsolve_);
1309  }
1310  else
1311  {
1312  funcId = zombifyPoolFuncWithScaling( *i );
1313  }
1314  PoolBase::zombify( ei, zombiePoolCinfo, ksolve_, dsolve_ );
1315  ei->resize( numVoxels_ );
1316  for ( unsigned int j = 0; j < numVoxels_; ++j )
1317  {
1318  ObjId oi( ei->id(), j );
1319  Field< double >::set( oi, "concInit", concInit );
1320  }
1321  }
1322  else if ( ei->cinfo() == bufPoolCinfo )
1323  {
1324  double concInit =
1325  Field< double >::get( ObjId( ei->id(), 0 ), "concInit" );
1326  // Look for func setting conc of pool
1327  // Id funcId = Neutral::child( i->eref(), "func" );
1328  Id funcId = zombifyPoolFuncWithScaling( *i );
1329  if ( funcId == Id() )
1330  {
1331  funcId = findFuncMsgSrc( *i, "increment" );
1332  if ( funcId != Id() )
1333  {
1334  cout << "Warning: Stoich::zombifyModel: Probably you don't want to send increment to a BufPool:" << i->path() << endl;
1335  Element* fe = funcId.element();
1336  installAndUnschedFuncRate( funcId, (*i) );
1337  ZombieFunction::zombify( fe, zfCinfo,ksolve_,dsolve_);
1338  }
1339  }
1340  PoolBase::zombify( ei, zombieBufPoolCinfo, ksolve_, dsolve_ );
1341  ei->resize( numVoxels_ );
1342  for ( unsigned int j = 0; j < numVoxels_; ++j )
1343  {
1344  ObjId oi( ei->id(), j );
1345  Field< double >::set( oi, "concInit", concInit );
1346  }
1347  }
1348  else if ( ei->cinfo() == reacCinfo )
1349  {
1350  ReacBase::zombify( ei, zombieReacCinfo, e.id() );
1351  // Id funcId = Neutral::child( i->eref(), "func" );
1352  Id funcId = findFuncMsgSrc( *i, "setNumKf" );
1353  if ( funcId != Id() )
1354  {
1355  Element* fe = funcId.element();
1356  installAndUnschedFuncReac( funcId, (*i) );
1357  ZombieFunction::zombify( fe, zfCinfo,ksolve_,dsolve_);
1358  /*
1359  } else {
1360  cout << "Warning: Stoich::zombifyModel: Failed to connect Func to Reac :" << i->path() << endl;
1361  return;
1362  */
1363  }
1364  }
1365  else if ( ei->cinfo() == mmEnzCinfo )
1366  {
1367  EnzBase::zombify( ei, zombieMMenzCinfo, e.id() );
1368  }
1369  else if ( ei->cinfo() == enzCinfo )
1370  {
1371  CplxEnzBase::zombify( ei, zombieEnzCinfo, e.id() );
1372  }
1373  }
1374 }
1375 
1377 {
1378  static const Cinfo* poolCinfo = Cinfo::find( "Pool" );
1379  static const Cinfo* bufPoolCinfo = Cinfo::find( "BufPool" );
1380  static const Cinfo* zombiePoolCinfo = Cinfo::find( "ZombiePool" );
1381  static const Cinfo* zombieBufPoolCinfo = Cinfo::find( "ZombieBufPool");
1382  unsigned int i;
1383  for ( i = 0; i < varPoolVec_.size(); ++i )
1384  {
1385  Element* e = varPoolVec_[i].element();
1386  if ( !e || e->isDoomed() )
1387  continue;
1388  if ( e != 0 && e->cinfo() == zombiePoolCinfo )
1389  PoolBase::zombify( e, poolCinfo, Id(), Id() );
1390  }
1391 
1392  for ( i = 0; i < bufPoolVec_.size(); ++i )
1393  {
1394  Element* e = bufPoolVec_[i].element();
1395  if ( !e || e->isDoomed() )
1396  continue;
1397  if ( e != 0 && e->cinfo() == zombieBufPoolCinfo )
1398  PoolBase::zombify( e, bufPoolCinfo, Id(), Id() );
1399  }
1400 }
1401 
1403 {
1404  static const Cinfo* reacCinfo = Cinfo::find( "Reac" );
1405  static const Cinfo* enzCinfo = Cinfo::find( "Enz" );
1406  static const Cinfo* mmEnzCinfo = Cinfo::find( "MMenz" );
1407  static const Cinfo* functionCinfo = Cinfo::find( "Function");
1408  static const Cinfo* zombieReacCinfo = Cinfo::find( "ZombieReac");
1409  static const Cinfo* zombieMMenzCinfo = Cinfo::find( "ZombieMMenz");
1410  static const Cinfo* zombieEnzCinfo = Cinfo::find( "ZombieEnz");
1411  static const Cinfo* zombieFunctionCinfo = Cinfo::find( "ZombieFunction");
1412 
1413  unZombifyPools();
1414 
1415  vector< Id > temp = reacVec_;
1416  temp.insert( temp.end(),
1417  offSolverReacVec_.begin(), offSolverReacVec_.end() );
1418  for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i )
1419  {
1420  Element* e = i->element();
1421  if ( e != 0 && e->cinfo() == zombieReacCinfo )
1422  ReacBase::zombify( e, reacCinfo, Id() );
1423  }
1424 
1425  temp = mmEnzVec_;
1426  temp.insert( temp.end(),
1427  offSolverMMenzVec_.begin(), offSolverMMenzVec_.end() );
1428  for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i )
1429  {
1430  Element* e = i->element();
1431  if ( e != 0 && e->cinfo() == zombieMMenzCinfo )
1432  EnzBase::zombify( e, mmEnzCinfo, Id() );
1433  }
1434 
1435  temp = enzVec_;
1436  temp.insert( temp.end(),
1437  offSolverEnzVec_.begin(), offSolverEnzVec_.end() );
1438  for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i )
1439  {
1440  Element* e = i->element();
1441  if ( e != 0 && e->cinfo() == zombieEnzCinfo )
1442  CplxEnzBase::zombify( e, enzCinfo, Id() );
1443  }
1444 
1445  temp = poolFuncVec_;
1446  temp.insert( temp.end(),
1447  incrementFuncVec_.begin(), incrementFuncVec_.end() );
1448  for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i )
1449  {
1450  Element* e = i->element();
1451  if ( e != 0 && e->cinfo() == zombieFunctionCinfo )
1452  {
1453  ZombieFunction::zombify( e, functionCinfo, Id(), Id() );
1454  //cout << "ZombieFunction unzombify: " << e->getTick() << endl;
1455  }
1456  if ( e != 0 && e->getTick() == -2 )
1457  {
1458  int t = Clock::lookupDefaultTick( e->cinfo()->name() );
1459  e->setTick( t );
1460  }
1461  }
1462 }
1463 
1464 unsigned int Stoich::convertIdToPoolIndex( Id id ) const
1465 {
1466  map< Id, unsigned int >::const_iterator i = poolLookup_.find( id );
1467  if ( i != poolLookup_.end() )
1468  {
1469  return i->second;
1470  }
1471  return ~0U;
1472 }
1473 
1474 unsigned int Stoich::convertIdToReacIndex( Id id ) const
1475 {
1476  map< Id, unsigned int >::const_iterator i = rateTermLookup_.find( id );
1477  if ( i != rateTermLookup_.end() )
1478  {
1479  return i->second;
1480  }
1481  return ~0U;
1482 }
1483 
1484 unsigned int Stoich::convertIdToFuncIndex( Id id ) const
1485 {
1486  map< Id, unsigned int >::const_iterator i = funcLookup_.find( id );
1487  if ( i != funcLookup_.end() )
1488  {
1489  return i->second;
1490  }
1491  return ~0U;
1492 }
1493 
1495  double rate, const vector< Id >& reactants )
1496 {
1497  ZeroOrder* rateTerm = 0;
1498  if ( reactants.size() == 1 )
1499  {
1500  rateTerm = new FirstOrder(
1501  rate, convertIdToPoolIndex( reactants[0] ) );
1502  }
1503  else if ( reactants.size() == 2 )
1504  {
1505  rateTerm = new SecondOrder( rate,
1506  convertIdToPoolIndex( reactants[0] ),
1507  convertIdToPoolIndex( reactants[1] ) );
1508  }
1509  else if ( reactants.size() > 2 )
1510  {
1511  vector< unsigned int > temp;
1512  for ( unsigned int i = 0; i < reactants.size(); ++i )
1513  temp.push_back( convertIdToPoolIndex( reactants[i] ) );
1514  rateTerm = new NOrder( rate, temp );
1515  }
1516  else
1517  {
1518  cout << "Warning: Stoich::makeHalfReaction: no reactants\n";
1519  status_ |= 1;
1520  rateTerm = new ZeroOrder(0.0); // Dummy RateTerm to avoid crash.
1521  }
1522  return rateTerm;
1523 }
1524 
1526  const vector< Id >& subs,
1527  const vector< Id >& prds )
1528 {
1529  static vector< Id > dummy;
1530  unsigned int rateIndex = innerInstallReaction( reacId, subs, prds );
1531  if ( rateIndex < getNumCoreRates() ) // Only handle off-compt reacs
1532  return;
1533  vector< Id > subCompt;
1534  vector< Id > prdCompt;
1535  for ( vector< Id >::const_iterator
1536  i = subs.begin(); i != subs.end(); ++i )
1537  subCompt.push_back( getCompt( *i ).id );
1538  for ( vector< Id >::const_iterator
1539  i = prds.begin(); i != prds.end(); ++i )
1540  prdCompt.push_back( getCompt( *i ).id );
1541 
1542  assert ( rateIndex - getNumCoreRates() == subComptVec_.size() );
1543  assert ( rateIndex - getNumCoreRates() == prdComptVec_.size() );
1544  if ( useOneWay_ )
1545  {
1546  subComptVec_.push_back( subCompt );
1547  subComptVec_.push_back( prdCompt );
1548  prdComptVec_.push_back( dummy );
1549  prdComptVec_.push_back( dummy );
1550  }
1551  else
1552  {
1553  subComptVec_.push_back( subCompt );
1554  prdComptVec_.push_back( prdCompt );
1555  }
1556 }
1557 
1562 unsigned int Stoich::innerInstallReaction( Id reacId,
1563  const vector< Id >& subs,
1564  const vector< Id >& prds )
1565 {
1566  ZeroOrder* forward = makeHalfReaction( 0, subs );
1567  ZeroOrder* reverse = makeHalfReaction( 0, prds );
1568  unsigned int rateIndex = convertIdToReacIndex( reacId );
1569  unsigned int revRateIndex = rateIndex;
1570  if ( useOneWay_ )
1571  {
1572  rates_[ rateIndex ] = forward;
1573  revRateIndex = rateIndex + 1;
1574  rates_[ revRateIndex ] = reverse;
1575  }
1576  else
1577  {
1578  rates_[ rateIndex ] =
1579  new BidirectionalReaction( forward, reverse );
1580  }
1581 
1582  vector< unsigned int > molIndex;
1583  vector< double > reacScaleSubstrates;
1584  vector< double > reacScaleProducts;
1585 
1586  if ( useOneWay_ )
1587  {
1588  unsigned int numReactants = forward->getReactants( molIndex );
1589  for ( unsigned int i = 0; i < numReactants; ++i )
1590  {
1591  int temp = N_.get( molIndex[i], rateIndex );
1592  N_.set( molIndex[i], rateIndex, temp - 1 );
1593  temp = N_.get( molIndex[i], revRateIndex );
1594  N_.set( molIndex[i], revRateIndex, temp + 1 );
1595  }
1596 
1597  numReactants = reverse->getReactants( molIndex );
1598  for ( unsigned int i = 0; i < numReactants; ++i )
1599  {
1600  int temp = N_.get( molIndex[i], rateIndex );
1601  N_.set( molIndex[i], rateIndex, temp + 1 );
1602  temp = N_.get( molIndex[i], revRateIndex );
1603  N_.set( molIndex[i], revRateIndex, temp - 1 );
1604  }
1605  }
1606  else
1607  {
1608  unsigned int numReactants = forward->getReactants( molIndex );
1609  for ( unsigned int i = 0; i < numReactants; ++i )
1610  {
1611  int temp = N_.get( molIndex[i], rateIndex );
1612  N_.set( molIndex[i], rateIndex, temp - 1 );
1613  }
1614 
1615  numReactants = reverse->getReactants( molIndex );
1616  for ( unsigned int i = 0; i < numReactants; ++i )
1617  {
1618  int temp = N_.get( molIndex[i], revRateIndex );
1619  N_.set( molIndex[i], rateIndex, temp + 1 );
1620  }
1621  }
1622  return rateIndex;
1623 }
1624 
1625 void installDummy( RateTerm** entry, Id enzId, const string& s )
1626 {
1627  cout << "Warning: Stoich::installMMenz: No " << s << " for: " <<
1628  enzId.path() << endl;
1629  *entry = new ZeroOrder( 0.0 );
1630 }
1631 
1636 void Stoich::installMMenz( Id enzId, const vector< Id >& enzMols,
1637  const vector< Id >& subs, const vector< Id >& prds )
1638 {
1639  MMEnzymeBase* meb;
1640  unsigned int enzSiteIndex = convertIdToReacIndex( enzId );
1641  RateTerm** entry = &rates_[enzSiteIndex];
1642  if ( enzMols.size() != 1 )
1643  {
1644  installDummy( entry, enzId, "enzmols" );
1645  status_ |= 2;
1646  return;
1647  }
1648 
1649  if ( prds.size() < 1 )
1650  {
1651  installDummy( entry, enzId, "products" );
1652  status_ |= 1;
1653  return;
1654  }
1655  unsigned int enzIndex = convertIdToPoolIndex( enzMols[0] );
1656 
1657  if ( subs.size() == 1 )
1658  {
1659  unsigned int subIndex = convertIdToPoolIndex( subs[0] );
1660  meb = new MMEnzyme1( 1, 1, enzIndex, subIndex );
1661  }
1662  else if ( subs.size() > 1 )
1663  {
1664  vector< unsigned int > v;
1665  for ( unsigned int i = 0; i < subs.size(); ++i )
1666  v.push_back( convertIdToPoolIndex( subs[i] ) );
1667  ZeroOrder* rateTerm = new NOrder( 1.0, v );
1668  meb = new MMEnzyme( 1, 1, enzIndex, rateTerm );
1669  }
1670  else
1671  {
1672  installDummy( entry, enzId, "substrates" );
1673  status_ |= 2;
1674  return;
1675  }
1676  installMMenz( meb, enzSiteIndex, subs, prds );
1677  if ( enzSiteIndex < getNumCoreRates() ) // Only handle off-compt reacs
1678  return;
1679  vector< Id > subCompt;
1680  vector< Id > dummy;
1681  for ( vector< Id >::const_iterator
1682  i = subs.begin(); i != subs.end(); ++i )
1683  subCompt.push_back( getCompt( *i ).id );
1684  subComptVec_.push_back( subCompt );
1685  prdComptVec_.push_back( dummy );
1686  assert ( enzSiteIndex - getNumCoreRates() == subComptVec_.size() );
1687  assert ( enzSiteIndex - getNumCoreRates() == prdComptVec_.size() );
1688 }
1689 
1691 void Stoich::installMMenz( MMEnzymeBase* meb, unsigned int rateIndex,
1692  const vector< Id >& subs, const vector< Id >& prds )
1693 {
1694  rates_[rateIndex] = meb;
1695 
1696  for ( unsigned int i = 0; i < subs.size(); ++i )
1697  {
1698  unsigned int poolIndex = convertIdToPoolIndex( subs[i] );
1699  int temp = N_.get( poolIndex, rateIndex );
1700  N_.set( poolIndex, rateIndex, temp - 1 );
1701  }
1702  for ( unsigned int i = 0; i < prds.size(); ++i )
1703  {
1704  unsigned int poolIndex = convertIdToPoolIndex( prds[i] );
1705  int temp = N_.get( poolIndex, rateIndex );
1706  N_.set( poolIndex, rateIndex, temp + 1 );
1707  }
1708 }
1709 
1710 // Handles dangling enzymes.
1711 void Stoich::installDummyEnzyme( Id enzId, Id enzMolId )
1712 {
1713  ZeroOrder* r1 = new ZeroOrder( 0.0 ); // Dummy
1714  ZeroOrder* r2 = new ZeroOrder( 0.0 ); // Dummy
1715  ZeroOrder* r3 = new ZeroOrder( 0.0 ); // Dummy
1716  vector< Id > dummy;
1717  unsigned int rateIndex = convertIdToReacIndex( enzId );
1718  if ( useOneWay_ )
1719  {
1720  rates_[ rateIndex ] = r1;
1721  rates_[ rateIndex + 1 ] = r2;
1722  rates_[ rateIndex + 2 ] = r3;
1723  }
1724  else
1725  {
1726  rates_[ rateIndex ] = new BidirectionalReaction( r1, r2 );
1727  rates_[ rateIndex + 1 ] = r3;
1728  }
1729  status_ = 1;
1730 }
1731 
1732 void Stoich::installEnzyme( Id enzId, Id enzMolId, Id cplxId,
1733  const vector< Id >& subs, const vector< Id >& prds )
1734 {
1735  vector< Id > temp( subs );
1736  temp.insert( temp.begin(), enzMolId );
1737  ZeroOrder* r1 = makeHalfReaction( 0, temp );
1738  temp.clear();
1739  temp.resize( 1, cplxId );
1740  ZeroOrder* r2 = makeHalfReaction( 0, temp );
1741  ZeroOrder* r3 = makeHalfReaction( 0, temp );
1742 
1743  installEnzyme( r1, r2, r3, enzId, enzMolId, prds );
1744  unsigned int rateIndex = convertIdToReacIndex( enzId );
1745  if ( rateIndex < getNumCoreRates() ) // Only handle off-compt reacs
1746  return;
1747  vector< Id > subCompt;
1748  vector< Id > dummy;
1749  for ( vector< Id >::const_iterator
1750  i = subs.begin(); i != subs.end(); ++i )
1751  subCompt.push_back( getCompt( *i ).id );
1752 
1753  if ( useOneWay_ )
1754  {
1755  // enz is split into 3 reactions. Only the first might be off-compt
1756  subComptVec_.push_back( subCompt );
1757  subComptVec_.push_back( dummy );
1758  subComptVec_.push_back( dummy );
1759  prdComptVec_.push_back( dummy );
1760  prdComptVec_.push_back( dummy );
1761  prdComptVec_.push_back( dummy );
1762  //assert ( 2 + rateIndex - getNumCoreRates() == subComptVec_.size());
1763  //assert ( 2 + rateIndex - getNumCoreRates() == prdComptVec_.size());
1764  }
1765  else
1766  {
1767  // enz is split into 2 reactions. Only the first might be off-compt
1768  subComptVec_.push_back( subCompt );
1769  subComptVec_.push_back( dummy );
1770  prdComptVec_.push_back( dummy );
1771  prdComptVec_.push_back( dummy );
1772  //assert ( 1+rateIndex - getNumCoreRates() == subComptVec_.size() );
1773  // assert ( 1+rateIndex - getNumCoreRates() == prdComptVec_.size() );
1774  }
1775 }
1776 
1778  Id enzId, Id enzMolId, const vector< Id >& prds )
1779 {
1780  unsigned int rateIndex = convertIdToReacIndex( enzId );
1781 
1782  if ( useOneWay_ )
1783  {
1784  rates_[ rateIndex ] = r1;
1785  rates_[ rateIndex + 1 ] = r2;
1786  rates_[ rateIndex + 2 ] = r3;
1787  }
1788  else
1789  {
1790  rates_[ rateIndex ] = new BidirectionalReaction( r1, r2 );
1791  rates_[ rateIndex + 1 ] = r3;
1792  }
1793 
1794  vector< unsigned int > poolIndex;
1795  unsigned int numReactants = r2->getReactants( poolIndex );
1796  assert( numReactants == 1 ); // Should be cplx as the only product
1797  unsigned int cplxPool = poolIndex[0];
1798 
1799  if ( useOneWay_ )
1800  {
1801  numReactants = r1->getReactants( poolIndex ); // Substrates
1802  for ( unsigned int i = 0; i < numReactants; ++i )
1803  {
1804  int temp = N_.get( poolIndex[i], rateIndex ); // terms for r1
1805  N_.set( poolIndex[i], rateIndex, temp - 1 );
1806  temp = N_.get( poolIndex[i], rateIndex + 1 ); //terms for r2
1807  N_.set( poolIndex[i], rateIndex + 1, temp + 1 );
1808  }
1809 
1810  int temp = N_.get( cplxPool, rateIndex ); // term for r1
1811  N_.set( cplxPool, rateIndex, temp + 1 );
1812  temp = N_.get( cplxPool, rateIndex + 1 ); // term for r2
1813  N_.set( cplxPool, rateIndex + 1, temp -1 );
1814  }
1815  else // Regular bidirectional reactions.
1816  {
1817  numReactants = r1->getReactants( poolIndex ); // Substrates
1818  for ( unsigned int i = 0; i < numReactants; ++i )
1819  {
1820  int temp = N_.get( poolIndex[i], rateIndex );
1821  N_.set( poolIndex[i], rateIndex, temp - 1 );
1822  }
1823  int temp = N_.get( cplxPool, rateIndex );
1824  N_.set( cplxPool, rateIndex, temp + 1 );
1825  }
1826 
1827  // Now assign reaction 3. The complex is the only substrate here.
1828  // Reac 3 is already unidirectional, so all we need to do to handle
1829  // one-way reactions is to get the index right.
1830  unsigned int reac3index = ( useOneWay_ ) ? rateIndex + 2 : rateIndex + 1;
1831  int temp = N_.get( cplxPool, reac3index );
1832  N_.set( cplxPool, reac3index, temp - 1 );
1833 
1834  // For the products, we go to the prd list directly.
1835  for ( unsigned int i = 0; i < prds.size(); ++i )
1836  {
1837  unsigned int j = convertIdToPoolIndex( prds[i] );
1838  int temp = N_.get( j, reac3index );
1839  N_.set( j, reac3index, temp + 1 );
1840  }
1841  // Enz is also a product here.
1842  unsigned int enzPool = convertIdToPoolIndex( enzMolId );
1843  temp = N_.get( enzPool, reac3index );
1844  N_.set( enzPool, reac3index, temp + 1 );
1845 }
1846 
1848 // Field interface functions
1850 
1860 void Stoich::setReacKf( const Eref& e, double v ) const
1861 {
1862  unsigned int i = convertIdToReacIndex( e.id() );
1863  if ( i != ~0U )
1864  {
1865  // rates_[ i ]->setR1( v / volScale );
1866  rates_[ i ]->setR1( v );
1868  }
1869 }
1870 
1874 void Stoich::setReacKb( const Eref& e, double v ) const
1875 {
1876  unsigned int i = convertIdToReacIndex( e.id() );
1877  if ( i == ~0U )
1878  return;
1879 
1880  if ( useOneWay_ )
1881  {
1882  rates_[ i + 1 ]->setR1( v );
1883  kinterface_->updateRateTerms( i + 1 );
1884  }
1885  else
1886  {
1887  rates_[ i ]->setR2( v );
1889  }
1890 }
1891 
1892 // This uses Km to set the StoichR1, which is actually in # units.
1893 // It is OK to do for the Stoich because the volume is defined to be
1894 // 1.66e-21, such that conc == #.
1895 void Stoich::setMMenzKm( const Eref& e, double v ) const
1896 {
1897  // Identify MMenz rate term
1898  unsigned int index = convertIdToReacIndex( e.id() );
1899  RateTerm* rt = rates_[ index ];
1900  //MMEnzymeBase* enz = dynamic_cast< MMEnzymeBase* >( rt );
1901  //assert( enz );
1902  // Identify MMenz Enzyme substrate. I would have preferred the parent,
1903  // but that gets messy.
1904  // unsigned int enzMolIndex = enz->getEnzIndex();
1905 
1906  // This function can be replicated to handle multiple different voxels.
1907  /*
1908  vector< double > vols;
1909  getReactantVols( e, subOut, vols );
1910  if ( vols.size() == 0 ) {
1911  cerr << "Error: Stoich::setMMenzKm: no substrates for enzyme " <<
1912  e << endl;
1913  return;
1914  }
1915  */
1916  // Do scaling and assignment.
1917  rt->setR1( v );
1918  kinterface_->updateRateTerms( index );
1919 }
1920 
1921 double Stoich::getMMenzNumKm( const Eref& e ) const
1922 {
1923  return getR1( e );
1924 }
1925 
1926 void Stoich::setMMenzKcat( const Eref& e, double v ) const
1927 {
1928  unsigned int index = convertIdToReacIndex( e.id() );
1929  RateTerm* rt = rates_[ index ];
1930  // MMEnzymeBase* enz = dynamic_cast< MMEnzymeBase* >( rt );
1931  // assert( enz );
1932 
1933  rt->setR2( v );
1934  kinterface_->updateRateTerms( index );
1935 }
1936 
1937 double Stoich::getMMenzKcat( const Eref& e ) const
1938 {
1939  return getR2( e );
1940 }
1941 
1943 void Stoich::setEnzK1( const Eref& e, double v ) const
1944 {
1945  unsigned int index = convertIdToReacIndex( e.id() );
1946 
1947  rates_[ index ]->setR1( v );
1948  kinterface_->updateRateTerms( index );
1949 }
1950 
1951 void Stoich::setEnzK2( const Eref& e, double v ) const
1952 {
1953  unsigned int index = convertIdToReacIndex( e.id() );
1954  if ( useOneWay_ )
1955  {
1956  rates_[ index + 1 ]->setR1( v );
1957  kinterface_->updateRateTerms( index + 1 );
1958  }
1959  else
1960  {
1961  rates_[ index ]->setR2( v );
1962  kinterface_->updateRateTerms( index );
1963  }
1964 }
1965 
1966 void Stoich::setEnzK3( const Eref& e, double v ) const
1967 {
1968  unsigned int index = convertIdToReacIndex( e.id() );
1969  if ( useOneWay_ )
1970  {
1971  rates_[ index + 2 ]->setR1( v );
1972  kinterface_->updateRateTerms( index + 2 );
1973  }
1974  else
1975  {
1976  rates_[ index + 1 ]->setR1( v );
1977  kinterface_->updateRateTerms( index + 1 );
1978  }
1979 }
1980 
1981 double Stoich::getEnzNumK1( const Eref& e ) const
1982 {
1983  return getR1( e );
1984 }
1985 
1986 double Stoich::getEnzK2( const Eref& e ) const
1987 {
1988  if ( useOneWay_ )
1989  return getR1offset1( e );
1990  else
1991  return getR2( e );
1992 }
1993 
1994 double Stoich::getEnzK3( const Eref& e ) const
1995 {
1996  if ( useOneWay_ )
1997  return getR1offset2( e );
1998  else
1999  return getR1offset1( e );
2000 }
2001 
2006 double Stoich::getR1( const Eref& e ) const
2007 {
2008  return rates_[ convertIdToReacIndex( e.id() ) ]->getR1();
2009 }
2010 double Stoich::getR1offset1( const Eref& e ) const
2011 {
2012  return rates_[ convertIdToReacIndex( e.id() ) + 1 ]->getR1();
2013 }
2014 double Stoich::getR1offset2( const Eref& e ) const
2015 {
2016  return rates_[ convertIdToReacIndex( e.id() ) + 2 ]->getR1();
2017 }
2018 
2023 double Stoich::getR2( const Eref& e ) const
2024 {
2025  return rates_[ convertIdToReacIndex( e.id() ) ]->getR2();
2026 }
2027 
2028 void Stoich::setFunctionExpr( const Eref& e, string expr )
2029 {
2030  unsigned int index = convertIdToReacIndex( e.id() );
2031  FuncRate* fr = 0;
2032  if ( index != ~0U )
2033  fr = dynamic_cast< FuncRate* >( rates_[index] );
2034  if ( fr )
2035  {
2036  fr->setExpr( expr );
2037  }
2038  else
2039  {
2040  index = convertIdToFuncIndex( e.id() );
2041  if ( index != ~0U )
2042  {
2043  FuncTerm *ft = dynamic_cast< FuncTerm* >( funcs_[index] );
2044  if ( ft )
2045  {
2046  ft->setExpr( expr );
2047  return;
2048  }
2049  }
2050  cout << "Warning: Stoich::setFunctionExpr( " << e.id().path() <<
2051  ", " << expr << " ): func not found";
2052  }
2053 }
2055 SpeciesId Stoich::getSpecies( unsigned int poolIndex ) const
2056 {
2057  return species_[ poolIndex ];
2058 }
2059 
2060 void Stoich::setSpecies( unsigned int poolIndex, SpeciesId s )
2061 {
2062  species_[ poolIndex ] = s;
2063 }
2064 
2065 // for debugging.
2066 void Stoich::print() const
2067 {
2068  N_.print();
2069 }
2070 
2071 // for debugging
2073 {
2074  for ( vector< Id >::const_iterator
2075  i = reacVec_.begin(); i != reacVec_.end(); ++i )
2076  {
2077  double Kf = Field< double >::get( *i, "Kf");
2078  double Kb = Field< double >::get( *i, "Kb");
2079  double kf = Field< double >::get( *i, "kf");
2080  double kb = Field< double >::get( *i, "kb");
2081  cout << "Id=" << *i << ", (Kf,Kb) = (" << Kf << ", " << Kb <<
2082  "), (kf, kb) = (" << kf << ", " << kb << ")\n";
2083  }
2084 }
2085 
2087 const vector< Id >& Stoich::getOffSolverPools() const
2088 {
2089  return offSolverPoolVec_;
2090 }
2091 
2092 vector< Id > Stoich::getOffSolverCompts() const
2093 {
2094  vector< Id > ret;
2095  for ( map< Id, vector< Id > >::const_iterator
2096  i = offSolverPoolMap_.begin(); i != offSolverPoolMap_.end(); ++i )
2097  ret.push_back( i->first );
2098 
2099  return ret;
2100 }
2101 
2102 const vector< Id >& Stoich::offSolverPoolMap( Id compt ) const
2103 {
2104  static vector< Id > blank( 0 );
2105  map< Id, vector < Id > >::const_iterator i =
2106  offSolverPoolMap_.find( compt );
2107  if ( i != offSolverPoolMap_.end() )
2108  return i->second;
2109  return blank;
2110 }
2111 
2113 // Numeric funcs. These are in Stoich because the rate terms are here.
2115 
2116 
2117 // s is the array of pools, S_[meshIndex][0]
2118 void Stoich::updateFuncs( double* s, double t ) const
2119 {
2120  for ( vector< FuncTerm* >::const_iterator i = funcs_.begin();
2121  i != funcs_.end(); ++i )
2122  {
2123  if ( *i )
2124  {
2125  (*i)->evalPool( s, t );
2126  // s holds arguments and also result location
2127  }
2128  }
2129 }
2130 
2149 {
2150  for ( vector< Id >::iterator
2151  i = reacVec_.begin(); i != reacVec_.end(); ++i )
2152  {
2153  double Kf = Field< double >::get( *i, "Kf");
2154  double Kb = Field< double >::get( *i, "Kb");
2155  setReacKf( i->eref(), Kf );
2156  setReacKb( i->eref(), Kb );
2157  }
2158  vector< Id >::iterator i;
2159  for (i = offSolverReacVec_.begin(); i != offSolverReacVec_.end(); ++i)
2160  {
2161  assert ( i->element()->cinfo()->isA( "ReacBase" ) );
2162  double Kf = Field< double >::get( *i, "Kf");
2163  double Kb = Field< double >::get( *i, "Kb");
2164  setReacKf( i->eref(), Kf );
2165  setReacKb( i->eref(), Kb );
2166  }
2167  for (i = offSolverEnzVec_.begin(); i != offSolverEnzVec_.end(); ++i)
2168  {
2169  assert ( i->element()->cinfo()->isA( "CplxEnzBase" ) );
2170  double concK1 = Field< double >::get( *i, "concK1");
2171  double k3 = Field< double >::get( *i, "k3");
2172  double k2 = Field< double >::get( *i, "k2");
2173  setEnzK3( i->eref(), k3 );
2174  setEnzK2( i->eref(), k2 );
2175  setEnzK1( i->eref(), concK1 );
2176  }
2177  for (i=offSolverMMenzVec_.begin(); i != offSolverMMenzVec_.end(); ++i)
2178  {
2179  assert( i->element()->cinfo()->isA( "MMEnzBase" ) );
2180  double Km = Field< double >::get( *i, "Km");
2181  double kcat = Field< double >::get( *i, "kcat");
2182  setMMenzKm( i->eref(), Km );
2183  setMMenzKcat( i->eref(), kcat );
2184  }
2185 }
2186 
2187 
2188 /*
2189 unsigned int Stoich::indexOfMatchingVolume( double vol ) const
2190 {
2191  assert( rates_.size() == uniqueVols_.size() );
2192  assert( rates_.size() > 0 );
2193 
2194  if ( rates_.size() == 1 && uniqueVols_[0] < 0 ) {
2195  return 0;
2196  }
2197  double bigVol = uniqueVols_[0];
2198  for ( unsigned int i = 0; i < uniqueVols_.size(); ++i ) {
2199  if ( doubleEq( vol/bigVol, uniqueVols_[i]/bigVol ) )
2200  return i;
2201  }
2202  assert( 0 );
2203  return 0;
2204 }
2205 */
2206 
2207 
2209 // Functions for resizing of specified voxels
2211 
2212 void Stoich::scaleBufsAndRates( unsigned int index, double volScale )
2213 {
2214  if ( !kinterface_ || status_ != 0 )
2215  return;
2216  kinterface_->pools( index )->scaleVolsBufsRates( volScale, this );
2217 }
void setExpr(const string &e)
Definition: FuncTerm.cpp:83
unsigned int innerInstallReaction(Id reacId, const vector< Id > &subs, const vector< Id > &prds)
Definition: Stoich.cpp:1562
void updateFuncs(double *s, double t) const
Updates the function values, within s.
Definition: Stoich.cpp:2118
double getEnzNumK1(const Eref &e) const
Definition: Stoich.cpp:1981
pair< Id, Id > extractCompts(const vector< Id > &compts)
Definition: Stoich.cpp:694
int wildcardFind(const string &path, vector< ObjId > &ret)
Definition: Wildcard.cpp:169
Id id() const
Definition: Eref.cpp:62
vector< vector< Id > > prdComptVec_
Definition: Stoich.h:724
Id zombifyPoolFuncWithScaling(Id pool)
Definition: Stoich.cpp:1244
void setMMenzKm(const Eref &e, double v) const
Definition: Stoich.cpp:1895
char * data() const
Definition: Eref.cpp:41
double getEnzK2(const Eref &e) const
Get rate k2 (1/sec) for enzyme.
Definition: Stoich.cpp:1986
vector< Id > offSolverMMenzVec_
Definition: Stoich.h:603
Id getCompartment() const
Definition: Stoich.cpp:505
void installAndUnschedFunc(Id func, Id pool, double volScale)
Definition: Stoich.cpp:1067
void setEnzK3(const Eref &e, double v) const
Set rate k3 (1/sec) for enzyme.
Definition: Stoich.cpp:1966
void setReacKf(const Eref &e, double v) const
Definition: Stoich.cpp:1860
void installAndUnschedFuncRate(Id func, Id pool)
Definition: Stoich.cpp:1113
const vector< T > & matrixEntry() const
Here we expose the sparse matrix for MOOSE use.
Definition: SparseMatrix.h:427
Id compartment_
Contains Id of compartment holding reac system. Optional.
Definition: Stoich.h:507
map< Id, vector< Id > > offSolverPoolMap_
Definition: Stoich.h:697
void setAllowNegative(bool v)
Definition: Stoich.cpp:310
T get(unsigned int row, unsigned int column) const
Definition: SparseMatrix.h:253
static bool isOffSolverReac(const Element *e, Id myCompt, vector< Id > &poolCompts, map< Id, Id > &poolComptMap)
Definition: Stoich.cpp:658
vector< unsigned int > species_
Definition: Stoich.h:518
const double NA
Definition: consts.cpp:15
static const Cinfo * stoichCinfo
Definition: Stoich.cpp:251
double getR1(const Eref &e) const
Definition: Stoich.cpp:2006
Element * element() const
Synonym for Id::operator()()
Definition: Id.cpp:113
vector< pair< Id, Id > > offSolverMMenzCompts_
Definition: Stoich.h:710
void installAndUnschedFuncReac(Id func, Id reac)
Definition: Stoich.cpp:1158
std::string path(const std::string &separator="/") const
Definition: Id.cpp:76
map< Id, unsigned int > rateTermLookup_
Definition: Stoich.h:633
unsigned int value() const
Definition: Id.cpp:197
void set(unsigned int row, unsigned int column, T value)
Definition: SparseMatrix.h:161
vector< Id > offSolverPoolVec_
Definition: Stoich.h:585
Definition: Dinfo.h:60
void setEnzK1(const Eref &e, double v) const
Later handle all the volumes when this conversion is done.
Definition: Stoich.cpp:1943
string path_
Definition: Stoich.h:498
void resizeArrays()
Using the computed array sizes, now allocate space for them.
Definition: Stoich.cpp:932
Definition: SetGet.h:236
void setMMenzKcat(const Eref &e, double v) const
Definition: Stoich.cpp:1926
static void zombify(Element *original, const Cinfo *zClass, Id solver)
Definition: ReacBase.cpp:299
static DestFinfo dummy("dummy","This Finfo is a dummy. If you are reading this you have used an invalid index", 0)
virtual void setNumPools(unsigned int num)=0
Specifies number of pools (species) handled by system.
Id getKsolve() const
Definition: Stoich.cpp:446
static void zombify(Element *original, const Cinfo *zClass, Id solver)
Definition: EnzBase.cpp:291
Id id
Definition: ObjId.h:98
~Stoich()
Definition: Stoich.cpp:273
void setVolScale(double vs)
Definition: FuncTerm.cpp:110
void setReactantIndex(const vector< unsigned int > &mol)
Definition: FuncTerm.cpp:47
unsigned int getMsgTargetAndFunctions(DataId srcDataId, const SrcFinfo *finfo, vector< ObjId > &tgt, vector< string > &func) const
Definition: Element.cpp:772
int status_
Definition: Stoich.h:684
static const Cinfo * find(const std::string &name)
Definition: Cinfo.cpp:200
Stoich()
Definition: Stoich.cpp:255
static const Cinfo * zombieMMenzCinfo
Definition: ZombieMMenz.cpp:60
bool useOneWay_
Definition: Stoich.h:488
void filterWildcards(vector< Id > &ret, const vector< ObjId > &elist)
Definition: Stoich.cpp:348
const KinSparseMatrix & getStoichiometryMatrix() const
Updates the rates for cross-compartment reactions.
Definition: Stoich.cpp:1221
Definition: ObjId.h:20
static const Cinfo * bufPoolCinfo
Definition: BufPool.cpp:47
static const Cinfo * mmEnzCinfo
Definition: MMenz.cpp:43
ZombiePoolInterface * dinterface_
Pointer for dsolve.
Definition: Stoich.h:512
Eref eref() const
Definition: Id.cpp:125
void myUnique(vector< Id > &v)
Definition: Stoich.cpp:924
static void zombify(Element *original, const Cinfo *zClass, Id solver)
static bool set(const ObjId &dest, const string &field, A arg)
Definition: SetGet.h:245
vector< Id > poolFuncVec_
Definition: Stoich.h:608
unsigned int convertIdToFuncIndex(Id id) const
Definition: Stoich.cpp:1484
bool allowNegative_
Definition: Stoich.h:496
void installReaction(Id reacId, const vector< Id > &subs, const vector< Id > &prds)
Definition: Stoich.cpp:1525
static const Cinfo * enzCinfo
Definition: Enz.cpp:54
vector< Id > getOffSolverCompts() const
Definition: Stoich.cpp:2092
void installEnzyme(Id enzId, Id enzMolId, Id cplxId, const vector< Id > &subs, const vector< Id > &prds)
Definition: Stoich.cpp:1732
vector< Id > reacVec_
Definition: Stoich.h:590
void allocateModelObject(Id id)
Identifies and allocates objects in the Stoich.
Definition: Stoich.cpp:844
void installDummy(RateTerm **entry, Id enzId, const string &s)
Definition: Stoich.cpp:1625
void setFunctionExpr(const Eref &e, string expr)
Definition: Stoich.cpp:2028
void setOneWay(bool v)
Definition: Stoich.cpp:300
Id id() const
Definition: Element.cpp:71
int getTick() const
Definition: Element.cpp:186
void buildPoolLookup()
Functions to build the maps between Ids and internal indices.
Definition: Stoich.cpp:997
static void zombify(Element *original, const Cinfo *zClass, Id ksolve, Id dsolve)
Definition: PoolBase.cpp:430
Definition: OpFunc.h:40
vector< Id > reacFuncVec_
Definition: Stoich.h:627
const vector< Id > & getOffSolverPools() const
Definition: Stoich.cpp:2087
void scaleBufsAndRates(unsigned int index, double volScale)
Used to handle run-time size updates for spines.
Definition: Stoich.cpp:2212
virtual void setCompartment(Id compartment)
Assigns compartment.
void setReacKb(const Eref &e, double v) const
Definition: Stoich.cpp:1874
void unZombifyModel()
Definition: Stoich.cpp:1402
void buildRateTermLookup()
Definition: Stoich.cpp:1011
virtual void updateRateTerms(unsigned int index=~0U)=0
double getR1offset1(const Eref &e) const
Definition: Stoich.cpp:2010
bool doubleEq(double x, double y)
Definition: doubleEq.cpp:16
const std::string & name() const
Definition: Cinfo.cpp:260
vector< Id > incrementFuncVec_
Definition: Stoich.h:621
void locateOffSolverReacs(Id myCompt, vector< Id > &elist)
Definition: Stoich.cpp:725
void allocateModel(const vector< Id > &elist)
Calculate sizes of all arrays, and allocate them.
Definition: Stoich.cpp:968
map< Id, unsigned int > funcLookup_
Definition: Stoich.h:634
bool getAllowNegative() const
Definition: Stoich.cpp:315
vector< RateTerm * > rates_
Definition: Stoich.h:531
vector< pair< Id, Id > > offSolverEnzCompts_
Definition: Stoich.h:709
static const Cinfo * zombieReacCinfo
Definition: ZombieReac.cpp:55
unsigned int convertIdToPoolIndex(Id id) const
Definition: Stoich.cpp:1464
vector< unsigned int > getColIndex() const
Definition: Stoich.cpp:617
const vector< Id > & offSolverPoolMap(Id compt) const
Definition: Stoich.cpp:2102
static const Cinfo * poolCinfo
Definition: Pool.cpp:47
KinSparseMatrix N_
N_ is the stoichiometry matrix. All pools * all reac terms.
Definition: Stoich.h:546
virtual VoxelPoolsBase * pools(unsigned int i)=0
Return a pointer to the specified VoxelPool.
void setEnzK2(const Eref &e, double v) const
Set rate k2 (1/sec) for enzyme.
Definition: Stoich.cpp:1951
vector< Id > getProxyPools(Id i) const
Definition: Stoich.cpp:627
void unZombifyPools()
unZombifies Pools. Helper for unZombifyModel.
Definition: Stoich.cpp:1376
static const Cinfo * zombieBufPoolCinfo
vector< vector< Id > > subComptVec_
Definition: Stoich.h:717
void setTarget(unsigned int tgt)
Definition: FuncTerm.cpp:100
const vector< unsigned int > & colIndex() const
Definition: SparseMatrix.h:431
unsigned int getNumFuncs() const
Definition: Stoich.cpp:594
const FuncTerm * funcs(unsigned int i) const
Definition: Stoich.cpp:599
virtual double getR1() const =0
Used by Zombie to return rate terms.
vector< pair< Id, Id > > offSolverReacCompts_
Definition: Stoich.h:708
Id dsolve_
This contains the Id of the Diffusion solver. Optional.
Definition: Stoich.h:504
Definition: Eref.h:26
bool isA(const string &ancestor) const
Definition: Cinfo.cpp:280
void scaleVolsBufsRates(double ratio, const Stoich *stoichPtr)
void setExpr(const string &s)
Definition: FuncRateTerm.h:59
static unsigned int lookupDefaultTick(const string &className)
Definition: Clock.cpp:1035
void setDsolve(Id v)
assigns diffusion solver: Dsovle or a Gillespie voxel stepper
Definition: Stoich.cpp:451
static const Cinfo * functionCinfo
Definition: Function.cpp:327
const Cinfo * cinfo() const
Definition: Element.cpp:66
vector< int > getMatrixEntry() const
Definition: Stoich.cpp:612
void setSize(unsigned int nrows, unsigned int ncolumns)
Definition: SparseMatrix.h:126
unsigned int SpeciesId
Definition: PoolBase.h:18
Id getDsolve() const
Definition: Stoich.cpp:469
unsigned int getNumBufPools() const
Returns number of local buffered pools.
Definition: Stoich.cpp:515
vector< unsigned int > funcTarget_
Definition: Stoich.h:615
void print() const
Definition: SparseMatrix.h:650
unsigned int getNumRates() const
Definition: Stoich.cpp:568
void installDummyEnzyme(Id enzId, Id enzMolId)
This is used when the enzyme lacks sub or prd.
Definition: Stoich.cpp:1711
unsigned int getNumVarPools() const
Returns number of local pools that are updated by solver.
Definition: Stoich.cpp:510
void setElist(const Eref &e, const vector< ObjId > &elist)
Definition: Stoich.cpp:363
static Id findFuncMsgSrc(Id pa, const string &msg)
Returns Function, if any, acting as src of specified msg into pa.
Definition: Stoich.cpp:1231
static const Cinfo * initCinfo()
Definition: Stoich.cpp:34
ZeroOrder * makeHalfReaction(double rate, const vector< Id > &reactants)
Utility function to make a half reac and return the rate term.
Definition: Stoich.cpp:1494
void convertRatesToStochasticForm()
Definition: Stoich.cpp:1196
const RateTerm * rates(unsigned int i) const
Utility function to return a rates_ entry.
Definition: Stoich.cpp:583
void printRates() const
Another utility function, prints out all Kf, kf, Kb, kb.
Definition: Stoich.cpp:2072
void buildFuncLookup()
Definition: Stoich.cpp:1054
double getEnzK3(const Eref &e) const
Get rate k3, aka kcat, for enzyme.
Definition: Stoich.cpp:1994
vector< unsigned int > getPoolIdMap() const
Definition: Stoich.cpp:530
ObjId getCompt(Id id)
static const Cinfo * zombieFunctionCinfo
bool isFuncTarget(unsigned int poolIndex) const
Returns true if the specified pool is controlled by a func.
Definition: Stoich.cpp:606
static const Cinfo * zombieEnzCinfo
Definition: ZombieEnz.cpp:53
void setKsolve(Id v)
assigns kinetic solver: Ksovle or GSSAsolve.
Definition: Stoich.cpp:421
ObjId doAddMsg(const string &msgType, ObjId src, const string &srcField, ObjId dest, const string &destField)
Definition: Shell.cpp:269
virtual void setStoich(Id stoich)=0
double getMMenzKcat(const Eref &e) const
Definition: Stoich.cpp:1937
unsigned int convertIdToReacIndex(Id id) const
Definition: Stoich.cpp:1474
void zombifyModel(const Eref &e, const vector< Id > &elist)
Definition: Stoich.cpp:1270
void updateRatesAfterRemesh()
Definition: Stoich.cpp:2148
static const Cinfo * reacCinfo
Definition: Reac.cpp:41
Definition: Id.h:17
void setTick(int t)
Definition: Element.cpp:251
void setCompartment(Id v)
assigns compartment occupied by Stoich.
Definition: Stoich.cpp:474
unsigned int getNumCoreRates() const
Number of rate terms for reactions purely on this compartment.
Definition: Stoich.cpp:574
unsigned int getNeighbors(vector< Id > &ret, const Finfo *finfo) const
Definition: Element.cpp:949
Definition: OpFunc.h:13
const vector< unsigned int > & rowStart() const
Definition: SparseMatrix.h:435
Id ksolve_
This contains the Id of the Kinetic solver.
Definition: Stoich.h:501
vector< Id > varPoolVec_
Definition: Stoich.h:573
vector< FuncTerm * > funcs_
The FuncTerms handle mathematical ops on mol levels.
Definition: Stoich.h:543
unsigned int getNumAllPools() const
Definition: Stoich.cpp:520
static A get(const ObjId &dest, const string &field)
Definition: SetGet.h:284
const vector< RateTerm * > & getRateTerms() const
Returns a reference to the entire rates_ vector.
Definition: Stoich.cpp:589
void setSpecies(unsigned int poolIndex, unsigned int s)
Definition: Stoich.cpp:2060
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
double getR2(const Eref &e) const
Definition: Stoich.cpp:2023
vector< unsigned int > getRowStart() const
Definition: Stoich.cpp:622
int getStatus() const
Definition: Stoich.cpp:644
string getPath(const Eref &e) const
Definition: Stoich.cpp:416
ZombiePoolInterface * kinterface_
Pointer for ksolve.
Definition: Stoich.h:510
static void zombify(Element *orig, const Cinfo *zClass, Id ksolve, Id dsolve)
vector< Id > bufPoolVec_
Definition: Stoich.h:578
bool getOneWay() const
Definition: Stoich.cpp:305
unsigned int getNumProxyPools() const
Definition: Stoich.cpp:525
bool isDoomed() const
Definition: Element.cpp:701
double getR1offset2(const Eref &e) const
Definition: Stoich.cpp:2014
void installMMenz(Id enzId, const vector< Id > &enzMolId, const vector< Id > &subs, const vector< Id > &prds)
Definition: Stoich.cpp:1636
void convWildcards(vector< Id > &ret, const vector< ObjId > &elist)
Definition: Stoich.cpp:341
void print() const
Utility function, prints out N_, used for debugging.
Definition: Stoich.cpp:2066
Definition: Cinfo.h:18
static char path[]
Definition: mfield.cpp:403
unsigned int getReactants(vector< unsigned int > &molIndex) const
Definition: RateTerm.h:294
double getMMenzNumKm(const Eref &e) const
Definition: Stoich.cpp:1921
void setPath(const Eref &e, string path)
Definition: Stoich.cpp:320
map< Id, unsigned int > poolLookup_
Definition: Stoich.h:632
vector< Id > enzVec_
Definition: Stoich.h:596
Id getPoolByIndex(unsigned int index) const
Definition: Stoich.cpp:557
virtual void setDsolve(Id dsolve)=0
Assigns the diffusion solver. Used by the reac solvers.
virtual void resize(unsigned int newNumData)=0
void setFuncArgIndex(const vector< unsigned int > &mol)
Definition: FuncRateTerm.h:55
Definition: Shell.h:43
const Finfo * findFinfo(const string &name) const
Definition: Cinfo.cpp:224
vector< Id > mmEnzVec_
Definition: Stoich.h:602
unsigned int numVoxels_
Number of voxels in reac system.
Definition: Stoich.h:540
vector< Id > offSolverReacVec_
Definition: Stoich.h:591
vector< Id > offSolverEnzVec_
Definition: Stoich.h:597
static const Cinfo * zombiePoolCinfo
Definition: ZombiePool.cpp:59
Definition: Finfo.h:12
unsigned int getSpecies(unsigned int poolIndex) const
Definition: Stoich.cpp:2055