Xyce  6.1
N_DEV_Neuron3.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2015 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_Neuron3.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Richard Schiek, Electrical and Microsytem Modeling
33 //
34 // Creation Date : 06/10/09
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.46 $
40 //
41 // Revision Date : $Date: 2015/10/20 22:32:48 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 // ---------- Standard Includes ----------
49 
50 // ---------- Xyce Includes ----------
51 #include <N_DEV_DeviceOptions.h>
52 #include <N_DEV_DeviceMaster.h>
53 #include <N_DEV_ExternData.h>
54 #include <N_DEV_MatrixLoadData.h>
55 #include <N_DEV_Neuron3.h>
56 #include <N_DEV_SolverState.h>
57 #include <N_DEV_Message.h>
58 #include <N_ERH_ErrorMgr.h>
59 
60 #include <N_DEV_Neuron.h>
61 
62 #include <N_LAS_Vector.h>
63 #include <N_LAS_Matrix.h>
64 #include <N_UTL_FeatureTest.h>
65 #include <N_UTL_Math.h>
66 
67 namespace Xyce {
68 namespace Device {
69 
70 namespace Neuron3 {
71 
73 {
74  p.addPar ("R",0.0,&Neuron3::Instance::rInt)
75  .setGivenMember(&Neuron3::Instance::rIntGiven)
76  .setUnit(U_OHMMM1)
77  .setCategory(CAT_NONE)
78  .setDescription("Intracellular resistivity");
79 
81  .setGivenMember(&Neuron3::Instance::radiusGiven)
82  .setUnit(U_METER)
83  .setCategory(CAT_NONE)
84  .setDescription("Segment radius");
85 
87  .setGivenMember(&Neuron3::Instance::lengthGiven)
88  .setUnit(U_METER)
89  .setCategory(CAT_NONE)
90  .setDescription("Cable length");
91 
92  p.addPar ("RPS",1.0e-6,&Neuron3::Instance::rIntPrevious)
93  .setGivenMember(&Neuron3::Instance::rIntPreviousGiven)
94  .setUnit(U_OHMMM1)
95  .setCategory(CAT_NONE)
96  .setDescription("Previous segment,intracellular resistivity");
97 
100  .setUnit(U_METER)
101  .setCategory(CAT_NONE)
102  .setDescription("Previous segment,segment radius");
103 
106  .setUnit(U_METER)
107  .setCategory(CAT_NONE)
108  .setDescription("Previous segment length");
109 
110  p.addPar ("RNS",1.0e-6,&Neuron3::Instance::rIntNext)
111  .setGivenMember(&Neuron3::Instance::rIntNextGiven)
112  .setUnit(U_OHMMM1)
113  .setCategory(CAT_NONE)
114  .setDescription("Next segment,intracellular resistivity");
115 
117  .setGivenMember(&Neuron3::Instance::radiusNextGiven)
118  .setUnit(U_METER)
119  .setCategory(CAT_NONE)
120  .setDescription("Next segment,segment radius");
121 
123  .setGivenMember(&Neuron3::Instance::lengthNextGiven)
124  .setUnit(U_METER)
125  .setCategory(CAT_NONE)
126  .setDescription("Next segment length");
127 
129  .setGivenMember(&Neuron3::Instance::nSegGiven)
130  .setUnit(U_NONE)
131  .setCategory(CAT_NONE)
132  .setDescription("Number of segments" );
133 }
134 
136 {
137  p.addPar ("CMEM",0.0,&Neuron3::Model::cMem)
138  .setGivenMember(&Neuron3::Model::cMemGiven)
139  .setUnit(U_FARAD)
140  .setCategory(CAT_NONE)
141  .setDescription("Membrane capacitance");
142 
143  p.addPar ("GMEM",0.0,&Neuron3::Model::gMem)
144  .setGivenMember(&Neuron3::Model::gMemGiven)
145  .setUnit(U_OHMM1)
146  .setCategory(CAT_NONE)
147  .setDescription("Membrane conductance");
148 
149  p.addPar ("VREST",0.0,&Neuron3::Model::vRest)
150  .setGivenMember(&Neuron3::Model::vRestGiven)
151  .setUnit(U_VOLT)
152  .setCategory(CAT_NONE)
153  .setDescription("Resting potential");
154 
155  p.addPar ("EK",0.0,&Neuron3::Model::eK)
156  .setGivenMember(&Neuron3::Model::eKGiven)
157  .setUnit(U_VOLT)
158  .setCategory(CAT_NONE)
159  .setDescription("Potassium resting potential");
160 
161  p.addPar ("GK",0.0,&Neuron3::Model::gK)
162  .setGivenMember(&Neuron3::Model::gKGiven)
163  .setUnit(U_OHMM1)
164  .setCategory(CAT_NONE)
165  .setDescription("Potassium base conductance");
166 
167  p.addPar ("ENA",0.0,&Neuron3::Model::eNa)
168  .setGivenMember(&Neuron3::Model::eNaGiven)
169  .setUnit(U_VOLT)
170  .setCategory(CAT_NONE)
171  .setDescription("Sodium resting potential");
172 
173  p.addPar ("GNA",0.0,&Neuron3::Model::gNa)
174  .setGivenMember(&Neuron3::Model::gNaGiven)
175  .setUnit(U_OHMM1)
176  .setCategory(CAT_NONE)
177  .setDescription("Sodium base conductance");
178 
179  p.addPar ("R",0.0,&Neuron3::Model::rInt)
180  .setGivenMember(&Neuron3::Model::rIntGiven)
181  .setUnit(U_OHMMM1)
182  .setCategory(CAT_NONE)
183  .setDescription("Intracellular resistivity");
184 
185  p.addPar ("A",0.0,&Neuron3::Model::radius)
186  .setGivenMember(&Neuron3::Model::radiusGiven)
187  .setUnit(U_METER)
188  .setCategory(CAT_NONE)
189  .setDescription("Segment radius");
190 
191  p.addPar ("L",0.0,&Neuron3::Model::length)
192  .setGivenMember(&Neuron3::Model::lengthGiven)
193  .setUnit(U_METER)
194  .setCategory(CAT_NONE)
195  .setDescription("Cable length");
196 
197  p.addPar ("RPS",1.0e-6,&Neuron3::Model::rIntPrevious)
198  .setGivenMember(&Neuron3::Model::rIntPreviousGiven)
199  .setUnit(U_OHMMM1)
200  .setCategory(CAT_NONE)
201  .setDescription("Previous segment,intracellular resistivity");
202 
204  .setGivenMember(&Neuron3::Model::radiusPreviousGiven)
205  .setUnit(U_METER)
206  .setCategory(CAT_NONE)
207  .setDescription("Previous segment,segment radius");
208 
210  .setGivenMember(&Neuron3::Model::lengthPreviousGiven)
211  .setUnit(U_METER)
212  .setCategory(CAT_NONE)
213  .setDescription("Previous segment length");
214 
215  p.addPar ("RNS",1.0e-6,&Neuron3::Model::rIntNext)
216  .setGivenMember(&Neuron3::Model::rIntNextGiven)
217  .setUnit(U_OHMMM1)
218  .setCategory(CAT_NONE)
219  .setDescription("Next segment,intracellular resistivity");
220 
221  p.addPar ("ANS",0.0,&Neuron3::Model::radiusNext)
222  .setGivenMember(&Neuron3::Model::radiusNextGiven)
223  .setUnit(U_METER)
224  .setCategory(CAT_NONE)
225  .setDescription("Next segment,segment radius");
226 
227  p.addPar ("LNS",0.0,&Neuron3::Model::lengthNext)
228  .setGivenMember(&Neuron3::Model::lengthNextGiven)
229  .setUnit(U_METER)
230  .setCategory(CAT_NONE)
231  .setDescription("Next segment length");
232 
233  p.addPar("N",0,&Neuron3::Model::nSeg)
234  .setGivenMember(&Neuron3::Model::nSegGiven)
235  .setUnit(U_NONE)
236  .setCategory(CAT_NONE)
237  .setDescription("Number of segments" );
238 }
239 
240 
241 
242 //
243 // static class member inits
244 //
245 
246 
247 // Class Instance
248 //-----------------------------------------------------------------------------
249 // Function : Instance::processParams
250 // Purpose :
251 // Special Notes :
252 // Scope : public
253 // Creator : Richard Schiek, Electrical and Microsytem Modeling
254 // Creation Date : 06/10/09
255 //-----------------------------------------------------------------------------
257 {
258  // If there are any time dependent parameters, set their values at for
259  // the current time.
260 
261  // pull unspecified params out of the model if they weren't specified here
262  if( !nSegGiven)
263  {
264  if ( model_.nSegGiven )
265  nSeg = model_.nSeg;
266  else
267  nSeg = 10;
268  }
269  if( !rIntGiven && model_.rIntGiven )
270  {
271  rInt = model_.rInt;
272  }
273  if( !radiusGiven && model_.radiusGiven )
274  {
275  radius = model_.radius;
276  }
277  if( !lengthGiven && model_.lengthGiven )
278  {
279  length = model_.length;
280  }
281 
282  // now that nSeg, length and radius are set calculate segment area
283  segArea = 2.0 * M_PI * radius * length / nSeg;
284 
285  return true;
286 }
287 
288 //-----------------------------------------------------------------------------
289 // Function : Instance::updateTemperature
290 // Purpose :
291 // Special Notes :
292 // Scope : public
293 // Creator : Richard Schiek, Electrical and Microsytem Modeling
294 // Creation Date : 06/10/09
295 //-----------------------------------------------------------------------------
296 bool Instance::updateTemperature ( const double & temp)
297 {
298  bool bsuccess = true;
299  return bsuccess;
300 }
301 
302 //-----------------------------------------------------------------------------
303 // Function : Instance::Instance
304 // Purpose : constructor
305 // Special Notes :
306 // Scope : public
307 // Creator : Richard Schiek, Electrical and Microsytem Modeling
308 // Creation Date : 06/10/09
309 //-----------------------------------------------------------------------------
311  const Configuration & configuration,
312  const InstanceBlock & IB,
313  Model & Miter,
314  const FactoryBlock & factory_block)
315  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
316  model_(Miter),
317  rInt(0.0),
318  radius(0.0),
319  length(0.0),
320  segArea(0.0),
321  nSeg(0),
322  rIntGiven(false),
323  radiusGiven(false),
324  lengthGiven(false),
325  nSegGiven(false),
326  rIntPrevious(0.0),
327  radiusPrevious(0.0),
328  lengthPrevious(0.0),
329  rIntNext(0.0),
330  radiusNext(0.0),
331  lengthNext(0.0),
332  rIntPreviousGiven(false),
333  radiusPreviousGiven(false),
334  lengthPreviousGiven(false),
335  rIntNextGiven(false),
336  radiusNextGiven(false),
337  lengthNextGiven(false),
338  kcl1Fvalue(0.0),
339  kcl2Fvalue(0.0),
340  dkcl1F_dVin(0.0),
341  dkcl1F_dVs0(0.0),
342  dkcl2F_dVout(0.0),
343  dkcl2F_dVsn(0.0),
344  li_Pos(0),
345  li_Neg(0),
346  APosEquPosNodeOffset(0),
347  APosEquNextNodeOffset(0),
348  ANegEquNegNodeOffset(0),
349  ANegEquLastNodeOffset(0)
350 {
351  // we have pased the model and instance parameters so now we can calculate
352  // the number of internal vars
353  numExtVars = 2; // input and output voltage
354 
355  // Set params to constant default values:
356  setDefaultParams ();
357 
358  // Set params according to instance line
359  setParams (IB.params);
360 
361  // Set any non-constant parameter defaults:
362 
363  //if (!given("TEMP"))
364  // temp = getDeviceOptions().temp.dVal();
365 
366  // Calculate any parameters specified as expressions:
368 
369  // calculate dependent (ie computed) params and check for errors:
370  processParams ();
371 
372  // now we can calculate the number of internal vars
373  numIntVars = nSeg * 4; // ion channel vars + one internal voltage node var for each segment
374  numStateVars = nSeg * 2;
375  int numVars = numExtVars + numIntVars;
376 
377 
378  //
379  // i(n) - I(n)/A - g(n,n+1) * (V(n+1) - V(n)) - g(n,n-1) * (V(n-1) - V(n)) + Cm dV(n)/d(t) = 0
380  //
381  // Vin : g(0,1) * (V(1) - Vin ) = 0
382  // Vout : g(n,n-1) * (V(n-1) - Vout) = 0
383  // Vnode : i(n) - I(n)/A - g(n,n+1) * (V(n+1) - V(n)) - g(n,n-1) * (V(n-1) - V(n)) + Cm dV(n)/d(t) = 0
384  // plus node supporting equations (a, b, m)
385  //
386  // jacobian format
387  // Vin Vout V1 n m h V2 n m h V(nSeg) n m h
388  // kcl Vin -g(0,1) g(0,1)
389  // kcl Vout -g(n,n-1) g(n,n-1)
390  // kcl V1 yes yes yes yes yes yes
391  // a yes yes
392  // b yes yes
393  // m yes yes
394  // kcl V2 yes yes yes yes yes yes
395  // a 2 yes yes
396  // b 2 yes yes
397  // m 2 yes yes
398  // kcl VnSeg yes yes yes yes yes yes
399  // a nSeg yes yes
400  // b nSeg yes yes
401  // m nSeg yes yes
402  //
403  // jacobian element count by row:
404  // vin: 2
405  // vout: 2
406  // v1: 6
407  // a1: 2
408  // b1: 2
409  // m1: 2
410  // v2: 6
411  // a2: 2
412  // b2: 2
413  // m2: 2
414  // vnSeg:6
415  // a: 2
416  // b: 2
417  // m: 2
418  //
419  // set up jacStamp
420  if( jacStamp.empty() ) // redundant as jacStamp is not static for this device
421  { // it can't be as each cable may have a different number of nodes
422  jacStamp.resize(numVars);
423  jacStamp[0].resize(2);
424  jacStamp[0][0] = 0;
425  jacStamp[0][1] = 1;
426  jacStamp[1].resize(2);
427  jacStamp[1][0] = 1;
428  jacStamp[1][1] = numVars - 4;
429  for( int i=2; i<numVars; i+=4)
430  {
431  jacStamp[i].resize(6);
432  if( i == 2 )
433  {
434  jacStamp[i][0] = 0;
435  }
436  else
437  {
438  jacStamp[i][0] = i-4;
439  }
440  jacStamp[i][1] = i;
441  jacStamp[i][2] = i+1;
442  jacStamp[i][3] = i+2;
443  jacStamp[i][4] = i+3;
444  if( i==(numVars-4) )
445  {
446  jacStamp[i][5] = 1;
447  }
448  else
449  {
450  jacStamp[i][5] = i+4;
451  }
452  jacStamp[i+1].resize(2);
453  jacStamp[i+1][0] = i;
454  jacStamp[i+1][1] = i+1;
455  jacStamp[i+2].resize(2);
456  jacStamp[i+2][0] = i;
457  jacStamp[i+2][1] = i+2;
458  jacStamp[i+3].resize(2);
459  jacStamp[i+3][0] = i;
460  jacStamp[i+3][1] = i+3;
461  }
462 
463  }
464 
465  /*
466  // print out jacStamp
467  int numRows = jacStamp.size();
468  for( int i=0; i< numRows; i++ )
469  {
470  int numCol = jacStamp[i].size();
471  Xyce::dout() << "jacStamp[ " << i << " ] = { ";
472  for(int j=0; j<numCol; j++)
473  {
474  Xyce::dout() << jacStamp[i][j] << " ";
475  }
476  Xyce::dout() << " } " << std::endl;
477  }
478  Xyce::dout() << std::endl;
479  */
480 
481  // calculate segment conductivities used in load calls:
482  // Note: conductivity to the previous and next segment is not symmetric if the segment length and/or radius is not are not equal
483  // the full formula is:
484  // g(n,n') = radius * (radius')^2 / ( rInt segLength * ( segLength * (radius')^2 + segLength' * (radius)^2 ) )
485  //
486  // equation 6.30 Theoretical neuroscience: computational and mathematical modeling of neural systems, Peter Dayan and L. F. Abbot 2001
487  // If we allow variable segment lengths and radii then we'll need to update this calculation
488  //
489  // Note: the above equation has the wrong units unless rInt (which is Ohm Length) is rLong (which is Ohm/Length).
490  //
491  gForward.resize(nSeg);
492  gBackward.resize(nSeg);
493  double segLength = length / nSeg;
494  double rLong = rInt / (M_PI * radius * radius); // longitudinal resistivity (ohm/length)
495  gBackward[0] = radius * (radiusPrevious * radiusPrevious) / (rLong * segLength * ( segLength * radiusPrevious * radiusPrevious + lengthPrevious * radius * radius ));
496  gForward[0] = radius * (radius * radius) / (rLong * segLength * ( segLength * radius * radius + segLength * radius * radius ));
497  gBackward[nSeg-1] = radius * (radius * radius) / (rLong * segLength * ( segLength * radius * radius + segLength * radius * radius ));
498  gForward[nSeg-1] = radius * (radiusNext * radiusNext) / (rLong * segLength * ( segLength * radiusNext * radiusNext + lengthNext * radius * radius ));
499  for(int i=1; i<(nSeg-1); i++)
500  {
501  gBackward[i] = radius * (radius * radius) / (rLong * segLength * ( segLength * radius * radius + segLength * radius * radius ));
502  gForward[i] = gBackward[i];
503  }
504  /*
505  gBackward[0] = radius * (radiusPrevious * radiusPrevious) / (rInt * segLength * ( segLength * radiusPrevious * radiusPrevious + lengthPrevious * radius * radius ));
506  gForward[0] = radius * (radius * radius) / (rInt * segLength * ( segLength * radius * radius + segLength * radius * radius ));
507  gBackward[nSeg-1] = radius * (radius * radius) / (rInt * segLength * ( segLength * radius * radius + segLength * radius * radius ));
508  gForward[nSeg-1] = radius * (radiusNext * radiusNext) / (rInt * segLength * ( segLength * radiusNext * radiusNext + lengthNext * radius * radius ));
509  for(int i=1; i<(nSeg-1); i++)
510  {
511  gBackward[i] = radius * (radius * radius) / (rInt * segLength * ( segLength * radius * radius + segLength * radius * radius ));
512  gForward[i] = gBackward[i];
513  }
514  */
515  // allocate space for load and jacobian terms per segment
516  // variable indecies loads
517  li_Vol.resize(nSeg);
518  li_nPro.resize(nSeg);
519  li_mPro.resize(nSeg);
520  li_hPro.resize(nSeg);
521  li_KCurrentState.resize(nSeg);
522  li_NaCurrentState.resize(nSeg);
523  segFvalue.resize(nSeg);
524  segQvalue.resize(nSeg);
525  segNEquFvalue.resize(nSeg);
526  segNEquQvalue.resize(nSeg);
527  segMEquFvalue.resize(nSeg);
528  segMEquQvalue.resize(nSeg);
529  segHEquFvalue.resize(nSeg);
530  segHEquQvalue.resize(nSeg);
531 
532  // jacobian elements
533  segF_dVp.resize(nSeg);
534  segF_dV.resize(nSeg);
535  segF_dVn.resize(nSeg);
536  segF_dn.resize(nSeg);
537  segF_dm.resize(nSeg);
538  segF_dh.resize(nSeg);
539  segQ_dV.resize(nSeg);
540  dnF_dV.resize(nSeg);
541  dnF_dn.resize(nSeg);
542  dnQ_dn.resize(nSeg);
543  dmF_dV.resize(nSeg);
544  dmF_dm.resize(nSeg);
545  dmQ_dm.resize(nSeg);
546  dhF_dV.resize(nSeg);
547  dhF_dh.resize(nSeg);
548  dhQ_dh.resize(nSeg);
549 
550  // state vars
551  potassiumCurrent.resize(nSeg);
552  sodiumCurrent.resize(nSeg);
553 
554 }
555 
556 //-----------------------------------------------------------------------------
557 // Function : Instance::~Instance
558 // Purpose : destructor
559 // Special Notes :
560 // Scope : public
561 // Creator : Richard Schiek, Electrical and Microsytem Modeling
562 // Creation Date : 06/10/09
563 //-----------------------------------------------------------------------------
565 {
566 }
567 
568 //-----------------------------------------------------------------------------
569 // Function : Instance::registerLIDs
570 // Purpose :
571 // Special Notes :
572 // Scope : public
573 // Creator : Richard Schiek, Electrical and Microsytem Modeling
574 // Creation Date : 06/10/09
575 //-----------------------------------------------------------------------------
576 void Instance::registerLIDs(const std::vector<int> & intLIDVecRef,
577  const std::vector<int> & extLIDVecRef)
578 {
579  AssertLIDs(intLIDVecRef.size() == numIntVars);
580  AssertLIDs(extLIDVecRef.size() == numExtVars);
581 
582  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
583  {
584  Xyce::dout() << std::endl << section_divider << std::endl;
585  Xyce::dout() << " Instance::registerLIDs" << std::endl;
586  Xyce::dout() << " name = " << getName() << std::endl;
587  }
588 
589  // copy over the global ID lists.
590  intLIDVec = intLIDVecRef;
591  extLIDVec = extLIDVecRef;
592 
593  li_Pos = extLIDVec[0];
594  li_Neg = extLIDVec[1];
595  for( int i=0, j=0; i<nSeg; i++, j+=4)
596  {
597  li_Vol[i] = intLIDVec[j];
598  li_nPro[i] = intLIDVec[j+1];
599  li_mPro[i] = intLIDVec[j+2];
600  li_hPro[i] = intLIDVec[j+3];
601  }
602 
603  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
604  {
605  Xyce::dout() << " li_Pos = " << li_Pos << std::endl
606  << " li_Neg = " << li_Neg << std::endl;
607  for( int i=0; i<nSeg; i++ )
608  {
609  Xyce::dout() << " li_Vol[ " << i << " ] = " << li_Vol[i] << std::endl
610  << " li_nPro[ " << i << " ] = " << li_nPro[i] << std::endl
611  << " li_mPro[ " << i << " ] = " << li_mPro[i] << std::endl
612  << " li_hPro[ " << i << " ] = " << li_hPro[i] << std::endl;
613  }
614  }
615 
616  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
617  {
618  Xyce::dout() << section_divider << std::endl;
619  }
620 }
621 
622 //-----------------------------------------------------------------------------
623 // Function : Instance::loadNodeSymbols
624 // Purpose :
625 // Special Notes :
626 // Scope : public
627 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
628 // Creation Date : 05/13/05
629 //-----------------------------------------------------------------------------
630 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
631 {
632  for (int i = 0; i < nSeg; i++)
633  {
634  std::ostringstream segNumber;
635  segNumber << i;
636  addInternalNode(symbol_table, li_Vol[i], getName(), "V" + segNumber.str());
637  addInternalNode(symbol_table, li_nPro[i], getName(), "N" + segNumber.str());
638  addInternalNode(symbol_table, li_mPro[i], getName(), "M" + segNumber.str());
639  addInternalNode(symbol_table, li_hPro[i], getName(), "H" + segNumber.str());
640  }
641 }
642 
643 //-----------------------------------------------------------------------------
644 // Function : Instance::registerStateLIDs
645 // Purpose :
646 // Special Notes :
647 // Scope : public
648 // Creator : Richard Schiek, Electrical and Microsytem Modeling
649 // Creation Date : 06/10/09
650 //-----------------------------------------------------------------------------
651 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
652 {
653  AssertLIDs(staLIDVecRef.size() == numStateVars);
654 
655  // copy over the global ID lists.
656  staLIDVec = staLIDVecRef;
657 
658  for( int i=0, j=0; i<nSeg; i++, j+=2)
659  {
660  li_KCurrentState[i] = staLIDVec[j];
661  li_NaCurrentState[i] = staLIDVec[j+1];
662  }
663 
664 }
665 
666 //-----------------------------------------------------------------------------
667 // Function : Instance::jacobianStamp
668 // Purpose :
669 // Special Notes :
670 // Scope : public
671 // Creator : Richard Schiek, Electrical and Microsytem Modeling
672 // Creation Date : 06/10/09
673 //-----------------------------------------------------------------------------
674 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
675 {
676  return jacStamp;
677 }
678 
679 //-----------------------------------------------------------------------------
680 // Function : Instance::registerJacLIDs
681 // Purpose :
682 // Special Notes :
683 // Scope : public
684 // Creator : Richard Schiek, Electrical and Microsytem Modeling
685 // Creation Date : 06/10/09
686 //-----------------------------------------------------------------------------
687 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
688 {
689  DeviceInstance::registerJacLIDs( jacLIDVec );
690 
691  // external terminals
692  APosEquPosNodeOffset = jacLIDVec[0][0];
693  APosEquNextNodeOffset = jacLIDVec[0][1];
694  ANegEquNegNodeOffset = jacLIDVec[1][0];
695  ANegEquLastNodeOffset = jacLIDVec[1][1];
696  /*
697  Xyce::dout() << "APosEquPosNodeOffset = " << APosEquPosNodeOffset << std::endl;
698  Xyce::dout() << "APosEquNextNodeOffset = " << APosEquNextNodeOffset << std::endl;
699  Xyce::dout() << "ANegEquNegNodeOffset = " << ANegEquNegNodeOffset << std::endl;
700  Xyce::dout() << "ANegEquLastNodeOffset = " << ANegEquLastNodeOffset << std::endl;
701  */
702 
703  // internal variables
704  SegVEqnVpreOffset.resize(nSeg);
705  SegVEqnVsegOffset.resize(nSeg);
706  SegVEqnVnexOffset.resize(nSeg);
707  SegVEqnNOffset.resize(nSeg);
708  SegVEqnMOffset.resize(nSeg);
709  SegVEqnHOffset.resize(nSeg);
710  NEquVNodeOffset.resize(nSeg);
711  NEquNNodeOffset.resize(nSeg);
712  MEquVNodeOffset.resize(nSeg);
713  MEquMNodeOffset.resize(nSeg);
714  HEquVNodeOffset.resize(nSeg);
715  HEquHNodeOffset.resize(nSeg);
716  for(int i=0, j=2; i<nSeg; i++, j+=4 )
717  {
718  SegVEqnVpreOffset[i] = jacLIDVec[j][0];
719  SegVEqnVsegOffset[i] = jacLIDVec[j][1];
720  SegVEqnNOffset[i] = jacLIDVec[j][2];
721  SegVEqnMOffset[i] = jacLIDVec[j][3];
722  SegVEqnHOffset[i] = jacLIDVec[j][4];
723  SegVEqnVnexOffset[i] = jacLIDVec[j][5];
724 
725  NEquVNodeOffset[i] = jacLIDVec[j+1][0];
726  NEquNNodeOffset[i] = jacLIDVec[j+1][1];
727  MEquVNodeOffset[i] = jacLIDVec[j+2][0];
728  MEquMNodeOffset[i] = jacLIDVec[j+2][1];
729  HEquVNodeOffset[i] = jacLIDVec[j+3][0];
730  HEquHNodeOffset[i] = jacLIDVec[j+3][1];
731  /*
732  Xyce::dout() << SegVEqnVpreOffset[i] << ", "
733  << SegVEqnVsegOffset[i] << ", "
734  << SegVEqnNOffset[i] << ", "
735  << SegVEqnMOffset[i] << ", "
736  << SegVEqnHOffset[i] << ", "
737  << SegVEqnVnexOffset[i] << ", "
738  << NEquVNodeOffset[i] << ", "
739  << NEquNNodeOffset[i] << ", "
740  << MEquVNodeOffset[i] << ", "
741  << MEquMNodeOffset[i] << ", "
742  << HEquVNodeOffset[i] << ", "
743  << HEquHNodeOffset[i] << std::endl;
744  */
745  }
746 }
747 
748 
749 //-----------------------------------------------------------------------------
750 // Function : Instance::updateIntermediateVars
751 // Purpose :
752 // Special Notes :
753 // Scope : public
754 // Creator : Richard Schiek, Electrical and Microsytem Modeling
755 // Creation Date : 06/10/09
756 //-----------------------------------------------------------------------------
758 {
759  //Xyce::dout() << "Instance::updateIntermediateVars()" << std::endl;
760 
761  bool bsuccess = true;
762 
763  // here we take the current solutions for V1, V2, n, m and h
764  // and use those to calculate all the terms needed for the next
765  // load cycle (F, Q, dFdX, dQdX)
766  Linear::Vector * solVectorPtr = extData.nextSolVectorPtr;
767 
768  double vIn = (*solVectorPtr)[li_Pos];
769  double vOut = (*solVectorPtr)[li_Neg];
770 
771  // take care of the input and output nodes as they are different
772  kcl1Fvalue = gForward[0] * ((*solVectorPtr)[li_Vol[0]] - vIn );
773  dkcl1F_dVin = -gForward[0];
774  dkcl1F_dVs0 = gForward[0];
775  kcl2Fvalue = gBackward[nSeg-1] * ((*solVectorPtr)[li_Vol[nSeg-1]] - vOut );
778  //Xyce::dout() << "end update: " << vIn << ", " << vOut << ", " << gForward[0] << ", " << gBackward[nSeg-1] << std::endl;
779 
780  // loop over segments getting all the load and jacobian terms for each segment
781  for( int i=0; i<nSeg; i++ )
782  {
783  // for this segment get the values of the local vars
784  double vSeg = (*solVectorPtr)[li_Vol[i]];
785  double vNext = 0.0;
786  if (i == (nSeg - 1))
787  {
788  vNext = vOut;
789  }
790  else
791  {
792  vNext = (*solVectorPtr)[li_Vol[i+1]];
793  }
794  double vPrev = 0.0;
795  if (i == 0 )
796  {
797  vPrev = vIn;
798  }
799  else
800  {
801  vPrev = (*solVectorPtr)[li_Vol[i-1]];
802  }
803  double nVarSeg = (*solVectorPtr)[li_nPro[i]];
804  double mVarSeg = (*solVectorPtr)[li_mPro[i]];
805  double hVarSeg = (*solVectorPtr)[li_hPro[i]];
806 
807  // do the voltage equation for this node
808  // get function and derivative values as we go.
809  {
810  // F part
811  // use scoping to avoid lots of similar variable names
812  const int numDeriv = 6;
813  Sacado::Fad::SFad<double,6> vVar( numDeriv, 0, vSeg );
814  Sacado::Fad::SFad<double,6> vVpr( numDeriv, 1, vPrev );
815  Sacado::Fad::SFad<double,6> vVne( numDeriv, 2, vNext );
816  Sacado::Fad::SFad<double,6> nVar( numDeriv, 3, nVarSeg );
817  Sacado::Fad::SFad<double,6> mVar( numDeriv, 4, mVarSeg );
818  Sacado::Fad::SFad<double,6> hVar( numDeriv, 5, hVarSeg );
819  // parameters
820  Sacado::Fad::SFad<double,6> gPrev( gBackward[i] );
821  Sacado::Fad::SFad<double,6> gNext( gForward[i] );
822  Sacado::Fad::SFad<double,6> gMemVar( model_.gMem * segArea );
823  Sacado::Fad::SFad<double,6> vRestVar( model_.vRest );
824  Sacado::Fad::SFad<double,6> gKVar( model_.gK * segArea );
825  Sacado::Fad::SFad<double,6> eKVar( model_.eK );
826  Sacado::Fad::SFad<double,6> gNaVar( model_.gNa * segArea );
827  Sacado::Fad::SFad<double,6> eNaVar( model_.eNa );
828  //Xyce::dout() << "segment update: " << i << ", " << vSeg << ", " << vPrev << ", " << vNext << ", " << gBackward[i] << ", " << gForward[i] << std::endl;
829  // compute the value and derivative terms for KCL 1 F
830  Sacado::Fad::SFad<double,6> resultFad;
831  resultFad = kcl1EquF( vVar, vVpr, vVne, nVar, mVar, hVar, gPrev, gNext, gMemVar, vRestVar, gKVar, eKVar, gNaVar, eNaVar );
832  segFvalue[i] = resultFad.val();
833  segF_dV[i] = resultFad.dx(0);
834  segF_dVp[i] = resultFad.dx(1);
835  segF_dVn[i] = resultFad.dx(2);
836  segF_dn[i] = resultFad.dx(3);
837  segF_dm[i] = resultFad.dx(4);
838  segF_dh[i] = resultFad.dx(5);
839  }
840  {
841  // Q part
842  const int numDeriv = 2;
843  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
844 
845  // parameters
846  Sacado::Fad::SFad<double,2> cMemVar( model_.cMem * segArea );
847 
848  Sacado::Fad::SFad<double,2> resultFad;
849  resultFad = kcl1EquQ( vVar, cMemVar );
850  segQvalue[i] = resultFad.val();
851  segQ_dV[i] = resultFad.dx(0);
852 
853  }
854 
855  // n - equation
856  {
857  const int numDeriv = 2;
858  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
859  Sacado::Fad::SFad<double,2> nVar( numDeriv, 1, nVarSeg );
860  // parameter
861  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
862 
863  Sacado::Fad::SFad<double,2> resultFad = nEquF( vVar, nVar, vRestVar);
864  segNEquFvalue[i] = resultFad.val();
865  dnF_dV[i] = resultFad.dx(0);
866  dnF_dn[i] = resultFad.dx(1);
867  }
868  {
869  const int numDeriv = 1;
870  Sacado::Fad::SFad<double,1> nVar( numDeriv, 0, nVarSeg );
871 
872  Sacado::Fad::SFad<double,1> resultFad = nEquQ( nVar );
873  segNEquQvalue[i] = resultFad.val();
874  dnQ_dn[i] = resultFad.dx(0);
875  }
876 
877  // m - equation
878  {
879  const int numDeriv = 2;
880  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
881  Sacado::Fad::SFad<double,2> mVar( numDeriv, 1, mVarSeg );
882  // parameter
883  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
884 
885  Sacado::Fad::SFad<double,2> resultFad = mEquF( vVar, mVar, vRestVar );
886  segMEquFvalue[i] = resultFad.val();
887  dmF_dV[i] = resultFad.dx(0);
888  dmF_dm[i] = resultFad.dx(1);
889  }
890  {
891  const int numDeriv = 1;
892  Sacado::Fad::SFad<double,1> mVar( numDeriv, 0, mVarSeg );
893 
894  Sacado::Fad::SFad<double,1> resultFad = mEquQ( mVar );
895  segMEquQvalue[i] = resultFad.val();
896  dmQ_dm[i] = resultFad.dx(0);
897  }
898 
899  // h - equation
900  {
901  const int numDeriv = 2;
902  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
903  Sacado::Fad::SFad<double,2> hVar( numDeriv, 1, hVarSeg );
904  // parameter
905  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
906 
907  Sacado::Fad::SFad<double,2> resultFad = hEquF( vVar, hVar, vRestVar );
908  segHEquFvalue[i] = resultFad.val();
909  dhF_dV[i] = resultFad.dx(0);
910  dhF_dh[i] = resultFad.dx(1);
911  }
912  {
913  const int numDeriv = 1;
914  Sacado::Fad::SFad<double,1> hVar( numDeriv, 0, hVarSeg );
915 
916  Sacado::Fad::SFad<double,1> resultFad = hEquQ( hVar );
917  segHEquQvalue[i] = resultFad.val();
918  dhQ_dh[i] = resultFad.dx(0);
919  }
920 
921  // calculate potassium current
922  potassiumCurrent[i] = model_.gK * pow(nVarSeg, 4.0) * (vSeg - model_.eK);
923 
924  // calculate sodium current
925  sodiumCurrent[i] = model_.gNa * pow(mVarSeg, 3.0) * hVarSeg * (vSeg - model_.eNa);
926 
927  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
928  {
929  Xyce::dout() << "Segment " << i << std::endl
930  << "vPrev = " << vPrev << std::endl
931  << "vSeg = " << vSeg << std::endl
932  << "vNext = " << vNext << std::endl
933  << "n, m, h = " << nVarSeg << ", " << mVarSeg << ", " << hVarSeg << std::endl
934  << "segFvalue = " << segFvalue[i] << std::endl
935  << "segQvalue = " << segQvalue[i] << std::endl
936  << "segNEquFvalue = " << segNEquFvalue[i] << std::endl
937  << "segNEquQvalue = " << segNEquQvalue[i] << std::endl
938  << "segMEquFvalue = " << segMEquFvalue[i] << std::endl
939  << "segMEquQvalue = " << segMEquQvalue[i] << std::endl
940  << "segHEquFvalue = " << segHEquFvalue[i] << std::endl
941  << "segHEquQvalue = " << segHEquQvalue[i] << std::endl
942  << std::endl;
943 
944  }
945 
946 
947  }
948 
949 
950 
951  return bsuccess;
952 }
953 //-----------------------------------------------------------------------------
954 // Function : Instance::updatePrimaryState
955 // Purpose :
956 // Special Notes :
957 // Scope : public
958 // Creator : Richard Schiek, Electrical and Microsytem Modeling
959 // Creation Date : 06/10/09
960 //-----------------------------------------------------------------------------
962 {
963  bool bsuccess = true;
964 
966 
967  Linear::Vector * solVectorPtr = extData.nextSolVectorPtr;
968  Linear::Vector * staVectorPtr = extData.nextStaVectorPtr;
969 
970  for( int i=0; i<nSeg; i++)
971  {
972  (*staVectorPtr)[li_KCurrentState[i]] = potassiumCurrent[i];
973  (*staVectorPtr)[li_NaCurrentState[i]] = sodiumCurrent[i];
974  }
975 
976  return bsuccess;
977 }
978 
979 //-----------------------------------------------------------------------------
980 // Function : Instance::updateSecondaryState
981 // Purpose :
982 // Special Notes :
983 // Scope : public
984 // Creator : Richard Schiek, Electrical and Microsytem Modeling
985 // Creation Date : 06/10/09
986 //-----------------------------------------------------------------------------
988 {
989  bool bsuccess = true;
990  Linear::Vector * staVectorPtr = extData.nextStaVectorPtr;
991 
992  return bsuccess;
993 }
994 
995 //-----------------------------------------------------------------------------
996 // Function : Instance::loadDAEQVector
997 //
998 // Purpose : Loads the Q-vector contributions
999 //
1000 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1001 // which the system of equations is represented as:
1002 //
1003 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1004 //
1005 // Scope : public
1006 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1007 // Creation Date : 06/10/09
1008 //-----------------------------------------------------------------------------
1010 {
1011  bool bsuccess = true;
1012 
1013  Linear::Vector * daeQVecPtr = extData.daeQVectorPtr;
1014 
1015  for( int i=0; i<nSeg ; i++)
1016  {
1017  (*daeQVecPtr)[li_Vol[i]] += segQvalue[i];
1018  (*daeQVecPtr)[li_nPro[i]] += segNEquQvalue[i];
1019  (*daeQVecPtr)[li_mPro[i]] += segMEquQvalue[i];
1020  (*daeQVecPtr)[li_hPro[i]] += segHEquQvalue[i];
1021  }
1022 
1023  return bsuccess;
1024 }
1025 
1026 
1027 
1028 //-----------------------------------------------------------------------------
1029 // Function : Instance::loadDAEFVector
1030 //
1031 // Purpose : Loads the F-vector contributions for a single
1032 // Neuron 3 instance.
1033 //
1034 // Special Notes :
1035 //
1036 // Scope : public
1037 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1038 // Creation Date : 06/10/09
1039 //-----------------------------------------------------------------------------
1041 {
1042  bool bsuccess=true;
1043 
1044  Linear::Vector * daeFVecPtr = extData.daeFVectorPtr;
1045 
1046  (*daeFVecPtr)[li_Pos] += kcl1Fvalue;
1047  (*daeFVecPtr)[li_Neg] += kcl2Fvalue;
1048 
1049  for( int i=0; i<nSeg ; i++)
1050  {
1051  (*daeFVecPtr)[li_Vol[i]] += segFvalue[i];
1052  (*daeFVecPtr)[li_nPro[i]] += segNEquFvalue[i];
1053  (*daeFVecPtr)[li_mPro[i]] += segMEquFvalue[i];
1054  (*daeFVecPtr)[li_hPro[i]] += segHEquFvalue[i];
1055  }
1056 
1057  return bsuccess;
1058 }
1059 
1060 //-----------------------------------------------------------------------------
1061 // Function : Instance::loadDAEdQdx
1062 //
1063 // Purpose : Loads the Q-vector contributions for a single
1064 // Neuron 3 instance.
1065 // Scope : public
1066 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1067 // Creation Date : 06/10/09
1068 //-----------------------------------------------------------------------------
1070 {
1071  bool bsuccess = true;
1072 
1073  Linear::Matrix * dQdxMatPtr = extData.dQdxMatrixPtr;
1074 
1075  for( int i=0; i<nSeg ; i++)
1076  {
1077  (*dQdxMatPtr)[li_Vol[i]][SegVEqnVsegOffset[i]] += segQ_dV[i];
1078  (*dQdxMatPtr)[li_nPro[i]][NEquNNodeOffset[i]] += dnQ_dn[i];
1079  (*dQdxMatPtr)[li_mPro[i]][MEquMNodeOffset[i]] += dmQ_dm[i];
1080  (*dQdxMatPtr)[li_hPro[i]][HEquHNodeOffset[i]] += dhQ_dh[i];
1081  }
1082 
1083  return bsuccess;
1084 }
1085 
1086 //-----------------------------------------------------------------------------
1087 // Function : Instance::loadDAEdFdx ()
1088 //
1089 // Purpose : Loads the F-vector contributions for a single
1090 // Neuron 3 instance.
1091 //
1092 // Special Notes : This is an algebraic constaint.
1093 //
1094 // Scope : public
1095 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1096 // Creation Date : 06/10/09
1097 //-----------------------------------------------------------------------------
1099 {
1100  bool bsuccess = true;
1101 
1102  Linear::Matrix * dFdxMatPtr = extData.dFdxMatrixPtr;
1103 
1104  (*dFdxMatPtr)[li_Pos][APosEquPosNodeOffset] += dkcl1F_dVin;
1105  (*dFdxMatPtr)[li_Pos][APosEquNextNodeOffset] += dkcl1F_dVs0;
1106 
1107  (*dFdxMatPtr)[li_Neg][ANegEquNegNodeOffset] += dkcl2F_dVout;
1108  (*dFdxMatPtr)[li_Neg][ANegEquLastNodeOffset] += dkcl2F_dVsn;
1109 
1110  for( int i=0; i<nSeg ; i++)
1111  {
1112  (*dFdxMatPtr)[li_Vol[i]][SegVEqnVpreOffset[i]] += segF_dVp[i];
1113  (*dFdxMatPtr)[li_Vol[i]][SegVEqnVsegOffset[i]] += segF_dV[i];
1114  (*dFdxMatPtr)[li_Vol[i]][SegVEqnVnexOffset[i]] += segF_dVn[i];
1115  (*dFdxMatPtr)[li_Vol[i]][SegVEqnNOffset[i]] += segF_dn[i];
1116  (*dFdxMatPtr)[li_Vol[i]][SegVEqnMOffset[i]] += segF_dm[i];
1117  (*dFdxMatPtr)[li_Vol[i]][SegVEqnHOffset[i]] += segF_dh[i];
1118 
1119  (*dFdxMatPtr)[li_nPro[i]][NEquVNodeOffset[i]] += dnF_dV[i];
1120  (*dFdxMatPtr)[li_nPro[i]][NEquNNodeOffset[i]] += dnF_dn[i];
1121  (*dFdxMatPtr)[li_mPro[i]][MEquVNodeOffset[i]] += dmF_dV[i];
1122  (*dFdxMatPtr)[li_mPro[i]][MEquMNodeOffset[i]] += dmF_dm[i];
1123  (*dFdxMatPtr)[li_hPro[i]][HEquVNodeOffset[i]] += dhF_dV[i];
1124  (*dFdxMatPtr)[li_hPro[i]][HEquHNodeOffset[i]] += dhF_dh[i];
1125  }
1126 
1127  return bsuccess;
1128 }
1129 
1130 //-----------------------------------------------------------------------------
1131 // Function : Instance::setIC
1132 // Purpose :
1133 // Special Notes :
1134 // Scope : public
1135 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1136 // Creation Date : 06/10/09
1137 //-----------------------------------------------------------------------------
1139 {
1140  bool bsuccess = true;
1141 
1142  return bsuccess;
1143 }
1144 
1145 //-----------------------------------------------------------------------------
1146 // Function : Instance::varTypes
1147 // Purpose :
1148 // Special Notes :
1149 // Scope : public
1150 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1151 // Creation Date : 06/10/09
1152 //-----------------------------------------------------------------------------
1153 void Instance::varTypes( std::vector<char> & varTypeVec )
1154 {
1155  //varTypeVec.resize(1);
1156  //varTypeVec[0] = 'I';
1157 }
1158 
1159 
1160 //-----------------------------------------------------------------------------
1161 // Function : Model::processParams
1162 // Purpose :
1163 // Special Notes :
1164 // Scope : public
1165 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1166 // Creation Date : 06/10/09
1167 //-----------------------------------------------------------------------------
1169 {
1170  return true;
1171 }
1172 
1173 //----------------------------------------------------------------------------
1174 // Function : Model::processInstanceParams
1175 // Purpose :
1176 // Special Notes :
1177 // Scope : public
1178 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1179 // Creation Date : 06/10/09
1180 //----------------------------------------------------------------------------
1182 {
1183  std::vector<Instance*>::iterator iter;
1184  std::vector<Instance*>::iterator first = instanceContainer.begin();
1185  std::vector<Instance*>::iterator last = instanceContainer.end();
1186 
1187  for (iter=first; iter!=last; ++iter)
1188  {
1189  (*iter)->processParams();
1190  }
1191 
1192  return true;
1193 }
1194 
1195 //-----------------------------------------------------------------------------
1196 // Function : Model::Model
1197 // Purpose : block constructor
1198 // Special Notes :
1199 // Scope : public
1200 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1201 // Creation Date : 06/10/09
1202 //-----------------------------------------------------------------------------
1204  const Configuration & configuration,
1205  const ModelBlock & MB,
1206  const FactoryBlock & factory_block)
1207  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
1208  rInt(0.0),
1209  radius(0.0),
1210  length(0.0),
1211  rIntGiven(false),
1212  radiusGiven(false),
1213  lengthGiven(false)
1214 {
1215 
1216  // Set params to constant default values:
1217  setDefaultParams ();
1218 
1219  // Set params according to .model line and constant defaults from metadata:
1220  setModParams (MB.params);
1221 
1222  // Set any non-constant parameter defaults:
1223  //if (!given("TNOM"))
1224  // tnom = getDeviceOptions().tnom;
1225 
1226  // Calculate any parameters specified as expressions:
1228 
1229  // calculate dependent (ie computed) params and check for errors:
1230 
1231  processParams ();
1232 }
1233 
1234 //-----------------------------------------------------------------------------
1235 // Function : Model::~Model
1236 // Purpose : destructor
1237 // Special Notes :
1238 // Scope : public
1239 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1240 // Creation Date : 06/10/09
1241 //-----------------------------------------------------------------------------
1243 {
1244  std::vector<Instance*>::iterator iter;
1245  std::vector<Instance*>::iterator first = instanceContainer.begin();
1246  std::vector<Instance*>::iterator last = instanceContainer.end();
1247 
1248  for (iter=first; iter!=last; ++iter)
1249  {
1250  delete (*iter);
1251  }
1252 
1253 }
1254 
1255 // additional Declarations
1256 
1257 //-----------------------------------------------------------------------------
1258 // Function : Model::printOutInstances
1259 // Purpose : debugging tool.
1260 // Special Notes :
1261 // Scope : public
1262 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1263 // Creation Date : 06/10/09
1264 //-----------------------------------------------------------------------------
1265 std::ostream &Model::printOutInstances(std::ostream &os) const
1266 {
1267  std::vector<Instance*>::const_iterator iter;
1268  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
1269  std::vector<Instance*>::const_iterator last = instanceContainer.end();
1270 
1271  int i, isize;
1272  isize = instanceContainer.size();
1273 
1274  os << std::endl;
1275  os << "Number of Neuron instances: " << isize << std::endl;
1276  os << " name=\t\tmodelName\tParameters" << std::endl;
1277  for (i=0, iter=first; iter!=last; ++iter, ++i)
1278  {
1279  os << " " << i << ": " << (*iter)->getName() << "\t";
1280  os << getName();
1281  os << std::endl;
1282  }
1283 
1284  os << std::endl;
1285  return os;
1286 }
1287 
1288 //-----------------------------------------------------------------------------
1289 // Function : Model::forEachInstance
1290 // Purpose :
1291 // Special Notes :
1292 // Scope : public
1293 // Creator : David Baur
1294 // Creation Date : 2/4/2014
1295 //-----------------------------------------------------------------------------
1296 /// Apply a device instance "op" to all instances associated with this
1297 /// model
1298 ///
1299 /// @param[in] op Operator to apply to all instances.
1300 ///
1301 ///
1302 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
1303 {
1304  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1305  op(*it);
1306 }
1307 
1308 
1309 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
1310 {
1311 
1312  return new DeviceMaster<Traits>(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
1313 }
1314 
1316 {
1318  .registerDevice("neuron", 3)
1319  .registerModelType("neuron", 3);
1320 }
1321 
1322 } // namespace Neuron3
1323 } // namespace Device
1324 } // namespace Xyce
const InstanceName & getName() const
std::vector< int > MEquVNodeOffset
std::vector< double > segNEquFvalue
std::vector< double > segF_dV
static ScalarT hEquF(const ScalarT &Vn1, const ScalarT &h, const ScalarT &Vrest)
std::vector< double > dhF_dh
std::vector< double > segF_dn
std::vector< int > SegVEqnVsegOffset
bool updateTemperature(const double &temp_tmp)
const SolverState & solverState_
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
Descriptor & addPar(const char *parName, T default_value, T U::*varPtr)
Adds the parameter description to the parameter map.
Definition: N_DEV_Pars.h:1429
std::vector< int > SegVEqnNOffset
std::vector< int > NEquVNodeOffset
Linear::Vector * nextSolVectorPtr
static ScalarT mEquF(const ScalarT &Vn1, const ScalarT &m, const ScalarT &Vrest)
std::vector< double > segQ_dV
std::vector< int > HEquHNodeOffset
Linear::Vector * daeQVectorPtr
std::vector< int > SegVEqnMOffset
Pure virtual class to augment a linear system.
std::vector< std::vector< int > > jacStamp
void addInternalNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
std::vector< double > dhF_dV
std::vector< double > dmF_dV
std::vector< double > dnF_dV
std::vector< double > gForward
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
std::vector< double > dnF_dn
static ScalarT mEquQ(const ScalarT &m)
std::vector< double > segF_dVn
#define AssertLIDs(cmp)
std::vector< double > segF_dh
std::vector< double > dmQ_dm
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
std::vector< Instance * > instanceContainer
std::vector< int > MEquMNodeOffset
std::vector< Param > params
Parameters from the line.
std::vector< double > segQvalue
std::vector< double > segHEquFvalue
std::vector< int > SegVEqnHOffset
void setParams(const std::vector< Param > &params)
const std::string & getName() const
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
std::vector< double > potassiumCurrent
bool processParams()
processParams
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
Definition: N_DEV_Neuron3.C:72
const DeviceOptions & deviceOptions_
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
std::vector< int > SegVEqnVpreOffset
Linear::Vector * nextStaVectorPtr
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
std::vector< double > dnQ_dn
Linear::Matrix * dFdxMatrixPtr
static ScalarT kcl1EquF(const ScalarT &VSeg, const ScalarT &VSegP, const ScalarT &VSegN, const ScalarT &n, const ScalarT &m, const ScalarT &h, const ScalarT &gPrev, const ScalarT &gNext, const ScalarT &memG, const ScalarT &restV, const ScalarT &Kg, const ScalarT &Ke, const ScalarT &NaG, const ScalarT &NaE)
The Device class is an interface for device implementations.
Definition: N_DEV_Device.h:101
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &Miter, const FactoryBlock &factory_block)
std::vector< int > HEquVNodeOffset
std::vector< double > segFvalue
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
std::vector< int > NEquNNodeOffset
std::vector< double > segHEquQvalue
const std::vector< std::vector< int > > & jacobianStamp() const
Class Configuration contains device configuration data.
std::vector< double > segNEquQvalue
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
std::vector< double > gBackward
std::vector< int > li_KCurrentState
bool processInstanceParams()
processInstanceParams
std::vector< double > dhQ_dh
std::vector< int > SegVEqnVnexOffset
static ScalarT hEquQ(const ScalarT &h)
static ScalarT kcl1EquQ(const ScalarT &VSeg, const ScalarT &memC)
const SolverState & getSolverState() const
#define M_PI
std::vector< double > segF_dVp
static ScalarT nEquQ(const ScalarT &n)
std::vector< int > li_NaCurrentState
Linear::Vector * daeFVectorPtr
static ScalarT nEquF(const ScalarT &Vn1, const ScalarT &n, const ScalarT &Vrest)
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
std::vector< double > segF_dm
std::vector< double > sodiumCurrent
ModelBlock represents a .MODEL line from the netlist.
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
InstanceBlock represent a device instance line from the netlist.
std::vector< Param > params
Linear::Matrix * dQdxMatrixPtr
std::vector< double > dmF_dm
void varTypes(std::vector< char > &varTypeVec)
virtual std::ostream & printOutInstances(std::ostream &os) const
std::vector< double > segMEquFvalue
void setModParams(const std::vector< Param > &params)
static void loadModelParameters(ParametricData< Model > &model_parameters)
std::vector< double > segMEquQvalue