MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
VoxelPools.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 #include "header.h"
10 
11 #ifdef USE_GSL
12 #include <gsl/gsl_errno.h>
13 #include <gsl/gsl_matrix.h>
14 #include <gsl/gsl_odeiv2.h>
15 #elif USE_BOOST_ODE
16 #include <boost/numeric/odeint.hpp>
17 using namespace boost::numeric;
18 #endif
19 
20 #include "OdeSystem.h"
21 #include "VoxelPoolsBase.h"
22 #include "VoxelPools.h"
23 #include "RateTerm.h"
24 #include "FuncTerm.h"
25 #include "SparseMatrix.h"
26 #include "KinSparseMatrix.h"
27 #include "../mesh/VoxelJunction.h"
28 #include "XferInfo.h"
29 #include "ZombiePoolInterface.h"
30 #include "Stoich.h"
31 
33 // Class definitions
35 
37 {
38 #ifdef USE_GSL
39  driver_ = 0;
40 #endif
41 }
42 
44 {
45  for ( unsigned int i = 0; i < rates_.size(); ++i )
46  delete( rates_[i] );
47 #ifdef USE_GSL
48  if ( driver_ )
49  gsl_odeiv2_driver_free( driver_ );
50 #endif
51 }
52 
54 // Solver ops
56 void VoxelPools::reinit( double dt )
57 {
59 #ifdef USE_GSL
60  if ( !driver_ )
61  return;
62  gsl_odeiv2_driver_reset( driver_ );
63  gsl_odeiv2_driver_reset_hstart( driver_, dt / 10.0 );
64 #endif
65 }
66 
67 void VoxelPools::setStoich( Stoich* s, const OdeSystem* ode )
68 {
69  stoichPtr_ = s;
70 #ifdef USE_GSL
71  if ( ode )
72  {
73  sys_ = ode->gslSys;
74  if ( driver_ )
75  gsl_odeiv2_driver_free( driver_ );
76 
77  driver_ = gsl_odeiv2_driver_alloc_y_new(
78  &sys_, ode->gslStep, ode->initStepSize,
79  ode->epsAbs, ode->epsRel
80  );
81  }
82 #elif USE_BOOST_ODE
83  if( ode )
84  sys_ = ode->boostSys;
85 #endif
87 }
88 
89 void VoxelPools::advance( const ProcInfo* p )
90 {
91  double t = p->currTime - p->dt;
92 #ifdef USE_GSL
93  int status = gsl_odeiv2_driver_apply( driver_, &t, p->currTime, varS());
94  if ( status != GSL_SUCCESS )
95  {
96  cout << "Error: VoxelPools::advance: GSL integration error at time "
97  << t << "\n";
98  cout << "Error info: " << status << ", " <<
99  gsl_strerror( status ) << endl;
100  if ( status == GSL_EMAXITER )
101  cout << "Max number of steps exceeded\n";
102  else if ( status == GSL_ENOPROG )
103  cout << "Timestep has gotten too small\n";
104  else if ( status == GSL_EBADFUNC )
105  cout << "Internal error\n";
106  assert( 0 );
107  }
108 
109 #elif USE_BOOST_ODE
110 
111 
112  // NOTE: Make sure to assing vp to BoostSys vp. In next call, it will be used by
113  // updateRates func. Unlike gsl call, we can't pass extra void* to gslFunc.
114  VoxelPools* vp = reinterpret_cast< VoxelPools* >( sys_.params );
115  sys_.vp = vp;
116  /*-----------------------------------------------------------------------------
117  NOTE: 04/21/2016 11:31:42 AM
118 
119  We need to call updateFuncs here (unlike in GSL solver) because there
120  is no way we can update const vector_type_& y in evalRatesUsingBoost
121  function. In gsl implmentation one could do it, because const_cast can
122  take away the constantness of double*. This probably makes the call bit
123  cleaner.
124  *-----------------------------------------------------------------------------*/
125  vp->stoichPtr_->updateFuncs( &Svec()[0], p->currTime );
126 
127  /*-----------------------------------------------------------------------------
128  * Using integrate function works with with default stepper type.
129  *
130  * NOTICE to developer:
131  * If you are planning your own custom typdedef of stepper_type_ (see
132  * file BoostSystem.h), the you may run into troble. Have a look at this
133  * http://boostw.boost.org/doc/libs/1_56_0/boost/numeric/odeint/integrate/integrate.hpp
134  *-----------------------------------------------------------------------------
135  */
136 
137  double absTol = sys_.epsAbs;
138  double relTol = sys_.epsRel;
139 
140 
147  const double fixedDt = 0.1;
148 
149  if( sys_.method == "rk2" )
150  odeint::integrate_const( rk_midpoint_stepper_type_()
151  , sys_ , Svec()
152  , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt )
153  );
154  else if( sys_.method == "rk4" )
155  odeint::integrate_const( rk4_stepper_type_()
156  , sys_ , Svec()
157  , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt )
158  );
159  else if( sys_.method == "rk5")
160  odeint::integrate_const( rk_karp_stepper_type_()
161  , sys_ , Svec()
162  , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt )
163  );
164  else if( sys_.method == "rk5a")
165  odeint::integrate_adaptive(
166  odeint::make_controlled<rk_karp_stepper_type_>( absTol, relTol)
167  , sys_
168  , Svec()
169  , p->currTime - p->dt
170  , p->currTime
171  , p->dt
172  );
173  else if ("rk54" == sys_.method )
174  odeint::integrate_const( rk_karp_stepper_type_()
175  , sys_ , Svec()
176  , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt )
177  );
178  else if ("rk54a" == sys_.method )
179  odeint::integrate_adaptive(
180  odeint::make_controlled<rk_karp_stepper_type_>( absTol, relTol )
181  , sys_, Svec()
182  , p->currTime - p->dt
183  , p->currTime
184  , p->dt
185  );
186  else if ("rk5" == sys_.method )
187  odeint::integrate_const( rk_dopri_stepper_type_()
188  , sys_ , Svec()
189  , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt )
190  );
191  else if ("rk5a" == sys_.method )
192  odeint::integrate_adaptive(
193  odeint::make_controlled<rk_dopri_stepper_type_>( absTol, relTol )
194  , sys_, Svec()
195  , p->currTime - p->dt
196  , p->currTime
197  , p->dt
198  );
199  else if( sys_.method == "rk8" )
200  odeint::integrate_const( rk_felhberg_stepper_type_()
201  , sys_ , Svec()
202  , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt )
203  );
204  else if( sys_.method == "rk8a" )
205  odeint::integrate_adaptive(
206  odeint::make_controlled<rk_felhberg_stepper_type_>( absTol, relTol )
207  , sys_, Svec()
208  , p->currTime - p->dt
209  , p->currTime
210  , p->dt
211  );
212 
213  else
214  odeint::integrate_adaptive(
215  odeint::make_controlled<rk_karp_stepper_type_>( absTol, relTol )
216  , sys_, Svec()
217  , p->currTime - p->dt
218  , p->currTime
219  , p->dt
220  );
221 #endif
222  if ( !stoichPtr_->getAllowNegative() ) // clean out negatives
223  {
224  unsigned int nv = stoichPtr_->getNumVarPools();
225  double* vs = varS();
226  for ( unsigned int i = 0; i < nv; ++i )
227  {
228  if ( signbit(vs[i]) )
229  vs[i] = 0.0;
230  }
231  }
232 }
233 
234 void VoxelPools::setInitDt( double dt )
235 {
236 #ifdef USE_GSL
237  gsl_odeiv2_driver_reset_hstart( driver_, dt );
238 #endif
239 }
240 
241 #ifdef USE_GSL
242 // static func. This is the function that goes into the Gsl solver.
243 int VoxelPools::gslFunc( double t, const double* y, double *dydt,
244  void* params )
245 {
246  VoxelPools* vp = reinterpret_cast< VoxelPools* >( params );
247  // Stoich* s = reinterpret_cast< Stoich* >( params );
248  double* q = const_cast< double* >( y ); // Assign the func portion.
249 
250  // Assign the buffered pools
251  // Not possible because this is a static function
252  // Not needed because dydt = 0;
253  /*
254  double* b = q + s->getNumVarPools();
255  vector< double >::const_iterator sinit = Sinit_.begin() + s->getNumVarPools();
256  for ( unsigned int i = 0; i < s->getNumBufPools(); ++i )
257  *b++ = *sinit++;
258  */
259 
260  vp->stoichPtr_->updateFuncs( q, t );
261  vp->updateRates( y, dydt );
262 #ifdef USE_GSL
263  return GSL_SUCCESS;
264 #else
265  return 0;
266 #endif
267 }
268 
269 #elif USE_BOOST_ODE
270 void VoxelPools::evalRates(
271  const vector_type_& y, vector_type_& dydt, const double t, VoxelPools* vp
272 )
273 {
274  vp->updateRates( &y[0], &dydt[0] );
275 }
276 #endif
277 
279 // Here are the internal reaction rate calculation functions
281 
282 void VoxelPools::updateAllRateTerms( const vector< RateTerm* >& rates,
283  unsigned int numCoreRates )
284 {
285  // Clear out old rates if any
286  for ( unsigned int i = 0; i < rates_.size(); ++i )
287  delete( rates_[i] );
288 
289  rates_.resize( rates.size() );
290  for ( unsigned int i = 0; i < numCoreRates; ++i )
291  rates_[i] = rates[i]->copyWithVolScaling( getVolume(), 1, 1 );
292  for ( unsigned int i = numCoreRates; i < rates.size(); ++i )
293  {
294  rates_[i] = rates[i]->copyWithVolScaling( getVolume(),
295  getXreacScaleSubstrates(i - numCoreRates),
296  getXreacScaleProducts(i - numCoreRates ) );
297  }
298 }
299 
300 void VoxelPools::updateRateTerms( const vector< RateTerm* >& rates,
301  unsigned int numCoreRates, unsigned int index )
302 {
303  // During setup or expansion of the reac system, it is possible to
304  // call this function before the rates_ term is assigned. Disable.
305  if ( index >= rates_.size() )
306  return;
307  delete( rates_[index] );
308  if ( index >= numCoreRates )
309  rates_[index] = rates[index]->copyWithVolScaling(
310  getVolume(),
311  getXreacScaleSubstrates(index - numCoreRates),
312  getXreacScaleProducts(index - numCoreRates ) );
313  else
314  rates_[index] = rates[index]->copyWithVolScaling(
315  getVolume(), 1.0, 1.0 );
316 }
317 
318 void VoxelPools::updateRates( const double* s, double* yprime ) const
319 {
320  const KinSparseMatrix& N = stoichPtr_->getStoichiometryMatrix();
321  vector< double > v( N.nColumns(), 0.0 );
322  vector< double >::iterator j = v.begin();
323  // totVar should include proxyPools only if this voxel uses them
324  unsigned int totVar = stoichPtr_->getNumVarPools() +
325  stoichPtr_->getNumProxyPools();
326  // totVar should include proxyPools if this voxel does not use them
327  unsigned int totInvar = stoichPtr_->getNumBufPools();
328  assert( N.nColumns() == 0 ||
329  N.nRows() == stoichPtr_->getNumAllPools() );
330  assert( N.nColumns() == rates_.size() );
331 
332  for ( vector< RateTerm* >::const_iterator
333  i = rates_.begin(); i != rates_.end(); i++)
334  {
335  *j++ = (**i)( s );
336  assert( !std::isnan( *( j-1 ) ) );
337  }
338 
339  for (unsigned int i = 0; i < totVar; ++i)
340  *yprime++ = N.computeRowRate( i , v );
341  for (unsigned int i = 0; i < totInvar ; ++i)
342  *yprime++ = 0.0;
343 }
344 
351  const double* s, vector< double >& v ) const
352 {
353  const KinSparseMatrix& N = stoichPtr_->getStoichiometryMatrix();
354  assert( N.nColumns() == rates_.size() );
355 
356  vector< RateTerm* >::const_iterator i;
357  v.clear();
358  v.resize( rates_.size(), 0.0 );
359  vector< double >::iterator j = v.begin();
360 
361  for ( i = rates_.begin(); i != rates_.end(); i++)
362  {
363  *j++ = (**i)( s );
364  assert( !std::isnan( *( j-1 ) ) );
365  }
366 }
367 
369 void VoxelPools::print() const
370 {
371  cout << "numAllRates = " << rates_.size() <<
372  ", numLocalRates= " << stoichPtr_->getNumCoreRates() << endl;
374 }
375 
377 
381 {
383  updateAllRateTerms( stoichPtr_->getRateTerms(),
384  stoichPtr_->getNumCoreRates() );
385 }
386 
void updateFuncs(double *s, double t) const
Updates the function values, within s.
Definition: Stoich.cpp:2118
const Stoich * stoichPtr_
void print() const
Debugging utility.
void advance(const ProcInfo *p)
Do the numerical integration. Advance the simulation.
Definition: VoxelPools.cpp:89
unsigned int nColumns() const
Definition: SparseMatrix.h:92
void updateRateTerms(const vector< RateTerm * > &rates, unsigned int numCoreRates, unsigned int index)
Definition: VoxelPools.cpp:300
double currTime
Definition: ProcInfo.h:19
double epsAbs
Definition: OdeSystem.h:36
unsigned int nRows() const
Definition: SparseMatrix.h:87
double epsRel
Definition: OdeSystem.h:37
void setStoich(Stoich *stoich, const OdeSystem *ode)
Definition: VoxelPools.cpp:67
Definition: Stoich.h:49
virtual ~VoxelPools()
Definition: VoxelPools.cpp:43
double initStepSize
Definition: OdeSystem.h:35
double dt
Definition: ProcInfo.h:18
double computeRowRate(unsigned int row, const vector< double > &v) const
void updateRates(const double *s, double *yprime) const
Definition: VoxelPools.cpp:318
void print() const
Used for debugging.
Definition: VoxelPools.cpp:369
virtual void setVolumeAndDependencies(double vol)
void updateReacVelocities(const double *s, vector< double > &v) const
Definition: VoxelPools.cpp:350
void updateAllRateTerms(const vector< RateTerm * > &rates, unsigned int numCoreRates)
Updates all the rate constants from the reference rates vector.
Definition: VoxelPools.cpp:282
void setVolumeAndDependencies(double vol)
Handles volume change and subsequent cascading updates.
Definition: VoxelPools.cpp:380
void setInitDt(double dt)
Set initial timestep to use by the solver.
Definition: VoxelPools.cpp:234