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.53.2.2 $
40 //
41 // Revision Date : $Date: 2014/03/06 23:33:43 $
42 //
43 // Current Owner : $Author: tvrusso $
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  {
353  std::string tmpstr;
354 
355  tmpstr = getName() + "_N";
356  spiceInternalName (tmpstr);
357  intNameMap[ li_nPro ] = tmpstr;
358  tmpstr = getName() + "_M";
359  spiceInternalName (tmpstr);
360  intNameMap[ li_mPro ] = tmpstr;
361  tmpstr = getName() + "_H";
362  spiceInternalName (tmpstr);
363  intNameMap[ li_hPro ] = tmpstr;
364  }
365  return intNameMap;
366 }
367 
368 //-----------------------------------------------------------------------------
369 // Function : Instance::registerStateLIDs
370 // Purpose :
371 // Special Notes :
372 // Scope : public
373 // Creator : Richard Schiek, Electrical and Microsytem Modeling
374 // Creation Date : 01/02/08
375 //-----------------------------------------------------------------------------
376 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
377 {
378  AssertLIDs(staLIDVecRef.size() == numStateVars);
379 
380  // copy over the global ID lists.
381  staLIDVec = staLIDVecRef;
382 
383  li_KCurrentState = staLIDVec[0];
384  li_NaCurrentState = staLIDVec[1];
385 
386 }
387 
388 //-----------------------------------------------------------------------------
389 // Function : Instance::loadDeviceMask
390 //
391 // Purpose : Loads the zero elements of the device mask
392 //
393 // Special Notes : elements of the error vector associated with zero
394 // elements of the mask will not be included in weighted
395 // norms by the time integrator.
396 //
397 // Scope : public
398 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
399 // Creation Date : 01/19/07
400 //-----------------------------------------------------------------------------
402 {
403  bool returnVal=false;
404  N_LAS_Vector * maskVectorPtr = extData.deviceMaskVectorPtr;
405 
406 // Xyce::dout() << "Masking n, m and h" << std::endl;
407 // (*maskVectorPtr)[li_nPro] = 0.0;
408 // (*maskVectorPtr)[li_mPro] = 0.0;
409 // (*maskVectorPtr)[li_hPro] = 0.0;
410 // returnVal = true;
411 
412  return (returnVal);
413 }
414 
415 //-----------------------------------------------------------------------------
416 // Function : Instance::jacobianStamp
417 // Purpose :
418 // Special Notes :
419 // Scope : public
420 // Creator : Richard Schiek, Electrical and Microsytem Modeling
421 // Creation Date : 01/02/08
422 //-----------------------------------------------------------------------------
423 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
424 {
425  return jacStamp;
426 }
427 
428 //-----------------------------------------------------------------------------
429 // Function : Instance::registerJacLIDs
430 // Purpose :
431 // Special Notes :
432 // Scope : public
433 // Creator : Richard Schiek, Electrical and Microsytem Modeling
434 // Creation Date : 01/02/08
435 //-----------------------------------------------------------------------------
436 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
437 {
438  DeviceInstance::registerJacLIDs( jacLIDVec );
439 
440  APosEquPosNodeOffset = jacLIDVec[0][0];
441  APosEquNegNodeOffset = jacLIDVec[0][1];
442  APosEquNNodeOffset = jacLIDVec[0][2];
443  APosEquMNodeOffset = jacLIDVec[0][3];
444  APosEquHNodeOffset = jacLIDVec[0][4];
445 
446  ANegEquPosNodeOffset = jacLIDVec[1][0];
447  ANegEquNegNodeOffset = jacLIDVec[1][1];
448  ANegEquNNodeOffset = jacLIDVec[1][2];
449  ANegEquMNodeOffset = jacLIDVec[1][3];
450  ANegEquHNodeOffset = jacLIDVec[1][4];
451 
452  ANEquPosNodeOffset = jacLIDVec[2][0];
453  ANEquNegNodeOffset = jacLIDVec[2][1];
454  ANEquNNodeOffset = jacLIDVec[2][2];
455 
456  AMEquPosNodeOffset = jacLIDVec[3][0];
457  AMEquNegNodeOffset = jacLIDVec[3][1];
458  AMEquMNodeOffset = jacLIDVec[3][2];
459 
460  AHEquPosNodeOffset = jacLIDVec[4][0];
461  AHEquNegNodeOffset = jacLIDVec[4][1];
462  AHEquHNodeOffset = jacLIDVec[4][2];
463 }
464 
465 
466 //-----------------------------------------------------------------------------
467 // Function : Instance::updateIntermediateVars
468 // Purpose :
469 // Special Notes :
470 // Scope : public
471 // Creator : Richard Schiek, Electrical and Microsytem Modeling
472 // Creation Date : 01/02/08
473 //-----------------------------------------------------------------------------
475 {
476  //Xyce::dout() << "Instance::updateIntermediateVars()" << std::endl;
477 
478  bool bsuccess = true;
479 
480  // here we take the current solutions for V1, V2, n, m and h
481  // and use those to calculate all the terms needed for the next
482  // load cycle (F, Q, dFdX, dQdX)
483  N_LAS_Vector * solVectorPtr = extData.nextSolVectorPtr;
484 
485  // use suffix "now" to to clarify that this for the latest solution
486  double v1Now = (*solVectorPtr)[li_Pos];
487  double v2Now = (*solVectorPtr)[li_Neg];
488  double nNow = (*solVectorPtr)[li_nPro];
489  double mNow = (*solVectorPtr)[li_mPro];
490  double hNow = (*solVectorPtr)[li_hPro];
491 
492  // get function and derivative values
493  // independent variables
494  // use scoping to avoid lots of similar variable names
495 
496  // kcl F
497  {
498  const int numDeriv = 5;
499  Sacado::Fad::SFad<double,5> v1Var( numDeriv, 0, v1Now );
500  Sacado::Fad::SFad<double,5> v2Var( numDeriv, 1, v2Now );
501  Sacado::Fad::SFad<double,5> nVar( numDeriv, 2, nNow );
502  Sacado::Fad::SFad<double,5> mVar( numDeriv, 3, mNow );
503  Sacado::Fad::SFad<double,5> hVar( numDeriv, 4, hNow );
504  // parameters
505  Sacado::Fad::SFad<double,5> gMemVar( model_.gMem );
506  Sacado::Fad::SFad<double,5> eLeakVar( model_.eLeak );
507  Sacado::Fad::SFad<double,5> gKVar( model_.gK );
508  Sacado::Fad::SFad<double,5> eKVar( model_.eK );
509  Sacado::Fad::SFad<double,5> gNaVar( model_.gNa );
510  Sacado::Fad::SFad<double,5> eNaVar( model_.eNa );
511 
512  // compute the vaud and derivative terms for KCL 1 F
513  Sacado::Fad::SFad<double,5> resultFad;
514  resultFad = kcl1EquF( v1Var, v2Var, nVar, mVar, hVar, gMemVar, eLeakVar, gKVar, eKVar, gNaVar, eNaVar );
515  kcl1Fvalue = resultFad.val();
516  dkcl1F_dV1 = resultFad.dx(0);
517  dkcl1F_dV2 = resultFad.dx(1);
518  dkcl1F_dn = resultFad.dx(2);
519  dkcl1F_dm = resultFad.dx(3);
520  dkcl1F_dh = resultFad.dx(4);
521 
522  // compute the vaud and derivative terms for KCL 2 F
523  resultFad = kcl2EquF( v1Var, v2Var, nVar, mVar, hVar, gMemVar, eLeakVar, gKVar, eKVar, gNaVar, eNaVar );
524  kcl2Fvalue = resultFad.val();
525  dkcl2F_dV1 = resultFad.dx(0);
526  dkcl2F_dV2 = resultFad.dx(1);
527  dkcl2F_dn = resultFad.dx(2);
528  dkcl2F_dm = resultFad.dx(3);
529  dkcl2F_dh = resultFad.dx(4);
530  }
531 
532  // kcl Q
533  {
534  const int numDeriv = 2;
535  Sacado::Fad::SFad<double,2> v1Var( numDeriv, 0, v1Now );
536  Sacado::Fad::SFad<double,2> v2Var( numDeriv, 1, v2Now );
537 
538  // parameters
539  Sacado::Fad::SFad<double,2> cMemVar( model_.cMem );
540 
541  Sacado::Fad::SFad<double,2> resultFad;
542  resultFad = kcl1EquQ( v1Var, v2Var, cMemVar );
543  kcl1Qvalue = resultFad.val();
544  dkcl1Q_dV1 = resultFad.dx(0);
545  dkcl1Q_dV2 = resultFad.dx(1);
546 
547  resultFad = kcl2EquQ( v1Var, v2Var, cMemVar );
548  kcl2Qvalue = resultFad.val();
549  dkcl2Q_dV1 = resultFad.dx(0);
550  dkcl2Q_dV2 = resultFad.dx(1);
551  }
552 
553  // n - equation
554  {
555  const int numDeriv = 3;
556  Sacado::Fad::SFad<double,3> v1Var( numDeriv, 0, v1Now );
557  Sacado::Fad::SFad<double,3> v2Var( numDeriv, 1, v2Now );
558  Sacado::Fad::SFad<double,3> nVar( numDeriv, 2, nNow );
559  // parameter
560  Sacado::Fad::SFad<double,3> vRestVar( model_.vRest );
561 
562  Sacado::Fad::SFad<double,3> resultFad = nEquF( v1Var, v2Var, nVar, vRestVar);
563  nEquFvalue = resultFad.val();
564  dnF_dV1 = resultFad.dx(0);
565  dnF_dV2 = resultFad.dx(1);
566  dnF_dn = resultFad.dx(2);
567  }
568  {
569  const int numDeriv = 1;
570  Sacado::Fad::SFad<double,1> nVar( numDeriv, 0, nNow );
571 
572  Sacado::Fad::SFad<double,1> resultFad = nEquQ( nVar );
573  nEquQvalue = resultFad.val();
574  dnQ_dn = resultFad.dx(0);
575  }
576 
577  // m - equation
578  {
579  const int numDeriv = 3;
580  Sacado::Fad::SFad<double,3> v1Var( numDeriv, 0, v1Now );
581  Sacado::Fad::SFad<double,3> v2Var( numDeriv, 1, v2Now );
582  Sacado::Fad::SFad<double,3> mVar( numDeriv, 2, mNow );
583  // parameter
584  Sacado::Fad::SFad<double,3> vRestVar( model_.vRest );
585 
586  Sacado::Fad::SFad<double,3> resultFad = mEquF( v1Var, v2Var, mVar, vRestVar );
587  mEquFvalue = resultFad.val();
588  dmF_dV1 = resultFad.dx(0);
589  dmF_dV2 = resultFad.dx(1);
590  dmF_dm = resultFad.dx(2);
591  }
592  {
593  const int numDeriv = 1;
594  Sacado::Fad::SFad<double,1> mVar( numDeriv, 0, mNow );
595 
596  Sacado::Fad::SFad<double,1> resultFad = mEquQ( mVar );
597  mEquQvalue = resultFad.val();
598  dmQ_dm = resultFad.dx(0);
599  }
600 
601  // h - equation
602  {
603  const int numDeriv = 3;
604  Sacado::Fad::SFad<double,3> v1Var( numDeriv, 0, v1Now );
605  Sacado::Fad::SFad<double,3> v2Var( numDeriv, 1, v2Now );
606  Sacado::Fad::SFad<double,3> hVar( numDeriv, 2, hNow );
607  // parameter
608  Sacado::Fad::SFad<double,3> vRestVar( model_.vRest );
609 
610  Sacado::Fad::SFad<double,3> resultFad = hEquF( v1Var, v2Var, hVar, vRestVar );
611  hEquFvalue = resultFad.val();
612  dhF_dV1 = resultFad.dx(0);
613  dhF_dV2 = resultFad.dx(1);
614  dhF_dh = resultFad.dx(2);
615  }
616  {
617  const int numDeriv = 1;
618  Sacado::Fad::SFad<double,1> hVar( numDeriv, 0, hNow );
619 
620  Sacado::Fad::SFad<double,1> resultFad = hEquQ( hVar );
621  hEquQvalue = resultFad.val();
622  dhQ_dh = resultFad.dx(0);
623  }
624 
625  // calculate potassium current
626  potassiumCurrent = model_.gK * pow(nNow, 4.0) * (v1Now - v2Now - model_.eK);
627 
628  // calculate sodium current
629  sodiumCurrent = model_.gNa * pow(mNow, 3.0) * hNow * (v1Now - v2Now - model_.eNa);
630 
631 #ifdef Xyce_DEBUG_DEVICE
633  {
634  double vRest = model_.vRest;
635  Xyce::dout() << "Instance::updateIntermediateVars()" << std::endl
636  << "vRest(input) = " << vRest << std::endl
637  << "v1 = " << v1Now << std::endl
638  << "v2 = " << v2Now << std::endl
639  << "nNow = " << nNow << std::endl
640  << "mNow = " << mNow << std::endl
641  << "hNow = " << hNow << std::endl
642  << "kcl1Fvalue = " << kcl1Fvalue << std::endl
643  << "dkcl1F_dV1 = " << dkcl1F_dV1 << std::endl
644  << "dkcl1F_dV2 = " << dkcl1F_dV2 << std::endl
645  << "dkcl1F_dn = " << dkcl1F_dn << std::endl
646  << "dkcl1F_dm = " << dkcl1F_dm << std::endl
647  << "dkcl1F_dh = " << dkcl1F_dh << std::endl
648  << "kcl2Fvalue = " << kcl2Fvalue << std::endl
649  << "dkcl2F_dV1 = " << dkcl2F_dV1 << std::endl
650  << "dkcl2F_dV2 = " << dkcl2F_dV2 << std::endl
651  << "dkcl2F_dn = " << dkcl2F_dn << std::endl
652  << "dkcl2F_dm = " << dkcl2F_dm << std::endl
653  << "dkcl2F_dh = " << dkcl2F_dh << std::endl
654  << "alphaN = " << alphaN<double>( v1Now, v2Now, vRest) << std::endl
655  << "betaN = " << betaN<double>( v1Now, v2Now, vRest) << std::endl
656  << "nEquFvalue = " << nEquFvalue << std::endl
657  << "dnF_dV1 = " << dnF_dV1 << std::endl
658  << "dnF_dV2 = " << dnF_dV2 << std::endl
659  << "dnF_dn = " << dnF_dn << std::endl
660  << "nEquQvalue = " << nEquQvalue << std::endl
661  << "dnQ_dn = " << dnQ_dn << std::endl
662  << "alphaM = " << alphaM<double>( v1Now, v2Now, vRest) << std::endl
663  << "betaM = " << betaM<double>( v1Now, v2Now, vRest) << std::endl
664  << "mEquFvalue = " << mEquFvalue << std::endl
665  << "dmF_dV1 = " << dmF_dV1 << std::endl
666  << "dmF_dV2 = " << dmF_dV2 << std::endl
667  << "dmF_dm = " << dmF_dm << std::endl
668  << "mEquQvalue = " << mEquQvalue << std::endl
669  << "dmQ_dm = " << dmQ_dm << std::endl
670  << "alphaH = " << alphaH<double>( v1Now, v2Now, vRest) << std::endl
671  << "betaH = " << betaH<double>( v1Now, v2Now, vRest) << std::endl
672  << "hEquFvalue = " << hEquFvalue << std::endl
673  << "dhF_dV1 = " << dhF_dV1 << std::endl
674  << "dhF_dV2 = " << dhF_dV2 << std::endl
675  << "dhF_dh = " << dhF_dh << std::endl
676  << "hEquQvalue = " << hEquQvalue << std::endl
677  << "dhQ_dh = " << dhQ_dh << std::endl
678  << std::endl;
679  }
680 #endif
681 
682  return bsuccess;
683 }
684 //-----------------------------------------------------------------------------
685 // Function : Instance::updatePrimaryState
686 // Purpose :
687 // Special Notes :
688 // Scope : public
689 // Creator : Richard Schiek, Electrical and Microsytem Modeling
690 // Creation Date : 01/02/08
691 //-----------------------------------------------------------------------------
693 {
694  bool bsuccess = true;
695 
697 
698  N_LAS_Vector * solVectorPtr = extData.nextSolVectorPtr;
699  N_LAS_Vector * staVectorPtr = extData.nextStaVectorPtr;
700 
701  (*staVectorPtr)[li_KCurrentState] = potassiumCurrent;
702  (*staVectorPtr)[li_NaCurrentState] = sodiumCurrent;
703 
704  return bsuccess;
705 }
706 
707 //-----------------------------------------------------------------------------
708 // Function : Instance::updateSecondaryState
709 // Purpose :
710 // Special Notes :
711 // Scope : public
712 // Creator : Richard Schiek, Electrical and Microsytem Modeling
713 // Creation Date : 01/02/08
714 //-----------------------------------------------------------------------------
716 {
717  bool bsuccess = true;
718  N_LAS_Vector * staVectorPtr = extData.nextStaVectorPtr;
719 
720  return bsuccess;
721 }
722 
723 //-----------------------------------------------------------------------------
724 // Function : Instance::loadDAEQVector
725 //
726 // Purpose : Loads the Q-vector contributions for a single
727 // Neuron instance.
728 //
729 // Special Notes : The "Q" vector is part of a standard DAE formalism in
730 // which the system of equations is represented as:
731 //
732 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
733 //
734 // Scope : public
735 // Creator : Richard Schiek, Electrical and Microsytem Modeling
736 // Creation Date : 01/02/08
737 //-----------------------------------------------------------------------------
739 {
740  bool bsuccess = true;
741 
742  N_LAS_Vector * daeQVecPtr = extData.daeQVectorPtr;
743 
744  (*daeQVecPtr)[li_Pos] += kcl1Qvalue;
745  (*daeQVecPtr)[li_Neg] += kcl2Qvalue;
746  (*daeQVecPtr)[li_nPro] += nEquQvalue;
747  (*daeQVecPtr)[li_mPro] += mEquQvalue;
748  (*daeQVecPtr)[li_hPro] += hEquQvalue;
749 
750  return bsuccess;
751 }
752 
753 
754 
755 //-----------------------------------------------------------------------------
756 // Function : Instance::loadDAEFVector
757 //
758 // Purpose : Loads the F-vector contributions for a single
759 // Neuron instance.
760 //
761 // Special Notes :
762 //
763 //
764 // Scope : public
765 // Creator : Richard Schiek, Electrical and Microsytem Modeling
766 // Creation Date : 01/02/08
767 //-----------------------------------------------------------------------------
769 {
770  bool bsuccess=true;
771 
772  N_LAS_Vector * daeFVecPtr = extData.daeFVectorPtr;
773 
774  (*daeFVecPtr)[li_Pos] += kcl1Fvalue;
775  (*daeFVecPtr)[li_Neg] += kcl2Fvalue;
776  (*daeFVecPtr)[li_nPro] += nEquFvalue;
777  (*daeFVecPtr)[li_mPro] += mEquFvalue;
778  (*daeFVecPtr)[li_hPro] += hEquFvalue;
779 
780  return bsuccess;
781 }
782 
783 //-----------------------------------------------------------------------------
784 // Function : Instance::loadDAEdQdx
785 //
786 // Purpose : Loads the Q-vector contributions for a single
787 // Neuron instance.
788 // Scope : public
789 // Creator : Richard Schiek, Electrical and Microsytem Modeling
790 // Creation Date : 01/02/08
791 //-----------------------------------------------------------------------------
793 {
794  bool bsuccess = true;
795 
796  N_LAS_Matrix * dQdxMatPtr = extData.dQdxMatrixPtr;
797 
798  (*dQdxMatPtr)[li_Pos][APosEquPosNodeOffset] += dkcl1Q_dV1;
799  (*dQdxMatPtr)[li_Pos][APosEquNegNodeOffset] += dkcl1Q_dV2;
800 
801  (*dQdxMatPtr)[li_Neg][ANegEquPosNodeOffset] += dkcl2Q_dV1;
802  (*dQdxMatPtr)[li_Neg][ANegEquNegNodeOffset] += dkcl2Q_dV2;
803 
804  (*dQdxMatPtr)[li_nPro][ANEquNNodeOffset] += dnQ_dn;
805 
806  (*dQdxMatPtr)[li_mPro][AMEquMNodeOffset] += dmQ_dm;
807 
808  (*dQdxMatPtr)[li_hPro][AHEquHNodeOffset] += dhQ_dh;
809 
810  return bsuccess;
811 }
812 
813 
814 
815 //-----------------------------------------------------------------------------
816 // Function : Instance::loadDAEdFdx ()
817 //
818 // Purpose : Loads the F-vector contributions for a single
819 // Neuron instance.
820 //
821 // Special Notes : This is an algebraic constaint.
822 //
823 // Scope : public
824 // Creator : Richard Schiek, Electrical and Microsytem Modeling
825 // Creation Date : 01/02/08
826 //-----------------------------------------------------------------------------
828 {
829  bool bsuccess = true;
830 
831  N_LAS_Matrix * dFdxMatPtr = extData.dFdxMatrixPtr;
832 
833  (*dFdxMatPtr)[li_Pos][APosEquPosNodeOffset] += dkcl1F_dV1;
834  (*dFdxMatPtr)[li_Pos][APosEquNegNodeOffset] += dkcl1F_dV2;
835  (*dFdxMatPtr)[li_Pos][APosEquNNodeOffset] += dkcl1F_dn;
836  (*dFdxMatPtr)[li_Pos][APosEquMNodeOffset] += dkcl1F_dm;
837  (*dFdxMatPtr)[li_Pos][APosEquHNodeOffset] += dkcl1F_dh;
838 
839  (*dFdxMatPtr)[li_Neg][ANegEquPosNodeOffset] += dkcl2F_dV1;
840  (*dFdxMatPtr)[li_Neg][ANegEquNegNodeOffset] += dkcl2F_dV2;
841  (*dFdxMatPtr)[li_Neg][ANegEquNNodeOffset] += dkcl2F_dn;
842  (*dFdxMatPtr)[li_Neg][ANegEquMNodeOffset] += dkcl2F_dm;
843  (*dFdxMatPtr)[li_Neg][ANegEquHNodeOffset] += dkcl2F_dh;
844 
845  (*dFdxMatPtr)[li_nPro][ANEquPosNodeOffset] += dnF_dV1;
846  (*dFdxMatPtr)[li_nPro][ANEquNegNodeOffset] += dnF_dV2;
847  (*dFdxMatPtr)[li_nPro][ANEquNNodeOffset] += dnF_dn;
848 
849  (*dFdxMatPtr)[li_mPro][AMEquPosNodeOffset] += dmF_dV1;
850  (*dFdxMatPtr)[li_mPro][AMEquNegNodeOffset] += dmF_dV2;
851  (*dFdxMatPtr)[li_mPro][AMEquMNodeOffset] += dmF_dm;
852 
853  (*dFdxMatPtr)[li_hPro][AHEquPosNodeOffset] += dhF_dV1;
854  (*dFdxMatPtr)[li_hPro][AHEquNegNodeOffset] += dhF_dV2;
855  (*dFdxMatPtr)[li_hPro][AHEquHNodeOffset] += dhF_dh;
856 
857  return bsuccess;
858 }
859 
860 //-----------------------------------------------------------------------------
861 // Function : Instance::setIC
862 // Purpose :
863 // Special Notes :
864 // Scope : public
865 // Creator : Richard Schiek, Electrical and Microsytem Modeling
866 // Creation Date : 01/02/08
867 //-----------------------------------------------------------------------------
869 {
870  bool bsuccess = true;
871 
872  return bsuccess;
873 }
874 
875 //-----------------------------------------------------------------------------
876 // Function : Instance::varTypes
877 // Purpose :
878 // Special Notes :
879 // Scope : public
880 // Creator : Richard Schiek, Electrical and Microsytem Modeling
881 // Creation Date : 01/02/08
882 //-----------------------------------------------------------------------------
883 void Instance::varTypes( std::vector<char> & varTypeVec )
884 {
885  //varTypeVec.resize(1);
886  //varTypeVec[0] = 'I';
887 }
888 
889 
890 //-----------------------------------------------------------------------------
891 // Function : Model::processParams
892 // Purpose :
893 // Special Notes :
894 // Scope : public
895 // Creator : Richard Schiek, Electrical and Microsytem Modeling
896 // Creation Date : 01/02/08
897 //-----------------------------------------------------------------------------
899 {
900  return true;
901 }
902 
903 //----------------------------------------------------------------------------
904 // Function : Model::processInstanceParams
905 // Purpose :
906 // Special Notes :
907 // Scope : public
908 // Creator : Richard Schiek, Electrical and Microsytem Modeling
909 // Creation Date : 01/02/08
910 //----------------------------------------------------------------------------
912 {
913 
914  std::vector<Instance*>::iterator iter;
915  std::vector<Instance*>::iterator first = instanceContainer.begin();
916  std::vector<Instance*>::iterator last = instanceContainer.end();
917 
918  for (iter=first; iter!=last; ++iter)
919  {
920  (*iter)->processParams();
921  }
922 
923  return true;
924 }
925 
926 //-----------------------------------------------------------------------------
927 // Function : Model::Model
928 // Purpose : block constructor
929 // Special Notes :
930 // Scope : public
931 // Creator : Richard Schiek, Electrical and Microsytem Modeling
932 // Creation Date : 01/02/08
933 //-----------------------------------------------------------------------------
935  const Configuration & configuration,
936  const ModelBlock & MB,
937  const FactoryBlock & factory_block)
938  : DeviceModel(MB, configuration.getModelParameters(), factory_block)
939 {
940 
941  // Set params to constant default values:
942  setDefaultParams ();
943 
944  // Set params according to .model line and constant defaults from metadata:
945  setModParams (MB.params);
946 
947  // Set any non-constant parameter defaults:
948  //if (!given("TNOM"))
949  // tnom = getDeviceOptions().tnom;
950 
951  // Calculate any parameters specified as expressions:
953 
954  // calculate dependent (ie computed) params and check for errors:
955 
956  processParams ();
957 }
958 
959 //-----------------------------------------------------------------------------
960 // Function : Model::~Model
961 // Purpose : destructor
962 // Special Notes :
963 // Scope : public
964 // Creator : Richard Schiek, Electrical and Microsytem Modeling
965 // Creation Date : 01/02/08
966 //-----------------------------------------------------------------------------
968 {
969  std::vector<Instance*>::iterator iter;
970  std::vector<Instance*>::iterator first = instanceContainer.begin();
971  std::vector<Instance*>::iterator last = instanceContainer.end();
972 
973  for (iter=first; iter!=last; ++iter)
974  {
975  delete (*iter);
976  }
977 }
978 
979 // additional Declarations
980 
981 //-----------------------------------------------------------------------------
982 // Function : Model::printOutInstances
983 // Purpose : debugging tool.
984 // Special Notes :
985 // Scope : public
986 // Creator : Richard Schiek, Electrical and Microsytem Modeling
987 // Creation Date : 01/02/08
988 //-----------------------------------------------------------------------------
989 std::ostream &Model::printOutInstances(std::ostream &os) const
990 {
991  std::vector<Instance*>::const_iterator iter;
992  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
993  std::vector<Instance*>::const_iterator last = instanceContainer.end();
994 
995  int i, isize;
996  isize = instanceContainer.size();
997 
998  os << std::endl;
999  os << "Number of Neuron instances: " << isize << std::endl;
1000  os << " name=\t\tmodelName\tParameters" << std::endl;
1001  for (i=0, iter=first; iter!=last; ++iter, ++i)
1002  {
1003  os << " " << i << ": " << (*iter)->getName() << "\t";
1004  os << getName();
1005  os << std::endl;
1006  }
1007 
1008  os << std::endl;
1009  return os;
1010 }
1011 
1012 //-----------------------------------------------------------------------------
1013 // Function : Model::forEachInstance
1014 // Purpose :
1015 // Special Notes :
1016 // Scope : public
1017 // Creator : David Baur
1018 // Creation Date : 2/4/2014
1019 //-----------------------------------------------------------------------------
1020 /// Apply a device instance "op" to all instances associated with this
1021 /// model
1022 ///
1023 /// @param[in] op Operator to apply to all instances.
1024 ///
1025 ///
1026 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
1027 {
1028  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1029  op(*it);
1030 }
1031 
1032 
1033 
1034 //-----------------------------------------------------------------------------
1035 // Function : Master::updateState
1036 // Purpose :
1037 // Special Notes :
1038 // Scope : public
1039 // Creator : Richard Schiek, SNL
1040 // Creation Date : 06/01/12
1041 //-----------------------------------------------------------------------------
1042 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
1043 {
1044  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1045  {
1046  (*it)->updatePrimaryState();
1047  }
1048 
1049  return true;
1050 }
1051 
1052 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
1053 {
1054 
1055  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
1056 }
1057 
1059 {
1061  .registerDevice("neuron", 1)
1062  .registerModelType("neuron", 1);
1063 }
1064 
1065 } // namespace Neuron
1066 } // namespace Device
1067 } // namespace Xyce