9 #include "../basecode/header.h"
11 #include <gsl/gsl_errno.h>
12 #include <gsl/gsl_matrix.h>
13 #include <gsl/gsl_odeiv2.h>
19 #include "../mesh/VoxelJunction.h"
24 #include "../basecode/SparseMatrix.h"
27 #include "../shell/Shell.h"
29 #include "../mesh/MeshEntry.h"
30 #include "../mesh/Boundary.h"
31 #include "../mesh/ChemCompt.h"
48 "Integration method, using GSL. So far only explict. Options are:"
49 "rk5: The default Runge-Kutta-Fehlberg 5th order adaptive dt method"
50 "gsl: alias for the above"
51 "rk4: The Runge-Kutta 4th order fixed dt method"
52 "rk2: The Runge-Kutta 2,3 embedded fixed dt method"
53 "rkck: The Runge-Kutta Cash-Karp (4,5) method"
54 "rk8: The Runge-Kutta Prince-Dormand (8,9) method" ,
61 "Absolute permissible integration error range.",
68 "Relative permissible integration error range.",
76 "Compartment in which the Ksolve reaction system lives.",
83 "Number of voxels in the core reac-diff system, on the "
88 Ksolve,
unsigned int, vector< double > > nVec(
90 "vector of pool counts. Index specifies which voxel.",
96 "Number of voxels in the entire reac-diff system, "
97 "including proxy voxels to represent abutting compartments.",
102 #if PARALLELIZE_KSOLVE_WITH_CPP11_ASYNC
105 "Number of threads to use (applicable in deterministic case)",
106 &Ksolve::setNumThreads,
107 &Ksolve::getNumThreads
113 "Number of molecular pools in the entire reac-diff system, "
114 "including variable, function and buffered.",
121 "Estimated timestep for reac system based on Euler error",
126 "Id for stoichiometry object tied to this Ksolve",
136 "Handles process call from Clock",
139 "Handles reinit call from Clock",
143 "Handles initProc call from Clock",
146 "Handles initReinit call from Clock",
150 "Handles updates to all voxels. Comes from parent "
152 new OpFunc1< Ksolve, vector< double > >(
158 static Finfo* procShared[] =
163 "Shared message for process and reinit. These are used for "
164 "all regular Ksolve calculations including interfacing with "
165 "the diffusion calculations by a Dsolve.",
166 procShared,
sizeof( procShared ) /
sizeof(
const Finfo* )
168 static Finfo* initShared[] =
173 "Shared message for initProc and initReinit. This is used"
174 " when the system has cross-compartment reactions. ",
175 initShared,
sizeof( initShared ) /
sizeof(
const Finfo* )
178 static Finfo* ksolveFinfos[] =
183 #if PARALLELIZE_KSOLVE_WITH_CPP11_ASYNC
203 sizeof(ksolveFinfos)/
sizeof(
Finfo *),
225 #if PARALLELIZE_KSOLVE_WITH_CPP11_ASYNC
253 if ( method ==
"rk5" || method ==
"gsl" )
257 else if ( method ==
"rk4" || method ==
"rk2" ||
258 method ==
"rk8" || method ==
"rkck" )
264 cout <<
"Warning: Ksolve::setMethod: '" << method <<
265 "' not known, using rk5\n";
305 #if PARALLELIZE_KSOLVE_WITH_CPP11_ASYNC
306 void Ksolve::setNumThreads(
unsigned int x )
311 unsigned int Ksolve::getNumThreads( )
const
323 void innerSetMethod(
OdeSystem& ode,
const string& method )
326 if ( method ==
"rk5" )
328 ode.gslStep = gsl_odeiv2_step_rkf45;
330 else if ( method ==
"rk4" )
332 ode.gslStep = gsl_odeiv2_step_rk4;
334 else if ( method ==
"rk2" )
336 ode.gslStep = gsl_odeiv2_step_rk2;
338 else if ( method ==
"rkck" )
340 ode.gslStep = gsl_odeiv2_step_rkck;
342 else if ( method ==
"rk8" )
344 ode.gslStep = gsl_odeiv2_step_rk8pd;
348 ode.gslStep = gsl_odeiv2_step_rkf45;
368 if ( ode.gslSys.dimension == 0 ) {
372 innerSetMethod( ode,
method_ );
373 ode.gslSys.function = &VoxelPools::gslFunc;
374 ode.gslSys.jacobian = 0;
375 innerSetMethod( ode,
method_ );
376 unsigned int numVoxels =
pools_.size();
377 for (
unsigned int i = 0 ; i < numVoxels; ++i )
379 ode.gslSys.params = &
pools_[i];
388 if ( ode.dimension == 0 )
390 unsigned int numVoxels =
pools_.size();
391 for (
unsigned int i = 0 ; i < numVoxels; ++i )
393 ode.boostSys.params = &
pools_[i];
408 if ( dsolve ==
Id () )
421 cout <<
"Warning: Ksolve::setDsolve: Object '" << dsolve.
path() <<
422 "' should be class Dsolve, is: " <<
440 if ( numVoxels == 0 )
444 pools_.resize( numVoxels );
449 static vector< double >
dummy;
450 if ( voxel <
pools_.size() )
459 if ( voxel <
pools_.size() )
461 if ( nVec.size() !=
pools_[voxel].size() )
463 cout <<
"Warning: Ksolve::setNvec: size mismatch ( " <<
464 nVec.size() <<
", " <<
pools_[voxel].size() <<
")\n";
467 double* s =
pools_[voxel].varS();
468 for (
unsigned int i = 0; i < nVec.size(); ++i )
476 static const double EPSILON = 1e-15;
480 if (
pools_.size() > 0.0 )
482 pools_[0].updateReacVelocities( &s[0], v );
483 for ( vector< double >::iterator
484 i = v.begin(); i != v.end(); ++i )
488 if ( maxVel < EPSILON )
505 vector< double > dvalues( 4 );
517 size_t nvPools =
pools_.size( );
519 #ifdef PARALLELIZE_KSOLVE_WITH_CPP11_ASYNC
521 size_t grainSize = min( nvPools, 1 + (nvPools / numThreads_ ) );
522 size_t nWorkers = nvPools / grainSize;
524 if( 1 == nWorkers || 1 == nvPools )
526 if( numThreads_ > 1 )
529 cout <<
"Debug: Reset to 1 threads " << endl;
534 for (
size_t i = 0; i < nvPools; i++ )
544 for (
size_t i = 0; i < nWorkers; i++)
545 parallel_advance( i * grainSize, (i+1) * grainSize, nWorkers, p );
548 for (
size_t i = 0; i < nvPools; i++ )
556 vector< double > kvalues( 4 );
571 #if PARALLELIZE_KSOLVE_WITH_CPP11_ASYNC
579 void Ksolve::parallel_advance(
int begin,
int end,
size_t nWorkers,
ProcPtr p)
581 std::atomic<int> idx( begin );
582 for (
size_t cpu = 0; cpu != nWorkers; ++cpu)
584 std::async( std::launch::async
585 , [
this, &idx, end, p]() {
607 for (
unsigned int i = 0 ; i <
pools_.size(); ++i )
612 cout <<
"Warning:Ksolve::reinit: Reaction system not initialized\n";
616 #if PARALLELIZE_KSOLVE_WITH_CPP11_ASYNC
617 if( 1 < getNumThreads( ) )
618 cout <<
"Debug: User wants Ksolve with " << numThreads_ <<
" threads" << endl;
632 for (
unsigned int i = 0 ; i <
pools_.size(); ++i )
646 for (
unsigned int i = 0 ; i <
pools_.size(); ++i )
653 else if ( index < stoichPtr_->getNumRates() )
655 for (
unsigned int i = 0 ; i <
pools_.size(); ++i )
725 unsigned int numVoxels =
pools_.size();
726 for (
unsigned int i = 0 ; i < numVoxels; ++i )
728 pools_[i].resizeArrays( numPoolSpecies );
749 return pools_[i].getVolume();
755 unsigned int startVoxel = values[0];
756 unsigned int numVoxels = values[1];
757 unsigned int startPool = values[2];
758 unsigned int numPools = values[3];
761 assert( numVoxels <=
pools_.size() );
762 assert(
pools_.size() > 0 );
763 assert( numPools + startPool <=
pools_[0].size() );
764 values.resize( 4 + numVoxels * numPools );
766 for (
unsigned int i = 0; i < numVoxels; ++i )
768 const double* v =
pools_[ startVoxel + i ].S();
769 for (
unsigned int j = 0; j < numPools; ++j )
771 values[ 4 + j * numVoxels + i] = v[ j + startPool ];
778 unsigned int startVoxel = values[0];
779 unsigned int numVoxels = values[1];
780 unsigned int startPool = values[2];
781 unsigned int numPools = values[3];
784 assert( numVoxels <=
pools_.size() );
785 assert(
pools_.size() > 0 );
786 assert( numPools + startPool <=
pools_[0].size() );
787 assert( values.size() == 4 + numVoxels * numPools );
789 for (
unsigned int i = 0; i < numVoxels; ++i )
791 double* v =
pools_[ startVoxel + i ].varS();
792 for (
unsigned int j = 0; j < numPools; ++j )
794 v[ j + startPool ] = values[ 4 + j * numVoxels + i ];
805 if ( vols.size() ==
pools_.size() )
807 for (
unsigned int i = 0; i < vols.size(); ++i )
809 pools_[i].setVolumeAndDependencies( vols[i] );
826 ", numPools = " <<
pools_.size() <<
"\n";
827 for (
unsigned int i = 0; i <
pools_.size(); ++i )
829 cout <<
"pools[" << i <<
"] contents = ";
void updateRateTerms(unsigned int index)
Id init(int argc, char **argv, bool &doUnitTests, bool &doRegressionTests, unsigned int &benchmark)
vector< VoxelPools > pools_
void setDsolve(Id dsolve)
Assigns the diffusion solver. Used by the reac solvers.
static const Cinfo * initCinfo()
void getBlock(vector< double > &values) const
void setNinit(const Eref &e, double v)
Set initial # of molecules in given pool and voxel. Bdry cond.
VoxelPoolsBase * pools(unsigned int i)
Return a pointer to the specified VoxelPool.
Element * element() const
Synonym for Id::operator()()
void setNumPools(unsigned int num)
string getMethod() const
Assigns integration method.
std::string path(const std::string &separator="/") const
void reinit(const Eref &e, ProcPtr p)
static DestFinfo dummy("dummy","This Finfo is a dummy. If you are reading this you have used an invalid index", 0)
unsigned int dataIndex() const
Stoich * stoichPtr_
Utility ptr used to help Pool Id lookups by the Ksolve.
void updateVoxelVol(vector< double > vols)
double volume(unsigned int i) const
Return volume of voxel i.
static const Cinfo * ksolveCinfo
virtual void updateJunctions(double dt)
Used for telling Dsolver to handle all ops across Junctions.
void advance(vector< double > &y, const vector< Triplet< double > > &ops, const vector< double > &diagVal)
unsigned int getPoolIndex(const Eref &e) const
Return pool index, using Stoich ptr to do lookup.
virtual void setCompartment(Id compartment)
Assigns compartment.
Id getCompartment() const
vector< double > & Svec()
Returns a handle to the mol # vector.
const std::string & name() const
unsigned int getNumPools() const
gets number of pools (species) handled by system.
ZombiePoolInterface * dsolvePtr_
Pointer to diffusion solver.
double getDiffConst(const Eref &e) const
Diffusion constant: Only one per pool, voxel number is ignored.
void setEpsRel(double val)
void setStoich(Id stoich)
unsigned int convertIdToPoolIndex(Id id) const
vector< double > getNvec(unsigned int voxel) const
Returns the vector of pool Num at the specified voxel.
unsigned int startVoxel_
First voxel indexed on the current node.
double getEpsAbs() const
Assigns Absolute tolerance for integration.
bool isBuilt_
Flag: True when solver setup has been completed.
bool isA(const string &ancestor) const
void setNumAllVoxels(unsigned int num)
virtual void setPrev()
Used to tell Dsolver to assign 'prev' values.
const Cinfo * cinfo() const
const unsigned int OFFNODE
void process(const Eref &e, ProcPtr p)
void setMethod(string method)
unsigned int getNumRates() const
unsigned int getNumVarPools() const
Returns number of local pools that are updated by solver.
unsigned int getNumLocalVoxels() const
Inherited from ZombiePoolInterface.
virtual void setBlock(const vector< double > &values)=0
Id getStoich() const
Assigns Stoich object to Ksolve.
Id compartment_
Id of Chem compartment used to figure out volumes of voxels.
void setN(const Eref &e, double v)
Set # of molecules in given pool and voxel. Varies with time.
void setNvec(unsigned int voxel, vector< double > vec)
void initReinit(const Eref &e, ProcPtr p)
unsigned int getNumCoreRates() const
Number of rate terms for reactions purely on this compartment.
unsigned int getNumAllPools() const
const vector< RateTerm * > & getRateTerms() const
Returns a reference to the entire rates_ vector.
static const Cinfo * initCinfo()
double getNinit(const Eref &e) const
get initial # of molecules in given pool and voxel. Bdry cond.
void setDiffConst(const Eref &e, double v)
Diffusion constant: Only one per pool, voxel number is ignored.
Id getDsolve() const
Inherited from ZombiePoolInterface.
void initProc(const Eref &e, ProcPtr p)
double getEpsRel() const
Assigns Relative tolerance for integration.
unsigned int getNumAllVoxels() const
double getEstimatedDt() const
void setEpsAbs(double val)
void setBlock(const vector< double > &values)
unsigned int getVoxelIndex(const Eref &e) const
virtual void getBlock(vector< double > &values) const =0
double getN(const Eref &e) const
Get # of molecules in given pool and voxel. Varies with time.