Skip to content

Commit 8d68b6d

Browse files
upibhallahrani
authored andcommitted
upi commit dec 2019 (#380)
* Fixed Ca channel proto, thanks to Harshavardan * Fix to vclamp in rdesigneur. Fix to ConcChan handling involving many files * Fix to HSolve so that assignment of passive properties Em, Cm and Rm reflects in the solver calculations without having to rebuild the entire solver. * Fix conversion for ConcChan in ReadKkit, corresponding fix to calculations in Dsolve * Fixed test_Xchan1.py to work with fixed ConcChan permeability units
1 parent 3d2d554 commit 8d68b6d

File tree

14 files changed

+169
-59
lines changed

14 files changed

+169
-59
lines changed

diffusion/ConcChanInfo.h

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,26 @@
1414
*/
1515
class ConcChanInfo
1616
{
17-
public:
18-
ConcChanInfo();
19-
ConcChanInfo( unsigned int my, unsigned int other,
20-
unsigned int chan, double perm, bool isSwapped )
21-
: myPool( my ), otherPool( other ), chanPool( chan ),
22-
swapped( isSwapped ),
23-
permeability( perm )
24-
{;}
17+
public:
18+
ConcChanInfo();
19+
ConcChanInfo( unsigned int my, unsigned int other,
20+
unsigned int chan, double perm, bool isSwapped, bool _isLocal )
21+
: myPool( my ), otherPool( other ), chanPool( chan ),
22+
swapped( isSwapped ),
23+
isLocal( _isLocal ),
24+
permeability( perm )
25+
{;}
2526

26-
unsigned int myPool;
27-
unsigned int otherPool;
28-
unsigned int chanPool;
29-
bool swapped; // Flag records whether myPool/otherPool are
30-
// swapped wrt inPool/outPool. System expects
31-
// that inPool should be in same compt as chanPool.
32-
double permeability;
27+
unsigned int myPool; /// This is not Id, it is internal PoolIndex
28+
/// Obtained using convertIdToPoolIndex.
29+
unsigned int otherPool; /// Internal PoolIndex
30+
unsigned int chanPool; /// Internal PoolIndex
31+
bool swapped; // Flag records whether myPool/otherPool are
32+
// swapped wrt inPool/outPool. System expects
33+
// that inPool should be in same compt as chanPool.
34+
bool isLocal; // Flag, records odd cases where the channel is
35+
// entirely local to one compartment.
36+
double permeability;
3337
};
3438

3539
#endif // _CONC_CHAN_INFO_H

diffusion/Dsolve.cpp

Lines changed: 111 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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

526570
void 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

10641120
unsigned 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

10771136
unsigned 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 )
10981157
double 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
11121171
void 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 )
11271186
double 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
11411200
void 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

11491208
double 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

11571216
void 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] );

diffusion/Dsolve.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ class Dsolve: public ZombiePoolInterface
136136

137137
void setNumPools( unsigned int num );
138138
unsigned int getNumPools() const;
139+
void setNumVarTotPools( unsigned int var, unsigned int tot );
140+
139141
unsigned int getNumLocalVoxels() const;
140142
VoxelPoolsBase* pools( unsigned int i );
141143
double volume( unsigned int i ) const;
@@ -185,6 +187,7 @@ class Dsolve: public ZombiePoolInterface
185187
void calcJnChan( const DiffJunction& jn, Dsolve* other, double dt );
186188
void calcOtherJnChan( const DiffJunction& jn, Dsolve* other,
187189
double dt );
190+
void calcLocalChan( double dt );
188191
void fillConcChans( const vector< ObjId >& chans );
189192

190193
/**

hsolve/HSolveInterface.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,10 @@ void HSolve::setCm( Id id, double value )
8989
{
9090
unsigned int index = localIndex( id );
9191
assert( index < tree_.size() );
92-
// Also update data structures used for calculations.
9392
tree_[ index ].Cm = value;
93+
// Also update data structures used for calculations.
94+
assert( tree_.size() == compartment_.size() );
95+
compartment_[index].CmByDt = 2.0 * value / dt_;
9496
}
9597

9698
double HSolve::getEm( Id id ) const
@@ -104,8 +106,10 @@ void HSolve::setEm( Id id, double value )
104106
{
105107
unsigned int index = localIndex( id );
106108
assert( index < tree_.size() );
107-
// Also update data structures used for calculations.
108109
tree_[ index ].Em = value;
110+
// Also update data structures used for calculations.
111+
assert( tree_.size() == compartment_.size() );
112+
compartment_[index].EmByRm = value / tree_[index].Rm;
109113
}
110114

111115
double HSolve::getRm( Id id ) const
@@ -119,8 +123,10 @@ void HSolve::setRm( Id id, double value )
119123
{
120124
unsigned int index = localIndex( id );
121125
assert( index < tree_.size() );
122-
// Also update data structures used for calculations.
123126
tree_[ index ].Rm = value;
127+
// Also update data structures used for calculations.
128+
assert( tree_.size() == compartment_.size() );
129+
compartment_[index].EmByRm = tree_[index].Em / value;
124130
}
125131

126132
double HSolve::getRa( Id id ) const

kinetics/ReadKkit.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,8 @@ Id ReadKkit::buildChan( const vector< string >& args )
11921192
//
11931193
double permeability = atof( args[ chanMap_["perm"] ].c_str() );
11941194
Id chan = shell_->doCreate( "ConcChan", pa, tail, 1 );
1195-
Field< double >::set( chan, "permeability", permeability );
1195+
// Convert from perm in uM in GENESIS, to mM for MOOSE.
1196+
Field< double >::set( chan, "permeability", permeability *1000.0 );
11961197
assert( chan != Id() );
11971198
string chanPath = clean.substr( 10 );
11981199
chanIds_[ chanPath ] = chan;

0 commit comments

Comments
 (0)