MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
GssaVoxelPools.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 #ifdef ENABLE_CPP11
11 #include <memory>
12 #endif
13 
14 #include "header.h"
15 #include "RateTerm.h"
16 #include "FuncTerm.h"
17 #include "SparseMatrix.h"
18 #include "KinSparseMatrix.h"
19 #include "VoxelPoolsBase.h"
20 #include "../mesh/VoxelJunction.h"
21 #include "XferInfo.h"
22 #include "ZombiePoolInterface.h"
23 #include "Stoich.h"
24 #include "GssaSystem.h"
25 #include "GssaVoxelPools.h"
26 #include "../randnum/RNG.h"
27 #include "../basecode/global.h"
28 
44 const double SAFETY_FACTOR = 1.0 + 1.0e-9;
45 
47 // Class definitions
49 
51  VoxelPoolsBase(), t_( 0.0 ), atot_( 0.0 )
52 { ; }
53 
55 {
56  for ( unsigned int i = 0; i < rates_.size(); ++i )
57  delete( rates_[i] );
58 }
59 
61 // Solver ops
63 
65  const GssaSystem* g, unsigned int rindex, double time )
66 {
67  // The issue is that if the expression depends on t, we really need
68  // to update it every timestep. But then a cascading set of reacs
69  // should also be updated.
70  // The lower commented block has all funcs updated every time step,
71  // but this too
72  // doesn't update the cascading reacs. So this is now handled by the
73  // useClockedUpdate flag, and we use the lower block here instead.
74  /*
75  const vector< unsigned int >& deps = g->dependentMathExpn[ rindex ];
76  for( vector< unsigned int >::const_iterator
77  i = deps.begin(); i != deps.end(); ++i ) {
78  g->stoich->funcs( *i )->evalPool( varS(), time );
79  }
80  */
81  /*
82  unsigned int numFuncs = g->stoich->getNumFuncs();
83  for( unsigned int i = 0; i < numFuncs; ++i )
84  {
85  g->stoich->funcs( i )->evalPool( varS(), time );
86  }
87  */
88  // This function is equivalent to the loop above.
89  g->stoich->updateFuncs( varS(), time );
90 }
91 
93  const vector< unsigned int >& deps, const Stoich* stoich )
94 {
95  for ( vector< unsigned int >::const_iterator
96  i = deps.begin(); i != deps.end(); ++i )
97  {
98  atot_ -= fabs( v_[ *i ] );
99  // atot_ += ( v[ *i ] = ( *rates_[ *i ] )( S() );
100  atot_ += fabs( v_[ *i ] = getReacVelocity( *i, S() ) );
101  }
102 }
103 
105 {
106  double r = rng_.uniform( ) * atot_;
107  double sum = 0.0;
108 
109  // This is an inefficient way to do it. Can easily get to
110  // log time or thereabouts by doing one or two levels of
111  // subsidiary tables. Too many levels causes slow-down because
112  // of overhead in managing the tree.
113  // Slepoy, Thompson and Plimpton 2008
114  // report a linear time version.
115  for ( vector< double >::const_iterator
116  i = v_.begin(); i != v_.end(); ++i )
117  {
118  if ( r < ( sum += fabs( *i ) ) )
119  {
120  // double vel = fabs( getReacVelocity( i - v_.begin(), S() ) );
121  // assert( vel >= 0 );
122  return static_cast< unsigned int >( i - v_.begin() );
123  }
124  }
125  return v_.size();
126 }
127 
128 void GssaVoxelPools::setNumReac( unsigned int n )
129 {
130  v_.clear();
131  v_.resize( n, 0.0 );
132  numFire_.resize( n, 0 );
133 }
134 
141 {
142  g->stoich->updateFuncs( varS(), t_ );
143  updateReacVelocities( g, S(), v_ );
144  atot_ = 0;
145  for ( vector< double >::const_iterator
146  i = v_.begin(); i != v_.end(); ++i )
147  atot_ += fabs(*i);
148  atot_ *= SAFETY_FACTOR;
149  // Check if the system is in a stuck state. If so, terminate.
150  if ( atot_ <= 0.0 )
151  {
152  return false;
153  }
154  return true;
155 }
156 
162 void GssaVoxelPools::recalcTime( const GssaSystem* g, double currTime )
163 {
164  refreshAtot( g );
165  assert( t_ > currTime );
166  t_ = currTime;
167  double r = rng_.uniform( );
168  while( r == 0.0 )
169  r = rng_.uniform( );
170  t_ -= ( 1.0 / atot_ ) * log( r );
171 }
172 
173 void GssaVoxelPools::advance( const ProcInfo* p, const GssaSystem* g )
174 {
175  double nextt = p->currTime;
176  while ( t_ < nextt )
177  {
178  if ( atot_ <= 0.0 ) // reac system is stuck, will not advance.
179  {
180  t_ = nextt;
181  g->stoich->updateFuncs( varS(), t_ );
182  // updateDependentMathExpn( g, 0, t_ );
183  return;
184  }
185  unsigned int rindex = pickReac();
186  assert( g->stoich->getNumRates() == v_.size() );
187  if ( rindex >= g->stoich->getNumRates() )
188  {
189  // probably cumulative roundoff error here.
190  // Recalculate atot to avoid, and redo.
191  if ( !refreshAtot( g ) ) // Stuck state.
192  {
193  t_ = nextt;
194  g->stoich->updateFuncs( varS(), t_ );
195  // updateDependentMathExpn( g, 0, t_ );
196  return;
197  }
198  // We had a roundoff error, fixed it, but now need to be sure
199  // we only fire a reaction where this is permissible.
200  for ( unsigned int i = v_.size(); i > 0; --i )
201  {
202  if ( fabs( v_[i-1] ) > 0.0 )
203  {
204  rindex = i - 1;
205  break;
206  }
207  }
208  assert( rindex < v_.size() );
209  }
210 
211 #if ENABLE_CPP11
212  double sign = std::copysign( 1, v_[rindex] );
213 #else
214  double sign = double(v_[rindex] >= 0) - double(0 > v_[rindex] );
215 #endif
216 
217  g->transposeN.fireReac( rindex, Svec(), sign );
218  numFire_[rindex]++;
219 
220  double r = rng_.uniform();
221 
222  while ( r <= 0.0 )
223  r = rng_.uniform();
224 
225  t_ -= ( 1.0 / atot_ ) * log( r );
226  g->stoich->updateFuncs( varS(), t_ );
227  // updateDependentMathExpn( g, rindex, t_ );
228  updateDependentRates( g->dependency[ rindex ], g->stoich );
229  }
230 }
231 
233 {
235  VoxelPoolsBase::reinit(); // Assigns S = Sinit;
236  unsigned int numVarPools = g->stoich->getNumVarPools();
237  g->stoich->updateFuncs( varS(), 0 );
238 
239  double* n = varS();
240 
241  if( g->useRandInit )
242  {
243  vector<double> error(numVarPools, 0.0);
244  map<double, vector<Eref>> groupByVal;
245 
246  for ( unsigned int i = 0; i < numVarPools; ++i )
247  {
248  error[i] = n[i];
249  double base = std::floor( n[i] );
250  assert( base >= 0.0 );
251  double frac = n[i] - base;
252  if ( rng_.uniform() >= frac )
253  n[i] = base;
254  else
255  n[i] = base + 1.0;
256 
257  error[i] -= n[i];
258 
259  //if( true )
260  //{
261  // //NOTE: Thats how I get the name of the pool at this index.
262  // Eref e = g->stoich->getPoolByIndex( i ).eref();
263  // groupByVal[n[i]].push_back( e );
264 
265  // // Guess the fix the error.
266  //}
267 
268 
269  }
270 
271  double extra = std::accumulate( error.begin(), error.end(), 0.0 );
272  if( std::abs(extra) > 0.1 )
273  {
274  cout << "WARNING: Extra " << extra
275  << " molecules in system after converting fractional to integer e.g. 1.1 = 1 (~90% of times) or 2 (~10% of times)." << endl;
276  }
277  }
278  else // Just round to the nearest int.
279  {
280  for ( unsigned int i = 0; i < numVarPools; ++i )
281  {
282 #if ENABLE_CPP11
283  // Just like rint but does not raise exception.
284  // See http://en.cppreference.com/w/cpp/numeric/math/nearbyint for
285  // details.
286  n[i] = std::nearbyint(n[i]);
287 #else
288  n[i] = round( n[i] );
289 #endif
290  }
291  }
292 
293  t_ = 0.0;
294  refreshAtot( g );
295  numFire_.assign( v_.size(), 0 );
296 }
297 
298 vector< unsigned int > GssaVoxelPools::numFire() const
299 {
300  return numFire_;
301 }
302 
304 // Rate computation functions
306 
307 void GssaVoxelPools::updateAllRateTerms( const vector< RateTerm* >& rates,
308  unsigned int numCoreRates )
309 {
310  for ( unsigned int i = 0; i < rates_.size(); ++i )
311  delete( rates_[i] );
312  rates_.resize( rates.size() );
313 
314  for ( unsigned int i = 0; i < numCoreRates; ++i )
315  rates_[i] = rates[i]->copyWithVolScaling( getVolume(), 1, 1 );
316  for ( unsigned int i = numCoreRates; i < rates.size(); ++i )
317  rates_[i] = rates[i]->copyWithVolScaling( getVolume(),
318  getXreacScaleSubstrates(i - numCoreRates),
319  getXreacScaleProducts(i - numCoreRates ) );
320 }
321 
322 void GssaVoxelPools::updateRateTerms( const vector< RateTerm* >& rates,
323  unsigned int numCoreRates, unsigned int index )
324 {
325  // During setup or expansion of the reac system, this might be called
326  // before the local rates_ term is assigned. If so, ignore.
327  if ( index >= rates_.size() )
328  return;
329  delete( rates_[index] );
330  if ( index >= numCoreRates )
331  rates_[index] = rates[index]->copyWithVolScaling(
332  getVolume(),
333  getXreacScaleSubstrates(index - numCoreRates),
334  getXreacScaleProducts(index - numCoreRates ) );
335  else
336  rates_[index] = rates[index]->copyWithVolScaling(
337  getVolume(), 1.0, 1.0 );
338 }
345  const double* s, vector< double >& v ) const
346 {
348  assert( N.nColumns() == rates_.size() );
349 
350  vector< RateTerm* >::const_iterator i;
351  v.clear();
352  v.resize( rates_.size(), 0.0 );
353  vector< double >::iterator j = v.begin();
354 
355  for ( i = rates_.begin(); i != rates_.end(); i++)
356  {
357  *j++ = (**i)( s );
358  assert( !std::isnan( *( j-1 ) ) );
359  }
360 }
361 
363  unsigned int r, const double* s ) const
364 {
365  double v = rates_[r]->operator()( s );
366  // assert( v >= 0.0 );
367  return v;
368 
369  // return rates_[r]->operator()( s );
370 }
371 
372 void GssaVoxelPools::setStoich( const Stoich* stoichPtr )
373 {
374  stoichPtr_ = stoichPtr;
375 }
376 
377 // Handle volume updates. Inherited virtual func.
379 {
383 }
384 
386 // Handle cross compartment reactions
388 
389 /*
390  * Not sure if we need it. Hold off for now.
391 static double integralTransfer( double propensity )
392 {
393  double t= floor( propensity );
394  if ( rng_.uniform() < propensity - t )
395  return t + 1;
396  return t;
397 }
398 */
399 
401  unsigned int voxelIndex, const GssaSystem* g )
402 {
403  unsigned int offset = voxelIndex * xf.xferPoolIdx.size();
404  vector< double >::const_iterator i = xf.values.begin() + offset;
405  vector< double >::const_iterator j = xf.lastValues.begin() + offset;
406  vector< double >::iterator m = xf.subzero.begin() + offset;
407  double* s = varS();
408  bool hasChanged = false;
409  for ( vector< unsigned int >::const_iterator
410  k = xf.xferPoolIdx.begin(); k != xf.xferPoolIdx.end(); ++k )
411  {
412  double& x = s[*k];
413  // cout << x << " i = " << *i << *j << " m = " << *m << endl;
414  double dx = *i++ - *j++;
415  double base = floor( dx );
416  if ( rng_.uniform() >= (dx - base) )
417  x += base;
418  else
419  x += base + 1.0;
420 
421  // x += round( *i++ - *j );
422  if ( x < *m )
423  {
424  *m -= x;
425  x = 0;
426  }
427  else
428  {
429  x -= *m;
430  *m = 0;
431  }
432  /*
433  double y = fabs( x - *j );
434  // hasChanged |= ( fabs( x - *j ) < 0.1 ); // they are all integers.
435  hasChanged |= ( y > 0.1 ); // they are all integers.
436  */
437  // j++;
438  m++;
439  }
440  // If S has changed, then I should update rates of all affected reacs.
441  // Go through stoich matrix to find affected reacs for each mol
442  // Store in list, since some may be hit more than once in this func.
443  // When done, go through and update all affected ones.
444  /*
445  if ( hasChanged ) {
446  refreshAtot( g );
447  }
448  */
449  // Does this fix the problem of negative concs?
450  refreshAtot( g );
451 }
double getXreacScaleProducts(unsigned int i) const
void updateFuncs(double *s, double t) const
Updates the function values, within s.
Definition: Stoich.cpp:2118
const Stoich * stoichPtr_
bool refreshAtot(const GssaSystem *g)
vector< double > subzero
Definition: XferInfo.h:39
vector< unsigned int > numFire_
const double * S() const
unsigned int nColumns() const
Definition: SparseMatrix.h:92
void recalcTime(const GssaSystem *g, double currTime)
vector< unsigned int > xferPoolIdx
Definition: XferInfo.h:45
vector< vector< unsigned int > > dependency
Definition: GssaSystem.h:25
double currTime
Definition: ProcInfo.h:19
void xferIn(XferInfo &xf, unsigned int voxelIndex, const GssaSystem *g)
void setNumReac(unsigned int n)
double getReacVelocity(unsigned int r, const double *s) const
void updateDependentRates(const vector< unsigned int > &deps, const Stoich *stoich)
void setSeed(const unsigned long seed)
If seed if 0 then set seed to a random number else set seed to the given number.
Definition: RNG.h:73
const KinSparseMatrix & getStoichiometryMatrix() const
Updates the rates for cross-compartment reactions.
Definition: Stoich.cpp:1221
void advance(const ProcInfo *p)
double getVolume() const
Return the volume of the voxel.
void setStoich(const Stoich *stoichPtr)
void fireReac(unsigned int reacIndex, vector< double > &S, double direction) const
Stoich * stoich
Definition: GssaSystem.h:31
void log(string msg, serverity_level_ type=debug, bool redirectToConsole=true, bool removeTicks=true)
Log to console (and to a log-file)
Definition: Stoich.h:49
virtual ~GssaVoxelPools()
unsigned int pickReac()
vector< double > & Svec()
Returns a handle to the mol # vector.
moose::RNG< double > rng_
RNG.
double getXreacScaleSubstrates(unsigned int i) const
unsigned long __rng_seed__
A global seed for all RNGs in moose. When moose.seed( x ) is called, this variable is set...
Definition: global.cpp:45
KinSparseMatrix transposeN
Transpose of stoichiometry matrix.
Definition: GssaSystem.h:30
void updateReacVelocities(const GssaSystem *g, const double *s, vector< double > &v) const
void setVolumeAndDependencies(double vol)
unsigned int getNumRates() const
Definition: Stoich.cpp:568
const double SAFETY_FACTOR
unsigned int getNumVarPools() const
Returns number of local pools that are updated by solver.
Definition: Stoich.cpp:510
void updateAllRateTerms(const vector< RateTerm * > &rates, unsigned int numCoreRates)
vector< double > v_
vector< unsigned int > numFire() const
void updateDependentMathExpn(const GssaSystem *g, unsigned int rindex, double time)
vector< double > lastValues
Definition: XferInfo.h:32
unsigned int getNumCoreRates() const
Number of rate terms for reactions purely on this compartment.
Definition: Stoich.cpp:574
void updateRateTerms(const vector< RateTerm * > &rates, unsigned int numCoreRates, unsigned int index)
const vector< RateTerm * > & getRateTerms() const
Returns a reference to the entire rates_ vector.
Definition: Stoich.cpp:589
virtual void setVolumeAndDependencies(double vol)
vector< double > values
Definition: XferInfo.h:27
T uniform(const T a, const T b)
Generate a uniformly distributed random number between a and b.
Definition: RNG.h:90
double t_
Time at which next event will occur.
vector< RateTerm * > rates_
bool useRandInit
Definition: GssaSystem.h:44