Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_Neuron2.h
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-2011 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_Neuron2.h,v $
27 //
28 // Purpose : Neuron classes.
29 //
30 // Special Notes :
31 //
32 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
33 //
34 // Creation Date : 01/02/08
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.23.2.1 $
40 //
41 // Revision Date : $Date: 2014/02/26 20:16:30 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-----------------------------------------------------------------------------
45 
46 #ifndef Xyce_N_DEV_Neuron2_h
47 #define Xyce_N_DEV_Neuron2_h
48 
49 #include <Sacado.hpp>
50 
51 #include <N_DEV_Configuration.h>
52 #include <N_DEV_DeviceBlock.h>
53 #include <N_DEV_DeviceInstance.h>
54 #include <N_DEV_DeviceModel.h>
55 
56 #include <N_DEV_Neuron.h>
57 
58 #ifdef HAVE_MATH_H
59 #include <math.h>
60 #endif
61 
62 namespace Xyce {
63 namespace Device {
64 namespace Neuron2 {
65 
66 class Model;
67 class Instance;
68 
69 struct Traits : public DeviceTraits<Model, Instance, Neuron::Traits>
70 {
71  static const char *name() {return "Neuron";}
72  static const char *deviceTypeName() {return "YNEURON level 2";}
73  static const int numNodes() {return 2;}
74  static const bool modelRequired() {return true;}
75  static const bool isLinearDevice() {return true;}
76 
77  static Device *factory(const Configuration &configuration, const FactoryBlock &factory_block);
78  static void loadModelParameters(ParametricData<Model> &model_parameters);
79  static void loadInstanceParameters(ParametricData<Instance> &instance_parameters);
80 };
81 
82 //-----------------------------------------------------------------------------
83 // Class : Instance
84 // Purpose : This is class refers to a single instance of the
85 // Neuron device. It has two nodes associated with it, a
86 // positive and a negative node. See the NeuronInstance
87 // class for a more detailed explanation.
88 // Special Notes :
89 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
90 // Creation Date : 01/02/08
91 //-----------------------------------------------------------------------------
92 class Instance : public DeviceInstance
93 {
94  friend class ParametricData<Instance>;
95  friend class Model;
96  friend class Traits;
97 
98 public:
99  static std::vector< std::vector<int> > jacStamp;
100 
101  Instance(
102  const Configuration & configuration,
103  const InstanceBlock & IB,
104  Model & Miter,
105  const FactoryBlock & factory_block);
106 
107  ~Instance();
108 
109 private:
110  Instance(const Instance &right);
111  Instance &operator=(const Instance &);
112 
113 public:
114  void registerLIDs( const std::vector<int> & intLIDVecRef,
115  const std::vector<int> & extLIDVecRef );
116  void registerStateLIDs( const std::vector<int> & staLIDVecRef );
117 
118  std::map<int,std::string> & getIntNameMap ();
119  bool loadDeviceMask();
120  const std::vector< std::vector<int> > & jacobianStamp() const;
121  void registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec );
122 
123  bool processParams ();
124  bool updateTemperature(const double & temp_tmp);
125 
126  bool updateIntermediateVars ();
127  bool updatePrimaryState ();
128  bool updateSecondaryState ();
129  bool setIC ();
130 
131  void varTypes( std::vector<char> & varTypeVec );
132 
133  // load functions, residual:
134  bool loadDAEQVector ();
135  bool loadDAEFVector ();
136 
137  void auxDAECalculations ();
138 
139  // load functions, Jacobian:
140  bool loadDAEdQdx ();
141  bool loadDAEdFdx ();
142 
143 protected:
144 private:
145  // These functions represents the equations that need to be solved
146  // for this device. Since Xyce loads an F and Q contribution, the
147  // equations are broken up into their F and Q components. Thus there
148  // is a kcl1EquF() and kcl1EquQ(). Automatic differentiation will
149  // be used to generate all the derivatives of these equations for the
150  // dF/dX and dQ/dX loads
151 
152  // first we list some utility functions for calculating coefficients
153  //
154  // These functions expect V to be in milli-volts and then return values that
155  // are in 1/ms. Thus the extra factor's of 1000 here and there
156 
157  // potassium current, functions for activator equation
158  template <typename ScalarT>
159  static ScalarT alphaN( const ScalarT Vin)
160  {
161  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
162  ScalarT r = 1000.0 * (0.02 * (vScaled + 45.7)) / (1.0 - std::exp(-0.1*(vScaled+45.7)));
163  // result. the 1000 factor is to change from 1/ms to 1/s
164  return r;
165  }
166 
167  template <typename ScalarT>
168  static ScalarT betaN( const ScalarT Vin)
169  {
170  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
171  ScalarT r = 1000.0 * 0.25 * std::exp( -0.0125 * (vScaled + 55.7));
172  // result. the 1000 factor is to change from 1/ms to 1/s
173  return r;
174  }
175 
176  // sodium current, functions for activator equation
177  template <typename ScalarT>
178  static ScalarT alphaM( const ScalarT Vin)
179  {
180  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
181  ScalarT r = 1000.0 * (0.38 * (vScaled + 29.7)) / (1.0 - std::exp(-0.1*(vScaled+29.7)));
182  // result. the 1000 factor is to change from 1/ms to 1/s
183  return r;
184  }
185 
186  template <typename ScalarT>
187  static ScalarT betaM( const ScalarT Vin)
188  {
189  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
190  ScalarT r = 1000.0 * 15.2 * std::exp( -0.0556 * (vScaled + 54.7));
191  // result. the 1000 factor is to change from 1/ms to 1/s
192  return r;
193  }
194 
195  template <typename ScalarT>
196  static ScalarT alphaH( const ScalarT Vin)
197  {
198  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
199  ScalarT r = 1000.0 * 0.266 * std::exp( -0.05 * (vScaled + 48.0));
200  // result. the 1000 factor is to change from 1/ms to 1/s
201  return r;
202  }
203 
204  template <typename ScalarT>
205  static ScalarT betaH( const ScalarT Vin)
206  {
207  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
208  ScalarT r = 1000.0 * 3.8 / (1.0 + std::exp(-0.1*(vScaled+18.0)));
209  // result. the 1000 factor is to change from 1/ms to 1/s
210  return r;
211  }
212 
213  // a-current functions
214  template <typename ScalarT>
215  static ScalarT aInf( const ScalarT Vin)
216  {
217  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
218  ScalarT r = std::pow( ((0.0761 * std::exp(0.0314 * (vScaled+94.22))) / (1.0+std::exp(0.0346*(vScaled+1.17)))), 1.0/3.0);
219  return r;
220  }
221 
222  template <typename ScalarT>
223  static ScalarT aTau( const ScalarT Vin)
224  {
225  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
226  ScalarT r = (0.3632 + 1.158 / (1.0 + std::exp(0.0497 * (vScaled + 55.96)))) / 1000.0;
227  // the 1000.0 factor is to change ms to s.
228  return r;
229  }
230 
231  template <typename ScalarT>
232  static ScalarT bInf( const ScalarT Vin)
233  {
234  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
235  ScalarT r = std::pow( (1.0 / (1.0 + std::exp(0.0688*(vScaled+53.3)))), 4.0);
236  return r;
237  }
238 
239  template <typename ScalarT>
240  static ScalarT bTau( const ScalarT Vin)
241  {
242  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
243  ScalarT r = (1.24 + 2.678 / (1.0 + std::exp(0.0624 * (vScaled + 50.0)))) / 1000.0;
244  return r;
245  }
246 
247  // transient calcium functions
248  template <typename ScalarT>
249  static ScalarT M_Inf( const ScalarT Vin)
250  {
251  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
252  ScalarT r = 1.0/(1.0 + std::exp(-(vScaled+57)/6.2));
253  return r;
254  }
255 
256  template <typename ScalarT>
257  static ScalarT M_Tau( const ScalarT Vin)
258  {
259  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
260  ScalarT r = (0.612 + 1.0/(std::exp(-(vScaled+132)/16.7) + std::exp((vScaled+16.8)/18.2)) ) / 1000.0;
261  return r;
262  }
263 
264  template <typename ScalarT>
265  static ScalarT H_Inf( const ScalarT Vin)
266  {
267  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
268  ScalarT r = 1.0 / (1.0 + std::exp((vScaled+81)/4.0));
269  return r;
270  }
271 
272  template <typename ScalarT>
273  static ScalarT H_Tau( const ScalarT Vin)
274  {
275  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
276  ScalarT r;
277  if( vScaled < -80.0 )
278  {
279  r = std::exp( (vScaled + 467)/66.6 ) / 1000.0;
280  }
281  else
282  {
283  r = ( 28.0 + std::exp(-(vScaled+22.0)/10.5)) / 1000.0;
284  }
285  return r;
286  }
287 
288  // Calcium dependent Potassium conductances
289  template <typename ScalarT>
290  static ScalarT C_Inf( const ScalarT Vin, const ScalarT CaConc)
291  {
292  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
293  ScalarT r = (CaConc / (CaConc + 3.0)) * (1.0 / (1.0 + std::exp(-(vScaled+28.3)/12.6 )));
294  return r;
295  }
296 
297  template <typename ScalarT>
298  static ScalarT C_Tau( const ScalarT Vin)
299  {
300  ScalarT vScaled = 1000.0 * Vin; // convert voltage to milli-volts
301  ScalarT r = (90.3 - 75.1/(1.0 + std::exp(-(vScaled+46)/22.7))) / 1000.0;
302  return r;
303  }
304 
305 
306  // now the device equations
307  // KCL equation 1
308  template <typename ScalarT>
309  static ScalarT kcl1EquF( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& n, const ScalarT& m, const ScalarT& h,
310  const ScalarT& a, const ScalarT& b, const ScalarT& MC, const ScalarT& HC, const ScalarT& CC,
311  const ScalarT& memG, const ScalarT& restV, const ScalarT& Kg, const ScalarT& Ke, const ScalarT& NaG, const ScalarT& NaE,
312  const ScalarT& Ag, const ScalarT& Ae, const ScalarT& CaTg, const ScalarT& CaE, const ScalarT& KCaG)
313  {
314  ScalarT powN = n * n * n * n;
315  ScalarT powM = m * m * m;
316  ScalarT powA = a * a * a;
317  ScalarT powMC = MC * MC;
318  ScalarT powCC = CC * CC * CC * CC;
319  ScalarT r = memG * (Vn1 - Vn2 - restV) + Kg * powN * (Vn1 - Vn2 - Ke ) + NaG * powM * h * (Vn1 - Vn2 - NaE )
320  + Ag * powA * b * (Vn1 - Vn2 - Ae) + CaTg * powMC * HC * (Vn1 - Vn2 - CaE) + KCaG * powCC * (Vn1 - Vn2 - Ke);
321  return r;
322  }
323 
324  template <typename ScalarT>
325  static ScalarT kcl1EquQ( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& memC )
326  {
327  ScalarT r = memC * (Vn1 - Vn2);
328  return r;
329  }
330 
331  // KCL equation 2 -- -1 * equation 1 because of device symmetry
332  template <typename ScalarT>
333  static ScalarT kcl2EquF( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& n, const ScalarT& m, const ScalarT& h,
334  const ScalarT& a, const ScalarT& b, const ScalarT& MC, const ScalarT& HC, const ScalarT& CC,
335  const ScalarT& memG, const ScalarT& restV, const ScalarT& Kg, const ScalarT& Ke, const ScalarT& NaG, const ScalarT& NaE,
336  const ScalarT& Ag, const ScalarT& Ae, const ScalarT& CaTg, const ScalarT& CaE, const ScalarT& KCaG)
337  {
338  ScalarT powN = n * n * n * n;
339  ScalarT powM = m * m * m;
340  ScalarT powA = a * a * a;
341  ScalarT powMC = MC * MC;
342  ScalarT powCC = CC * CC * CC * CC;
343  ScalarT r = -1.0 * (memG * (Vn1 - Vn2 - restV) + Kg * powN * (Vn1 - Vn2 - Ke ) + NaG * powM * h * (Vn1 - Vn2 - NaE )
344  + Ag * powA * b * (Vn1 - Vn2 - Ae) + CaTg * powMC * HC * (Vn1 - Vn2 - CaE) + KCaG * powCC * (Vn1 - Vn2 - Ke) );
345  return r;
346  }
347 
348  template <typename ScalarT>
349  static ScalarT kcl2EquQ( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& memC )
350  {
351  ScalarT r = -1.0 * memC * (Vn1 - Vn2);
352  return r;
353  }
354 
355  // n conservation equation
356  template <typename ScalarT>
357  static ScalarT nEquF( const ScalarT& Vn1, const ScalarT& n, const ScalarT& Vrest )
358  {
359  ScalarT vDiff = Vn1; // - Vrest
360  ScalarT alpha = alphaN<ScalarT>(vDiff);
361  ScalarT beta = betaN<ScalarT>(vDiff);
362  ScalarT r = (alpha + beta) * n - alpha;
363  return r;
364  }
365 
366  template <typename ScalarT>
367  static ScalarT nEquQ( const ScalarT& n )
368  {
369  ScalarT r = n;
370  return r;
371  }
372 
373  // m conservation equation
374  template <typename ScalarT>
375  static ScalarT mEquF( const ScalarT& Vn1, const ScalarT& m, const ScalarT& Vrest )
376  {
377  ScalarT vDiff = Vn1; // - Vrest
378  ScalarT alpha = alphaM<ScalarT>(vDiff);
379  ScalarT beta = betaM<ScalarT>(vDiff);
380  ScalarT r = (alpha + beta) * m - alpha;
381  return r;
382  }
383 
384  template <typename ScalarT>
385  static ScalarT mEquQ( const ScalarT& m )
386  {
387  ScalarT r = m;
388  return r;
389  }
390 
391  // h conservation equation
392  template <typename ScalarT>
393  static ScalarT hEquF( const ScalarT& Vn1, const ScalarT& h, const ScalarT& Vrest )
394  {
395  ScalarT vDiff = Vn1; // - Vrest
396  ScalarT alpha = alphaH<ScalarT>(vDiff);
397  ScalarT beta = betaH<ScalarT>(vDiff);
398  ScalarT r = (alpha + beta) * h - alpha;
399  return r;
400  }
401 
402  template <typename ScalarT>
403  static ScalarT hEquQ( const ScalarT& h )
404  {
405  ScalarT r = h;
406  return r;
407  }
408 
409  // a conservation equation
410  template <typename ScalarT>
411  static ScalarT aEquF( const ScalarT& Vn1, const ScalarT& a, const ScalarT& Vrest )
412  {
413  ScalarT vDiff = Vn1; // - Vrest
414  ScalarT Inf = aInf<ScalarT>(vDiff);
415  ScalarT Tau = aTau<ScalarT>(vDiff);
416  ScalarT r = (a - Inf)/Tau;
417  return r;
418  }
419 
420  template <typename ScalarT>
421  static ScalarT aEquQ( const ScalarT& a )
422  {
423  ScalarT r = a;
424  return r;
425  }
426 
427  // b conservation equation
428  template <typename ScalarT>
429  static ScalarT bEquF( const ScalarT& Vn1, const ScalarT& b, const ScalarT& Vrest )
430  {
431  ScalarT vDiff = Vn1; // - Vrest
432  ScalarT Inf = bInf<ScalarT>(vDiff);
433  ScalarT Tau = bTau<ScalarT>(vDiff);
434  ScalarT r = (b - Inf)/Tau;
435  return r;
436  }
437 
438  template <typename ScalarT>
439  static ScalarT bEquQ( const ScalarT& b )
440  {
441  ScalarT r = b;
442  return r;
443  }
444 
445  // M conservation equation
446  template <typename ScalarT>
447  static ScalarT M_EquF( const ScalarT& Vn1, const ScalarT& M, const ScalarT& Vrest )
448  {
449  ScalarT vDiff = Vn1; // - Vrest
450  ScalarT Inf = M_Inf<ScalarT>(vDiff);
451  ScalarT Tau = M_Tau<ScalarT>(vDiff);
452  ScalarT r = (M - Inf)/Tau;
453  return r;
454  }
455 
456  template <typename ScalarT>
457  static ScalarT M_EquQ( const ScalarT& M )
458  {
459  ScalarT r = M;
460  return r;
461  }
462 
463  // H conservation equation
464  template <typename ScalarT>
465  static ScalarT H_EquF( const ScalarT& Vn1, const ScalarT& H, const ScalarT& Vrest )
466  {
467  ScalarT vDiff = Vn1; // - Vrest
468  ScalarT Inf = H_Inf<ScalarT>(vDiff);
469  ScalarT Tau = H_Tau<ScalarT>(vDiff);
470  ScalarT r = (H - Inf)/Tau;
471  return r;
472  }
473 
474  template <typename ScalarT>
475  static ScalarT H_EquQ( const ScalarT& H )
476  {
477  ScalarT r = H;
478  return r;
479  }
480 
481  // C conservation equation
482  template <typename ScalarT>
483  static ScalarT C_EquF( const ScalarT& Vn1, const ScalarT& C, const ScalarT& CaConc, const ScalarT& Vrest )
484  {
485  ScalarT vDiff = Vn1; // - Vrest
486  ScalarT Inf = C_Inf<ScalarT>(vDiff, CaConc);
487  ScalarT Tau = C_Tau<ScalarT>(vDiff);
488  ScalarT r = (C - Inf)/Tau;
489  return r;
490  }
491 
492  template <typename ScalarT>
493  static ScalarT C_EquQ( const ScalarT& C )
494  {
495  ScalarT r = C;
496  return r;
497  }
498 
499  // Calcium conservation equation
500  template <typename ScalarT>
501  static ScalarT Ca_EquF( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& MC, const ScalarT& HC, const ScalarT& Ca,
502  const ScalarT& CaTg, const ScalarT& CaE, const ScalarT& CaGamma, const ScalarT& CaTau )
503  {
504  ScalarT r = CaGamma * CaTg * MC * MC * HC * (Vn1 - Vn2 - CaE) + Ca / CaTau;
505  return r;
506  }
507 
508  template <typename ScalarT>
509  static ScalarT Ca_EquQ( const ScalarT& Ca)
510  {
511  ScalarT r = Ca;
512  return r;
513  }
514 
515 public:
516  // iterator reference to the Neuron model which owns this instance.
517  // Getters and setters
519  {
520  return model_;
521  }
522 
523 private:
524 
525  Model & model_; //< Owning model
526 
527  // derrived quantities computed in updateIntermediateVars
528  // and used in the load functions
540 
554 
555  // state variables
558 
559  // local state indices (offsets)
562 
563  // local solution indices (offsets)
564  int li_Pos; // local index to positive node on this device
565  int li_Neg; // local index to negative node on this device
566  int li_nPro; // local index to n promoter value (Na current)
567  int li_mPro; // local index to m promoter value (K current)
568  int li_hPro; // local index to h promoter value (K current)
569  int li_aPro; // local index to
570  int li_bPro; // local index
571  int li_M_Pro; // local index
572  int li_H_Pro; // local index
573  int li_cPro; // local index
574  int li_CaPro; // local index
575 
576  // Matrix equation index variables:
577 
578  // Offset variables corresponding to the above declared indices.
589 
600 
603 
606 
609 
612 
615 
618 
621 
625 
631 };
632 
633 //-----------------------------------------------------------------------------
634 // Class : Model
635 // Purpose :
636 // Special Notes :
637 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
638 // Creation Date : 01/02/08
639 //-----------------------------------------------------------------------------
640 class Model : public DeviceModel
641 {
642  typedef std::vector<Instance *> InstanceVector;
643 
644  friend class ParametricData<Model>;
645  friend class Instance;
646  friend class Traits;
647 
648 public:
649  Model(
650  const Configuration & configuration,
651  const ModelBlock & MB,
652  const FactoryBlock & factory_block);
653  ~Model();
654 
655 private:
656  Model();
657  Model(const Model &);
658  Model &operator=(const Model &);
659 
660 public:
661  virtual void forEachInstance(DeviceInstanceOp &op) const /* override */;
662 
663  virtual std::ostream &printOutInstances(std::ostream &os) const;
664 
665  bool processParams ();
666  bool processInstanceParams ();
667 
668 private:
669 
670  // parameter variables
671  double cMem; // membrane capacitance
672  double gMem; // membrane conductance
673  double vRest; // resting potential
674  double eNa; // sodium rest potential
675  double gNa; // sodium base conductance
676  double eK; // potassium rest potential
677  double gK; // potassium base conductance
678  double eA; // a-current rest potential
679  double gA; // a-current base conductance
680  double eCa; // Calcium rest potential
681  double gCa; // Calcium base conductance
682  double eKCa; // potassium-calcium rest potential
683  double gKCa; // potassium-calcium base conductance
684  double CaInit; // initial intra-cellular calcium concentration
685  double CaGamma; // calcium current to concentration multiplier
686  double CaTau; // calcium removal time constant
687 
688  // flags that parameters were given
689  bool cMemGiven;
690  bool gMemGiven;
692  bool eNaGiven;
693  bool gNaGiven;
694  bool eKGiven;
695  bool gKGiven;
696  bool eAGiven;
697  bool gAGiven;
698  bool eCaGiven;
699  bool gCaGiven;
700  bool eKCaGiven;
701  bool gKCaGiven;
705 
706 public:
707  void addInstance(Instance *instance)
708  {
709  instanceContainer.push_back(instance);
710  }
711 
713  {
714  return instanceContainer;
715  }
716 
718  {
719  return instanceContainer;
720  }
721 
722 private:
723  std::vector<Instance*> instanceContainer;
724 };
725 
726 void registerDevice();
727 
728 } // namespace Neuron2
729 } // namespace Device
730 } // namespace Xyce
731 
734 
735 #endif