MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
HSolveActive.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 <queue>
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/CompartmentBase.h"
19 #include "../biophysics/Compartment.h"
20 #include "../biophysics/CaConcBase.h"
21 #include "../biophysics/ChanBase.h"
22 #include "ZombieCaConc.h"
23 using namespace moose;
24 //~ #include "ZombieCompartment.h"
25 //~ #include "ZombieCaConc.h"
26 
27 extern ostream& operator <<( ostream& s, const HinesMatrix& m );
28 
29 const int HSolveActive::INSTANT_X = 1;
30 const int HSolveActive::INSTANT_Y = 2;
31 const int HSolveActive::INSTANT_Z = 4;
32 
34 {
35  caAdvance_ = 1;
36 
37  // Default lookup table size
38  //~ vDiv_ = 3000; // for voltage
39  //~ caDiv_ = 3000; // for calcium
40 }
41 
43 // Solving differential equations
46 {
47  if ( nCompt_ <= 0 )
48  return;
49 
50  if ( !current_.size() )
51  {
52  current_.resize( channel_.size() );
53  }
54 
55  advanceChannels( info->dt );
56  calculateChannelCurrents();
57  updateMatrix();
60  advanceCalcium();
61  advanceSynChans( info );
62 
63  sendValues( info );
64  sendSpikes( info );
65 
66  externalCurrent_.assign( externalCurrent_.size(), 0.0 );
67 }
68 
70 {
71  vector< ChannelStruct >::iterator ichan;
72  vector< CurrentStruct >::iterator icurrent = current_.begin();
73 
74  if ( state_.size() != 0 )
75  {
76  double* istate = &state_[ 0 ];
77 
78  for ( ichan = channel_.begin(); ichan != channel_.end(); ++ichan )
79  {
80  ichan->process( istate, *icurrent );
81  ++icurrent;
82  }
83  }
84 }
85 
87 {
88  /*
89  * Copy contents of HJCopy_ into HJ_. Cannot do a vector assign() because
90  * iterators to HJ_ get invalidated in MS VC++
91  */
92  if ( HJ_.size() != 0 )
93  memcpy( &HJ_[ 0 ], &HJCopy_[ 0 ], sizeof( double ) * HJ_.size() );
94 
95  double GkSum, GkEkSum; vector< CurrentStruct >::iterator icurrent = current_.begin();
96  vector< currentVecIter >::iterator iboundary = currentBoundary_.begin();
97  vector< double >::iterator ihs = HS_.begin();
98  vector< double >::iterator iv = V_.begin();
99 
100  vector< CompartmentStruct >::iterator ic;
101  for ( ic = compartment_.begin(); ic != compartment_.end(); ++ic )
102  {
103  GkSum = 0.0;
104  GkEkSum = 0.0;
105  for ( ; icurrent < *iboundary; ++icurrent )
106  {
107  GkSum += icurrent->Gk;
108  GkEkSum += icurrent->Gk * icurrent->Ek;
109  }
110 
111  *ihs = *( 2 + ihs ) + GkSum;
112  *( 3 + ihs ) = *iv * ic->CmByDt + ic->EmByRm + GkEkSum;
113 
114  ++iboundary, ihs += 4, ++iv;
115  }
116 
117  map< unsigned int, InjectStruct >::iterator inject;
118  for ( inject = inject_.begin(); inject != inject_.end(); ++inject )
119  {
120  unsigned int ic = inject->first;
121  InjectStruct& value = inject->second;
122 
123  HS_[ 4 * ic + 3 ] += value.injectVarying + value.injectBasal;
124 
125  value.injectVarying = 0.0;
126  }
127 
128  // Synapses are being handled as external channels.
129  //~ double Gk, Ek;
130  //~ vector< SynChanStruct >::iterator isyn;
131  //~ for ( isyn = synchan_.begin(); isyn != synchan_.end(); ++isyn ) {
132  //~ get< double >( isyn->elm_, synGkFinfo, Gk );
133  //~ get< double >( isyn->elm_, synEkFinfo, Ek );
134  //~
135  //~ unsigned int ic = isyn->compt_;
136  //~ HS_[ 4 * ic ] += Gk;
137  //~ HS_[ 4 * ic + 3 ] += Gk * Ek;
138  //~ }
139 
140  ihs = HS_.begin();
141  vector< double >::iterator iec;
142  for ( iec = externalCurrent_.begin(); iec != externalCurrent_.end(); iec += 2 )
143  {
144  *ihs += *iec;
145  *( 3 + ihs ) += *( iec + 1 );
146 
147  ihs += 4;
148  }
149 
150  stage_ = 0; // Update done.
151 }
152 
154 {
155  vector< double* >::iterator icatarget = caTarget_.begin();
156  vector< double >::iterator ivmid = VMid_.begin();
157  vector< CurrentStruct >::iterator icurrent = current_.begin();
158  vector< currentVecIter >::iterator iboundary = currentBoundary_.begin();
159 
160  /*
161  * caAdvance_: This flag determines how current flowing into a calcium pool
162  * is computed. A value of 0 means that the membrane potential at the
163  * beginning of the time-step is used for the calculation. This is how
164  * GENESIS does its computations. A value of 1 means the membrane potential
165  * at the middle of the time-step is used. This is the correct way of
166  * integration, and is the default way.
167  */
168  if ( caAdvance_ == 1 )
169  {
170  for ( ; iboundary != currentBoundary_.end(); ++iboundary )
171  {
172  for ( ; icurrent < *iboundary; ++icurrent )
173  {
174  if ( *icatarget )
175  **icatarget += icurrent->Gk * ( icurrent->Ek - *ivmid );
176 
177  ++icatarget;
178  }
179 
180  ++ivmid;
181  }
182  }
183  else if ( caAdvance_ == 0 )
184  {
185  vector< double >::iterator iv = V_.begin();
186  double v0;
187 
188  for ( ; iboundary != currentBoundary_.end(); ++iboundary )
189  {
190  for ( ; icurrent < *iboundary; ++icurrent )
191  {
192  if ( *icatarget )
193  {
194  v0 = ( 2 * *ivmid - *iv );
195 
196  **icatarget += icurrent->Gk * ( icurrent->Ek - v0 );
197  }
198 
199  ++icatarget;
200  }
201 
202  ++ivmid, ++iv;
203  }
204  }
205 
206  vector< CaConcStruct >::iterator icaconc;
207  vector< double >::iterator icaactivation = caActivation_.begin();
208  vector< double >::iterator ica = ca_.begin();
209  for ( icaconc = caConc_.begin(); icaconc != caConc_.end(); ++icaconc )
210  {
211  *ica = icaconc->process( *icaactivation );
212  ++ica, ++icaactivation;
213  }
214 
215  caActivation_.assign( caActivation_.size(), 0.0 );
216 }
217 
219 {
220  vector< double >::iterator iv;
221  vector< double >::iterator istate = state_.begin();
222  vector< int >::iterator ichannelcount = channelCount_.begin();
223  vector< ChannelStruct >::iterator ichan = channel_.begin();
224  vector< ChannelStruct >::iterator chanBoundary;
225  vector< unsigned int >::iterator icacount = caCount_.begin();
226  vector< double >::iterator ica = ca_.begin();
227  vector< double >::iterator caBoundary;
228  vector< LookupColumn >::iterator icolumn = column_.begin();
229  vector< LookupRow >::iterator icarowcompt;
230  vector< LookupRow* >::iterator icarow = caRow_.begin();
231  vector< double >::iterator iextca = externalCalcium_.begin();
232 
233  LookupRow vRow;
234  LookupRow dRow;
235  double C1, C2;
236 
237  for ( iv = V_.begin(); iv != V_.end(); ++iv )
238  {
239  vTable_.row( *iv, vRow );
240  icarowcompt = caRowCompt_.begin();
241  caBoundary = ica + *icacount;
242  for ( ; ica < caBoundary; ++ica )
243  {
244  caTable_.row( *ica, *icarowcompt );
245 
246  ++icarowcompt;
247  }
248 
249  /*
250  * Optimize by moving "if ( instant )" outside the loop, because it is
251  * rarely used. May also be able to avoid "if ( power )".
252  *
253  * Or not: excellent branch predictors these days.
254  *
255  * Will be nice to test these optimizations.
256  */
257  chanBoundary = ichan + *ichannelcount;
258  for ( ; ichan < chanBoundary; ++ichan )
259  {
260 
261  caTable_.row( *iextca, dRow );
262 
263  if ( ichan->Xpower_ > 0.0 )
264  {
265  vTable_.lookup( *icolumn, vRow, C1, C2 );
266  //~ *istate = *istate * C1 + C2;
267  //~ *istate = ( C1 + ( 2 - C2 ) * *istate ) / C2;
268  if ( ichan->instant_ & INSTANT_X )
269  *istate = C1 / C2;
270  else
271  {
272  double temp = 1.0 + dt / 2.0 * C2;
273  *istate = ( *istate * ( 2.0 - temp ) + dt * C1 ) / temp;
274  }
275 
276  ++icolumn, ++istate;
277  }
278 
279  if ( ichan->Ypower_ > 0.0 )
280  {
281  vTable_.lookup( *icolumn, vRow, C1, C2 );
282  //~ *istate = *istate * C1 + C2;
283  //~ *istate = ( C1 + ( 2 - C2 ) * *istate ) / C2;
284  if ( ichan->instant_ & INSTANT_Y )
285  *istate = C1 / C2;
286  else
287  {
288  double temp = 1.0 + dt / 2.0 * C2;
289  *istate = ( *istate * ( 2.0 - temp ) + dt * C1 ) / temp;
290 
291 }
292  ++icolumn, ++istate;
293  }
294 
295  if ( ichan->Zpower_ > 0.0 )
296  {
297  LookupRow* caRow = *icarow;
298 
299  if ( caRow )
300  {
301  caTable_.lookup( *icolumn, *caRow, C1, C2 );
302 
303  }
304  else if (*iextca >0)
305 
306  {
307  caTable_.lookup( *icolumn, dRow, C1, C2 );
308  }
309  else
310  {
311  vTable_.lookup( *icolumn, vRow, C1, C2 );
312 
313  }
314 
315  //~ *istate = *istate * C1 + C2;
316  //~ *istate = ( C1 + ( 2 - C2 ) * *istate ) / C2;
317  if ( ichan->instant_ & INSTANT_Z )
318  *istate = C1 / C2;
319  else
320  {
321  double temp = 1.0 + dt / 2.0 * C2;
322  *istate = ( *istate * ( 2.0 - temp ) + dt * C1 ) / temp;
323  }
324 
325  ++icolumn, ++istate, ++icarow;
326 
327  }
328  ++iextca;
329  }
330 
331  ++ichannelcount, ++icacount;
332  }
333 }
334 
339 {
340  return;
341 }
342 
344 {
345  vector< SpikeGenStruct >::iterator ispike;
346  for ( ispike = spikegen_.begin(); ispike != spikegen_.end(); ++ispike )
347  ispike->send( info );
348 }
349 
356 {
357  vector< unsigned int >::iterator i;
358 
359  for ( i = outVm_.begin(); i != outVm_.end(); ++i ) {
360  Compartment::VmOut()->send(
361  //~ ZombieCompartment::VmOut()->send(
362  compartmentId_[ *i ].eref(),
363  V_[ *i ]
364  );
365  }
366 
367  for ( i = outIk_.begin(); i != outIk_.end(); ++i ){
368 
369  unsigned int comptIndex = chan2compt_[ *i ];
370 
371  assert( comptIndex < V_.size() );
372 
373  ChanBase::IkOut()->send(channelId_[*i].eref(),
374  (current_[ *i ].Ek - V_[ comptIndex ]) * current_[ *i ].Gk);
375 
376  }
377 
378  for ( i = outCa_.begin(); i != outCa_.end(); ++i )
379  //~ CaConc::concOut()->send(
380  CaConcBase::concOut()->send(
381  caConcId_[ *i ].eref(),
382  ca_[ *i ]
383  );
384 }
uint32_t value
Definition: moosemodule.h:42
static const int INSTANT_X
Definition: HSolveActive.h:172
static const int INSTANT_Z
Definition: HSolveActive.h:174
void sendValues(ProcPtr info)
static SrcFinfo1< double > * concOut()
Definition: CaConcBase.cpp:25
void advanceSynChans(ProcPtr info)
double injectBasal
Definition: HSolveStruct.h:41
void forwardEliminate()
void advanceChannels(double dt)
void sendSpikes(ProcPtr info)
void backwardSubstitute()
static SrcFinfo1< double > * IkOut()
Definition: ChanBase.cpp:28
double dt
Definition: ProcInfo.h:18
double injectVarying
Definition: HSolveStruct.h:40
static const int INSTANT_Y
Definition: HSolveActive.h:173
static SrcFinfo1< double > * VmOut()
void advanceCalcium()
ostream & operator<<(ostream &s, const HinesMatrix &m)
void step(ProcPtr info)
Equivalent to process.
void calculateChannelCurrents()
double * row
Pointer to the first column on a row.
Definition: RateLookup.h:15
void updateMatrix()