@@ -412,6 +412,8 @@ void Dsolve::calcJnChan( const DiffJunction& jn, Dsolve* other, double dt )
412412
413413 for ( unsigned int i = 0 ; i < jn.myChannels .size (); ++i )
414414 {
415+ if ( channels_[ jn.myChannels [i] ].isLocal )
416+ continue ;
415417 ConcChanInfo& myChan = channels_[ jn.myChannels [i] ];
416418 DiffPoolVec& myDv = pools_[ myChan.myPool ];
417419 DiffPoolVec& otherDv = other->pools_ [ myChan.otherPool ];
@@ -426,7 +428,7 @@ void Dsolve::calcJnChan( const DiffJunction& jn, Dsolve* other, double dt )
426428 double chanN = chanDv.getN ( j->first );
427429 // Stick in a conversion factor for the myN and otherN into
428430 // concentrations. Note that SI is millimolar.
429- double perm = myChan.permeability * chanN * 1000.0 / NA;
431+ double perm = myChan.permeability * chanN / NA;
430432 myN = integ ( myN, perm * myN/j->firstVol ,
431433 perm * otherN/j->secondVol , dt );
432434 otherN += lastN - myN; // Mass consv
@@ -446,6 +448,8 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt )
446448{
447449 for ( unsigned int i = 0 ; i < jn.otherChannels .size (); ++i )
448450 {
451+ if ( other->channels_ [ jn.otherChannels [i] ].isLocal )
452+ continue ;
449453 ConcChanInfo& otherChan = other->channels_ [ jn.otherChannels [i] ];
450454 // This is the DiffPoolVec for the pools on the other Dsolve,
451455 // the one with the channel.
@@ -465,7 +469,7 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt )
465469 double chanN = chanDv.getN ( j->second );
466470 // Stick in a conversion factor for the myN and otherN into
467471 // concentrations. Note that SI is millimolar.
468- double perm = otherChan.permeability * chanN * 1000.0 / NA;
472+ double perm = otherChan.permeability * chanN / NA;
469473 myN = integ ( myN, perm * myN/j->firstVol ,
470474 perm * otherN/j->secondVol , dt );
471475 otherN += lastN - myN; // Mass consv
@@ -480,6 +484,46 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt )
480484 }
481485}
482486
487+ void Dsolve::calcLocalChan ( double dt )
488+ {
489+ // There may be some chans which connect within the compartment.
490+ // This is odd biologically, but happens for modelling convenience.
491+ // The channels have a flag indicating if this is so. It is a simple
492+ // calculation, but lacks numerical accuracy as it is outside the
493+ // solver framework.
494+
495+ ChemCompt* cc = reinterpret_cast < ChemCompt* >( compartment_.eref ().data () );
496+ const vector< double >& vols = cc->vGetVoxelVolume ();
497+ for (auto ch = channels_.begin (); ch != channels_.end (); ++ch ) {
498+ if ( ch->isLocal ) {
499+ DiffPoolVec& myDv = pools_[ ch->myPool ];
500+ DiffPoolVec& otherDv = pools_[ ch->otherPool ];
501+ DiffPoolVec& chanDv = pools_[ ch->chanPool ];
502+ assert ( myDv.getNumVoxels () == numVoxels_ );
503+ for (unsigned int i = 0 ; i < numVoxels_; ++i ) {
504+ double myN = myDv.getN ( i );
505+ double lastN = myN;
506+ double otherN = otherDv.getN ( i );
507+ double chanN = chanDv.getN ( i );
508+ double vol = vols[i];
509+ // Stick in a conversion factor for the myN and otherN into
510+ // concentrations. Note that SI is millimolar.
511+ double perm = ch->permeability * chanN / NA;
512+ myN = integ ( myN, perm * myN/vol, perm * otherN/vol, dt );
513+ otherN += lastN - myN; // Mass consv
514+ if ( otherN < 0.0 ) // Avoid negatives
515+ {
516+ myN += otherN;
517+ otherN = 0.0 ;
518+ }
519+ myDv.setN ( i, myN );
520+ otherDv.setN ( i, otherN );
521+ }
522+ }
523+ }
524+ }
525+
526+
483527/* *
484528 * Computes flux through a junction between diffusion solvers.
485529 * Most used at junctions on spines and PSDs, but can also be used
@@ -525,6 +569,7 @@ void Dsolve::reinit( const Eref& e, ProcPtr p )
525569
526570void Dsolve::updateJunctions ( double dt )
527571{
572+ calcLocalChan ( dt );
528573 for (auto i = junctions_.begin (); i != junctions_.end (); ++i )
529574 calcJunction ( *i, dt );
530575}
@@ -614,7 +659,8 @@ void Dsolve::fillConcChans( const vector< ObjId >& chans )
614659 ret.clear ();
615660 unsigned int outPoolValue = outPool.id .value ();
616661 bool swapped = false ;
617- if ( !( inPool.bad () or chanPool.bad () ) )
662+ bool isLocal = false ;
663+ if ( !( inPool.bad () || chanPool.bad () ) )
618664 {
619665 unsigned int inPoolIndex = convertIdToPoolIndex ( inPool.id );
620666 unsigned int chanPoolIndex = convertIdToPoolIndex (chanPool.id );
@@ -623,14 +669,22 @@ void Dsolve::fillConcChans( const vector< ObjId >& chans )
623669 inPoolIndex = convertIdToPoolIndex ( outPool.id );
624670 outPoolValue = inPool.id .value ();
625671 swapped = true ;
626- }
672+ } else {
673+ unsigned int outPoolIndex = convertIdToPoolIndex ( outPool.id );
674+ // edge case where both in and out are on same compartment.
675+ // Not much sense in bio, but a common convenience hack.
676+ if ( outPoolIndex != ~0U ) {
677+ outPoolValue = outPoolIndex;
678+ isLocal = true ;
679+ }
680+
681+ }
627682 if ( ( inPoolIndex != ~0U ) && (chanPoolIndex != ~0U ) )
628683 {
629684 ConcChanInfo cci (
630685 inPoolIndex, outPoolValue, chanPoolIndex,
631686 Field< double >::get ( *i, " permeability" ),
632- // //// Fix it below ////////
633- swapped
687+ swapped, isLocal
634688 );
635689 channels_.push_back ( cci );
636690 }
@@ -972,27 +1026,29 @@ void Dsolve::mapChansBetweenDsolves( DiffJunction& jn, Id self, Id other)
9721026 unsigned int outIndex;
9731027 for ( unsigned int i = 0 ; i < ch.size (); ++i )
9741028 {
975- unsigned int chanIndex = ch[i].chanPool ;
976- outIndex = otherSolve->convertIdToPoolIndex ( ch[i].otherPool );
977- if ( (outIndex != ~0U ) && (chanIndex != ~0U ) )
978- {
1029+ if ( ch[i].isLocal ) {
9791030 jn.myChannels .push_back (i);
980- ch[i].otherPool = outIndex; // replace the Id with the index.
981- ch[i].chanPool = chanIndex; // chanIndex may be on either Dsolve
1031+ } else {
1032+ outIndex = otherSolve->convertIdToPoolIndex ( ch[i].otherPool );
1033+ if (outIndex != ~0U ) {
1034+ ch[i].otherPool = outIndex; // replace Id with the index.
1035+ jn.myChannels .push_back (i);
1036+ }
9821037 }
9831038 }
9841039 // Now set up the other Dsolve.
9851040 vector< ConcChanInfo >& ch2 = otherSolve->channels_ ;
9861041 for ( unsigned int i = 0 ; i < ch2.size (); ++i )
9871042 {
988- unsigned int chanIndex = ch2[i].chanPool ;
989- outIndex = selfSolve->convertIdToPoolIndex ( ch2[i].otherPool );
990- if ( (outIndex != ~0U ) && (chanIndex != ~0U ) )
991- {
1043+ if ( ch2[i].isLocal ) {
9921044 jn.otherChannels .push_back (i);
993- ch2[i].otherPool = outIndex; // replace the Id with the index
994- ch2[i].chanPool = chanIndex; // chanIndex may be on either Dsolve
995- }
1045+ } else {
1046+ outIndex = selfSolve->convertIdToPoolIndex ( ch2[i].otherPool );
1047+ if ( outIndex != ~0U ) {
1048+ ch2[i].otherPool = outIndex; // replace Id with the index
1049+ jn.otherChannels .push_back (i);
1050+ }
1051+ }
9961052 }
9971053}
9981054
@@ -1063,15 +1119,18 @@ void Dsolve::setNumAllVoxels( unsigned int num )
10631119
10641120unsigned int Dsolve::convertIdToPoolIndex ( const Id id ) const
10651121{
1122+ bool verbose = false ;
10661123 unsigned int i = id.value () - poolMapStart_;
10671124 if ( i < poolMap_.size () )
10681125 {
10691126 return poolMap_[i];
10701127 }
1071- cout << " Warning: Dsolve::convertIdToPoollndex: Id out of range, (" <<
1128+ if ( verbose ) {
1129+ cout << " Warning: Dsolve::convertIdToPoollndex: Id out of range, (" <<
10721130 poolMapStart_ << " , " << id << " , " << id.path () << " , " <<
10731131 poolMap_.size () + poolMapStart_ << " \n " ;
1074- return 0 ;
1132+ }
1133+ return ~0U ;
10751134}
10761135
10771136unsigned int Dsolve::convertIdToPoolIndex ( const Eref& e ) const
@@ -1083,7 +1142,7 @@ void Dsolve::setN( const Eref& e, double v )
10831142{
10841143 unsigned int pid = convertIdToPoolIndex ( e );
10851144 // Ignore silently, as this may be a valid pid for the ksolve to use.
1086- if ( pid >= pools_.size () )
1145+ if ( pid == ~ 0U || pid >= pools_.size () )
10871146 return ;
10881147 unsigned int vox = e.dataIndex ();
10891148 if ( vox < numVoxels_ )
@@ -1098,7 +1157,7 @@ void Dsolve::setN( const Eref& e, double v )
10981157double Dsolve::getN ( const Eref& e ) const
10991158{
11001159 unsigned int pid = convertIdToPoolIndex ( e );
1101- if ( pid >= pools_.size () ) return 0.0 ; // ignore silently
1160+ if ( pid == ~ 0U || pid >= pools_.size () ) return 0.0 ; // ignore silently
11021161 unsigned int vox = e.dataIndex ();
11031162 if ( vox < numVoxels_ )
11041163 {
@@ -1112,7 +1171,7 @@ double Dsolve::getN( const Eref& e ) const
11121171void Dsolve::setNinit ( const Eref& e, double v )
11131172{
11141173 unsigned int pid = convertIdToPoolIndex ( e );
1115- if ( pid >= pools_.size () ) // Ignore silently
1174+ if ( pid == ~ 0U || pid >= pools_.size () ) // Ignore silently
11161175 return ;
11171176 unsigned int vox = e.dataIndex ();
11181177 if ( vox < numVoxels_ )
@@ -1127,7 +1186,7 @@ void Dsolve::setNinit( const Eref& e, double v )
11271186double Dsolve::getNinit ( const Eref& e ) const
11281187{
11291188 unsigned int pid = convertIdToPoolIndex ( e );
1130- if ( pid >= pools_.size () ) return 0.0 ; // ignore silently
1189+ if ( pid == ~ 0U || pid >= pools_.size () ) return 0.0 ; // ignore silently
11311190 unsigned int vox = e.dataIndex ();
11321191 if ( vox < numVoxels_ )
11331192 {
@@ -1141,36 +1200,52 @@ double Dsolve::getNinit( const Eref& e ) const
11411200void Dsolve::setDiffConst ( const Eref& e, double v )
11421201{
11431202 unsigned int pid = convertIdToPoolIndex ( e );
1144- if ( pid >= pools_.size () ) // Ignore silently, out of range.
1203+ if ( pid == ~ 0U || pid >= pools_.size () ) // Ignore silently, out of range.
11451204 return ;
1146- pools_[ convertIdToPoolIndex ( e ) ].setDiffConst ( v );
1205+ pools_[ pid ].setDiffConst ( v );
11471206}
11481207
11491208double Dsolve::getDiffConst ( const Eref& e ) const
11501209{
11511210 unsigned int pid = convertIdToPoolIndex ( e );
1152- if ( pid >= pools_.size () ) // Ignore silently, out of range.
1211+ if ( pid == ~ 0U || pid >= pools_.size () ) // Ignore silently, out of range.
11531212 return 0.0 ;
1154- return pools_[ convertIdToPoolIndex ( e ) ].getDiffConst ();
1213+ return pools_[ pid ].getDiffConst ();
11551214}
11561215
11571216void Dsolve::setMotorConst ( const Eref& e, double v )
11581217{
11591218 unsigned int pid = convertIdToPoolIndex ( e );
1160- if ( pid >= pools_.size () ) // Ignore silently, out of range.
1219+ if ( pid == ~ 0U || pid >= pools_.size () ) // Ignore silently, out of range.
11611220 return ;
1162- pools_[ convertIdToPoolIndex ( e ) ].setMotorConst ( v );
1221+ pools_[ pid ].setMotorConst ( v );
11631222}
11641223
1165- void Dsolve::setNumPools ( unsigned int numPoolSpecies )
1224+ void Dsolve::setNumVarTotPools ( unsigned int var, unsigned int tot )
11661225{
11671226 // Decompose numPoolSpecies here, assigning some to each node.
1168- numTotPools_ = numPoolSpecies ;
1169- numLocalPools_ = numPoolSpecies ;
1227+ numTotPools_ = tot ;
1228+ numLocalPools_ = var ;
11701229 poolStartIndex_ = 0 ;
11711230
1172- pools_.resize ( numLocalPools_ );
1173- for ( unsigned int i = 0 ; i < numLocalPools_; ++i )
1231+ pools_.resize ( numTotPools_ );
1232+ for ( unsigned int i = 0 ; i < numTotPools_; ++i )
1233+ {
1234+ pools_[i].setNumVoxels ( numVoxels_ );
1235+ // pools_[i].setId( reversePoolMap_[i] );
1236+ // pools_[i].setParent( me );
1237+ }
1238+ }
1239+
1240+ void Dsolve::setNumPools ( unsigned int numVarPoolSpecies )
1241+ {
1242+ // Decompose numPoolSpecies here, assigning some to each node.
1243+ numTotPools_ = numVarPoolSpecies;
1244+ numLocalPools_ = numVarPoolSpecies;
1245+ poolStartIndex_ = 0 ;
1246+
1247+ pools_.resize ( numTotPools_ );
1248+ for ( unsigned int i = 0 ; i < numTotPools_; ++i )
11741249 {
11751250 pools_[i].setNumVoxels ( numVoxels_ );
11761251 // pools_[i].setId( reversePoolMap_[i] );
0 commit comments