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.44.2.1 $
40 //
41 // Revision Date : $Date: 2015/04/02 18:29:37 $
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  // now set the temperature related stuff.
262  //updateTemperature(temp);
263 
264  return true;
265 }
266 
267 //-----------------------------------------------------------------------------
268 // Function : Instance::updateTemperature
269 // Purpose :
270 // Special Notes :
271 // Scope : public
272 // Creator : Richard Schiek, Electrical and Microsytem Modeling
273 // Creation Date : 06/10/09
274 //-----------------------------------------------------------------------------
275 bool Instance::updateTemperature ( const double & temp)
276 {
277  bool bsuccess = true;
278  return bsuccess;
279 }
280 
281 //-----------------------------------------------------------------------------
282 // Function : Instance::Instance
283 // Purpose : constructor
284 // Special Notes :
285 // Scope : public
286 // Creator : Richard Schiek, Electrical and Microsytem Modeling
287 // Creation Date : 06/10/09
288 //-----------------------------------------------------------------------------
290  const Configuration & configuration,
291  const InstanceBlock & IB,
292  Model & Miter,
293  const FactoryBlock & factory_block)
294  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
295  model_(Miter),
296  rInt(0.0),
297  radius(0.0),
298  length(0.0),
299  segArea(0.0),
300  nSeg(0),
301  rIntGiven(false),
302  radiusGiven(false),
303  lengthGiven(false),
304  nSegGiven(false),
305  rIntPrevious(0.0),
306  radiusPrevious(0.0),
307  lengthPrevious(0.0),
308  rIntNext(0.0),
309  radiusNext(0.0),
310  lengthNext(0.0),
311  rIntPreviousGiven(false),
312  radiusPreviousGiven(false),
313  lengthPreviousGiven(false),
314  rIntNextGiven(false),
315  radiusNextGiven(false),
316  lengthNextGiven(false),
317  kcl1Fvalue(0.0),
318  kcl2Fvalue(0.0),
319  dkcl1F_dVin(0.0),
320  dkcl1F_dVs0(0.0),
321  dkcl2F_dVout(0.0),
322  dkcl2F_dVsn(0.0),
323  li_Pos(0),
324  li_Neg(0),
325  APosEquPosNodeOffset(0),
326  APosEquNextNodeOffset(0),
327  ANegEquNegNodeOffset(0),
328  ANegEquLastNodeOffset(0)
329 {
330  // we have pased the model and instance parameters so now we can calculate
331  // the number of internal vars
332  numExtVars = 2; // input and output voltage
333 
334  // Set params to constant default values:
335  setDefaultParams ();
336 
337  // Set params according to instance line
338  setParams (IB.params);
339 
340  // Set any non-constant parameter defaults:
341 
342  //if (!given("TEMP"))
343  // temp = getDeviceOptions().temp.dVal();
344 
345  // Calculate any parameters specified as expressions:
347 
348  // calculate dependent (ie computed) params and check for errors:
349  processParams ();
350 
351  // pull unspecified params out of the model if they weren't specified here
352  if( !nSegGiven && model_.nSegGiven )
353  {
354  nSeg = model_.nSeg;
355  nSegGiven = true;
356  }
357  if( !rIntGiven && model_.rIntGiven )
358  {
359  rInt = model_.rInt;
360  rIntGiven = true;
361  }
362  if( !radiusGiven && model_.radiusGiven )
363  {
364  radius = model_.radius;
365  radiusGiven = true;
366  }
367  if( !lengthGiven && model_.lengthGiven )
368  {
369  length = model_.length;
370  lengthGiven = true;
371  }
372 
373  // if nSeg is still unknown then estimate it via lambda-d rule (TO DO)
374  if( !nSegGiven )
375  {
376  nSeg = 10;
377  }
378 
379  // now that nSeg, length and radius are set calculate segment area
380  segArea = 2.0 * M_PI * radius * length / nSeg;
381 
382  // now we can calculate the number of internal vars
383  numIntVars = nSeg * 4; // ion channel vars + one internal voltage node var for each segment
384  numStateVars = nSeg * 2;
385  int numVars = numExtVars + numIntVars;
386 
387 
388  //
389  // 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
390  //
391  // Vin : g(0,1) * (V(1) - Vin ) = 0
392  // Vout : g(n,n-1) * (V(n-1) - Vout) = 0
393  // 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
394  // plus node supporting equations (a, b, m)
395  //
396  // jacobian format
397  // Vin Vout V1 n m h V2 n m h V(nSeg) n m h
398  // kcl Vin -g(0,1) g(0,1)
399  // kcl Vout -g(n,n-1) g(n,n-1)
400  // kcl V1 yes yes yes yes yes yes
401  // a yes yes
402  // b yes yes
403  // m yes yes
404  // kcl V2 yes yes yes yes yes yes
405  // a 2 yes yes
406  // b 2 yes yes
407  // m 2 yes yes
408  // kcl VnSeg yes yes yes yes yes yes
409  // a nSeg yes yes
410  // b nSeg yes yes
411  // m nSeg yes yes
412  //
413  // jacobian element count by row:
414  // vin: 2
415  // vout: 2
416  // v1: 6
417  // a1: 2
418  // b1: 2
419  // m1: 2
420  // v2: 6
421  // a2: 2
422  // b2: 2
423  // m2: 2
424  // vnSeg:6
425  // a: 2
426  // b: 2
427  // m: 2
428  //
429  // set up jacStamp
430  if( jacStamp.empty() ) // redundant as jacStamp is not static for this device
431  { // it can't be as each cable may have a different number of nodes
432  jacStamp.resize(numVars);
433  jacStamp[0].resize(2);
434  jacStamp[0][0] = 0;
435  jacStamp[0][1] = 1;
436  jacStamp[1].resize(2);
437  jacStamp[1][0] = 1;
438  jacStamp[1][1] = numVars - 4;
439  for( int i=2; i<numVars; i+=4)
440  {
441  jacStamp[i].resize(6);
442  if( i == 2 )
443  {
444  jacStamp[i][0] = 0;
445  }
446  else
447  {
448  jacStamp[i][0] = i-4;
449  }
450  jacStamp[i][1] = i;
451  jacStamp[i][2] = i+1;
452  jacStamp[i][3] = i+2;
453  jacStamp[i][4] = i+3;
454  if( i==(numVars-4) )
455  {
456  jacStamp[i][5] = 1;
457  }
458  else
459  {
460  jacStamp[i][5] = i+4;
461  }
462  jacStamp[i+1].resize(2);
463  jacStamp[i+1][0] = i;
464  jacStamp[i+1][1] = i+1;
465  jacStamp[i+2].resize(2);
466  jacStamp[i+2][0] = i;
467  jacStamp[i+2][1] = i+2;
468  jacStamp[i+3].resize(2);
469  jacStamp[i+3][0] = i;
470  jacStamp[i+3][1] = i+3;
471  }
472 
473  }
474 
475  /*
476  // print out jacStamp
477  int numRows = jacStamp.size();
478  for( int i=0; i< numRows; i++ )
479  {
480  int numCol = jacStamp[i].size();
481  Xyce::dout() << "jacStamp[ " << i << " ] = { ";
482  for(int j=0; j<numCol; j++)
483  {
484  Xyce::dout() << jacStamp[i][j] << " ";
485  }
486  Xyce::dout() << " } " << std::endl;
487  }
488  Xyce::dout() << std::endl;
489  */
490 
491  // calculate segment conductivities used in load calls:
492  // Note: conductivity to the previous and next segment is not symmetric if the segment length and/or radius is not are not equal
493  // the full formula is:
494  // g(n,n') = radius * (radius')^2 / ( rInt segLength * ( segLength * (radius')^2 + segLength' * (radius)^2 ) )
495  //
496  // equation 6.30 Theoretical neuroscience: computational and mathematical modeling of neural systems, Peter Dayan and L. F. Abbot 2001
497  // If we allow variable segment lengths and radii then we'll need to update this calculation
498  //
499  // Note: the above equation has the wrong units unless rInt (which is Ohm Length) is rLong (which is Ohm/Length).
500  //
501  gForward.resize(nSeg);
502  gBackward.resize(nSeg);
503  double segLength = length / nSeg;
504  double rLong = rInt / (M_PI * radius * radius); // longitudinal resistivity (ohm/length)
505  gBackward[0] = radius * (radiusPrevious * radiusPrevious) / (rLong * segLength * ( segLength * radiusPrevious * radiusPrevious + lengthPrevious * radius * radius ));
506  gForward[0] = radius * (radius * radius) / (rLong * segLength * ( segLength * radius * radius + segLength * radius * radius ));
507  gBackward[nSeg-1] = radius * (radius * radius) / (rLong * segLength * ( segLength * radius * radius + segLength * radius * radius ));
508  gForward[nSeg-1] = radius * (radiusNext * radiusNext) / (rLong * segLength * ( segLength * radiusNext * radiusNext + lengthNext * radius * radius ));
509  for(int i=1; i<(nSeg-1); i++)
510  {
511  gBackward[i] = radius * (radius * radius) / (rLong * segLength * ( segLength * radius * radius + segLength * radius * radius ));
512  gForward[i] = gBackward[i];
513  }
514  /*
515  gBackward[0] = radius * (radiusPrevious * radiusPrevious) / (rInt * segLength * ( segLength * radiusPrevious * radiusPrevious + lengthPrevious * radius * radius ));
516  gForward[0] = radius * (radius * radius) / (rInt * segLength * ( segLength * radius * radius + segLength * radius * radius ));
517  gBackward[nSeg-1] = radius * (radius * radius) / (rInt * segLength * ( segLength * radius * radius + segLength * radius * radius ));
518  gForward[nSeg-1] = radius * (radiusNext * radiusNext) / (rInt * segLength * ( segLength * radiusNext * radiusNext + lengthNext * radius * radius ));
519  for(int i=1; i<(nSeg-1); i++)
520  {
521  gBackward[i] = radius * (radius * radius) / (rInt * segLength * ( segLength * radius * radius + segLength * radius * radius ));
522  gForward[i] = gBackward[i];
523  }
524  */
525  // allocate space for load and jacobian terms per segment
526  // variable indecies loads
527  li_Vol.resize(nSeg);
528  li_nPro.resize(nSeg);
529  li_mPro.resize(nSeg);
530  li_hPro.resize(nSeg);
531  li_KCurrentState.resize(nSeg);
532  li_NaCurrentState.resize(nSeg);
533  segFvalue.resize(nSeg);
534  segQvalue.resize(nSeg);
535  segNEquFvalue.resize(nSeg);
536  segNEquQvalue.resize(nSeg);
537  segMEquFvalue.resize(nSeg);
538  segMEquQvalue.resize(nSeg);
539  segHEquFvalue.resize(nSeg);
540  segHEquQvalue.resize(nSeg);
541 
542  // jacobian elements
543  segF_dVp.resize(nSeg);
544  segF_dV.resize(nSeg);
545  segF_dVn.resize(nSeg);
546  segF_dn.resize(nSeg);
547  segF_dm.resize(nSeg);
548  segF_dh.resize(nSeg);
549  segQ_dV.resize(nSeg);
550  dnF_dV.resize(nSeg);
551  dnF_dn.resize(nSeg);
552  dnQ_dn.resize(nSeg);
553  dmF_dV.resize(nSeg);
554  dmF_dm.resize(nSeg);
555  dmQ_dm.resize(nSeg);
556  dhF_dV.resize(nSeg);
557  dhF_dh.resize(nSeg);
558  dhQ_dh.resize(nSeg);
559 
560  // state vars
561  potassiumCurrent.resize(nSeg);
562  sodiumCurrent.resize(nSeg);
563 
564 }
565 
566 //-----------------------------------------------------------------------------
567 // Function : Instance::~Instance
568 // Purpose : destructor
569 // Special Notes :
570 // Scope : public
571 // Creator : Richard Schiek, Electrical and Microsytem Modeling
572 // Creation Date : 06/10/09
573 //-----------------------------------------------------------------------------
575 {
576 }
577 
578 //-----------------------------------------------------------------------------
579 // Function : Instance::registerLIDs
580 // Purpose :
581 // Special Notes :
582 // Scope : public
583 // Creator : Richard Schiek, Electrical and Microsytem Modeling
584 // Creation Date : 06/10/09
585 //-----------------------------------------------------------------------------
586 void Instance::registerLIDs(const std::vector<int> & intLIDVecRef,
587  const std::vector<int> & extLIDVecRef)
588 {
589  AssertLIDs(intLIDVecRef.size() == numIntVars);
590  AssertLIDs(extLIDVecRef.size() == numExtVars);
591 
592  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
593  {
594  Xyce::dout() << std::endl << section_divider << std::endl;
595  Xyce::dout() << " Instance::registerLIDs" << std::endl;
596  Xyce::dout() << " name = " << getName() << std::endl;
597  }
598 
599  // copy over the global ID lists.
600  intLIDVec = intLIDVecRef;
601  extLIDVec = extLIDVecRef;
602 
603  li_Pos = extLIDVec[0];
604  li_Neg = extLIDVec[1];
605  for( int i=0, j=0; i<nSeg; i++, j+=4)
606  {
607  li_Vol[i] = intLIDVec[j];
608  li_nPro[i] = intLIDVec[j+1];
609  li_mPro[i] = intLIDVec[j+2];
610  li_hPro[i] = intLIDVec[j+3];
611  }
612 
613  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
614  {
615  Xyce::dout() << " li_Pos = " << li_Pos << std::endl
616  << " li_Neg = " << li_Neg << std::endl;
617  for( int i=0; i<nSeg; i++ )
618  {
619  Xyce::dout() << " li_Vol[ " << i << " ] = " << li_Vol[i] << std::endl
620  << " li_nPro[ " << i << " ] = " << li_nPro[i] << std::endl
621  << " li_mPro[ " << i << " ] = " << li_mPro[i] << std::endl
622  << " li_hPro[ " << i << " ] = " << li_hPro[i] << std::endl;
623  }
624  }
625 
626  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
627  {
628  Xyce::dout() << section_divider << std::endl;
629  }
630 }
631 
632 //-----------------------------------------------------------------------------
633 // Function : Instance::loadNodeSymbols
634 // Purpose :
635 // Special Notes :
636 // Scope : public
637 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
638 // Creation Date : 05/13/05
639 //-----------------------------------------------------------------------------
640 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
641 {
642  for (int i = 0; i < nSeg; i++)
643  {
644  std::ostringstream segNumber;
645  segNumber << i;
646  addInternalNode(symbol_table, li_Vol[i], getName(), "V" + segNumber.str());
647  addInternalNode(symbol_table, li_nPro[i], getName(), "N" + segNumber.str());
648  addInternalNode(symbol_table, li_mPro[i], getName(), "M" + segNumber.str());
649  addInternalNode(symbol_table, li_hPro[i], getName(), "H" + segNumber.str());
650  }
651 }
652 
653 //-----------------------------------------------------------------------------
654 // Function : Instance::registerStateLIDs
655 // Purpose :
656 // Special Notes :
657 // Scope : public
658 // Creator : Richard Schiek, Electrical and Microsytem Modeling
659 // Creation Date : 06/10/09
660 //-----------------------------------------------------------------------------
661 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
662 {
663  AssertLIDs(staLIDVecRef.size() == numStateVars);
664 
665  // copy over the global ID lists.
666  staLIDVec = staLIDVecRef;
667 
668  for( int i=0, j=0; i<nSeg; i++, j+=2)
669  {
670  li_KCurrentState[i] = staLIDVec[j];
671  li_NaCurrentState[i] = staLIDVec[j+1];
672  }
673 
674 }
675 
676 //-----------------------------------------------------------------------------
677 // Function : Instance::jacobianStamp
678 // Purpose :
679 // Special Notes :
680 // Scope : public
681 // Creator : Richard Schiek, Electrical and Microsytem Modeling
682 // Creation Date : 06/10/09
683 //-----------------------------------------------------------------------------
684 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
685 {
686  return jacStamp;
687 }
688 
689 //-----------------------------------------------------------------------------
690 // Function : Instance::registerJacLIDs
691 // Purpose :
692 // Special Notes :
693 // Scope : public
694 // Creator : Richard Schiek, Electrical and Microsytem Modeling
695 // Creation Date : 06/10/09
696 //-----------------------------------------------------------------------------
697 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
698 {
699  DeviceInstance::registerJacLIDs( jacLIDVec );
700 
701  // external terminals
702  APosEquPosNodeOffset = jacLIDVec[0][0];
703  APosEquNextNodeOffset = jacLIDVec[0][1];
704  ANegEquNegNodeOffset = jacLIDVec[1][0];
705  ANegEquLastNodeOffset = jacLIDVec[1][1];
706  /*
707  Xyce::dout() << "APosEquPosNodeOffset = " << APosEquPosNodeOffset << std::endl;
708  Xyce::dout() << "APosEquNextNodeOffset = " << APosEquNextNodeOffset << std::endl;
709  Xyce::dout() << "ANegEquNegNodeOffset = " << ANegEquNegNodeOffset << std::endl;
710  Xyce::dout() << "ANegEquLastNodeOffset = " << ANegEquLastNodeOffset << std::endl;
711  */
712 
713  // internal variables
714  SegVEqnVpreOffset.resize(nSeg);
715  SegVEqnVsegOffset.resize(nSeg);
716  SegVEqnVnexOffset.resize(nSeg);
717  SegVEqnNOffset.resize(nSeg);
718  SegVEqnMOffset.resize(nSeg);
719  SegVEqnHOffset.resize(nSeg);
720  NEquVNodeOffset.resize(nSeg);
721  NEquNNodeOffset.resize(nSeg);
722  MEquVNodeOffset.resize(nSeg);
723  MEquMNodeOffset.resize(nSeg);
724  HEquVNodeOffset.resize(nSeg);
725  HEquHNodeOffset.resize(nSeg);
726  for(int i=0, j=2; i<nSeg; i++, j+=4 )
727  {
728  SegVEqnVpreOffset[i] = jacLIDVec[j][0];
729  SegVEqnVsegOffset[i] = jacLIDVec[j][1];
730  SegVEqnNOffset[i] = jacLIDVec[j][2];
731  SegVEqnMOffset[i] = jacLIDVec[j][3];
732  SegVEqnHOffset[i] = jacLIDVec[j][4];
733  SegVEqnVnexOffset[i] = jacLIDVec[j][5];
734 
735  NEquVNodeOffset[i] = jacLIDVec[j+1][0];
736  NEquNNodeOffset[i] = jacLIDVec[j+1][1];
737  MEquVNodeOffset[i] = jacLIDVec[j+2][0];
738  MEquMNodeOffset[i] = jacLIDVec[j+2][1];
739  HEquVNodeOffset[i] = jacLIDVec[j+3][0];
740  HEquHNodeOffset[i] = jacLIDVec[j+3][1];
741  /*
742  Xyce::dout() << SegVEqnVpreOffset[i] << ", "
743  << SegVEqnVsegOffset[i] << ", "
744  << SegVEqnNOffset[i] << ", "
745  << SegVEqnMOffset[i] << ", "
746  << SegVEqnHOffset[i] << ", "
747  << SegVEqnVnexOffset[i] << ", "
748  << NEquVNodeOffset[i] << ", "
749  << NEquNNodeOffset[i] << ", "
750  << MEquVNodeOffset[i] << ", "
751  << MEquMNodeOffset[i] << ", "
752  << HEquVNodeOffset[i] << ", "
753  << HEquHNodeOffset[i] << std::endl;
754  */
755  }
756 }
757 
758 
759 //-----------------------------------------------------------------------------
760 // Function : Instance::updateIntermediateVars
761 // Purpose :
762 // Special Notes :
763 // Scope : public
764 // Creator : Richard Schiek, Electrical and Microsytem Modeling
765 // Creation Date : 06/10/09
766 //-----------------------------------------------------------------------------
768 {
769  //Xyce::dout() << "Instance::updateIntermediateVars()" << std::endl;
770 
771  bool bsuccess = true;
772 
773  // here we take the current solutions for V1, V2, n, m and h
774  // and use those to calculate all the terms needed for the next
775  // load cycle (F, Q, dFdX, dQdX)
776  Linear::Vector * solVectorPtr = extData.nextSolVectorPtr;
777 
778  double vIn = (*solVectorPtr)[li_Pos];
779  double vOut = (*solVectorPtr)[li_Neg];
780 
781  // take care of the input and output nodes as they are different
782  kcl1Fvalue = gForward[0] * ((*solVectorPtr)[li_Vol[0]] - vIn );
783  dkcl1F_dVin = -gForward[0];
784  dkcl1F_dVs0 = gForward[0];
785  kcl2Fvalue = gBackward[nSeg-1] * ((*solVectorPtr)[li_Vol[nSeg-1]] - vOut );
788  //Xyce::dout() << "end update: " << vIn << ", " << vOut << ", " << gForward[0] << ", " << gBackward[nSeg-1] << std::endl;
789 
790  // loop over segments getting all the load and jacobian terms for each segment
791  for( int i=0; i<nSeg; i++ )
792  {
793  // for this segment get the values of the local vars
794  double vSeg = (*solVectorPtr)[li_Vol[i]];
795  double vNext = 0.0;
796  if (i == (nSeg - 1))
797  {
798  vNext = vOut;
799  }
800  else
801  {
802  vNext = (*solVectorPtr)[li_Vol[i+1]];
803  }
804  double vPrev = 0.0;
805  if (i == 0 )
806  {
807  vPrev = vIn;
808  }
809  else
810  {
811  vPrev = (*solVectorPtr)[li_Vol[i-1]];
812  }
813  double nVarSeg = (*solVectorPtr)[li_nPro[i]];
814  double mVarSeg = (*solVectorPtr)[li_mPro[i]];
815  double hVarSeg = (*solVectorPtr)[li_hPro[i]];
816 
817  // do the voltage equation for this node
818  // get function and derivative values as we go.
819  {
820  // F part
821  // use scoping to avoid lots of similar variable names
822  const int numDeriv = 6;
823  Sacado::Fad::SFad<double,6> vVar( numDeriv, 0, vSeg );
824  Sacado::Fad::SFad<double,6> vVpr( numDeriv, 1, vPrev );
825  Sacado::Fad::SFad<double,6> vVne( numDeriv, 2, vNext );
826  Sacado::Fad::SFad<double,6> nVar( numDeriv, 3, nVarSeg );
827  Sacado::Fad::SFad<double,6> mVar( numDeriv, 4, mVarSeg );
828  Sacado::Fad::SFad<double,6> hVar( numDeriv, 5, hVarSeg );
829  // parameters
830  Sacado::Fad::SFad<double,6> gPrev( gBackward[i] );
831  Sacado::Fad::SFad<double,6> gNext( gForward[i] );
832  Sacado::Fad::SFad<double,6> gMemVar( model_.gMem * segArea );
833  Sacado::Fad::SFad<double,6> vRestVar( model_.vRest );
834  Sacado::Fad::SFad<double,6> gKVar( model_.gK * segArea );
835  Sacado::Fad::SFad<double,6> eKVar( model_.eK );
836  Sacado::Fad::SFad<double,6> gNaVar( model_.gNa * segArea );
837  Sacado::Fad::SFad<double,6> eNaVar( model_.eNa );
838  //Xyce::dout() << "segment update: " << i << ", " << vSeg << ", " << vPrev << ", " << vNext << ", " << gBackward[i] << ", " << gForward[i] << std::endl;
839  // compute the value and derivative terms for KCL 1 F
840  Sacado::Fad::SFad<double,6> resultFad;
841  resultFad = kcl1EquF( vVar, vVpr, vVne, nVar, mVar, hVar, gPrev, gNext, gMemVar, vRestVar, gKVar, eKVar, gNaVar, eNaVar );
842  segFvalue[i] = resultFad.val();
843  segF_dV[i] = resultFad.dx(0);
844  segF_dVp[i] = resultFad.dx(1);
845  segF_dVn[i] = resultFad.dx(2);
846  segF_dn[i] = resultFad.dx(3);
847  segF_dm[i] = resultFad.dx(4);
848  segF_dh[i] = resultFad.dx(5);
849  }
850  {
851  // Q part
852  const int numDeriv = 2;
853  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
854 
855  // parameters
856  Sacado::Fad::SFad<double,2> cMemVar( model_.cMem * segArea );
857 
858  Sacado::Fad::SFad<double,2> resultFad;
859  resultFad = kcl1EquQ( vVar, cMemVar );
860  segQvalue[i] = resultFad.val();
861  segQ_dV[i] = resultFad.dx(0);
862 
863  }
864 
865  // n - equation
866  {
867  const int numDeriv = 2;
868  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
869  Sacado::Fad::SFad<double,2> nVar( numDeriv, 1, nVarSeg );
870  // parameter
871  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
872 
873  Sacado::Fad::SFad<double,2> resultFad = nEquF( vVar, nVar, vRestVar);
874  segNEquFvalue[i] = resultFad.val();
875  dnF_dV[i] = resultFad.dx(0);
876  dnF_dn[i] = resultFad.dx(1);
877  }
878  {
879  const int numDeriv = 1;
880  Sacado::Fad::SFad<double,1> nVar( numDeriv, 0, nVarSeg );
881 
882  Sacado::Fad::SFad<double,1> resultFad = nEquQ( nVar );
883  segNEquQvalue[i] = resultFad.val();
884  dnQ_dn[i] = resultFad.dx(0);
885  }
886 
887  // m - equation
888  {
889  const int numDeriv = 2;
890  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
891  Sacado::Fad::SFad<double,2> mVar( numDeriv, 1, mVarSeg );
892  // parameter
893  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
894 
895  Sacado::Fad::SFad<double,2> resultFad = mEquF( vVar, mVar, vRestVar );
896  segMEquFvalue[i] = resultFad.val();
897  dmF_dV[i] = resultFad.dx(0);
898  dmF_dm[i] = resultFad.dx(1);
899  }
900  {
901  const int numDeriv = 1;
902  Sacado::Fad::SFad<double,1> mVar( numDeriv, 0, mVarSeg );
903 
904  Sacado::Fad::SFad<double,1> resultFad = mEquQ( mVar );
905  segMEquQvalue[i] = resultFad.val();
906  dmQ_dm[i] = resultFad.dx(0);
907  }
908 
909  // h - equation
910  {
911  const int numDeriv = 2;
912  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
913  Sacado::Fad::SFad<double,2> hVar( numDeriv, 1, hVarSeg );
914  // parameter
915  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
916 
917  Sacado::Fad::SFad<double,2> resultFad = hEquF( vVar, hVar, vRestVar );
918  segHEquFvalue[i] = resultFad.val();
919  dhF_dV[i] = resultFad.dx(0);
920  dhF_dh[i] = resultFad.dx(1);
921  }
922  {
923  const int numDeriv = 1;
924  Sacado::Fad::SFad<double,1> hVar( numDeriv, 0, hVarSeg );
925 
926  Sacado::Fad::SFad<double,1> resultFad = hEquQ( hVar );
927  segHEquQvalue[i] = resultFad.val();
928  dhQ_dh[i] = resultFad.dx(0);
929  }
930 
931  // calculate potassium current
932  potassiumCurrent[i] = model_.gK * pow(nVarSeg, 4.0) * (vSeg - model_.eK);
933 
934  // calculate sodium current
935  sodiumCurrent[i] = model_.gNa * pow(mVarSeg, 3.0) * hVarSeg * (vSeg - model_.eNa);
936 
937  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
938  {
939  Xyce::dout() << "Segment " << i << std::endl
940  << "vPrev = " << vPrev << std::endl
941  << "vSeg = " << vSeg << std::endl
942  << "vNext = " << vNext << std::endl
943  << "n, m, h = " << nVarSeg << ", " << mVarSeg << ", " << hVarSeg << std::endl
944  << "segFvalue = " << segFvalue[i] << std::endl
945  << "segQvalue = " << segQvalue[i] << std::endl
946  << "segNEquFvalue = " << segNEquFvalue[i] << std::endl
947  << "segNEquQvalue = " << segNEquQvalue[i] << std::endl
948  << "segMEquFvalue = " << segMEquFvalue[i] << std::endl
949  << "segMEquQvalue = " << segMEquQvalue[i] << std::endl
950  << "segHEquFvalue = " << segHEquFvalue[i] << std::endl
951  << "segHEquQvalue = " << segHEquQvalue[i] << std::endl
952  << std::endl;
953 
954  }
955 
956 
957  }
958 
959 
960 
961  return bsuccess;
962 }
963 //-----------------------------------------------------------------------------
964 // Function : Instance::updatePrimaryState
965 // Purpose :
966 // Special Notes :
967 // Scope : public
968 // Creator : Richard Schiek, Electrical and Microsytem Modeling
969 // Creation Date : 06/10/09
970 //-----------------------------------------------------------------------------
972 {
973  bool bsuccess = true;
974 
976 
977  Linear::Vector * solVectorPtr = extData.nextSolVectorPtr;
978  Linear::Vector * staVectorPtr = extData.nextStaVectorPtr;
979 
980  for( int i=0; i<nSeg; i++)
981  {
982  (*staVectorPtr)[li_KCurrentState[i]] = potassiumCurrent[i];
983  (*staVectorPtr)[li_NaCurrentState[i]] = sodiumCurrent[i];
984  }
985 
986  return bsuccess;
987 }
988 
989 //-----------------------------------------------------------------------------
990 // Function : Instance::updateSecondaryState
991 // Purpose :
992 // Special Notes :
993 // Scope : public
994 // Creator : Richard Schiek, Electrical and Microsytem Modeling
995 // Creation Date : 06/10/09
996 //-----------------------------------------------------------------------------
998 {
999  bool bsuccess = true;
1000  Linear::Vector * staVectorPtr = extData.nextStaVectorPtr;
1001 
1002  return bsuccess;
1003 }
1004 
1005 //-----------------------------------------------------------------------------
1006 // Function : Instance::loadDAEQVector
1007 //
1008 // Purpose : Loads the Q-vector contributions
1009 //
1010 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1011 // which the system of equations is represented as:
1012 //
1013 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1014 //
1015 // Scope : public
1016 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1017 // Creation Date : 06/10/09
1018 //-----------------------------------------------------------------------------
1020 {
1021  bool bsuccess = true;
1022 
1023  Linear::Vector * daeQVecPtr = extData.daeQVectorPtr;
1024 
1025  for( int i=0; i<nSeg ; i++)
1026  {
1027  (*daeQVecPtr)[li_Vol[i]] += segQvalue[i];
1028  (*daeQVecPtr)[li_nPro[i]] += segNEquQvalue[i];
1029  (*daeQVecPtr)[li_mPro[i]] += segMEquQvalue[i];
1030  (*daeQVecPtr)[li_hPro[i]] += segHEquQvalue[i];
1031  }
1032 
1033  return bsuccess;
1034 }
1035 
1036 
1037 
1038 //-----------------------------------------------------------------------------
1039 // Function : Instance::loadDAEFVector
1040 //
1041 // Purpose : Loads the F-vector contributions for a single
1042 // Neuron 3 instance.
1043 //
1044 // Special Notes :
1045 //
1046 // Scope : public
1047 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1048 // Creation Date : 06/10/09
1049 //-----------------------------------------------------------------------------
1051 {
1052  bool bsuccess=true;
1053 
1054  Linear::Vector * daeFVecPtr = extData.daeFVectorPtr;
1055 
1056  (*daeFVecPtr)[li_Pos] += kcl1Fvalue;
1057  (*daeFVecPtr)[li_Neg] += kcl2Fvalue;
1058 
1059  for( int i=0; i<nSeg ; i++)
1060  {
1061  (*daeFVecPtr)[li_Vol[i]] += segFvalue[i];
1062  (*daeFVecPtr)[li_nPro[i]] += segNEquFvalue[i];
1063  (*daeFVecPtr)[li_mPro[i]] += segMEquFvalue[i];
1064  (*daeFVecPtr)[li_hPro[i]] += segHEquFvalue[i];
1065  }
1066 
1067  return bsuccess;
1068 }
1069 
1070 //-----------------------------------------------------------------------------
1071 // Function : Instance::loadDAEdQdx
1072 //
1073 // Purpose : Loads the Q-vector contributions for a single
1074 // Neuron 3 instance.
1075 // Scope : public
1076 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1077 // Creation Date : 06/10/09
1078 //-----------------------------------------------------------------------------
1080 {
1081  bool bsuccess = true;
1082 
1083  Linear::Matrix * dQdxMatPtr = extData.dQdxMatrixPtr;
1084 
1085  for( int i=0; i<nSeg ; i++)
1086  {
1087  (*dQdxMatPtr)[li_Vol[i]][SegVEqnVsegOffset[i]] += segQ_dV[i];
1088  (*dQdxMatPtr)[li_nPro[i]][NEquNNodeOffset[i]] += dnQ_dn[i];
1089  (*dQdxMatPtr)[li_mPro[i]][MEquMNodeOffset[i]] += dmQ_dm[i];
1090  (*dQdxMatPtr)[li_hPro[i]][HEquHNodeOffset[i]] += dhQ_dh[i];
1091  }
1092 
1093  return bsuccess;
1094 }
1095 
1096 //-----------------------------------------------------------------------------
1097 // Function : Instance::loadDAEdFdx ()
1098 //
1099 // Purpose : Loads the F-vector contributions for a single
1100 // Neuron 3 instance.
1101 //
1102 // Special Notes : This is an algebraic constaint.
1103 //
1104 // Scope : public
1105 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1106 // Creation Date : 06/10/09
1107 //-----------------------------------------------------------------------------
1109 {
1110  bool bsuccess = true;
1111 
1112  Linear::Matrix * dFdxMatPtr = extData.dFdxMatrixPtr;
1113 
1114  (*dFdxMatPtr)[li_Pos][APosEquPosNodeOffset] += dkcl1F_dVin;
1115  (*dFdxMatPtr)[li_Pos][APosEquNextNodeOffset] += dkcl1F_dVs0;
1116 
1117  (*dFdxMatPtr)[li_Neg][ANegEquNegNodeOffset] += dkcl2F_dVout;
1118  (*dFdxMatPtr)[li_Neg][ANegEquLastNodeOffset] += dkcl2F_dVsn;
1119 
1120  for( int i=0; i<nSeg ; i++)
1121  {
1122  (*dFdxMatPtr)[li_Vol[i]][SegVEqnVpreOffset[i]] += segF_dVp[i];
1123  (*dFdxMatPtr)[li_Vol[i]][SegVEqnVsegOffset[i]] += segF_dV[i];
1124  (*dFdxMatPtr)[li_Vol[i]][SegVEqnVnexOffset[i]] += segF_dVn[i];
1125  (*dFdxMatPtr)[li_Vol[i]][SegVEqnNOffset[i]] += segF_dn[i];
1126  (*dFdxMatPtr)[li_Vol[i]][SegVEqnMOffset[i]] += segF_dm[i];
1127  (*dFdxMatPtr)[li_Vol[i]][SegVEqnHOffset[i]] += segF_dh[i];
1128 
1129  (*dFdxMatPtr)[li_nPro[i]][NEquVNodeOffset[i]] += dnF_dV[i];
1130  (*dFdxMatPtr)[li_nPro[i]][NEquNNodeOffset[i]] += dnF_dn[i];
1131  (*dFdxMatPtr)[li_mPro[i]][MEquVNodeOffset[i]] += dmF_dV[i];
1132  (*dFdxMatPtr)[li_mPro[i]][MEquMNodeOffset[i]] += dmF_dm[i];
1133  (*dFdxMatPtr)[li_hPro[i]][HEquVNodeOffset[i]] += dhF_dV[i];
1134  (*dFdxMatPtr)[li_hPro[i]][HEquHNodeOffset[i]] += dhF_dh[i];
1135  }
1136 
1137  return bsuccess;
1138 }
1139 
1140 //-----------------------------------------------------------------------------
1141 // Function : Instance::setIC
1142 // Purpose :
1143 // Special Notes :
1144 // Scope : public
1145 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1146 // Creation Date : 06/10/09
1147 //-----------------------------------------------------------------------------
1149 {
1150  bool bsuccess = true;
1151 
1152  return bsuccess;
1153 }
1154 
1155 //-----------------------------------------------------------------------------
1156 // Function : Instance::varTypes
1157 // Purpose :
1158 // Special Notes :
1159 // Scope : public
1160 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1161 // Creation Date : 06/10/09
1162 //-----------------------------------------------------------------------------
1163 void Instance::varTypes( std::vector<char> & varTypeVec )
1164 {
1165  //varTypeVec.resize(1);
1166  //varTypeVec[0] = 'I';
1167 }
1168 
1169 
1170 //-----------------------------------------------------------------------------
1171 // Function : Model::processParams
1172 // Purpose :
1173 // Special Notes :
1174 // Scope : public
1175 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1176 // Creation Date : 06/10/09
1177 //-----------------------------------------------------------------------------
1179 {
1180  return true;
1181 }
1182 
1183 //----------------------------------------------------------------------------
1184 // Function : Model::processInstanceParams
1185 // Purpose :
1186 // Special Notes :
1187 // Scope : public
1188 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1189 // Creation Date : 06/10/09
1190 //----------------------------------------------------------------------------
1192 {
1193  std::vector<Instance*>::iterator iter;
1194  std::vector<Instance*>::iterator first = instanceContainer.begin();
1195  std::vector<Instance*>::iterator last = instanceContainer.end();
1196 
1197  for (iter=first; iter!=last; ++iter)
1198  {
1199  (*iter)->processParams();
1200  }
1201 
1202  return true;
1203 }
1204 
1205 //-----------------------------------------------------------------------------
1206 // Function : Model::Model
1207 // Purpose : block constructor
1208 // Special Notes :
1209 // Scope : public
1210 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1211 // Creation Date : 06/10/09
1212 //-----------------------------------------------------------------------------
1214  const Configuration & configuration,
1215  const ModelBlock & MB,
1216  const FactoryBlock & factory_block)
1217  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
1218  rInt(0.0),
1219  radius(0.0),
1220  length(0.0),
1221  rIntGiven(false),
1222  radiusGiven(false),
1223  lengthGiven(false)
1224 {
1225 
1226  // Set params to constant default values:
1227  setDefaultParams ();
1228 
1229  // Set params according to .model line and constant defaults from metadata:
1230  setModParams (MB.params);
1231 
1232  // Set any non-constant parameter defaults:
1233  //if (!given("TNOM"))
1234  // tnom = getDeviceOptions().tnom;
1235 
1236  // Calculate any parameters specified as expressions:
1238 
1239  // calculate dependent (ie computed) params and check for errors:
1240 
1241  processParams ();
1242 }
1243 
1244 //-----------------------------------------------------------------------------
1245 // Function : Model::~Model
1246 // Purpose : destructor
1247 // Special Notes :
1248 // Scope : public
1249 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1250 // Creation Date : 06/10/09
1251 //-----------------------------------------------------------------------------
1253 {
1254  std::vector<Instance*>::iterator iter;
1255  std::vector<Instance*>::iterator first = instanceContainer.begin();
1256  std::vector<Instance*>::iterator last = instanceContainer.end();
1257 
1258  for (iter=first; iter!=last; ++iter)
1259  {
1260  delete (*iter);
1261  }
1262 
1263 }
1264 
1265 // additional Declarations
1266 
1267 //-----------------------------------------------------------------------------
1268 // Function : Model::printOutInstances
1269 // Purpose : debugging tool.
1270 // Special Notes :
1271 // Scope : public
1272 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1273 // Creation Date : 06/10/09
1274 //-----------------------------------------------------------------------------
1275 std::ostream &Model::printOutInstances(std::ostream &os) const
1276 {
1277  std::vector<Instance*>::const_iterator iter;
1278  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
1279  std::vector<Instance*>::const_iterator last = instanceContainer.end();
1280 
1281  int i, isize;
1282  isize = instanceContainer.size();
1283 
1284  os << std::endl;
1285  os << "Number of Neuron instances: " << isize << std::endl;
1286  os << " name=\t\tmodelName\tParameters" << std::endl;
1287  for (i=0, iter=first; iter!=last; ++iter, ++i)
1288  {
1289  os << " " << i << ": " << (*iter)->getName() << "\t";
1290  os << getName();
1291  os << std::endl;
1292  }
1293 
1294  os << std::endl;
1295  return os;
1296 }
1297 
1298 //-----------------------------------------------------------------------------
1299 // Function : Model::forEachInstance
1300 // Purpose :
1301 // Special Notes :
1302 // Scope : public
1303 // Creator : David Baur
1304 // Creation Date : 2/4/2014
1305 //-----------------------------------------------------------------------------
1306 /// Apply a device instance "op" to all instances associated with this
1307 /// model
1308 ///
1309 /// @param[in] op Operator to apply to all instances.
1310 ///
1311 ///
1312 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
1313 {
1314  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1315  op(*it);
1316 }
1317 
1318 
1319 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
1320 {
1321 
1322  return new DeviceMaster<Traits>(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
1323 }
1324 
1326 {
1328  .registerDevice("neuron", 3)
1329  .registerModelType("neuron", 3);
1330 }
1331 
1332 } // namespace Neuron3
1333 } // namespace Device
1334 } // 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