Xyce  6.1
N_DEV_Neuron.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-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_Neuron.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.42.2.1 $
40 //
41 // Revision Date : $Date: 2015/04/02 18:29:37 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-----------------------------------------------------------------------------
45 
46 #ifndef Xyce_N_DEV_Neuron_h
47 #define Xyce_N_DEV_Neuron_h
48 
49 #include <N_DEV_Configuration.h>
50 #include <Sacado.hpp>
51 
52 // ---------- Xyce Includes ----------
53 #include <N_DEV_DeviceMaster.h>
54 #include <N_DEV_DeviceBlock.h>
55 #include <N_DEV_DeviceInstance.h>
56 #include <N_DEV_DeviceModel.h>
57 
58 namespace Xyce {
59 namespace Device {
60 namespace Neuron {
61 
62 class Model;
63 class Instance;
64 
65 struct Traits : public DeviceTraits<Model, Instance>
66 {
67  static const char *name() {return "Neuron";}
68  static const char *deviceTypeName() {return "YNEURON level 1";}
69  static int numNodes() {return 2;}
70  static bool modelRequired() {return true;}
71  static bool isLinearDevice() {return true;}
72 
73  static Device *factory(const Configuration &configuration, const FactoryBlock &factory_block);
74  static void loadModelParameters(ParametricData<Model> &model_parameters);
75  static void loadInstanceParameters(ParametricData<Instance> &instance_parameters);
76 };
77 
78 //-----------------------------------------------------------------------------
79 // Class : Instance
80 // Purpose : This is class refers to a single instance of the
81 // Neuron device. It has two nodes associated with it, a
82 // positive and a negative node. See the NeuronInstance
83 // class for a more detailed explanation.
84 // Special Notes :
85 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
86 // Creation Date : 01/02/08
87 //-----------------------------------------------------------------------------
88 class Instance : public DeviceInstance
89 {
90  friend class ParametricData<Instance>;
91  friend class Model;
92  friend class Traits;friend class Master;
93 
94 public:
95  static std::vector< std::vector<int> > jacStamp;
96 
97  Instance(
98  const Configuration & configuration,
99  const InstanceBlock & IB,
100  Model & Miter,
101  const FactoryBlock & factory_block);
102 
103 
104  ~Instance();
105 
106 private:
107  Instance(const Instance &);
108  Instance &operator=(const Instance &);
109 
110 public:
111  void registerLIDs( const std::vector<int> & intLIDVecRef,
112  const std::vector<int> & extLIDVecRef );
113  void registerStateLIDs( const std::vector<int> & staLIDVecRef );
114 
115  void loadNodeSymbols(Util::SymbolTable &symbol_table) const; // override
116 
117  const std::vector< std::vector<int> > & jacobianStamp() const;
118  void registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec );
119 
120  bool processParams ();
121  bool updateTemperature(const double & temp_tmp);
122 
123  bool updateIntermediateVars ();
124  bool updatePrimaryState ();
125  bool updateSecondaryState ();
126  bool setIC ();
127 
128  void varTypes( std::vector<char> & varTypeVec );
129 
130  // load functions, residual:
131  bool loadDAEQVector ();
132  bool loadDAEFVector ();
133 
134  void auxDAECalculations ();
135 
136  // load functions, Jacobian:
137  bool loadDAEdQdx ();
138  bool loadDAEdFdx ();
139 
140 private:
141  // These functions represent the equations that need to be solved
142  // for this device. Since Xyce loads an F and Q contribution, the
143  // equations are broken up into their F and Q components. Thus there
144  // is a kcl1EquF() and kcl1EquQ(). Automatic differentiation will
145  // be used to generate all the derivatives of these equations for the
146  // dF/dX and dQ/dX loads
147 
148  // first we list some utility functions for calculating coefficients.
149  // alpha and beta equations are taken from Koch.
150  // They're generally functions of membrane voltage; here, the membrane voltage is
151  // the difference between Vn1 and Vn2.
152  // Also, in the Koch formulation, the voltage is relative to the resting potential;
153  // equations adjusted here to accommodate a nonzero resting potential vRest.
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 & Vn1, const ScalarT & Vn2, const ScalarT & Vrest)
160  {
161  ScalarT vDiff = 1000.0 * (Vn1 - Vn2 - Vrest); // convert voltage to milli-volts
162  // and shift to account for nonzero Vrest
163  ScalarT r;
164  if ((vDiff > 9.99) && (vDiff < 10.01) )
165  {
166  r = 1.0/(10.0 * ( std::exp( (10.0 - vDiff)/10.0 )));
167  }
168  else
169  {
170  r = (10.0 - vDiff) /
171  (100.0 * ( std::exp( (10.0 - vDiff)/10.0 ) - 1.0 ));
172  }
173  r *= 1000.0; // change from 1/ms to 1/s
174  return r;
175  }
176 
177  template <typename ScalarT>
178  static ScalarT betaN( const ScalarT & Vn1, const ScalarT & Vn2, const ScalarT & Vrest)
179  {
180  ScalarT vDiff = 1000.0 * (Vn1 - Vn2 - Vrest);
181  ScalarT r = 0.125 * std::exp( -vDiff/80.0 );
182  r *= 1000.0; // change from 1/ms to 1/s
183  return r;
184  }
185 
186  // sodium current, functions for activator equation
187  template <typename ScalarT>
188  static ScalarT alphaM( const ScalarT & Vn1, const ScalarT & Vn2, const ScalarT & Vrest)
189  {
190  ScalarT vDiff = 1000.0 * (Vn1 - Vn2 - Vrest);
191  ScalarT r;
192  if ((vDiff > 24.99) && (vDiff < 25.01) )
193  {
194  r = (1.0) /
195  (( std::exp( (25.0 - vDiff)/10.0 )));
196  }
197  else
198  {
199  r = (25.0 - vDiff) /
200  (10.0 * ( std::exp( (25.0 - vDiff)/10.0 ) - 1.0 ));
201  }
202  r *= 1000.0; // change from 1/ms to 1/s
203  return r;
204  }
205 
206  template <typename ScalarT>
207  static ScalarT betaM( const ScalarT & Vn1, const ScalarT & Vn2, const ScalarT & Vrest)
208  {
209  ScalarT vDiff = 1000.0 * (Vn1 - Vn2 - Vrest);
210  ScalarT r = 4.0 * std::exp( -vDiff/18.0 );
211  r *= 1000.0; // change from 1/ms to 1/s
212 
213  return r;
214  }
215 
216  template <typename ScalarT>
217  static ScalarT alphaH( const ScalarT & Vn1, const ScalarT & Vn2, const ScalarT & Vrest)
218  {
219  ScalarT vDiff = 1000.0 * (Vn1 - Vn2 - Vrest);
220  ScalarT r = 0.07 * std::exp( -vDiff/20.0 );
221  r *= 1000.0; // change from 1/ms to 1/s
222  return r;
223  }
224 
225  template <typename ScalarT>
226  static ScalarT betaH( const ScalarT & Vn1, const ScalarT & Vn2, const ScalarT & Vrest)
227  {
228  ScalarT vDiff = 1000.0 * (Vn1 - Vn2 - Vrest);
229  ScalarT r = 1.0 / ( std::exp( (30.0 - vDiff)/10.0 ) + 1.0 );
230  r *= 1000.0; // change from 1/ms to 1/s
231  return r;
232  }
233 
234  // now the device equations
235  // KCL equation 1
236  template <typename ScalarT>
237  static ScalarT kcl1EquF( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& n, const ScalarT& m, const ScalarT& h,
238  const ScalarT& memG, const ScalarT& leakE, const ScalarT& Kg, const ScalarT& Ke, const ScalarT& NaG, const ScalarT& NaE )
239  {
240  ScalarT powN = n * n * n * n;
241  ScalarT powM = m * m * m;
242  ScalarT r = memG * (Vn1 - Vn2 - leakE) + Kg * powN * (Vn1 - Vn2 - Ke ) + NaG * powM * h * (Vn1 - Vn2 - NaE );
243  return r;
244  }
245 
246  template <typename ScalarT>
247  static ScalarT kcl1EquQ( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& memC )
248  {
249  ScalarT r = memC * (Vn1 - Vn2);
250  return r;
251  }
252 
253  // KCL equation 2 -- -1 * equation 1 because of device symmetry
254  template <typename ScalarT>
255  static ScalarT kcl2EquF( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& n, const ScalarT& m, const ScalarT& h,
256  const ScalarT& memG, const ScalarT& leakE, const ScalarT& Kg, const ScalarT& Ke, const ScalarT& NaG, const ScalarT& NaE )
257  {
258  ScalarT powN = n * n * n * n;
259  ScalarT powM = m * m * m;
260  ScalarT r = -1.0*(memG * (Vn1 - Vn2 - leakE) + Kg * powN * (Vn1 - Vn2 - Ke ) + NaG * powM * h * (Vn1 - Vn2 - NaE ));
261  return r;
262  }
263 
264  template <typename ScalarT>
265  static ScalarT kcl2EquQ( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& memC )
266  {
267  ScalarT r = -1.0 * memC * (Vn1 - Vn2);
268  return r;
269  }
270 
271  // n conservation equation
272  template <typename ScalarT>
273  static ScalarT nEquF( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& n, const ScalarT& Vrest )
274  {
275  ScalarT r = alphaN<ScalarT>( Vn1, Vn2, Vrest ) * (1.0 - n ) - betaN<ScalarT>( Vn1, Vn2, Vrest ) * n;
276  return r;
277  }
278 
279  template <typename ScalarT>
280  static ScalarT nEquQ( const ScalarT& n )
281  {
282  ScalarT r = -n;
283  return r;
284  }
285 
286  // m conservation equation
287  template <typename ScalarT>
288  static ScalarT mEquF( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& m, const ScalarT& Vrest )
289  {
290  ScalarT r = alphaM<ScalarT>( Vn1, Vn2, Vrest ) * (1.0 - m ) - betaM<ScalarT>( Vn1, Vn2, Vrest ) * m;
291  return r;
292  }
293 
294  template <typename ScalarT>
295  static ScalarT mEquQ( const ScalarT& m )
296  {
297  ScalarT r = -m;
298  return r;
299  }
300 
301  // h conservation equation
302  template <typename ScalarT>
303  static ScalarT hEquF( const ScalarT& Vn1, const ScalarT& Vn2, const ScalarT& h, const ScalarT& Vrest )
304  {
305  ScalarT r = alphaH<ScalarT>( Vn1, Vn2, Vrest ) * (1.0 - h ) - betaH<ScalarT>( Vn1, Vn2, Vrest ) * h;
306  return r;
307  }
308 
309  template <typename ScalarT>
310  static ScalarT hEquQ( const ScalarT& h )
311  {
312  ScalarT r = -h;
313  return r;
314  }
315 
316 public:
317  // iterator reference to the Neuron model which owns this instance.
318  // Getters and setters
320  {
321  return model_;
322  }
323 
324 private:
325 
326  Model & model_; //< Owning model
327 
328  // derrived quantities computed in updateIntermediateVars
329  // and used in the load functions
340 
341  // state variables
344 
345  // local state indices (offsets)
348 
349  // local solution indices (offsets)
350  int li_Pos; // local index to positive node on this device
351  int li_Neg; // local index to negative node on this device
352  int li_nPro; // local index to n promoter value (Na current)
353  int li_mPro; // local index to m promoter value (K current)
354  int li_hPro; // local index to h promoter value (K current)
355 
356  // Matrix equation index variables:
357 
358  // Offset variables corresponding to the above declared indices.
364 
370 
374 
378 
382 };
383 
384 //-----------------------------------------------------------------------------
385 // Class : Model
386 // Purpose :
387 // Special Notes :
388 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
389 // Creation Date : 01/02/08
390 //-----------------------------------------------------------------------------
391 class Model : public DeviceModel
392 {
393  typedef std::vector<Instance *> InstanceVector;
394 
395  friend class ParametricData<Model>;
396  friend class Instance;
397  friend class Traits;friend class Master;
398 
399 public:
400  Model(
401  const Configuration & configuration,
402  const ModelBlock & MB,
403  const FactoryBlock & factory_block);
404  ~Model();
405 
406 private:
407  Model();
408  Model(const Model &);
409  Model &operator=(const Model &);
410 
411 public:
412  virtual void forEachInstance(DeviceInstanceOp &op) const /* override */;
413 
414  virtual std::ostream &printOutInstances(std::ostream &os) const;
415 
416  bool processParams ();
417  bool processInstanceParams ();
418 
419 private:
420 
421  // parameter variables
422  double cMem; // membrane capacitance
423  double gMem; // membrane conductance of leak current
424  double eLeak; // reversal potential of leak current
425  double eNa; // sodium reversal potential
426  double gNa; // sodium base conductance
427  double eK; // potassium reversal potential
428  double gK; // potassium base conductance
429  double vRest; // resting potential
430 
431  // flags that parameters were given
432  bool cMemGiven;
433  bool gMemGiven;
435  bool eNaGiven;
436  bool gNaGiven;
437  bool eKGiven;
438  bool gKGiven;
440 
441 
442 public:
443  void addInstance(Instance *instance)
444  {
445  instanceContainer.push_back(instance);
446  }
447 
448 private:
449  std::vector<Instance*> instanceContainer;
450 };
451 
452 
453 //-----------------------------------------------------------------------------
454 // Class : Master
455 // Purpose :
456 // Special Notes :
457 // Creator : Richard Schiek, SNL, Parallel Computational Sciences
458 // Creation Date : 06/01/12
459 //-----------------------------------------------------------------------------
460 class Master : public DeviceMaster<Traits>
461 {
462  friend class Neuron::Instance;
463  friend class Neuron::Model;
464 
465 public:
467  const Configuration & configuration,
468  const FactoryBlock & factory_block,
469  const SolverState & ss1,
470  const DeviceOptions & do1)
471  : DeviceMaster<Traits>(configuration, factory_block, ss1, do1)
472  {}
473 
474  virtual bool updateState (double * solVec, double * staVec, double * stoVec);
475 };
476 
477 void registerDevice();
478 
479 } // namespace Neuron
480 } // namespace Device
481 } // namespace Xyce
482 
483 #endif
static ScalarT hEquF(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &h, const ScalarT &Vrest)
Definition: N_DEV_Neuron.h:303
bool processParams()
processParams
Definition: N_DEV_Neuron.C:853
static ScalarT kcl1EquQ(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &memC)
Definition: N_DEV_Neuron.h:247
Pure virtual class to augment a linear system.
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
Definition: N_DEV_Neuron.C:360
static ScalarT hEquQ(const ScalarT &h)
Definition: N_DEV_Neuron.h:310
static ScalarT alphaN(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &Vrest)
Definition: N_DEV_Neuron.h:159
static ScalarT nEquF(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &n, const ScalarT &Vrest)
Definition: N_DEV_Neuron.h:273
Model & operator=(const Model &)
std::vector< Instance * > instanceContainer
Definition: N_DEV_Neuron.h:449
static ScalarT alphaH(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &Vrest)
Definition: N_DEV_Neuron.h:217
bool processInstanceParams()
processInstanceParams
Definition: N_DEV_Neuron.C:866
DeviceMaster instantiates a device as described by the device traits T.
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
Definition: N_DEV_Neuron.C:71
static ScalarT kcl2EquF(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &n, const ScalarT &m, const ScalarT &h, const ScalarT &memG, const ScalarT &leakE, const ScalarT &Kg, const ScalarT &Ke, const ScalarT &NaG, const ScalarT &NaE)
Definition: N_DEV_Neuron.h:255
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
Instance & operator=(const Instance &)
static ScalarT nEquQ(const ScalarT &n)
Definition: N_DEV_Neuron.h:280
bool updateTemperature(const double &temp_tmp)
Definition: N_DEV_Neuron.C:157
static const char * name()
Definition: N_DEV_Neuron.h:67
static ScalarT betaN(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &Vrest)
Definition: N_DEV_Neuron.h:178
The Device class is an interface for device implementations.
Definition: N_DEV_Device.h:101
static std::vector< std::vector< int > > jacStamp
Definition: N_DEV_Neuron.h:95
static const char * deviceTypeName()
Definition: N_DEV_Neuron.h:68
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
Definition: N_DEV_Neuron.C:299
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
Definition: N_DEV_Neuron.C:981
static ScalarT mEquF(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &m, const ScalarT &Vrest)
Definition: N_DEV_Neuron.h:288
Class Configuration contains device configuration data.
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
Definition: N_DEV_Neuron.C:345
const std::vector< std::vector< int > > & jacobianStamp() const
Definition: N_DEV_Neuron.C:380
void varTypes(std::vector< char > &varTypeVec)
Definition: N_DEV_Neuron.C:838
static ScalarT mEquQ(const ScalarT &m)
Definition: N_DEV_Neuron.h:295
static ScalarT kcl2EquQ(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &memC)
Definition: N_DEV_Neuron.h:265
void addInstance(Instance *instance)
Definition: N_DEV_Neuron.h:443
virtual bool updateState(double *solVec, double *staVec, double *stoVec)
Updates the devices state information.
Definition: N_DEV_Neuron.C:997
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
Definition: N_DEV_Neuron.C:393
static void loadModelParameters(ParametricData< Model > &model_parameters)
Definition: N_DEV_Neuron.C:75
Master(const Configuration &configuration, const FactoryBlock &factory_block, const SolverState &ss1, const DeviceOptions &do1)
Definition: N_DEV_Neuron.h:466
static ScalarT betaM(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &Vrest)
Definition: N_DEV_Neuron.h:207
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &Miter, const FactoryBlock &factory_block)
Definition: N_DEV_Neuron.C:171
ModelBlock represents a .MODEL line from the netlist.
The DeviceTraits template describes the configuration of a device.
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
InstanceBlock represent a device instance line from the netlist.
static ScalarT kcl1EquF(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &n, const ScalarT &m, const ScalarT &h, const ScalarT &memG, const ScalarT &leakE, const ScalarT &Kg, const ScalarT &Ke, const ScalarT &NaG, const ScalarT &NaE)
Definition: N_DEV_Neuron.h:237
static ScalarT betaH(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &Vrest)
Definition: N_DEV_Neuron.h:226
std::vector< Instance * > InstanceVector
Definition: N_DEV_Neuron.h:393
virtual std::ostream & printOutInstances(std::ostream &os) const
Definition: N_DEV_Neuron.C:944
static ScalarT alphaM(const ScalarT &Vn1, const ScalarT &Vn2, const ScalarT &Vrest)
Definition: N_DEV_Neuron.h:188