15 #include "../mesh/VoxelJunction.h"
18 #include "../kinetics/ConcChan.h"
22 #include "../mesh/VoxelJunction.h"
25 #include "../mesh/Boundary.h"
26 #include "../mesh/MeshEntry.h"
27 #include "../mesh/ChemCompt.h"
28 #include "../mesh/MeshCompt.h"
29 #include "../shell/Wildcard.h"
30 #include "../kinetics/PoolBase.h"
31 #include "../kinetics/Pool.h"
32 #include "../kinetics/BufPool.h"
33 #include "../ksolve/ZombiePool.h"
34 #include "../ksolve/ZombieBufPool.h"
44 "Stoichiometry object for handling this reaction system.",
51 "Path of reaction system. Must include all the pools that "
52 "are to be handled by the Dsolve, can also include other "
53 "random objects, which will be ignored.",
60 "Number of voxels in the core reac-diff system, on the "
61 "current diffusion solver. ",
66 "Number of voxels in the core reac-diff system, on the "
67 "current diffusion solver. ",
71 Dsolve,
unsigned int, vector< double > > nVec(
73 "vector of # of molecules along diffusion length, "
74 "looked up by pool index",
81 "Number of molecular pools in the entire reac-diff system, "
82 "including variable, function and buffered.",
89 "Reac-diff compartment in which this diffusion system is "
97 "Volume used to set diffusion scaling: firstVol[ voxel# ] "
98 "Particularly relevant for diffusion between PSD and head.",
105 "Volume used to set diffusion scaling: secondVol[ voxel# ] "
106 "Particularly relevant for diffusion between spine and dend.",
113 "Geometry term to set diffusion scaling: diffScale[ voxel# ] "
114 "Here the scaling term is given by cross-section area/length "
115 "Relevant for diffusion between spine head and dend, or PSD.",
126 "Handles process call",
129 "Handles reinit call",
133 "Builds junctions between mesh on current Dsolve, and another"
134 " Dsolve. The meshes have to be compatible. ",
139 "Builds junctions between NeuroMesh, SpineMesh and PsdMesh",
146 static Finfo* procShared[] = {
150 "Shared message for process and reinit",
151 procShared,
sizeof( procShared ) /
sizeof(
const Finfo* )
154 static Finfo* dsolveFinfos[] =
176 sizeof(dsolveFinfos)/
sizeof(
Finfo *),
193 poolStartIndex_( 0 ),
206 if ( pool <
pools_.size() ) {
207 if ( vec.size() !=
pools_[pool].getNumVoxels() ) {
208 cout <<
"Warning: Dsolve::setNvec: pool index out of range\n";
210 pools_[ pool ].setNvec( vec );
217 static vector< double > ret;
218 if ( pool <
pools_.size() )
221 cout <<
"Warning: Dsolve::setNvec: pool index out of range\n";
225 static bool checkJn(
const vector< DiffJunction >& jn,
unsigned int voxel,
228 if ( jn.size() < 1 ) {
229 cout <<
"Warning: Dsolve::" << info <<
": junctions not defined.\n";
232 if ( jn[0].vj.size() < voxel + 1 ) {
233 cout <<
"Warning: Dsolve:: " << info <<
": " << voxel <<
295 static double integ(
double myN,
double rf,
double rb,
double dt )
298 if ( myN > EPSILON && rf > EPSILON ) {
299 double C = exp( -rf * dt / myN );
300 myN *= C + ( rb / rf ) * ( 1.0 - C );
302 myN += ( rb - rf ) * dt;
313 for (
unsigned int i = 0; i < jn.
myPools.size(); ++i ) {
322 double effectiveDiffConst =
324 for ( vector< VoxelJunction >::const_iterator
325 j = jn.
vj.begin(); j != jn.
vj.end(); ++j ) {
326 double myN = myDv.
getN( j->first );
327 double otherN = otherDv.
getN( j->second );
331 double k = effectiveDiffConst * j->diffScale;
334 k * myN / j->firstVol,
335 k * otherN / j->secondVol,
338 otherN += lastN - myN;
339 if ( otherN < 0.0 ) {
343 myDv.
setN( j->first, myN );
344 otherDv.
setN( j->second, otherN );
350 const vector< unsigned int >& srcXfer,
351 const vector< unsigned int >& destXfer,
354 assert( destXfer.size() == srcXfer.size() );
355 for (
unsigned int i = 0; i < srcXfer.size(); ++i ) {
358 for ( vector< VoxelJunction >::const_iterator
359 j = jn.
vj.begin(); j != jn.
vj.end(); ++j ) {
360 double prevSrc = srcDv.
getPrev( j->first );
361 double prevDest = destDv.
getPrev( j->second );
362 double srcN = srcDv.
getN( j->first );
363 double destN = destDv.
getN( j->second );
366 double newN = srcN + destN - prevSrc;
367 srcDv.
setN( j->first, newN );
368 destDv.
setN( j->second, newN );
388 for (
unsigned int i = 0; i < jn.
myChannels.size(); ++i ) {
393 for ( vector< VoxelJunction >::const_iterator
394 j = jn.
vj.begin(); j != jn.
vj.end(); ++j ) {
396 double myN = myDv.
getN( j->first );
398 double otherN = otherDv.
getN( j->second );
399 double chanN = chanDv.
getN( j->first );
401 myN =
integ( myN, perm * myN/j->firstVol,
402 perm * otherN/j->secondVol, dt );
403 otherN += lastN - myN;
404 if ( otherN < 0.0 ) {
408 myDv.
setN( j->first, myN );
409 otherDv.
setN( j->second, otherN );
417 for (
unsigned int i = 0; i < jn.
otherChannels.size(); ++i ) {
427 for ( vector< VoxelJunction >::const_iterator
428 j = jn.
vj.begin(); j != jn.
vj.end(); ++j ) {
430 double myN = myDv.
getN( j->first );
432 double otherN = otherDv.
getN( j->second );
433 double chanN = chanDv.
getN( j->second );
435 myN =
integ( myN, perm * myN/j->firstVol,
436 perm * otherN/j->secondVol, dt );
437 otherN += lastN - myN;
438 if ( otherN < 0.0 ) {
442 myDv.
setN( j->first, myN );
443 otherDv.
setN( j->second, otherN );
460 assert ( oid !=
Id() );
480 for ( vector< DiffPoolVec >::iterator
489 for ( vector< DiffPoolVec >::iterator
497 for ( vector< DiffJunction >::const_iterator
508 if ( !
id.element()->cinfo()->isA(
"Stoich" ) ) {
509 cout <<
"Dsolve::setStoich::( " <<
id <<
" ): Error: provided Id is not a Stoich\n";
521 for (
unsigned int i = 0; i <
poolMap_.size(); ++i ) {
522 unsigned int poolIndex =
poolMap_[i];
523 if ( poolIndex != ~0U && poolIndex <
pools_.size() ) {
530 double motorConst = pb->getMotorConst( pid.
eref() );
532 pools_[ poolIndex ].setDiffConst( diffConst );
533 pools_[ poolIndex ].setMotorConst( motorConst );
541 string chanpath =
path_ +
"[ISA=ConcChan]";
542 vector< ObjId > chans;
552 static const Finfo* chanPoolFinfo = ccc->
findFinfo(
"setNumChan" );
554 FuncId fout =
static_cast< const DestFinfo*
>(outPoolFinfo )->getFid();
556 static_cast< const DestFinfo*
>(chanPoolFinfo )->getFid();
561 for (
auto i = chans.begin(); i != chans.end(); ++i ) {
563 if (i->element()->getNeighbors( ret, inPoolFinfo ) == 0 )
return;
564 ObjId inPool( ret[0] );
566 if (i->element()->getNeighbors( ret, outPoolFinfo ) == 0 )
return;
567 ObjId outPool( ret[0] );
569 if (i->element()->getNeighbors( ret, chanPoolFinfo ) == 0 )
return;
570 ObjId chanPool( ret[0] );
572 unsigned int outPoolValue = outPool.
id.
value();
573 bool swapped =
false;
574 if ( !( inPool.
bad() or chanPool.
bad() ) ) {
577 if ( inPoolIndex == ~0U ) {
579 outPoolValue = inPool.
id.
value();
582 if ( ( inPoolIndex != ~0U) && (chanPoolIndex != ~0U ) ) {
584 inPoolIndex, outPoolValue, chanPoolIndex,
606 const Cinfo* c =
id.element()->cinfo();
609 if ( c->
isA(
"CubeMesh" ) ) {
613 if ( !( nx*ny == 1 || nx*nz == 1 || ny*nz == 1 ) ) {
614 cout <<
"Warning: Dsolve::setCompartment:: Cube mesh: " <<
615 c->
name() <<
" found with >1 dimension of voxels. " <<
616 "Only 1-D diffusion supported for now.\n";
625 unsigned int minId = 0;
626 unsigned int maxId = 0;
628 for ( vector< ObjId >::const_iterator
629 i = elist.begin(); i != elist.end(); ++i ) {
630 if ( i->element()->cinfo()->isA(
"PoolBase" ) ) {
631 temp.push_back( i->id );
633 maxId = minId = i->id.value();
634 else if ( i->id.value() < minId )
635 minId = i->id.value();
636 else if ( i->id.value() > maxId )
637 maxId = i->id.value();
641 if ( temp.size() == 0 ) {
642 cout <<
"Dsolve::makePoolMapFromElist::( " <<
path_ <<
643 " ): Error: path is has no pools\n";
649 poolMap_.resize( 1 + maxId - minId );
652 for (
unsigned int i = 0; i < temp.size(); ++i ) {
653 unsigned int idValue = temp[i].value();
654 assert( idValue >= minId );
655 assert( idValue - minId <
poolMap_.size() );
662 vector< ObjId > elist;
664 if ( elist.size() == 0 ) {
665 cout <<
"Dsolve::setPath::( " << path <<
" ): Error: path is empty\n";
672 for (
unsigned int i = 0; i < temp.size(); ++i ) {
676 const Cinfo* c =
id.element()->cinfo();
685 cout <<
"Error: Dsolve::setPath( " << path <<
" ): unknown pool class:" << c->
name() << endl;
728 cout <<
"Dsolve::build: Warning: No compartment defined. \n"
729 "Did you forget to assign 'stoich.dsolve = this' ?\n";
738 bool debugFlag =
false;
739 vector< unsigned int > diagIndex;
740 vector< double > diagVal;
741 vector< Triplet< double > > fops;
746 pools_[i].getDiffConst(),
pools_[i].getMotorConst(), dt ) )
750 vector< unsigned int > lookupOldRowsFromNew;
756 elim.
opsReorder( lookupOldRowsFromNew, fops, diagVal );
760 pools_[i].setOps( fops, diagVal );
771 cout <<
"Warning: Dsolve::buildNeuroMeshJunction: Compartment '" <<
777 cout <<
"Warning: Dsolve::buildNeuroMeshJunction: Compartment '" <<
778 spineMesh.
path() <<
"' is not a SpineMesh\n";
783 cout <<
"Warning: Dsolve::buildNeuroMeshJunction: Compartment '" <<
784 psdMesh.
path() <<
"' is not a PsdMesh\n";
799 bool isMembraneBound =
805 cout <<
"Warning: Dsolve::buildMeshJunctions: one of '" <<
812 cout <<
"Junction between " <<
self.path() <<
", " << other.
path() << endl;
813 cout <<
"Pool indices: myPools, otherPools\n";
814 for (
unsigned int i = 0; i < jn.
myPools.size(); ++i )
816 cout <<
"Voxel junctions: first second firstVol secondVol diffScale\n";
817 for (
unsigned int i = 0; i < jn.
vj.size(); ++i ) {
818 cout << i <<
" " << jn.
vj[i].first <<
" " << jn.
vj[i].second <<
819 " " << jn.
vj[i].firstVol <<
" " << jn.
vj[i].secondVol <<
820 " " << jn.
vj[i].diffScale << endl;
827 Dsolve* mySolve =
reinterpret_cast< Dsolve*
>(
self.eref().data() );
828 unordered_map< string, unsigned int > myPools;
829 for (
unsigned int i = 0; i < mySolve->
pools_.size(); ++i ) {
830 Id pool( mySolve->
pools_[i].getId() );
831 assert( pool !=
Id() );
832 myPools[ pool.element()->getName() ] = i;
835 const Dsolve* otherSolve =
reinterpret_cast< const Dsolve*
>(
837 for (
unsigned int i = 0; i < otherSolve->
pools_.size(); ++i ) {
838 Id otherPool( otherSolve->
pools_[i].getId() );
839 unordered_map< string, unsigned int >::iterator p =
840 myPools.find( otherPool.element()->getName() );
841 if ( p != myPools.end() ) {
843 jn.
myPools.push_back( p->second );
859 vector< unsigned int >& srcPools, vector< unsigned int >& destPools,
863 string xferPost(
string(
"_xfer_" ) + destMesh.
element()->
getName() );
864 size_t xlen = xferPost.length();
867 unordered_map< string, unsigned int > srcMap;
868 for (
unsigned int i = 0; i < srcSolve->
pools_.size(); ++i ) {
869 Id pool( srcSolve->
pools_[i].getId() );
870 assert( pool !=
Id() );
871 string poolName = pool.element()->getName();
872 if ( poolName.length() > xlen ) {
873 size_t prefixLen = poolName.length() - xlen;
874 if ( poolName.rfind( xferPost ) == prefixLen )
875 srcMap[ poolName.substr( 0, prefixLen) ] = i;
879 const Dsolve* destSolve =
reinterpret_cast< const Dsolve*
>(
881 for (
unsigned int i = 0; i < destSolve->
pools_.size(); ++i ) {
882 Id destPool( destSolve->
pools_[i].getId() );
883 unordered_map< string, unsigned int >::iterator p =
884 srcMap.find( destPool.element()->getName() );
885 if ( p != srcMap.end() ) {
886 destPools.push_back( i );
887 srcPools.push_back( p->second );
896 Dsolve* selfSolve =
reinterpret_cast< Dsolve*
>(
self.eref().data() );
897 vector< ConcChanInfo >& ch = selfSolve->
channels_;
898 unsigned int outIndex;
899 for (
unsigned int i = 0; i < ch.size(); ++i ) {
900 unsigned int chanIndex = ch[i].chanPool;
902 if ( (outIndex != ~0U) && (chanIndex != ~0U ) ) {
904 ch[i].otherPool = outIndex;
905 ch[i].chanPool = chanIndex;
909 vector< ConcChanInfo >& ch2 = otherSolve->
channels_;
910 for (
unsigned int i = 0; i < ch2.size(); ++i ) {
911 unsigned int chanIndex = ch2[i].chanPool;
913 if ( (outIndex != ~0U) && (chanIndex != ~0U) ) {
915 ch2[i].otherPool = outIndex;
916 ch2[i].chanPool = chanIndex;
933 for ( vector< VoxelJunction >::iterator
934 i = jn.
vj.begin(); i != jn.
vj.end(); ++i ) {
935 i->firstVol = myVols[i->first];
936 i->secondVol = otherVols[i->second];
945 Dsolve* dself =
reinterpret_cast< Dsolve*
>(
self.eref().data() );
946 if ( selfIsMembraneBound ) {
988 cout <<
"Warning: Dsolve::convertIdToPoollndex: Id out of range, (" <<
1003 if ( pid >=
pools_.size() )
1007 pools_[ pid ].setN( vox, v );
1010 cout <<
"Warning: Dsolve::setN: Eref " << e <<
" out of range " <<
1017 if ( pid >=
pools_.size() )
return 0.0;
1020 return pools_[ pid ].getN( vox );
1022 cout <<
"Warning: Dsolve::setN: Eref " << e <<
" out of range " <<
1030 if ( pid >=
pools_.size() )
1034 pools_[ pid ].setNinit( vox, v );
1037 cout <<
"Warning: Dsolve::setNinit: Eref " << e <<
" out of range " <<
1044 if ( pid >=
pools_.size() )
return 0.0;
1047 return pools_[ pid ].getNinit( vox );
1049 cout <<
"Warning: Dsolve::setNinit: Eref " << e <<
" out of range " <<
1057 if ( pid >=
pools_.size() )
1065 if ( pid >=
pools_.size() )
1073 if ( pid >=
pools_.size() )
1101 unsigned int startVoxel = values[0];
1102 unsigned int numVoxels = values[1];
1103 unsigned int startPool = values[2];
1104 unsigned int numPools = values[3];
1106 assert( startVoxel + numVoxels <=
numVoxels_ );
1111 for (
unsigned int i = 0; i < numPools; ++i ) {
1112 unsigned int j = i + startPool;
1114 vector< double >::const_iterator q =
1117 values.insert( values.end(),
1118 q + startVoxel, q + startVoxel + numVoxels );
1126 for (
auto i =
pools_.begin(); i !=
pools_.end(); ++i ) {
1134 unsigned int startVoxel = values[0];
1135 unsigned int numVoxels = values[1];
1136 unsigned int startPool = values[2];
1137 unsigned int numPools = values[3];
1139 assert( startVoxel + numVoxels <=
numVoxels_ );
1142 assert( values.size() == 4 + numVoxels * numPools );
1144 for (
unsigned int i = 0; i < numPools; ++i ) {
1145 unsigned int j = i + startPool;
1147 vector< double >::const_iterator
1148 q = values.begin() + 4 + i * numVoxels;
void setNumAllVoxels(unsigned int numVoxels)
Inherited virtual.
int wildcardFind(const string &path, vector< ObjId > &ret)
void fillConcChans(const vector< ObjId > &chans)
void calcJunction(const DiffJunction &jn, double dt)
string getPath(const Eref &e) const
double getDiffScale(unsigned int voxel) const
void setDiffScale(unsigned int voxel, double scale)
string path_
Path of pools managed by Dsolve, may include other classes too.
unsigned int poolMapStart_
smallest Id value for poolMap_
void setN(unsigned int vox, double value)
unsigned int getNumVoxels() const
Element * element() const
Synonym for Id::operator()()
void setPath(const Eref &e, string path)
Dummy, inherited but not used.
void buildBackwardSub(vector< unsigned int > &diag, vector< Triplet< double > > &bops, vector< double > &diagVal)
static const Cinfo * initCinfo()
static void innerBuildMeshJunctions(Id self, Id other, bool isMembraneBound)
unsigned int getNumLocalVoxels() const
Number of voxels here. pools_.size() == getNumLocalVoxels.
std::string path(const std::string &separator="/") const
void setNumPools(unsigned int num)
Specifies number of pools (species) handled by system.
unsigned int value() const
vector< double > getVoxelVolume() const
Returns vector of all voxel volumes in compartment.
unsigned int dataIndex() const
double getNinit(const Eref &e) const
get initial # of molecules in given pool and voxel. Bdry cond.
unsigned int numTotPools_
static const Cinfo * find(const std::string &name)
vector< unsigned int > otherPools
int simpleWildcardFind(const string &path, vector< ObjId > &ret)
vector< DiffJunction > junctions_
double getDiffVol2(unsigned int voxel) const
bool hinesReorder(const vector< unsigned int > &parentVoxel, vector< unsigned int > &lookupOldRowsFromNew)
static void mapChansBetweenDsolves(DiffJunction &jn, Id self, Id other)
void calcJnDiff(const DiffJunction &jn, Dsolve *other, double dt)
double dt_
Timestep used by diffusion calculations.
vector< unsigned int > otherXferSrc
virtual vector< unsigned int > getParentVoxel() const =0
void setMotorConst(const Eref &e, double value)
static void zombify(Element *original, const Cinfo *zClass, Id ksolve, Id dsolve)
unsigned int getNumEntries() const
Id getCompartment() const
double getDiffConst() const
vector< double > getNvec(unsigned int pool) const
bool doubleEq(double x, double y)
const std::string & name() const
void setNinit(const Eref &e, double value)
Set initial # of molecules in given pool and voxel. Bdry cond.
void setNvec(unsigned int pool, vector< double > vec)
static double integ(double myN, double rf, double rb, double dt)
static const Cinfo * initCinfo()
double volume(unsigned int i) const
Return volume of voxel i.
static const Cinfo * initCinfo()
void printJunction(Id self, Id other, const DiffJunction &jn)
void calcJnChan(const DiffJunction &jn, Dsolve *other, double dt)
vector< ConcChanInfo > channels_
Internal vector, one for each ConcChan managed by Dsolve.
void setDiffConst(const Eref &e, double value)
Diffusion constant: Only one per pool, voxel number is ignored.
static const Cinfo * dsolveCinfo
void setPrev()
Used to tell Dsolver to assign 'prev' values.
static const Cinfo * initCinfo()
static const Cinfo * initCinfo()
vector< unsigned int > myPools
void getBlock(vector< double > &values) const
vector< unsigned int > myChannels
void buildMeshJunctions(const Eref &e, Id other)
static void mapVoxelsBetweenMeshes(DiffJunction &jn, Id self, Id other)
void setDsolve(Id id)
Inherited, defining dummy function here.
static void opsReorder(const vector< unsigned int > &lookupOldRowsFromNew, vector< Triplet< double > > &ops, vector< double > &diagVal)
vector< unsigned int > myXferSrc
void makePoolMapFromElist(const vector< ObjId > &elist, vector< Id > &temp)
bool isA(const string &ancestor) const
bool checkSymmetricShape() const
const Cinfo * cinfo() const
vector< unsigned int > otherXferDest
static void mapXfersBetweenDsolves(vector< unsigned int > &srcPools, vector< unsigned int > &destPools, Id src, Id dest)
void calcJnXfer(const DiffJunction &jn, const vector< unsigned int > &srcXfer, const vector< unsigned int > &destXfer, Dsolve *srcDsolve, Dsolve *destDsolve)
unsigned int numLocalPools_
double firstVol
MeshIndex for second compartment.
void setBlock(const vector< double > &values)
vector< unsigned int > myXferDest
vector< DiffPoolVec > pools_
Internal vector, one for each pool species managed by Dsolve.
virtual const vector< double > & getVoxelArea() const =0
unsigned int getPoolIndex(const Eref &e) const
Return pool index, using Stoich ptr to do lookup.
unsigned int getNumVarPools() const
void setDiffVol2(unsigned int voxel, double vol)
void updateJunctions(double dt)
Used for telling Dsolver to handle all ops across Junctions.
double getDiffVol1(unsigned int voxel) const
LookupFied for examining cross-solver diffusion terms.
void setN(const Eref &e, double value)
Set # of molecules in given pool and voxel. Varies with time.
static void mapDiffPoolsBetweenDsolves(DiffJunction &jn, Id self, Id other)
Sets up map of matching pools for diffusion.
void setCompartment(Id id)
Assigns compartment.
static bool checkJn(const vector< DiffJunction > &jn, unsigned int voxel, const string &info)
virtual const vector< double > & getVoxelLength() const =0
Id compartment_
Id of Chem compartment used to figure out volumes of voxels.
unsigned int getNumPools() const
gets number of pools (species) handled by system.
void calcOtherJnChan(const DiffJunction &jn, Dsolve *other, double dt)
bool buildForDiffusion(const vector< unsigned int > &parentVoxel, const vector< double > &volume, const vector< double > &area, const vector< double > &length, double diffConst, double motorConst, double dt)
This function makes the diffusion matrix.
virtual void matchMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const =0
void reinit(const Eref &e, ProcPtr p)
vector< VoxelJunction > vj
static A get(const ObjId &dest, const string &field)
static const Cinfo * initCinfo()
VoxelPoolsBase * pools(unsigned int i)
Return a pointer to the specified VoxelPool.
void setDiffVol1(unsigned int voxel, double vol)
void process(const Eref &e, ProcPtr p)
double getDiffConst(const Eref &e) const
double getN(const Eref &e) const
Get # of molecules in given pool and voxel. Varies with time.
const string & getName() const
double getDiffConst(const Eref &e) const
Diffusion constant: Only one per pool, voxel number is ignored.
void buildNeuroMeshJunctions(const Eref &e, Id spineD, Id psdD)
void updateRateTerms(unsigned int index)
void buildForwardElim(vector< unsigned int > &diag, vector< Triplet< double > > &fops)
vector< unsigned int > poolMap_
Looks up pool# from pool Id, using poolMapStart_ as offset.
unsigned int convertIdToPoolIndex(Id id) const
vector< unsigned int > otherChannels
double getN(unsigned int vox) const
double getPrev(unsigned int vox) const
const Finfo * findFinfo(const string &name) const
unsigned int poolStartIndex_