MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
HSolve.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, Niraj Dudani 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 "header.h"
11 #include "ElementValueFinfo.h"
12 #include "HSolveStruct.h"
13 #include "HinesMatrix.h"
14 #include "HSolvePassive.h"
15 #include "RateLookup.h"
16 #include "HSolveActive.h"
17 #include "HSolve.h"
18 #include "../biophysics/Compartment.h"
19 #include "ZombieCompartment.h"
20 #include "../biophysics/CaConcBase.h"
21 #include "ZombieCaConc.h"
22 #include "../biophysics/HHGate.h"
23 #include "../biophysics/ChanBase.h"
24 #include "../biophysics/ChanCommon.h"
25 #include "../biophysics/HHChannel.h"
26 #include "../biophysics/CaConc.h"
27 #include "ZombieHHChannel.h"
28 #include "../shell/Shell.h"
29 
31 {
32  static DestFinfo process(
33  "process",
34  "Handles 'process' call: Solver advances by one time-step.",
36  );
37 
38  static DestFinfo reinit(
39  "reinit",
40  "Handles 'reinit' call: Solver reads in model.",
42  );
43 
44  static Finfo* processShared[] =
45  {
46  &process,
47  &reinit
48  };
49 
50  static SharedFinfo proc(
51  "proc",
52  "Handles 'reinit' and 'process' calls from a clock.",
53  processShared,
54  sizeof( processShared ) / sizeof( Finfo* )
55  );
56 
57  static ValueFinfo< HSolve, Id > seed(
58  "seed",
59  "Use this field to specify path to a 'seed' compartment, that is, "
60  "any compartment within a neuron. The HSolve object uses this seed as "
61  "a handle to discover the rest of the neuronal model, which means all "
62  "the remaining compartments, channels, synapses, etc.",
65  );
66 
68  "target",
69  "Specifies the path to a compartmental model to be taken over. "
70  "This can be the path to any container object that has the model "
71  "under it (found by performing a deep search). Alternatively, this "
72  "can also be the path to any compartment within the neuron. This "
73  "compartment will be used as a handle to discover the rest of the "
74  "model, which means all the remaining compartments, channels, "
75  "synapses, etc.",
78  );
79 
81  "dt",
82  "The time-step for this solver.",
85  );
86 
87  static ValueFinfo< HSolve, int > caAdvance(
88  "caAdvance",
89  "This flag determines how current flowing into a calcium pool "
90  "is computed. A value of 0 means that the membrane potential at the "
91  "beginning of the time-step is used for the calculation. This is how "
92  "GENESIS does its computations. A value of 1 means the membrane "
93  "potential at the middle of the time-step is used. This is the "
94  "correct way of integration, and is the default way.",
97  );
98 
99  static ValueFinfo< HSolve, int > vDiv(
100  "vDiv",
101  "Specifies number of divisions for lookup tables of voltage-sensitive "
102  "channels.",
105  );
106 
107  static ValueFinfo< HSolve, double > vMin(
108  "vMin",
109  "Specifies the lower bound for lookup tables of voltage-sensitive "
110  "channels. Default is to automatically decide based on the tables of "
111  "the channels that the solver reads in.",
114  );
115 
116  static ValueFinfo< HSolve, double > vMax(
117  "vMax",
118  "Specifies the upper bound for lookup tables of voltage-sensitive "
119  "channels. Default is to automatically decide based on the tables of "
120  "the channels that the solver reads in.",
123  );
124 
125  static ValueFinfo< HSolve, int > caDiv(
126  "caDiv",
127  "Specifies number of divisions for lookup tables of calcium-sensitive "
128  "channels.",
131  );
132 
133  static ValueFinfo< HSolve, double > caMin(
134  "caMin",
135  "Specifies the lower bound for lookup tables of calcium-sensitive "
136  "channels. Default is to automatically decide based on the tables of "
137  "the channels that the solver reads in.",
140  );
141 
142  static ValueFinfo< HSolve, double > caMax(
143  "caMax",
144  "Specifies the upper bound for lookup tables of calcium-sensitive "
145  "channels. Default is to automatically decide based on the tables of "
146  "the channels that the solver reads in.",
149  );
150 
151  static Finfo* hsolveFinfos[] =
152  {
153  &seed, // Value
154  &target, // Value
155  &dt, // Value
156  &caAdvance, // Value
157  &vDiv, // Value
158  &vMin, // Value
159  &vMax, // Value
160  &caDiv, // Value
161  &caMin, // Value
162  &caMax, // Value
163  &proc, // Shared
164  };
165 
166  static string doc[] =
167  {
168  "Name", "HSolve",
169  "Author", "Niraj Dudani, 2007, NCBS",
170  "Description", "HSolve: Hines solver, for solving "
171  "branching neuron models.",
172  };
173 
174  static Dinfo< HSolve > dinfo;
175  static Cinfo hsolveCinfo(
176  "HSolve",
178  hsolveFinfos,
179  sizeof( hsolveFinfos ) / sizeof( Finfo* ),
180  &dinfo,
181  doc,
182  sizeof(doc)/sizeof(string)
183  );
184 
185  return &hsolveCinfo;
186 }
187 
189 
191  : dt_( 50e-6 )
192 {
193  ;
194 }
195 
197 {
198  unzombify();
199 }
200 
201 
203 // Dest function definitions
205 
206 void HSolve::process( const Eref& hsolve, ProcPtr p )
207 {
208  this->HSolveActive::step( p );
209 }
210 
211 void HSolve::reinit( const Eref& hsolve, ProcPtr p )
212 {
213  dt_ = p->dt;
214  this->HSolveActive::reinit( p );
215 }
216 
217 void HSolve::zombify( Eref hsolve ) const
218 {
219  vector< Id >::const_iterator i;
220  vector< ObjId > temp;
221 
222  for ( i = compartmentId_.begin(); i != compartmentId_.end(); ++i )
223  temp.push_back( ObjId( *i, 0 ) );
224  for ( i = compartmentId_.begin(); i != compartmentId_.end(); ++i ) {
225  CompartmentBase::zombify( i->eref().element(),
226  ZombieCompartment::initCinfo(), hsolve.id() );
227  }
228 
229  temp.clear();
230  for ( i = caConcId_.begin(); i != caConcId_.end(); ++i )
231  temp.push_back( ObjId( *i, 0 ) );
232  // Shell::dropClockMsgs( temp, "process" );
233  for ( i = caConcId_.begin(); i != caConcId_.end(); ++i ) {
234  CaConcBase::zombify( i->eref().element(), ZombieCaConc::initCinfo(), hsolve.id() );
235  }
236 
237  temp.clear();
238  for ( i = channelId_.begin(); i != channelId_.end(); ++i )
239  temp.push_back( ObjId( *i, 0 ) );
240  for ( i = channelId_.begin(); i != channelId_.end(); ++i ) {
241  HHChannelBase::zombify( i->eref().element(),
242  ZombieHHChannel::initCinfo(), hsolve.id() );
243  }
244 }
245 
246 void HSolve::unzombify() const
247 {
248  vector< Id >::const_iterator i;
249 
250  for ( i = compartmentId_.begin(); i != compartmentId_.end(); ++i )
251  if ( i->element() ) {
252  CompartmentBase::zombify( i->eref().element(),
253  Compartment::initCinfo(), Id() );
254  }
255 
256  for ( i = caConcId_.begin(); i != caConcId_.end(); ++i )
257  if ( i->element() ) {
258  CaConcBase::zombify( i->eref().element(), CaConc::initCinfo(), Id() );
259  }
260 
261  for ( i = channelId_.begin(); i != channelId_.end(); ++i )
262  if ( i->element() ) {
263  HHChannelBase::zombify( i->eref().element(),
264  HHChannel::initCinfo(), Id() );
265  }
266 }
267 
268 void HSolve::setup( Eref hsolve )
269 {
270  // Setup solver.
271  this->HSolveActive::setup( seed_, dt_ );
272 
273  mapIds();
274  zombify( hsolve );
275 }
276 
278 // Field function definitions
280 
281 void HSolve::setSeed( Id seed )
282 {
283  if ( !seed.element()->cinfo()->isA( "Compartment" ) )
284  {
285  cerr << "Error: HSolve::setSeed(): Seed object '" << seed.path()
286  << "' is not derived from type 'Compartment'." << endl;
287  return;
288  }
289 
290  seed_ = seed;
291 }
292 
294 {
295  return seed_;
296 }
297 
298 void HSolve::setPath( const Eref& hsolve, string path )
299 {
300  if ( dt_ == 0.0 )
301  {
302  cerr << "Error: HSolve::setPath(): Must set 'dt' first.\n";
303  return;
304  }
305 
306  seed_ = deepSearchForCompartment( Id( path ) );
307 
308  if ( seed_ == Id() )
309  cerr << "Warning: HSolve::setPath(): No compartments found at or below '"
310  << path << "'.\n";
311  else
312  {
313  // cout << "HSolve: Seed compartment found at '" << seed_.path() << "'.\n";
314  path_ = path;
315  setup( hsolve );
316  }
317 }
318 
319 string HSolve::getPath( const Eref& e) const
320 {
321  return path_;
322 }
323 
330 {
331  /*
332  * 'cstack' is a stack-of-stacks used to perform the depth-first search.
333  * The 0th entry in 'cstack' is a stack containing simply the base.
334  * The i-th entry in 'cstack' contains children of the node at the top
335  * of the stack at position ( i - 1 ).
336  * Hence, at any time, the top of the i-th stack is the i-th node on
337  * the ancestral path from the 'base' node to the 'current' node
338  * (more below) which is being examined. Also, the remaining nodes in
339  * the i-th stack are the siblings of this ancestor.
340  *
341  * 'current' is the node at the top of the top of 'cstack'. If this node is
342  * a Compartment, then the search is completed, returning 'current'.
343  * Otherwise, the children of 'current' are pushed onto 'cstack' for a
344  * deeper search. If the deeper search yields nothing, then this
345  * 'current' node is discarded. When an entire stack of siblings is
346  * exhausted in this way, then this empty stack is discarded, and
347  * the search moves 1 level up.
348  *
349  * 'result' is a blank Id (moose root element) if the search failed.
350  * Otherwise, it is a compartment that was found under 'base'.
351  */
352  vector< vector< Id > > cstack( 1, vector< Id >( 1, base ) );
353  Id current;
354  Id result;
355 
356  while ( !cstack.empty() )
357  if ( cstack.back().empty() )
358  {
359  cstack.pop_back();
360 
361  if ( !cstack.empty() )
362  cstack.back().pop_back();
363  }
364  else
365  {
366  current = cstack.back().back();
367 
368  // if ( current()->cinfo() == moose::Compartment::initCinfo() )
369  // Compartment is base class for SymCompartment.
370  if ( current.element()->cinfo()->isA( "Compartment" ) )
371  {
372  result = current;
373  break;
374  }
375  cstack.push_back( children( current ) );
376  }
377 
378  return result;
379 }
380 
381 vector< Id > HSolve::children( Id obj )
382 {
383  //~ return Field< vector< Id > >::get( obj, "children" );
384  //~ return Field< vector< Id > >::fastGet( obj.eref(), "children" );
385  //~ return localGet< Neutral, vector< Id > >( obj.eref(), "children" );
386 
387  vector< Id > c;
388  Neutral::children( obj.eref(), c );
389  return c;
390 }
391 
392 void HSolve::setDt( double dt )
393 {
394  if ( dt < 0.0 )
395  {
396  cerr << "Error: HSolve: 'dt' must be positive.\n";
397  return;
398  }
399 
400  dt_ = dt;
401 }
402 
403 double HSolve::getDt() const
404 {
405  return dt_;
406 }
407 
408 void HSolve::setCaAdvance( int caAdvance )
409 {
410  if ( caAdvance != 0 && caAdvance != 1 )
411  {
412  cerr << "Error: HSolve: caAdvance should be either 0 or 1.\n";
413  return;
414  }
415 
416  caAdvance_ = caAdvance;
417 }
418 
420 {
421  return caAdvance_;
422 }
423 
424 void HSolve::setVDiv( int vDiv )
425 {
426  vDiv_ = vDiv;
427 }
428 
429 int HSolve::getVDiv() const
430 {
431  return vDiv_;
432 }
433 
434 void HSolve::setVMin( double vMin )
435 {
436  vMin_ = vMin;
437 }
438 
439 double HSolve::getVMin() const
440 {
441  return vMin_;
442 }
443 
444 void HSolve::setVMax( double vMax )
445 {
446  vMax_ = vMax;
447 }
448 
449 double HSolve::getVMax() const
450 {
451  return vMax_;
452 }
453 
454 void HSolve::setCaDiv( int caDiv )
455 {
456  caDiv_ = caDiv;
457 }
458 
459 int HSolve::getCaDiv() const
460 {
461  return caDiv_;
462 }
463 
464 void HSolve::setCaMin( double caMin )
465 {
466  caMin_ = caMin;
467 }
468 
469 double HSolve::getCaMin() const
470 {
471  return caMin_;
472 }
473 
474 void HSolve::setCaMax( double caMax )
475 {
476  caMax_ = caMax;
477 }
478 
479 double HSolve::getCaMax() const
480 {
481  return caMax_;
482 }
483 
484 const set<string>& HSolve::handledClasses()
485 {
486  static set<string> classes;
487  if (classes.empty())
488  {
489  classes.insert("CaConc");
490  classes.insert("ZombieCaConc");
491  classes.insert("HHChannel");
492  classes.insert("ZombieHHChannel");
493  classes.insert("Compartment");
494  classes.insert("SymCompartment");
495  classes.insert("ZombieCompartment");
496  }
497  return classes;
498 }
499 
504 void HSolve::deleteIncomingMessages( Element * orig, const string finfo)
505 {
506  const DestFinfo * concenDest = dynamic_cast<const DestFinfo*>(orig->cinfo()->findFinfo(finfo));
507  assert(concenDest);
508  ObjId mid = orig->findCaller(concenDest->getFid());
509  while (! mid.bad())
510  {
511  const Msg * msg = Msg::getMsg(mid);
512  assert(msg);
513  ObjId other = msg->findOtherEnd(orig->id());
514  Element * otherEl = other.id.element();
515  if (otherEl && HSolve::handledClasses().find(otherEl->cinfo()->name()) != HSolve::handledClasses().end())
516  {
517  Msg::deleteMsg(mid);
518  }
519  else
520  {
521  break; // Have to do this otherwise it is an infinite loop
522  }
523  mid = orig->findCaller(concenDest->getFid());
524  }
525 }
526 
527 #if 0
528 
530 Id create_testobject(vector<Id> & container, string classname, Id parent, string name, vector<int> dims)
531 {
532  Shell * shell = reinterpret_cast< Shell* >( ObjId( Id(), 0 ).data() );
533  Id nid = shell->doCreate( classname, parent, name, dims );
534  container.push_back(nid);
535  return nid;
536 }
537 
538 void clear_testobjects(vector<Id>& container)
539 {
540  Shell * shell = reinterpret_cast< Shell* >( ObjId( Id(), 0 ).data() );
541  while (!container.empty())
542  {
543  Id id = container.back();
544  shell->doDelete(id);
545  container.pop_back();
546  }
547 }
548 
549 
550 void testHSolvePassiveSingleComp()
551 {
552  Shell * shell = reinterpret_cast< Shell* >( ObjId( Id(), 0 ).data() );
553  vector< int > dims( 1, 1 );
554  vector<Id> to_cleanup;
555  Id nid = create_testobject(to_cleanup, "Neuron", Id(), "n", dims );
556  Id comptId = create_testobject(to_cleanup, "Compartment", nid, "compt", dims );
557  Id hsolve = create_testobject(to_cleanup, "HSolve", nid, "solver", dims);
558  Field<string>::set(hsolve, "target", nid.path());
559  to_cleanup.push_back(nid);
560  clear_testobjects(to_cleanup);
561  cout << "." << flush;
562 }
563 
564 
565 
566 #endif // if 0
void setCaAdvance(int caAdvance)
Definition: HSolve.cpp:408
Id id() const
Definition: Eref.cpp:62
virtual ObjId findOtherEnd(ObjId) const =0
static void deleteIncomingMessages(Element *orig, const string finfo)
Definition: HSolve.cpp:504
static vector< Id > children(Id obj)
Definition: HSolve.cpp:381
void process(const Eref &hsolve, ProcPtr p)
Definition: HSolve.cpp:206
char * data() const
Definition: ObjId.cpp:113
Element * element() const
Synonym for Id::operator()()
Definition: Id.cpp:113
Id seed_
Definition: HSolve.h:171
bool bad() const
Definition: ObjId.cpp:18
std::string path(const std::string &separator="/") const
Definition: Id.cpp:76
Definition: Dinfo.h:60
static const std::set< string > & handledClasses()
Definition: HSolve.cpp:484
static const Cinfo * initCinfo()
~HSolve()
Definition: HSolve.cpp:196
Id id
Definition: ObjId.h:98
HSolve()
Definition: HSolve.cpp:190
void reinit(const Eref &hsolve, ProcPtr p)
Definition: HSolve.cpp:211
string path_
Definition: HSolve.h:170
void setVMin(double vMin)
Definition: HSolve.cpp:434
static void zombify(Element *orig, const Cinfo *zClass, Id hsolve)
Definition: CaConcBase.cpp:343
static const Cinfo * initCinfo()
string getPath(const Eref &e) const
Definition: HSolve.cpp:319
Definition: ObjId.h:20
Eref eref() const
Definition: Id.cpp:125
static void children(const Eref &e, vector< Id > &ret)
Definition: Neutral.cpp:342
vector< Id > compartmentId_
Definition: HSolvePassive.h:37
static bool set(const ObjId &dest, const string &field, A arg)
Definition: SetGet.h:245
void zombify(Eref hsolve) const
Definition: HSolve.cpp:217
void setup(Eref hsolve)
Definition: HSolve.cpp:268
void setDt(double dt)
Definition: HSolve.cpp:392
Id doCreate(string type, ObjId parent, string name, unsigned int numData, NodePolicy nodePolicy=MooseBlockBalance, unsigned int preferredNode=1)
Definition: Shell.cpp:181
void setup(Id seed, double dt)
void reinit(ProcPtr info)
Id id() const
Definition: Element.cpp:71
double getCaMax() const
Definition: HSolve.cpp:479
void setCaMax(double caMax)
Definition: HSolve.cpp:474
const std::string & name() const
Definition: Cinfo.cpp:260
int getCaDiv() const
Definition: HSolve.cpp:459
double vMin_
Definition: HSolveActive.h:63
static const Cinfo * initCinfo()
Definition: HHChannel.cpp:24
static const Cinfo * initCinfo()
static void deleteMsg(ObjId mid)
Definition: Msg.cpp:52
void mapIds()
ObjId findCaller(FuncId fid) const
Definition: Element.cpp:350
static const Cinfo * initCinfo()
Definition: CaConc.cpp:16
FuncId getFid() const
Definition: DestFinfo.cpp:45
double getDt() const
Definition: HSolve.cpp:403
double dt
Definition: ProcInfo.h:18
static void zombify(Element *orig, const Cinfo *zClass, Id hsolve)
Definition: Eref.h:26
bool isA(const string &ancestor) const
Definition: Cinfo.cpp:280
double getCaMin() const
Definition: HSolve.cpp:469
int getCaAdvance() const
Definition: HSolve.cpp:419
Id getSeed() const
Definition: HSolve.cpp:293
const Cinfo * cinfo() const
Definition: Element.cpp:66
void unzombify() const
Definition: HSolve.cpp:246
Definition: Msg.h:18
double caMin_
Definition: HSolveActive.h:66
double caMax_
Definition: HSolveActive.h:67
double getVMax() const
Definition: HSolve.cpp:449
void setVDiv(int vDiv)
Definition: HSolve.cpp:424
static char name[]
Definition: mfield.cpp:401
void setPath(const Eref &e, string path)
Definition: HSolve.cpp:298
void setSeed(Id seed)
Definition: HSolve.cpp:281
static const Cinfo * initCinfo()
Interface to external channels.
Definition: HSolve.cpp:30
void step(ProcPtr info)
Equivalent to process.
double getVMin() const
Definition: HSolve.cpp:439
bool doDelete(ObjId oid)
Definition: Shell.cpp:259
Definition: Id.h:17
int getVDiv() const
Definition: HSolve.cpp:429
static const Msg * getMsg(ObjId m)
Definition: Msg.cpp:59
void setCaMin(double caMin)
Definition: HSolve.cpp:464
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
void setCaDiv(int caDiv)
Definition: HSolve.cpp:454
vector< Id > channelId_
Used for localIndex-ing.
Definition: HSolveActive.h:124
static const Cinfo * hsolveCinfo
Definition: HSolve.cpp:188
vector< Id > caConcId_
calcium from difshells
Definition: HSolveActive.h:123
static Id deepSearchForCompartment(Id base)
Definition: HSolve.cpp:329
Definition: Cinfo.h:18
static char path[]
Definition: mfield.cpp:403
void setVMax(double vMax)
Definition: HSolve.cpp:444
double vMax_
Definition: HSolveActive.h:64
double dt_
Definition: HSolve.h:169
Definition: Shell.h:43
const Finfo * findFinfo(const string &name) const
Definition: Cinfo.cpp:224
Definition: Finfo.h:12