MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Compartment.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 ** This program is part of 'MOOSE', the
3 ** Messaging Object Oriented Simulation Environment.
4 ** Copyright (C) 2003-2007 Upinder S. Bhalla. and NCBS
5 ** It is made available under the terms of the
6 ** GNU Lesser General Public License version 2.1
7 ** See the file COPYING.LIB for the full notice.
8 **********************************************************************/
9 
10 #include "../basecode/header.h"
11 #include "../basecode/global.h"
12 #include "CompartmentBase.h"
13 #include "Compartment.h"
14 
15 using namespace moose;
16 const double Compartment::EPSILON = 1.0e-15;
17 
27 {
29  // static Finfo* compartmentFinfos[] = { };
30 
31  static string doc[] =
32  {
33  "Name", "Compartment",
34  "Author", "Upi Bhalla",
35  "Description", "Compartment object, for branching neuron models.",
36  };
37  static Dinfo< Compartment > dinfo;
38  static Cinfo compartmentCinfo(
39  "Compartment",
41  0,
42  0,
43  // compartmentFinfos,
44  // sizeof( compartmentFinfos ) / sizeof( Finfo* ),
45  &dinfo,
46  doc,
47  sizeof(doc)/sizeof(string)
48  );
49 
50  return &compartmentCinfo;
51 }
52 
54 
55 
56 /*
57 const SrcFinfo1< double >* VmOut =
58  dynamic_cast< const SrcFinfo1< double >* >(
59  compartmentCinfo->findFinfo( "VmOut" ) );
60  */
61 
63  dynamic_cast< const SrcFinfo1< double >* > (
64  compartmentCinfo->findFinfo( "axialOut" ) );
65 
67  dynamic_cast< const SrcFinfo2< double, double >* > (
68  compartmentCinfo->findFinfo( "raxialOut" ) );
69 
71 // Here we put the Compartment class functions.
73 
75 {
76  Vm_ = -0.06;
77  Em_ = -0.06;
78  Cm_ = 1.0;
79  Rm_ = 1.0;
80  invRm_ = 1.0;
81  Ra_ = 1.0;
82  Im_ = 0.0;
83  lastIm_ = 0.0;
84  inject_ = 0.0;
85  sumInject_ = 0.0;
86  initVm_ = -0.06;
87  A_ = 0.0;
88  B_ = 0.0;
89 }
90 
92 {
93  ;
94 }
95 
96 // Value Field access function definitions.
97 void Compartment::vSetVm( const Eref& e, double Vm )
98 {
99  Vm_ = Vm;
100 }
101 
102 double Compartment::vGetVm( const Eref& e ) const
103 {
104  return Vm_;
105 }
106 
107 void Compartment::vSetEm( const Eref& e, double Em )
108 {
109  Em_ = Em;
110 }
111 
112 double Compartment::vGetEm( const Eref& e ) const
113 {
114  return Em_;
115 }
116 
117 void Compartment::vSetCm( const Eref& e, double Cm )
118 {
119  if ( rangeWarning( "Cm", Cm ) ) return;
120  Cm_ = Cm;
121 }
122 
123 double Compartment::vGetCm( const Eref& e ) const
124 {
125  return Cm_;
126 }
127 
128 void Compartment::vSetRm( const Eref& e, double Rm )
129 {
130  if ( rangeWarning( "Rm", Rm ) ) return;
131  Rm_ = Rm;
132  invRm_ = 1.0/Rm;
133 }
134 
135 double Compartment::vGetRm( const Eref& e ) const
136 {
137  return Rm_;
138 }
139 
140 void Compartment::vSetRa( const Eref& e, double Ra )
141 {
142  if ( rangeWarning( "Ra", Ra ) ) return;
143  Ra_ = Ra;
144 }
145 
146 double Compartment::vGetRa( const Eref& e ) const
147 {
148  return Ra_;
149 }
150 
151 double Compartment::vGetIm( const Eref& e ) const
152 {
153  return lastIm_;
154 }
155 
156 void Compartment::vSetInject( const Eref& e, double inject )
157 {
158  inject_ = inject;
159 }
160 
161 double Compartment::vGetInject( const Eref& e ) const
162 {
163  return inject_;
164 }
165 
166 void Compartment::vSetInitVm( const Eref& e, double initVm )
167 {
168  initVm_ = initVm;
169 }
170 
171 double Compartment::vGetInitVm( const Eref& e ) const
172 {
173  return initVm_;
174 }
175 
176 
178 // Compartment::Dest function definitions.
180 
181 void Compartment::vProcess( const Eref& e, ProcPtr p )
182 {
183  //cout << "Compartment " << e.id().path() << ":: process: A = " << A_ << ", B = " << B_ << endl;
184  A_ += inject_ + sumInject_ + Em_ * invRm_;
185  if ( B_ > EPSILON )
186  {
187  double x = exp( -B_ * p->dt / Cm_ );
188  Vm_ = Vm_ * x + ( A_ / B_ ) * ( 1.0 - x );
189  }
190  else
191  {
192  Vm_ += ( A_ - Vm_ * B_ ) * p->dt / Cm_;
193  }
194  A_ = 0.0;
195  B_ = invRm_;
196  lastIm_ = Im_;
197  Im_ = 0.0;
198  sumInject_ = 0.0;
199  // Send out Vm to channels, SpikeGens, etc.
200  VmOut()->send( e, Vm_ );
201 
202  // The axial/raxial messages go out in the 'init' phase.
203 }
204 
205 void Compartment::vReinit( const Eref& e, ProcPtr p )
206 {
207  Vm_ = initVm_;
208  A_ = 0.0;
209  B_ = invRm_;
210  Im_ = 0.0;
211  lastIm_ = 0.0;
212  sumInject_ = 0.0;
213  dt_ = p->dt;
214 
215  // Send out the resting Vm to channels, SpikeGens, etc.
216  VmOut()->send( e, Vm_ );
217 }
218 
220 {
221  // Send out the axial messages
222  axialOut->send( e, Vm_ );
223  // Send out the raxial messages
224  raxialOut->send( e, Ra_, Vm_ );
225 }
226 
228 {
229  ; // Nothing happens here
230 }
231 
232 void Compartment::vHandleChannel( const Eref& e, double Gk, double Ek)
233 {
234  A_ += Gk * Ek;
235  B_ += Gk;
236 }
237 
238 void Compartment::vHandleRaxial( double Ra, double Vm)
239 {
240  A_ += Vm / Ra;
241  B_ += 1.0 / Ra;
242  Im_ += ( Vm - Vm_ ) / Ra;
243 }
244 
246 {
247  A_ += Vm / Ra_;
248  B_ += 1.0 / Ra_;
249  Im_ += ( Vm - Vm_ ) / Ra_;
250 }
251 
252 void Compartment::vInjectMsg( const Eref& e, double current)
253 {
254  sumInject_ += current;
255  Im_ += current;
256 }
257 
258 void Compartment::vRandInject( const Eref& e, double prob, double current)
259 {
260  if ( moose::mtrand() < prob * dt_ )
261  {
262  sumInject_ += current;
263  Im_ += current;
264  }
265 }
266 
268 
269 #ifdef DO_UNIT_TESTS
270 
271 #include "header.h"
272 #include "../shell/Shell.h"
273 //#include "../randnum/randnum.h"
274 
275 void testCompartment()
276 {
277  unsigned int size = 1;
278  Eref sheller( Id().eref() );
279  Shell* shell = reinterpret_cast< Shell* >( sheller.data() );
280  Id comptId = shell->doCreate("Compartment", Id(), "compt", size);
281  assert( Id::isValid(comptId));
282  Eref compter = comptId.eref();
283  Compartment* c = reinterpret_cast< Compartment* >( comptId.eref().data() );
284  ProcInfo p;
285  p.dt = 0.002;
286  c->setInject( compter, 1.0 );
287  c->setRm( compter, 1.0 );
288  c->setRa( compter, 0.0025 );
289  c->setCm( compter, 1.0 );
290  c->setEm( compter, 0.0 );
291  c->setVm( compter, 0.0 );
292 
293  // First, test charging curve for a single compartment
294  // We want our charging curve to be a nice simple exponential
295  // Vm = 1.0 - 1.0 * exp( - t / 1.0 );
296  double delta = 0.0;
297  double Vm = 0.0;
298  double tau = 1.0;
299  double Vmax = 1.0;
300  for ( p.currTime = 0.0; p.currTime < 2.0; p.currTime += p.dt )
301  {
302  Vm = c->getVm( compter );
303  double x = Vmax - Vmax * exp( -p.currTime / tau );
304  delta += ( Vm - x ) * ( Vm - x );
305  c->process( compter, &p );
306  }
307  assert( delta < 1.0e-6 );
308  shell->doDelete(comptId);
309  cout << "." << flush;
310 }
311 
312 // Comment out this define if it takes too long (about 5 seconds on
313 // a modest machine, but could be much longer with valgrind)
314 #define DO_SPATIAL_TESTS
315 
323 #include "../shell/Shell.h"
325 {
326  Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() );
327  unsigned int size = 100;
328  double Rm = 1.0;
329  double Ra = 0.01;
330  double Cm = 1.0;
331  double dt = 0.01;
332  double runtime = 10;
333  double lambda = sqrt( Rm / Ra );
334 
335  Id cid = shell->doCreate( "Compartment", Id(), "compt", size );
336  assert( Id::isValid(cid));
337  assert( cid.eref().element()->numData() == size );
338 
339  bool ret = Field< double >::setRepeat( cid, "initVm", 0.0 );
340  assert( ret );
341  Field< double >::setRepeat( cid, "inject", 0 );
342  // Only apply current injection in first compartment
343  Field< double >::set( ObjId( cid, 0 ), "inject", 1.0 );
344  Field< double >::setRepeat( cid, "Rm", Rm );
345  Field< double >::setRepeat( cid, "Ra", Ra );
346  Field< double >::setRepeat( cid, "Cm", Cm );
347  Field< double >::setRepeat( cid, "Em", 0 );
348  Field< double >::setRepeat( cid, "Vm", 0 );
349 
350  // The diagonal message has a default stride of 1, so it connects
351  // successive compartments.
352  // Note that the src and dest elements here are identical, so we cannot
353  // use a shared message. The messaging system will get confused about
354  // direction to send data. So we split up the shared message that we
355  // might have used, below, into two individual messages.
356  // MsgId mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "raxial", ObjId( cid ), "axial" );
357  ObjId mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "axialOut", ObjId( cid ), "handleAxial" );
358  assert( !mid.bad());
359  // mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "handleRaxial", ObjId( cid ), "raxialOut" );
360  mid = shell->doAddMsg( "Diagonal", ObjId( cid ), "raxialOut", ObjId( cid ), "handleRaxial" );
361  assert( !mid.bad() );
362  // ObjId managerId = Msg::getMsg( mid )->manager().objId();
363  // Make the raxial data go from high to lower index compartments.
364  Field< int >::set( mid, "stride", -1 );
365 
366 #ifdef DO_SPATIAL_TESTS
367  shell->doSetClock( 0, dt );
368  shell->doSetClock( 1, dt );
369  // Ensure that the inter_compt msgs go between nodes once every dt.
370  shell->doSetClock( 9, dt );
371 
372  shell->doUseClock( "/compt", "init", 0 );
373  shell->doUseClock( "/compt", "process", 1 );
374 
375  shell->doReinit();
376  shell->doStart( runtime );
377 
378  double Vmax = Field< double >::get( ObjId( cid, 0 ), "Vm" );
379 
380  double delta = 0.0;
381  // We measure only the first 50 compartments as later we
382  // run into end effects because it is not an infinite cable
383  for ( unsigned int i = 0; i < size; i++ )
384  {
385  double Vm = Field< double >::get( ObjId( cid, i ), "Vm" );
386  double x = Vmax * exp( - static_cast< double >( i ) / lambda );
387  delta += ( Vm - x ) * ( Vm - x );
388  // cout << i << " (x, Vm) = ( " << x << ", " << Vm << " )\n";
389  }
390  assert( delta < 1.0e-5 );
391 #endif // DO_SPATIAL_TESTS
392  shell->doDelete( cid );
393  cout << "." << flush;
394 }
395 #endif // DO_UNIT_TESTS
virtual void vSetInitVm(const Eref &e, double initVm)
void doStart(double runtime, bool notify=false)
Definition: Shell.cpp:332
char * data() const
Definition: Eref.cpp:41
virtual double vGetInject(const Eref &e) const
virtual double vGetInitVm(const Eref &e) const
double getVm(const Eref &e) const
void vHandleChannel(const Eref &e, double Gk, double Ek)
virtual void vSetRm(const Eref &e, double Rm)
void setVm(const Eref &e, double Vm)
void vReinit(const Eref &e, ProcPtr p)
void process(const Eref &e, ProcPtr p)
void doSetClock(unsigned int tickNum, double dt)
Definition: Shell.cpp:377
double currTime
Definition: ProcInfo.h:19
bool bad() const
Definition: ObjId.cpp:18
static const Cinfo * initCinfo()
Definition: Compartment.cpp:26
Definition: Dinfo.h:60
static bool setRepeat(ObjId destId, const string &field, A arg)
Definition: SetGet.h:260
static const double EPSILON
Definition: Compartment.h:135
virtual double vGetCm(const Eref &e) const
virtual void vSetVm(const Eref &e, double Vm)
Definition: Compartment.cpp:97
const SrcFinfo2< double, double > * raxialOut
Definition: Compartment.cpp:66
void vInitProc(const Eref &e, ProcPtr p)
void vInitReinit(const Eref &e, ProcPtr p)
void vHandleRaxial(double Ra, double Vm)
static const Cinfo * compartmentCinfo
Definition: Compartment.cpp:53
Definition: ObjId.h:20
Eref eref() const
Definition: Id.cpp:125
void testCompartment()
Element * element() const
Definition: Eref.h:42
static bool set(const ObjId &dest, const string &field, A arg)
Definition: SetGet.h:245
bool rangeWarning(const string &field, double value)
void testCompartmentProcess()
Id doCreate(string type, ObjId parent, string name, unsigned int numData, NodePolicy nodePolicy=MooseBlockBalance, unsigned int preferredNode=1)
Definition: Shell.cpp:181
virtual void vSetInject(const Eref &e, double Inject)
virtual double vGetRa(const Eref &e) const
void vProcess(const Eref &e, ProcPtr p)
void setEm(const Eref &e, double Em)
void vHandleAxial(double Vm)
void setCm(const Eref &e, double Cm)
double dt
Definition: ProcInfo.h:18
virtual double vGetRm(const Eref &e) const
Definition: Eref.h:26
void vInjectMsg(const Eref &e, double current)
void setInject(const Eref &e, double Inject)
virtual unsigned int numData() const =0
Returns number of data entries across all nodes.
static bool isValid(Id id)
Definition: Id.h:145
virtual double vGetIm(const Eref &e) const
void vRandInject(const Eref &e, double prob, double current)
virtual ~Compartment()
Definition: Compartment.cpp:91
virtual void vSetRa(const Eref &e, double Ra)
static SrcFinfo1< double > * VmOut()
void doReinit()
Definition: Shell.cpp:362
ObjId doAddMsg(const string &msgType, ObjId src, const string &srcField, ObjId dest, const string &destField)
Definition: Shell.cpp:269
bool doDelete(ObjId oid)
Definition: Shell.cpp:259
double mtrand(void)
Generate a random double between 0 and 1.
Definition: global.cpp:97
Definition: Id.h:17
void doUseClock(string path, string field, unsigned int tick)
Definition: Shell.cpp:382
const SrcFinfo1< double > * axialOut
Definition: Compartment.cpp:62
static A get(const ObjId &dest, const string &field)
Definition: SetGet.h:284
void setRa(const Eref &e, double Ra)
virtual double vGetVm(const Eref &e) const
virtual void vSetCm(const Eref &e, double Cm)
virtual double vGetEm(const Eref &e) const
Definition: Cinfo.h:18
static const Cinfo * initCinfo()
void setRm(const Eref &e, double Rm)
virtual void vSetEm(const Eref &e, double Em)
Definition: Shell.h:43
const Finfo * findFinfo(const string &name) const
Definition: Cinfo.cpp:224