Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_Neuron.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-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_Neuron.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Richard Schiek, Electrical and Microsytem Modeling
33 //
34 // Creation Date : 02/28/00
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.55 $
40 //
41 // Revision Date : $Date: 2014/05/13 14:50:39 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 
49 // ---------- Standard Includes ----------
50 
51 #include <N_UTL_Misc.h>
52 
53 // ---------- Xyce Includes ----------
54 #include <N_DEV_DeviceOptions.h>
55 #include <N_DEV_DeviceMaster.h>
56 #include <N_DEV_ExternData.h>
57 #include <N_DEV_MatrixLoadData.h>
58 #include <N_DEV_Neuron.h>
59 #include <N_DEV_SolverState.h>
60 #include <N_DEV_Message.h>
61 #include <N_ERH_ErrorMgr.h>
62 
63 #include <N_LAS_Vector.h>
64 #include <N_LAS_Matrix.h>
65 
66 namespace Xyce {
67 namespace Device {
68 
69 
70 namespace Neuron {
71 
72 
74 {
75 }
76 
78 {
79  // Set up map for double precision variables:
80  p.addPar ("CMEM", 0.0, false, ParameterType::NO_DEP,
83  U_FARAD, CAT_NONE, "Membrane capacitance");
84 
85  p.addPar ("ELEAK", 0.0, false, ParameterType::NO_DEP,
88  U_VOLT, CAT_NONE, "Leak current reversal potential");
89 
90  p.addPar ("GMEM", 0.0, false, ParameterType::NO_DEP,
93  U_OHMM1, CAT_NONE, "Membrane conductance");
94 
95  p.addPar ("EK", 0.0, false, ParameterType::NO_DEP,
98  U_VOLT, CAT_NONE, "Potassium reversal potential");
99 
100  p.addPar ("GK", 0.0, false, ParameterType::NO_DEP,
103  U_OHMM1, CAT_NONE, "Potassium base conductance");
104 
105  p.addPar ("ENA", 0.0, false, ParameterType::NO_DEP,
108  U_VOLT, CAT_NONE, "Sodium reversal potential");
109 
110  p.addPar ("GNA", 0.0, false, ParameterType::NO_DEP,
113  U_OHMM1, CAT_NONE, "Sodium base conductance");
114 
115  p.addPar ("VREST", 0.0, false, ParameterType::NO_DEP,
118  U_VOLT, CAT_NONE, "Resting potential");
119 }
120 
121 
122 
123 std::vector<std::vector<int> >
125 
126 // Class Instance
127 //-----------------------------------------------------------------------------
128 // Function : Instance::processParams
129 // Purpose :
130 // Special Notes :
131 // Scope : public
132 // Creator : Richard Schiek, Electrical and Microsytem Modeling
133 // Creation Date : 01/02/08
134 //-----------------------------------------------------------------------------
136 {
137  // If there are any time dependent parameters, set their values at for
138  // the current time.
139 
140  // now set the temperature related stuff.
141  //updateTemperature(temp);
142 
143  return true;
144 }
145 
146 //-----------------------------------------------------------------------------
147 // Function : Instance::updateTemperature
148 // Purpose :
149 // Special Notes :
150 // Scope : public
151 // Creator : Richard Schiek, Electrical and Microsytem Modeling
152 // Creation Date : 01/02/08
153 //-----------------------------------------------------------------------------
154 bool Instance::updateTemperature ( const double & temp)
155 {
156  bool bsuccess = true;
157  return bsuccess;
158 }
159 
160 //-----------------------------------------------------------------------------
161 // Function : Instance::Instance
162 // Purpose : constructor
163 // Special Notes :
164 // Scope : public
165 // Creator : Richard Schiek, Electrical and Microsytem Modeling
166 // Creation Date : 01/02/08
167 //-----------------------------------------------------------------------------
169  const Configuration & configuration,
170  const InstanceBlock & IB,
171  Model & Miter,
172  const FactoryBlock & factory_block)
173  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
174  model_(Miter),
175  kcl1Fvalue(0.0),
176  kcl1Qvalue(0.0),
177  kcl2Fvalue(0.0),
178  kcl2Qvalue(0.0),
179  nEquFvalue(0.0),
180  nEquQvalue(0.0),
181  mEquFvalue(0.0),
182  mEquQvalue(0.0),
183  hEquFvalue(0.0),
184  hEquQvalue(0.0),
185  dkcl1F_dV1(0.0),
186  dkcl1F_dV2(0.0),
187  dkcl1F_dn(0.0),
188  dkcl1F_dm(0.0),
189  dkcl1F_dh(0.0),
190  dkcl1Q_dV1(0.0),
191  dkcl1Q_dV2(0.0),
192  dkcl2F_dV1(0.0),
193  dkcl2F_dV2(0.0),
194  dkcl2F_dn(0.0),
195  dkcl2F_dm(0.0),
196  dkcl2F_dh(0.0),
197  dkcl2Q_dV1(0.0),
198  dkcl2Q_dV2(0.0),
199  dnF_dV1(0.0),
200  dnF_dV2(0.0),
201  dnF_dn(0.0),
202  dnQ_dn(0.0),
203  dmF_dV1(0.0),
204  dmF_dV2(0.0),
205  dmF_dm(0.0),
206  dmQ_dm(0.0),
207  dhF_dV1(0.0),
208  dhF_dV2(0.0),
209  dhF_dh(0.0),
210  dhQ_dh(0.0)
211 {
212  numExtVars = 2;
213  numIntVars = 3;
214  numStateVars = 2;
215 
216  devConMap.resize(2);
217  devConMap[0] = 1;
218  devConMap[1] = 1;
219 
220  // set up jacStamp
221  if( jacStamp.empty() )
222  {
223  // V1, V2, n, m, h
224  // all values depend on Vm = V1-V2
225  // V1 and V2 depend on n, m, and h
226  // n, m, and h each depend on themselves as well as V1 and V2
227  jacStamp.resize(5);
228  jacStamp[0].resize(5); // V1
229  jacStamp[0][0] = 0;
230  jacStamp[0][1] = 1;
231  jacStamp[0][2] = 2;
232  jacStamp[0][3] = 3;
233  jacStamp[0][4] = 4;
234  jacStamp[1].resize(5); // V2
235  jacStamp[1][0] = 0;
236  jacStamp[1][1] = 1;
237  jacStamp[1][2] = 2;
238  jacStamp[1][3] = 3;
239  jacStamp[1][4] = 4;
240  jacStamp[2].resize(3); // n
241  jacStamp[2][0] = 0;
242  jacStamp[2][1] = 1;
243  jacStamp[2][2] = 2;
244  jacStamp[3].resize(3); // m
245  jacStamp[3][0] = 0;
246  jacStamp[3][1] = 1;
247  jacStamp[3][2] = 3;
248  jacStamp[4].resize(3); // h
249  jacStamp[4][0] = 0;
250  jacStamp[4][1] = 1;
251  jacStamp[4][2] = 4;
252  }
253 
254  // Set params to constant default values:
255  setDefaultParams ();
256 
257  // Set params according to instance line and constant defaults from metadata:
258  // there are no params for this device as yet, so calling setParams causes
259  // the code to exit.
260  // setParams (IB.params);
261 
262  // Set any non-constant parameter defaults:
263 
264  //if (!given("TEMP"))
265  // temp = getDeviceOptions().temp.dVal();
266 
267  // Calculate any parameters specified as expressions:
269 
270  // calculate dependent (ie computed) params and check for errors:
271  processParams ();
272 
273 }
274 
275 
276 //-----------------------------------------------------------------------------
277 // Function : Instance::~Instance
278 // Purpose : destructor
279 // Special Notes :
280 // Scope : public
281 // Creator : Richard Schiek, Electrical and Microsytem Modeling
282 // Creation Date : 01/02/08
283 //-----------------------------------------------------------------------------
285 {
286 }
287 
288 //-----------------------------------------------------------------------------
289 // Function : Instance::registerLIDs
290 // Purpose :
291 // Special Notes :
292 // Scope : public
293 // Creator : Richard Schiek, Electrical and Microsytem Modeling
294 // Creation Date : 01/02/08
295 //-----------------------------------------------------------------------------
296 void Instance::registerLIDs(const std::vector<int> & intLIDVecRef,
297  const std::vector<int> & extLIDVecRef)
298 {
299  AssertLIDs(intLIDVecRef.size() == numIntVars);
300  AssertLIDs(extLIDVecRef.size() == numExtVars);
301 
302 #ifdef Xyce_DEBUG_DEVICE
303  if (getDeviceOptions().debugLevel > 0)
304  {
305  Xyce::dout() << std::endl << section_divider << std::endl;
306  Xyce::dout() << " Instance::registerLIDs" << std::endl;
307  Xyce::dout() << " name = " << getName() << std::endl;
308  }
309 #endif
310 
311  // copy over the global ID lists.
312  intLIDVec = intLIDVecRef;
313  extLIDVec = extLIDVecRef;
314 
315  li_Pos = extLIDVec[0];
316  li_Neg = extLIDVec[1];
317  li_nPro = intLIDVec[0];
318  li_mPro = intLIDVec[1];
319  li_hPro = intLIDVec[2];
320 
321 #ifdef Xyce_DEBUG_DEVICE
322  if (getDeviceOptions().debugLevel > 0 )
323  {
324  Xyce::dout() << " li_Pos = " << li_Pos << std::endl
325  << " li_Neg = " << li_Neg << std::endl
326  << " li_nPro = " << li_nPro << std::endl
327  << " li_mPro = " << li_mPro << std::endl
328  << " li_hPro = " << li_hPro << std::endl;
329  }
330 #endif
331 
332 #ifdef Xyce_DEBUG_DEVICE
333  if (getDeviceOptions().debugLevel > 0 )
334  {
335  Xyce::dout() << section_divider << std::endl;
336  }
337 #endif
338 }
339 
340 //-----------------------------------------------------------------------------
341 // Function : Instance::getIntNameMap
342 // Purpose :
343 // Special Notes :
344 // Scope : public
345 // Creator : Richard Schiek, Electrical and Microsytem Modeling
346 // Creation Date : 01/02/08
347 //-----------------------------------------------------------------------------
348 std::map<int,std::string> & Instance::getIntNameMap ()
349 {
350  // set up the internal name map, if it hasn't been already.
351  if (intNameMap.empty ())
352  {
356  }
357  return intNameMap;
358 }
359 
360 //-----------------------------------------------------------------------------
361 // Function : Instance::registerStateLIDs
362 // Purpose :
363 // Special Notes :
364 // Scope : public
365 // Creator : Richard Schiek, Electrical and Microsytem Modeling
366 // Creation Date : 01/02/08
367 //-----------------------------------------------------------------------------
368 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
369 {
370  AssertLIDs(staLIDVecRef.size() == numStateVars);
371 
372  // copy over the global ID lists.
373  staLIDVec = staLIDVecRef;
374 
375  li_KCurrentState = staLIDVec[0];
376  li_NaCurrentState = staLIDVec[1];
377 
378 }
379 
380 //-----------------------------------------------------------------------------
381 // Function : Instance::loadDeviceMask
382 //
383 // Purpose : Loads the zero elements of the device mask
384 //
385 // Special Notes : elements of the error vector associated with zero
386 // elements of the mask will not be included in weighted
387 // norms by the time integrator.
388 //
389 // Scope : public
390 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
391 // Creation Date : 01/19/07
392 //-----------------------------------------------------------------------------
394 {
395  bool returnVal=false;
396  N_LAS_Vector * maskVectorPtr = extData.deviceMaskVectorPtr;
397 
398 // Xyce::dout() << "Masking n, m and h" << std::endl;
399 // (*maskVectorPtr)[li_nPro] = 0.0;
400 // (*maskVectorPtr)[li_mPro] = 0.0;
401 // (*maskVectorPtr)[li_hPro] = 0.0;
402 // returnVal = true;
403 
404  return (returnVal);
405 }
406 
407 //-----------------------------------------------------------------------------
408 // Function : Instance::jacobianStamp
409 // Purpose :
410 // Special Notes :
411 // Scope : public
412 // Creator : Richard Schiek, Electrical and Microsytem Modeling
413 // Creation Date : 01/02/08
414 //-----------------------------------------------------------------------------
415 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
416 {
417  return jacStamp;
418 }
419 
420 //-----------------------------------------------------------------------------
421 // Function : Instance::registerJacLIDs
422 // Purpose :
423 // Special Notes :
424 // Scope : public
425 // Creator : Richard Schiek, Electrical and Microsytem Modeling
426 // Creation Date : 01/02/08
427 //-----------------------------------------------------------------------------
428 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
429 {
430  DeviceInstance::registerJacLIDs( jacLIDVec );
431 
432  APosEquPosNodeOffset = jacLIDVec[0][0];
433  APosEquNegNodeOffset = jacLIDVec[0][1];
434  APosEquNNodeOffset = jacLIDVec[0][2];
435  APosEquMNodeOffset = jacLIDVec[0][3];
436  APosEquHNodeOffset = jacLIDVec[0][4];
437 
438  ANegEquPosNodeOffset = jacLIDVec[1][0];
439  ANegEquNegNodeOffset = jacLIDVec[1][1];
440  ANegEquNNodeOffset = jacLIDVec[1][2];
441  ANegEquMNodeOffset = jacLIDVec[1][3];
442  ANegEquHNodeOffset = jacLIDVec[1][4];
443 
444  ANEquPosNodeOffset = jacLIDVec[2][0];
445  ANEquNegNodeOffset = jacLIDVec[2][1];
446  ANEquNNodeOffset = jacLIDVec[2][2];
447 
448  AMEquPosNodeOffset = jacLIDVec[3][0];
449  AMEquNegNodeOffset = jacLIDVec[3][1];
450  AMEquMNodeOffset = jacLIDVec[3][2];
451 
452  AHEquPosNodeOffset = jacLIDVec[4][0];
453  AHEquNegNodeOffset = jacLIDVec[4][1];
454  AHEquHNodeOffset = jacLIDVec[4][2];
455 }
456 
457 
458 //-----------------------------------------------------------------------------
459 // Function : Instance::updateIntermediateVars
460 // Purpose :
461 // Special Notes :
462 // Scope : public
463 // Creator : Richard Schiek, Electrical and Microsytem Modeling
464 // Creation Date : 01/02/08
465 //-----------------------------------------------------------------------------
467 {
468  //Xyce::dout() << "Instance::updateIntermediateVars()" << std::endl;
469 
470  bool bsuccess = true;
471 
472  // here we take the current solutions for V1, V2, n, m and h
473  // and use those to calculate all the terms needed for the next
474  // load cycle (F, Q, dFdX, dQdX)
475  N_LAS_Vector * solVectorPtr = extData.nextSolVectorPtr;
476 
477  // use suffix "now" to to clarify that this for the latest solution
478  double v1Now = (*solVectorPtr)[li_Pos];
479  double v2Now = (*solVectorPtr)[li_Neg];
480  double nNow = (*solVectorPtr)[li_nPro];
481  double mNow = (*solVectorPtr)[li_mPro];
482  double hNow = (*solVectorPtr)[li_hPro];
483 
484  // get function and derivative values
485  // independent variables
486  // use scoping to avoid lots of similar variable names
487 
488  // kcl F
489  {
490  const int numDeriv = 5;
491  Sacado::Fad::SFad<double,5> v1Var( numDeriv, 0, v1Now );
492  Sacado::Fad::SFad<double,5> v2Var( numDeriv, 1, v2Now );
493  Sacado::Fad::SFad<double,5> nVar( numDeriv, 2, nNow );
494  Sacado::Fad::SFad<double,5> mVar( numDeriv, 3, mNow );
495  Sacado::Fad::SFad<double,5> hVar( numDeriv, 4, hNow );
496  // parameters
497  Sacado::Fad::SFad<double,5> gMemVar( model_.gMem );
498  Sacado::Fad::SFad<double,5> eLeakVar( model_.eLeak );
499  Sacado::Fad::SFad<double,5> gKVar( model_.gK );
500  Sacado::Fad::SFad<double,5> eKVar( model_.eK );
501  Sacado::Fad::SFad<double,5> gNaVar( model_.gNa );
502  Sacado::Fad::SFad<double,5> eNaVar( model_.eNa );
503 
504  // compute the vaud and derivative terms for KCL 1 F
505  Sacado::Fad::SFad<double,5> resultFad;
506  resultFad = kcl1EquF( v1Var, v2Var, nVar, mVar, hVar, gMemVar, eLeakVar, gKVar, eKVar, gNaVar, eNaVar );
507  kcl1Fvalue = resultFad.val();
508  dkcl1F_dV1 = resultFad.dx(0);
509  dkcl1F_dV2 = resultFad.dx(1);
510  dkcl1F_dn = resultFad.dx(2);
511  dkcl1F_dm = resultFad.dx(3);
512  dkcl1F_dh = resultFad.dx(4);
513 
514  // compute the vaud and derivative terms for KCL 2 F
515  resultFad = kcl2EquF( v1Var, v2Var, nVar, mVar, hVar, gMemVar, eLeakVar, gKVar, eKVar, gNaVar, eNaVar );
516  kcl2Fvalue = resultFad.val();
517  dkcl2F_dV1 = resultFad.dx(0);
518  dkcl2F_dV2 = resultFad.dx(1);
519  dkcl2F_dn = resultFad.dx(2);
520  dkcl2F_dm = resultFad.dx(3);
521  dkcl2F_dh = resultFad.dx(4);
522  }
523 
524  // kcl Q
525  {
526  const int numDeriv = 2;
527  Sacado::Fad::SFad<double,2> v1Var( numDeriv, 0, v1Now );
528  Sacado::Fad::SFad<double,2> v2Var( numDeriv, 1, v2Now );
529 
530  // parameters
531  Sacado::Fad::SFad<double,2> cMemVar( model_.cMem );
532 
533  Sacado::Fad::SFad<double,2> resultFad;
534  resultFad = kcl1EquQ( v1Var, v2Var, cMemVar );
535  kcl1Qvalue = resultFad.val();
536  dkcl1Q_dV1 = resultFad.dx(0);
537  dkcl1Q_dV2 = resultFad.dx(1);
538 
539  resultFad = kcl2EquQ( v1Var, v2Var, cMemVar );
540  kcl2Qvalue = resultFad.val();
541  dkcl2Q_dV1 = resultFad.dx(0);
542  dkcl2Q_dV2 = resultFad.dx(1);
543  }
544 
545  // n - equation
546  {
547  const int numDeriv = 3;
548  Sacado::Fad::SFad<double,3> v1Var( numDeriv, 0, v1Now );
549  Sacado::Fad::SFad<double,3> v2Var( numDeriv, 1, v2Now );
550  Sacado::Fad::SFad<double,3> nVar( numDeriv, 2, nNow );
551  // parameter
552  Sacado::Fad::SFad<double,3> vRestVar( model_.vRest );
553 
554  Sacado::Fad::SFad<double,3> resultFad = nEquF( v1Var, v2Var, nVar, vRestVar);
555  nEquFvalue = resultFad.val();
556  dnF_dV1 = resultFad.dx(0);
557  dnF_dV2 = resultFad.dx(1);
558  dnF_dn = resultFad.dx(2);
559  }
560  {
561  const int numDeriv = 1;
562  Sacado::Fad::SFad<double,1> nVar( numDeriv, 0, nNow );
563 
564  Sacado::Fad::SFad<double,1> resultFad = nEquQ( nVar );
565  nEquQvalue = resultFad.val();
566  dnQ_dn = resultFad.dx(0);
567  }
568 
569  // m - equation
570  {
571  const int numDeriv = 3;
572  Sacado::Fad::SFad<double,3> v1Var( numDeriv, 0, v1Now );
573  Sacado::Fad::SFad<double,3> v2Var( numDeriv, 1, v2Now );
574  Sacado::Fad::SFad<double,3> mVar( numDeriv, 2, mNow );
575  // parameter
576  Sacado::Fad::SFad<double,3> vRestVar( model_.vRest );
577 
578  Sacado::Fad::SFad<double,3> resultFad = mEquF( v1Var, v2Var, mVar, vRestVar );
579  mEquFvalue = resultFad.val();
580  dmF_dV1 = resultFad.dx(0);
581  dmF_dV2 = resultFad.dx(1);
582  dmF_dm = resultFad.dx(2);
583  }
584  {
585  const int numDeriv = 1;
586  Sacado::Fad::SFad<double,1> mVar( numDeriv, 0, mNow );
587 
588  Sacado::Fad::SFad<double,1> resultFad = mEquQ( mVar );
589  mEquQvalue = resultFad.val();
590  dmQ_dm = resultFad.dx(0);
591  }
592 
593  // h - equation
594  {
595  const int numDeriv = 3;
596  Sacado::Fad::SFad<double,3> v1Var( numDeriv, 0, v1Now );
597  Sacado::Fad::SFad<double,3> v2Var( numDeriv, 1, v2Now );
598  Sacado::Fad::SFad<double,3> hVar( numDeriv, 2, hNow );
599  // parameter
600  Sacado::Fad::SFad<double,3> vRestVar( model_.vRest );
601 
602  Sacado::Fad::SFad<double,3> resultFad = hEquF( v1Var, v2Var, hVar, vRestVar );
603  hEquFvalue = resultFad.val();
604  dhF_dV1 = resultFad.dx(0);
605  dhF_dV2 = resultFad.dx(1);
606  dhF_dh = resultFad.dx(2);
607  }
608  {
609  const int numDeriv = 1;
610  Sacado::Fad::SFad<double,1> hVar( numDeriv, 0, hNow );
611 
612  Sacado::Fad::SFad<double,1> resultFad = hEquQ( hVar );
613  hEquQvalue = resultFad.val();
614  dhQ_dh = resultFad.dx(0);
615  }
616 
617  // calculate potassium current
618  potassiumCurrent = model_.gK * pow(nNow, 4.0) * (v1Now - v2Now - model_.eK);
619 
620  // calculate sodium current
621  sodiumCurrent = model_.gNa * pow(mNow, 3.0) * hNow * (v1Now - v2Now - model_.eNa);
622 
623 #ifdef Xyce_DEBUG_DEVICE
625  {
626  double vRest = model_.vRest;
627  Xyce::dout() << "Instance::updateIntermediateVars()" << std::endl
628  << "vRest(input) = " << vRest << std::endl
629  << "v1 = " << v1Now << std::endl
630  << "v2 = " << v2Now << std::endl
631  << "nNow = " << nNow << std::endl
632  << "mNow = " << mNow << std::endl
633  << "hNow = " << hNow << std::endl
634  << "kcl1Fvalue = " << kcl1Fvalue << std::endl
635  << "dkcl1F_dV1 = " << dkcl1F_dV1 << std::endl
636  << "dkcl1F_dV2 = " << dkcl1F_dV2 << std::endl
637  << "dkcl1F_dn = " << dkcl1F_dn << std::endl
638  << "dkcl1F_dm = " << dkcl1F_dm << std::endl
639  << "dkcl1F_dh = " << dkcl1F_dh << std::endl
640  << "kcl2Fvalue = " << kcl2Fvalue << std::endl
641  << "dkcl2F_dV1 = " << dkcl2F_dV1 << std::endl
642  << "dkcl2F_dV2 = " << dkcl2F_dV2 << std::endl
643  << "dkcl2F_dn = " << dkcl2F_dn << std::endl
644  << "dkcl2F_dm = " << dkcl2F_dm << std::endl
645  << "dkcl2F_dh = " << dkcl2F_dh << std::endl
646  << "alphaN = " << alphaN<double>( v1Now, v2Now, vRest) << std::endl
647  << "betaN = " << betaN<double>( v1Now, v2Now, vRest) << std::endl
648  << "nEquFvalue = " << nEquFvalue << std::endl
649  << "dnF_dV1 = " << dnF_dV1 << std::endl
650  << "dnF_dV2 = " << dnF_dV2 << std::endl
651  << "dnF_dn = " << dnF_dn << std::endl
652  << "nEquQvalue = " << nEquQvalue << std::endl
653  << "dnQ_dn = " << dnQ_dn << std::endl
654  << "alphaM = " << alphaM<double>( v1Now, v2Now, vRest) << std::endl
655  << "betaM = " << betaM<double>( v1Now, v2Now, vRest) << std::endl
656  << "mEquFvalue = " << mEquFvalue << std::endl
657  << "dmF_dV1 = " << dmF_dV1 << std::endl
658  << "dmF_dV2 = " << dmF_dV2 << std::endl
659  << "dmF_dm = " << dmF_dm << std::endl
660  << "mEquQvalue = " << mEquQvalue << std::endl
661  << "dmQ_dm = " << dmQ_dm << std::endl
662  << "alphaH = " << alphaH<double>( v1Now, v2Now, vRest) << std::endl
663  << "betaH = " << betaH<double>( v1Now, v2Now, vRest) << std::endl
664  << "hEquFvalue = " << hEquFvalue << std::endl
665  << "dhF_dV1 = " << dhF_dV1 << std::endl
666  << "dhF_dV2 = " << dhF_dV2 << std::endl
667  << "dhF_dh = " << dhF_dh << std::endl
668  << "hEquQvalue = " << hEquQvalue << std::endl
669  << "dhQ_dh = " << dhQ_dh << std::endl
670  << std::endl;
671  }
672 #endif
673 
674  return bsuccess;
675 }
676 //-----------------------------------------------------------------------------
677 // Function : Instance::updatePrimaryState
678 // Purpose :
679 // Special Notes :
680 // Scope : public
681 // Creator : Richard Schiek, Electrical and Microsytem Modeling
682 // Creation Date : 01/02/08
683 //-----------------------------------------------------------------------------
685 {
686  bool bsuccess = true;
687 
689 
690  N_LAS_Vector * solVectorPtr = extData.nextSolVectorPtr;
691  N_LAS_Vector * staVectorPtr = extData.nextStaVectorPtr;
692 
693  (*staVectorPtr)[li_KCurrentState] = potassiumCurrent;
694  (*staVectorPtr)[li_NaCurrentState] = sodiumCurrent;
695 
696  return bsuccess;
697 }
698 
699 //-----------------------------------------------------------------------------
700 // Function : Instance::updateSecondaryState
701 // Purpose :
702 // Special Notes :
703 // Scope : public
704 // Creator : Richard Schiek, Electrical and Microsytem Modeling
705 // Creation Date : 01/02/08
706 //-----------------------------------------------------------------------------
708 {
709  bool bsuccess = true;
710  N_LAS_Vector * staVectorPtr = extData.nextStaVectorPtr;
711 
712  return bsuccess;
713 }
714 
715 //-----------------------------------------------------------------------------
716 // Function : Instance::loadDAEQVector
717 //
718 // Purpose : Loads the Q-vector contributions for a single
719 // Neuron instance.
720 //
721 // Special Notes : The "Q" vector is part of a standard DAE formalism in
722 // which the system of equations is represented as:
723 //
724 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
725 //
726 // Scope : public
727 // Creator : Richard Schiek, Electrical and Microsytem Modeling
728 // Creation Date : 01/02/08
729 //-----------------------------------------------------------------------------
731 {
732  bool bsuccess = true;
733 
734  N_LAS_Vector * daeQVecPtr = extData.daeQVectorPtr;
735 
736  (*daeQVecPtr)[li_Pos] += kcl1Qvalue;
737  (*daeQVecPtr)[li_Neg] += kcl2Qvalue;
738  (*daeQVecPtr)[li_nPro] += nEquQvalue;
739  (*daeQVecPtr)[li_mPro] += mEquQvalue;
740  (*daeQVecPtr)[li_hPro] += hEquQvalue;
741 
742  return bsuccess;
743 }
744 
745 
746 
747 //-----------------------------------------------------------------------------
748 // Function : Instance::loadDAEFVector
749 //
750 // Purpose : Loads the F-vector contributions for a single
751 // Neuron instance.
752 //
753 // Special Notes :
754 //
755 //
756 // Scope : public
757 // Creator : Richard Schiek, Electrical and Microsytem Modeling
758 // Creation Date : 01/02/08
759 //-----------------------------------------------------------------------------
761 {
762  bool bsuccess=true;
763 
764  N_LAS_Vector * daeFVecPtr = extData.daeFVectorPtr;
765 
766  (*daeFVecPtr)[li_Pos] += kcl1Fvalue;
767  (*daeFVecPtr)[li_Neg] += kcl2Fvalue;
768  (*daeFVecPtr)[li_nPro] += nEquFvalue;
769  (*daeFVecPtr)[li_mPro] += mEquFvalue;
770  (*daeFVecPtr)[li_hPro] += hEquFvalue;
771 
772  return bsuccess;
773 }
774 
775 //-----------------------------------------------------------------------------
776 // Function : Instance::loadDAEdQdx
777 //
778 // Purpose : Loads the Q-vector contributions for a single
779 // Neuron instance.
780 // Scope : public
781 // Creator : Richard Schiek, Electrical and Microsytem Modeling
782 // Creation Date : 01/02/08
783 //-----------------------------------------------------------------------------
785 {
786  bool bsuccess = true;
787 
788  N_LAS_Matrix * dQdxMatPtr = extData.dQdxMatrixPtr;
789 
790  (*dQdxMatPtr)[li_Pos][APosEquPosNodeOffset] += dkcl1Q_dV1;
791  (*dQdxMatPtr)[li_Pos][APosEquNegNodeOffset] += dkcl1Q_dV2;
792 
793  (*dQdxMatPtr)[li_Neg][ANegEquPosNodeOffset] += dkcl2Q_dV1;
794  (*dQdxMatPtr)[li_Neg][ANegEquNegNodeOffset] += dkcl2Q_dV2;
795 
796  (*dQdxMatPtr)[li_nPro][ANEquNNodeOffset] += dnQ_dn;
797 
798  (*dQdxMatPtr)[li_mPro][AMEquMNodeOffset] += dmQ_dm;
799 
800  (*dQdxMatPtr)[li_hPro][AHEquHNodeOffset] += dhQ_dh;
801 
802  return bsuccess;
803 }
804 
805 
806 
807 //-----------------------------------------------------------------------------
808 // Function : Instance::loadDAEdFdx ()
809 //
810 // Purpose : Loads the F-vector contributions for a single
811 // Neuron instance.
812 //
813 // Special Notes : This is an algebraic constaint.
814 //
815 // Scope : public
816 // Creator : Richard Schiek, Electrical and Microsytem Modeling
817 // Creation Date : 01/02/08
818 //-----------------------------------------------------------------------------
820 {
821  bool bsuccess = true;
822 
823  N_LAS_Matrix * dFdxMatPtr = extData.dFdxMatrixPtr;
824 
825  (*dFdxMatPtr)[li_Pos][APosEquPosNodeOffset] += dkcl1F_dV1;
826  (*dFdxMatPtr)[li_Pos][APosEquNegNodeOffset] += dkcl1F_dV2;
827  (*dFdxMatPtr)[li_Pos][APosEquNNodeOffset] += dkcl1F_dn;
828  (*dFdxMatPtr)[li_Pos][APosEquMNodeOffset] += dkcl1F_dm;
829  (*dFdxMatPtr)[li_Pos][APosEquHNodeOffset] += dkcl1F_dh;
830 
831  (*dFdxMatPtr)[li_Neg][ANegEquPosNodeOffset] += dkcl2F_dV1;
832  (*dFdxMatPtr)[li_Neg][ANegEquNegNodeOffset] += dkcl2F_dV2;
833  (*dFdxMatPtr)[li_Neg][ANegEquNNodeOffset] += dkcl2F_dn;
834  (*dFdxMatPtr)[li_Neg][ANegEquMNodeOffset] += dkcl2F_dm;
835  (*dFdxMatPtr)[li_Neg][ANegEquHNodeOffset] += dkcl2F_dh;
836 
837  (*dFdxMatPtr)[li_nPro][ANEquPosNodeOffset] += dnF_dV1;
838  (*dFdxMatPtr)[li_nPro][ANEquNegNodeOffset] += dnF_dV2;
839  (*dFdxMatPtr)[li_nPro][ANEquNNodeOffset] += dnF_dn;
840 
841  (*dFdxMatPtr)[li_mPro][AMEquPosNodeOffset] += dmF_dV1;
842  (*dFdxMatPtr)[li_mPro][AMEquNegNodeOffset] += dmF_dV2;
843  (*dFdxMatPtr)[li_mPro][AMEquMNodeOffset] += dmF_dm;
844 
845  (*dFdxMatPtr)[li_hPro][AHEquPosNodeOffset] += dhF_dV1;
846  (*dFdxMatPtr)[li_hPro][AHEquNegNodeOffset] += dhF_dV2;
847  (*dFdxMatPtr)[li_hPro][AHEquHNodeOffset] += dhF_dh;
848 
849  return bsuccess;
850 }
851 
852 //-----------------------------------------------------------------------------
853 // Function : Instance::setIC
854 // Purpose :
855 // Special Notes :
856 // Scope : public
857 // Creator : Richard Schiek, Electrical and Microsytem Modeling
858 // Creation Date : 01/02/08
859 //-----------------------------------------------------------------------------
861 {
862  bool bsuccess = true;
863 
864  return bsuccess;
865 }
866 
867 //-----------------------------------------------------------------------------
868 // Function : Instance::varTypes
869 // Purpose :
870 // Special Notes :
871 // Scope : public
872 // Creator : Richard Schiek, Electrical and Microsytem Modeling
873 // Creation Date : 01/02/08
874 //-----------------------------------------------------------------------------
875 void Instance::varTypes( std::vector<char> & varTypeVec )
876 {
877  //varTypeVec.resize(1);
878  //varTypeVec[0] = 'I';
879 }
880 
881 
882 //-----------------------------------------------------------------------------
883 // Function : Model::processParams
884 // Purpose :
885 // Special Notes :
886 // Scope : public
887 // Creator : Richard Schiek, Electrical and Microsytem Modeling
888 // Creation Date : 01/02/08
889 //-----------------------------------------------------------------------------
891 {
892  return true;
893 }
894 
895 //----------------------------------------------------------------------------
896 // Function : Model::processInstanceParams
897 // Purpose :
898 // Special Notes :
899 // Scope : public
900 // Creator : Richard Schiek, Electrical and Microsytem Modeling
901 // Creation Date : 01/02/08
902 //----------------------------------------------------------------------------
904 {
905 
906  std::vector<Instance*>::iterator iter;
907  std::vector<Instance*>::iterator first = instanceContainer.begin();
908  std::vector<Instance*>::iterator last = instanceContainer.end();
909 
910  for (iter=first; iter!=last; ++iter)
911  {
912  (*iter)->processParams();
913  }
914 
915  return true;
916 }
917 
918 //-----------------------------------------------------------------------------
919 // Function : Model::Model
920 // Purpose : block constructor
921 // Special Notes :
922 // Scope : public
923 // Creator : Richard Schiek, Electrical and Microsytem Modeling
924 // Creation Date : 01/02/08
925 //-----------------------------------------------------------------------------
927  const Configuration & configuration,
928  const ModelBlock & MB,
929  const FactoryBlock & factory_block)
930  : DeviceModel(MB, configuration.getModelParameters(), factory_block)
931 {
932 
933  // Set params to constant default values:
934  setDefaultParams ();
935 
936  // Set params according to .model line and constant defaults from metadata:
937  setModParams (MB.params);
938 
939  // Set any non-constant parameter defaults:
940  //if (!given("TNOM"))
941  // tnom = getDeviceOptions().tnom;
942 
943  // Calculate any parameters specified as expressions:
945 
946  // calculate dependent (ie computed) params and check for errors:
947 
948  processParams ();
949 }
950 
951 //-----------------------------------------------------------------------------
952 // Function : Model::~Model
953 // Purpose : destructor
954 // Special Notes :
955 // Scope : public
956 // Creator : Richard Schiek, Electrical and Microsytem Modeling
957 // Creation Date : 01/02/08
958 //-----------------------------------------------------------------------------
960 {
961  std::vector<Instance*>::iterator iter;
962  std::vector<Instance*>::iterator first = instanceContainer.begin();
963  std::vector<Instance*>::iterator last = instanceContainer.end();
964 
965  for (iter=first; iter!=last; ++iter)
966  {
967  delete (*iter);
968  }
969 }
970 
971 // additional Declarations
972 
973 //-----------------------------------------------------------------------------
974 // Function : Model::printOutInstances
975 // Purpose : debugging tool.
976 // Special Notes :
977 // Scope : public
978 // Creator : Richard Schiek, Electrical and Microsytem Modeling
979 // Creation Date : 01/02/08
980 //-----------------------------------------------------------------------------
981 std::ostream &Model::printOutInstances(std::ostream &os) const
982 {
983  std::vector<Instance*>::const_iterator iter;
984  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
985  std::vector<Instance*>::const_iterator last = instanceContainer.end();
986 
987  int i, isize;
988  isize = instanceContainer.size();
989 
990  os << std::endl;
991  os << "Number of Neuron instances: " << isize << std::endl;
992  os << " name=\t\tmodelName\tParameters" << std::endl;
993  for (i=0, iter=first; iter!=last; ++iter, ++i)
994  {
995  os << " " << i << ": " << (*iter)->getName() << "\t";
996  os << getName();
997  os << std::endl;
998  }
999 
1000  os << std::endl;
1001  return os;
1002 }
1003 
1004 //-----------------------------------------------------------------------------
1005 // Function : Model::forEachInstance
1006 // Purpose :
1007 // Special Notes :
1008 // Scope : public
1009 // Creator : David Baur
1010 // Creation Date : 2/4/2014
1011 //-----------------------------------------------------------------------------
1012 /// Apply a device instance "op" to all instances associated with this
1013 /// model
1014 ///
1015 /// @param[in] op Operator to apply to all instances.
1016 ///
1017 ///
1018 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
1019 {
1020  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1021  op(*it);
1022 }
1023 
1024 
1025 
1026 //-----------------------------------------------------------------------------
1027 // Function : Master::updateState
1028 // Purpose :
1029 // Special Notes :
1030 // Scope : public
1031 // Creator : Richard Schiek, SNL
1032 // Creation Date : 06/01/12
1033 //-----------------------------------------------------------------------------
1034 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
1035 {
1036  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1037  {
1038  (*it)->updatePrimaryState();
1039  }
1040 
1041  return true;
1042 }
1043 
1044 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
1045 {
1046 
1047  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
1048 }
1049 
1051 {
1053  .registerDevice("neuron", 1)
1054  .registerModelType("neuron", 1);
1055 }
1056 
1057 } // namespace Neuron
1058 } // namespace Device
1059 } // namespace Xyce