@@ -412,6 +412,8 @@ void Dsolve::calcJnChan( const DiffJunction& jn, Dsolve* other, double dt )
412
412
413
413
for ( unsigned int i = 0 ; i < jn.myChannels .size (); ++i )
414
414
{
415
+ if ( channels_[ jn.myChannels [i] ].isLocal )
416
+ continue ;
415
417
ConcChanInfo& myChan = channels_[ jn.myChannels [i] ];
416
418
DiffPoolVec& myDv = pools_[ myChan.myPool ];
417
419
DiffPoolVec& otherDv = other->pools_ [ myChan.otherPool ];
@@ -426,7 +428,7 @@ void Dsolve::calcJnChan( const DiffJunction& jn, Dsolve* other, double dt )
426
428
double chanN = chanDv.getN ( j->first );
427
429
// Stick in a conversion factor for the myN and otherN into
428
430
// concentrations. Note that SI is millimolar.
429
- double perm = myChan.permeability * chanN * 1000.0 / NA;
431
+ double perm = myChan.permeability * chanN / NA;
430
432
myN = integ ( myN, perm * myN/j->firstVol ,
431
433
perm * otherN/j->secondVol , dt );
432
434
otherN += lastN - myN; // Mass consv
@@ -446,6 +448,8 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt )
446
448
{
447
449
for ( unsigned int i = 0 ; i < jn.otherChannels .size (); ++i )
448
450
{
451
+ if ( other->channels_ [ jn.otherChannels [i] ].isLocal )
452
+ continue ;
449
453
ConcChanInfo& otherChan = other->channels_ [ jn.otherChannels [i] ];
450
454
// This is the DiffPoolVec for the pools on the other Dsolve,
451
455
// the one with the channel.
@@ -465,7 +469,7 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt )
465
469
double chanN = chanDv.getN ( j->second );
466
470
// Stick in a conversion factor for the myN and otherN into
467
471
// concentrations. Note that SI is millimolar.
468
- double perm = otherChan.permeability * chanN * 1000.0 / NA;
472
+ double perm = otherChan.permeability * chanN / NA;
469
473
myN = integ ( myN, perm * myN/j->firstVol ,
470
474
perm * otherN/j->secondVol , dt );
471
475
otherN += lastN - myN; // Mass consv
@@ -480,6 +484,46 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt )
480
484
}
481
485
}
482
486
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
+
483
527
/* *
484
528
* Computes flux through a junction between diffusion solvers.
485
529
* 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 )
525
569
526
570
void Dsolve::updateJunctions ( double dt )
527
571
{
572
+ calcLocalChan ( dt );
528
573
for (auto i = junctions_.begin (); i != junctions_.end (); ++i )
529
574
calcJunction ( *i, dt );
530
575
}
@@ -614,7 +659,8 @@ void Dsolve::fillConcChans( const vector< ObjId >& chans )
614
659
ret.clear ();
615
660
unsigned int outPoolValue = outPool.id .value ();
616
661
bool swapped = false ;
617
- if ( !( inPool.bad () or chanPool.bad () ) )
662
+ bool isLocal = false ;
663
+ if ( !( inPool.bad () || chanPool.bad () ) )
618
664
{
619
665
unsigned int inPoolIndex = convertIdToPoolIndex ( inPool.id );
620
666
unsigned int chanPoolIndex = convertIdToPoolIndex (chanPool.id );
@@ -623,14 +669,22 @@ void Dsolve::fillConcChans( const vector< ObjId >& chans )
623
669
inPoolIndex = convertIdToPoolIndex ( outPool.id );
624
670
outPoolValue = inPool.id .value ();
625
671
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
+ }
627
682
if ( ( inPoolIndex != ~0U ) && (chanPoolIndex != ~0U ) )
628
683
{
629
684
ConcChanInfo cci (
630
685
inPoolIndex, outPoolValue, chanPoolIndex,
631
686
Field< double >::get ( *i, " permeability" ),
632
- // //// Fix it below ////////
633
- swapped
687
+ swapped, isLocal
634
688
);
635
689
channels_.push_back ( cci );
636
690
}
@@ -972,27 +1026,29 @@ void Dsolve::mapChansBetweenDsolves( DiffJunction& jn, Id self, Id other)
972
1026
unsigned int outIndex;
973
1027
for ( unsigned int i = 0 ; i < ch.size (); ++i )
974
1028
{
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 ) {
979
1030
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
+ }
982
1037
}
983
1038
}
984
1039
// Now set up the other Dsolve.
985
1040
vector< ConcChanInfo >& ch2 = otherSolve->channels_ ;
986
1041
for ( unsigned int i = 0 ; i < ch2.size (); ++i )
987
1042
{
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 ) {
992
1044
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
+ }
996
1052
}
997
1053
}
998
1054
@@ -1063,15 +1119,18 @@ void Dsolve::setNumAllVoxels( unsigned int num )
1063
1119
1064
1120
unsigned int Dsolve::convertIdToPoolIndex ( const Id id ) const
1065
1121
{
1122
+ bool verbose = false ;
1066
1123
unsigned int i = id.value () - poolMapStart_;
1067
1124
if ( i < poolMap_.size () )
1068
1125
{
1069
1126
return poolMap_[i];
1070
1127
}
1071
- cout << " Warning: Dsolve::convertIdToPoollndex: Id out of range, (" <<
1128
+ if ( verbose ) {
1129
+ cout << " Warning: Dsolve::convertIdToPoollndex: Id out of range, (" <<
1072
1130
poolMapStart_ << " , " << id << " , " << id.path () << " , " <<
1073
1131
poolMap_.size () + poolMapStart_ << " \n " ;
1074
- return 0 ;
1132
+ }
1133
+ return ~0U ;
1075
1134
}
1076
1135
1077
1136
unsigned int Dsolve::convertIdToPoolIndex ( const Eref& e ) const
@@ -1083,7 +1142,7 @@ void Dsolve::setN( const Eref& e, double v )
1083
1142
{
1084
1143
unsigned int pid = convertIdToPoolIndex ( e );
1085
1144
// 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 () )
1087
1146
return ;
1088
1147
unsigned int vox = e.dataIndex ();
1089
1148
if ( vox < numVoxels_ )
@@ -1098,7 +1157,7 @@ void Dsolve::setN( const Eref& e, double v )
1098
1157
double Dsolve::getN ( const Eref& e ) const
1099
1158
{
1100
1159
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
1102
1161
unsigned int vox = e.dataIndex ();
1103
1162
if ( vox < numVoxels_ )
1104
1163
{
@@ -1112,7 +1171,7 @@ double Dsolve::getN( const Eref& e ) const
1112
1171
void Dsolve::setNinit ( const Eref& e, double v )
1113
1172
{
1114
1173
unsigned int pid = convertIdToPoolIndex ( e );
1115
- if ( pid >= pools_.size () ) // Ignore silently
1174
+ if ( pid == ~ 0U || pid >= pools_.size () ) // Ignore silently
1116
1175
return ;
1117
1176
unsigned int vox = e.dataIndex ();
1118
1177
if ( vox < numVoxels_ )
@@ -1127,7 +1186,7 @@ void Dsolve::setNinit( const Eref& e, double v )
1127
1186
double Dsolve::getNinit ( const Eref& e ) const
1128
1187
{
1129
1188
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
1131
1190
unsigned int vox = e.dataIndex ();
1132
1191
if ( vox < numVoxels_ )
1133
1192
{
@@ -1141,36 +1200,52 @@ double Dsolve::getNinit( const Eref& e ) const
1141
1200
void Dsolve::setDiffConst ( const Eref& e, double v )
1142
1201
{
1143
1202
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.
1145
1204
return ;
1146
- pools_[ convertIdToPoolIndex ( e ) ].setDiffConst ( v );
1205
+ pools_[ pid ].setDiffConst ( v );
1147
1206
}
1148
1207
1149
1208
double Dsolve::getDiffConst ( const Eref& e ) const
1150
1209
{
1151
1210
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.
1153
1212
return 0.0 ;
1154
- return pools_[ convertIdToPoolIndex ( e ) ].getDiffConst ();
1213
+ return pools_[ pid ].getDiffConst ();
1155
1214
}
1156
1215
1157
1216
void Dsolve::setMotorConst ( const Eref& e, double v )
1158
1217
{
1159
1218
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.
1161
1220
return ;
1162
- pools_[ convertIdToPoolIndex ( e ) ].setMotorConst ( v );
1221
+ pools_[ pid ].setMotorConst ( v );
1163
1222
}
1164
1223
1165
- void Dsolve::setNumPools ( unsigned int numPoolSpecies )
1224
+ void Dsolve::setNumVarTotPools ( unsigned int var, unsigned int tot )
1166
1225
{
1167
1226
// Decompose numPoolSpecies here, assigning some to each node.
1168
- numTotPools_ = numPoolSpecies ;
1169
- numLocalPools_ = numPoolSpecies ;
1227
+ numTotPools_ = tot ;
1228
+ numLocalPools_ = var ;
1170
1229
poolStartIndex_ = 0 ;
1171
1230
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 )
1174
1249
{
1175
1250
pools_[i].setNumVoxels ( numVoxels_ );
1176
1251
// pools_[i].setId( reversePoolMap_[i] );
0 commit comments