Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_Neuron4.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$
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Richard Schiek, Electrical and Microsytem Modeling
33 //
34 // Creation Date : 06/10/09
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision$
40 //
41 // Revision Date : $Date$
42 //
43 // Current Owner : $Author$
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_Neuron4.h>
59 #include <N_DEV_SolverState.h>
60 #include <N_DEV_Message.h>
61 #include <N_ERH_ErrorMgr.h>
62 
63 #include <N_DEV_Neuron.h>
64 
65 #include <N_LAS_Vector.h>
66 #include <N_LAS_Matrix.h>
67 
68 namespace Xyce {
69 namespace Device {
70 
71 
72 namespace Neuron4 {
73 
74 
76 {
77 // Set up map for double precision variables:
78  p.addPar ("R", 0.0, false, ParameterType::NO_DEP,
81  U_OHMMM1, CAT_NONE, "Intracellular resistivity");
82 
83  p.addPar ("A", 0.0, false, ParameterType::NO_DEP,
86  U_METER, CAT_NONE, "Segment radius");
87 
88  p.addPar ("L", 0.0, false, ParameterType::NO_DEP,
91  U_METER, CAT_NONE, "Cable length");
92 
93  p.addPar ("RPS", 1.0e-6, false, ParameterType::NO_DEP,
96  U_OHMMM1, CAT_NONE, "Previous segment, intracellular resistivity");
97 
98  p.addPar ("APS", 0.0, false, ParameterType::NO_DEP,
101  U_METER, CAT_NONE, "Previous segment, segment radius");
102 
103  p.addPar ("LPS", 0.0, false, ParameterType::NO_DEP,
106  U_METER, CAT_NONE, "Previous segment length");
107 
108  p.addPar ("RNS", 1.0e-6, false, ParameterType::NO_DEP,
111  U_OHMMM1, CAT_NONE, "Next segment, intracellular resistivity");
112 
113  p.addPar ("ANS", 0.0, false, ParameterType::NO_DEP,
116  U_METER, CAT_NONE, "Next segment, segment radius");
117 
118  p.addPar ("LNS", 0.0, false, ParameterType::NO_DEP,
121  U_METER, CAT_NONE, "Next segment length");
122 
123  // add non-double types
125  &Neuron4::Instance::nSegGiven , U_NONE, CAT_NONE, "Number of segments" );
126 
127 }
128 
130 {
131  // Set up map for double precision variables:
132  p.addPar ("CMEM", 0.0, false, ParameterType::NO_DEP,
135  U_FARAD, CAT_NONE, "Membrane capacitance");
136 
137  p.addPar ("GMEM", 0.0, false, ParameterType::NO_DEP,
140  U_OHMM1, CAT_NONE, "Membrane conductance");
141 
142  p.addPar ("VREST", 0.0, false, ParameterType::NO_DEP,
145  U_VOLT, CAT_NONE, "Resting potential");
146 
147  p.addPar ("EK", 0.0, false, ParameterType::NO_DEP,
150  U_VOLT, CAT_NONE, "Potassium resting potential");
151 
152  p.addPar ("GK", 0.0, false, ParameterType::NO_DEP,
155  U_OHMM1, CAT_NONE, "Potassium base conductance");
156 
157  p.addPar ("ENA", 0.0, false, ParameterType::NO_DEP,
160  U_VOLT, CAT_NONE, "Sodium resting potential");
161 
162  p.addPar ("GNA", 0.0, false, ParameterType::NO_DEP,
165  U_OHMM1, CAT_NONE, "Sodium base conductance");
166 
167  p.addPar ("EA", 0.0, false, ParameterType::NO_DEP,
170  U_CM, CAT_NONE, "a-current rest potential");
171 
172  p.addPar ("GA",0.0, false, ParameterType::NO_DEP,
175  U_NONE, CAT_NONE, "a-current base conductance");
176 
177  p.addPar ("ECA", 0.0, false, ParameterType::NO_DEP,
180  U_NONE, CAT_NONE, "Calcium rest potential");
181 
182  p.addPar ("GCA", 0.0, false, ParameterType::NO_DEP,
185  U_OHMM1, CAT_NONE, "Calcium base conductance");
186 
187  p.addPar ("EKCA", 0.0, false, ParameterType::NO_DEP,
190  U_OHMM1, CAT_NONE, "Potassium-calcium rest potential");
191 
192  p.addPar ("GKCA", 0.0, false, ParameterType::NO_DEP,
195  U_OHMM1, CAT_NONE, "Potassium-calcium base conductance");
196 
197  p.addPar ("CAINIT", 0.0, false, ParameterType::NO_DEP,
200  U_OHMM1, CAT_NONE, "initial intra-cellular calcium concentration");
201 
202  p.addPar ("CAGAMMA", 0.0, false, ParameterType::NO_DEP,
205  U_OHMM1, CAT_NONE, "calcium current to concentration multiplier");
206 
207  p.addPar ("CATAU", 0.0, false, ParameterType::NO_DEP,
210  U_OHMM1, CAT_NONE, "calcium removal time constant");
211 
212  p.addPar ("R", 0.0, false, ParameterType::NO_DEP,
215  U_OHMMM1, CAT_NONE, "Intracellular resistivity");
216 
217  p.addPar ("A", 0.0, false, ParameterType::NO_DEP,
220  U_METER, CAT_NONE, "Segment radius");
221 
222  p.addPar ("L", 0.0, false, ParameterType::NO_DEP,
225  U_METER, CAT_NONE, "Cable length");
226 
227  p.addPar ("RPS", 1.0e-6, false, ParameterType::NO_DEP,
230  U_OHMMM1, CAT_NONE, "Previous segment, intracellular resistivity");
231 
232  p.addPar ("APS", 0.0, false, ParameterType::NO_DEP,
235  U_METER, CAT_NONE, "Previous segment, segment radius");
236 
237  p.addPar ("LPS", 0.0, false, ParameterType::NO_DEP,
240  U_METER, CAT_NONE, "Previous segment length");
241 
242  p.addPar ("RNS", 1.0e-6, false, ParameterType::NO_DEP,
245  U_OHMMM1, CAT_NONE, "Next segment, intracellular resistivity");
246 
247  p.addPar ("ANS", 0.0, false, ParameterType::NO_DEP,
250  U_METER, CAT_NONE, "Next segment, segment radius");
251 
252  p.addPar ("LNS", 0.0, false, ParameterType::NO_DEP,
255  U_METER, CAT_NONE, "Next segment length");
256 
257  // add non-double types
259  &Neuron4::Model::nSegGiven , U_NONE, CAT_NONE, "Number of segments" );
260 }
261 
262 
263 // Class Instance
264 //-----------------------------------------------------------------------------
265 // Function : Instance::processParams
266 // Purpose :
267 // Special Notes :
268 // Scope : public
269 // Creator : Richard Schiek, Electrical and Microsytem Modeling
270 // Creation Date : 06/10/09
271 //-----------------------------------------------------------------------------
273 {
274  // If there are any time dependent parameters, set their values at for
275  // the current time.
276 
277  // now set the temperature related stuff.
278  //updateTemperature(temp);
279 
280  return true;
281 }
282 
283 //-----------------------------------------------------------------------------
284 // Function : Instance::updateTemperature
285 // Purpose :
286 // Special Notes :
287 // Scope : public
288 // Creator : Richard Schiek, Electrical and Microsytem Modeling
289 // Creation Date : 06/10/09
290 //-----------------------------------------------------------------------------
291 bool Instance::updateTemperature ( const double & temp)
292 {
293  bool bsuccess = true;
294  return bsuccess;
295 }
296 
297 //-----------------------------------------------------------------------------
298 // Function : Instance::Instance
299 // Purpose : constructor
300 // Special Notes :
301 // Scope : public
302 // Creator : Richard Schiek, Electrical and Microsytem Modeling
303 // Creation Date : 06/10/09
304 //-----------------------------------------------------------------------------
306  const Configuration & configuration,
307  const InstanceBlock & IB,
308  Model & Miter,
309  const FactoryBlock & factory_block)
310  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
311  model_(Miter),
312  rInt(0.0),
313  radius(0.0),
314  length(0.0),
315  segArea(0.0),
316  nSeg(0),
317  rIntGiven(false),
318  radiusGiven(false),
319  lengthGiven(false),
320  nSegGiven(false),
321  rIntPrevious(0.0),
322  radiusPrevious(0.0),
323  lengthPrevious(0.0),
324  rIntNext(0.0),
325  radiusNext(0.0),
326  lengthNext(0.0),
327  rIntPreviousGiven(false),
328  radiusPreviousGiven(false),
329  lengthPreviousGiven(false),
330  rIntNextGiven(false),
331  radiusNextGiven(false),
332  lengthNextGiven(false),
333  kcl1Fvalue(0.0),
334  kcl2Fvalue(0.0),
335  dkcl1F_dVin(0.0),
336  dkcl1F_dVs0(0.0),
337  dkcl2F_dVout(0.0),
338  dkcl2F_dVsn(0.0),
339  li_Pos(0),
340  li_Neg(0),
341  APosEquPosNodeOffset(0),
342  APosEquNextNodeOffset(0),
343  ANegEquNegNodeOffset(0),
344  ANegEquLastNodeOffset(0)
345 {
346  // we have pased the model and instance parameters so now we can calculate
347  // the number of internal vars
348  numExtVars = 2; // input and output voltage
349 
350  // Set params to constant default values:
351  setDefaultParams ();
352 
353  // Set params according to instance line
354  setParams (IB.params);
355 
356  // Set any non-constant parameter defaults:
357 
358  //if (!given("TEMP"))
359  // temp = getDeviceOptions().temp.dVal();
360 
361  // Calculate any parameters specified as expressions:
363 
364  // calculate dependent (ie computed) params and check for errors:
365  processParams ();
366 
367  // pull unspecified params out of the model if they weren't specified here
368  if( !nSegGiven && model_.nSegGiven )
369  {
370  nSeg = model_.nSeg;
371  nSegGiven = true;
372  }
373  if( !rIntGiven && model_.rIntGiven )
374  {
375  rInt = model_.rInt;
376  rIntGiven = true;
377  }
378  if( !radiusGiven && model_.radiusGiven )
379  {
380  radius = model_.radius;
381  radiusGiven = true;
382  }
383  if( !lengthGiven && model_.lengthGiven )
384  {
385  length = model_.length;
386  lengthGiven = true;
387  }
388 
389  // if nSeg is still unknown then estimate it via lambda-d rule (TO DO)
390  if( !nSegGiven )
391  {
392  nSeg = 10;
393  }
394 
395  // now that nSeg, length and radius are set calculate segment area
396  segArea = 2.0 * M_PI * radius * length / nSeg;
397 
398  // now we can calculate the number of internal vars
399  numIntVars = nSeg * 10; // ion channel vars + one internal voltage node var for each segment
400  numStateVars = nSeg * 2; // two currents per segment
401  int numVars = numExtVars + numIntVars;
402 
403  //
404  // i(n) - I(n)/A - g(n,n+1) * (V(n+1) - V(n)) - g(n,n-1) * (V(n-1) - V(n)) + Cm dV(n)/d(t) = 0
405  //
406  // Vin : g(0,1) * (V(1) - Vin ) = 0
407  // Vout : g(n,n-1) * (V(n-1) - Vout) = 0
408  // Vnode : i(n) - I(n)/A - g(n,n+1) * (V(n+1) - V(n)) - g(n,n-1) * (V(n-1) - V(n)) + Cm dV(n)/d(t) = 0
409  // plus node supporting equations (a, b, m)
410  //
411  // jacobian format
412  // Vin Vout V1 n m h a b M H c Ca V2 n m h V(nSeg) n m h
413  // kcl Vin -g(0,1) g(0,1)
414  // kcl Vout -g(n,n-1) g(n,n-1)
415  // kcl V1 yes yes yes yes yes y y y y y yes
416  // n yes yes
417  // m yes yes
418  // h yes yes
419  // a yes yes
420  // b yes yes
421  // M yes yes
422  // H yes yes
423  // c yes yes yes
424  // Ca yes yes yes yes
425  //
426  //
427  // jacobian element count by row:
428  // vin: 2
429  // vout: 2
430  // v1: 11
431  // n1: 2
432  // m1: 2
433  // h1: 2
434  // a1: 2
435  // b1: 2
436  // M1: 2
437  // H1: 2
438  // c1: 3
439  // Ca1: 4
440  //
441  // set up jacStamp
442  if( jacStamp.empty() ) // redundant as jacStamp is not static for this device
443  { // it can't be as each cable may have a different number of nodes
444  jacStamp.resize(numVars);
445  jacStamp[0].resize(2);
446  jacStamp[0][0] = 0;
447  jacStamp[0][1] = 1;
448  jacStamp[1].resize(2);
449  jacStamp[1][0] = 1;
450  jacStamp[1][1] = numVars - 10;
451  for( int i=2; i<numVars; i+=10)
452  {
453  jacStamp[i].resize(11);
454  if( i == 2 )
455  {
456  jacStamp[i][0] = 0; // v_in
457  }
458  else
459  {
460  jacStamp[i][0] = i-10; // v_prev
461  }
462  jacStamp[i][1] = i; // v
463  jacStamp[i][2] = i+1; // n
464  jacStamp[i][3] = i+2; // m
465  jacStamp[i][4] = i+3; // h
466  jacStamp[i][5] = i+4; // a
467  jacStamp[i][6] = i+5; // b
468  jacStamp[i][7] = i+6; // M
469  jacStamp[i][8] = i+7; // H
470  jacStamp[i][9] = i+8; // c
471  if( i==(numVars-10) )
472  {
473  jacStamp[i][10] = 1; // v_out
474  }
475  else
476  {
477  jacStamp[i][10] = i+10; // v_next
478  }
479  jacStamp[i+1].resize(2); // n
480  jacStamp[i+1][0] = i;
481  jacStamp[i+1][1] = i+1;
482  jacStamp[i+2].resize(2); // m
483  jacStamp[i+2][0] = i;
484  jacStamp[i+2][1] = i+2;
485  jacStamp[i+3].resize(2); // h
486  jacStamp[i+3][0] = i;
487  jacStamp[i+3][1] = i+3;
488  jacStamp[i+4].resize(2); // a
489  jacStamp[i+4][0] = i;
490  jacStamp[i+4][1] = i+4;
491  jacStamp[i+5].resize(2); // b
492  jacStamp[i+5][0] = i;
493  jacStamp[i+5][1] = i+5;
494  jacStamp[i+6].resize(2); // M
495  jacStamp[i+6][0] = i;
496  jacStamp[i+6][1] = i+6;
497  jacStamp[i+7].resize(2); // H
498  jacStamp[i+7][0] = i;
499  jacStamp[i+7][1] = i+7;
500  jacStamp[i+8].resize(3); // c
501  jacStamp[i+8][0] = i;
502  jacStamp[i+8][1] = i+8;
503  jacStamp[i+8][2] = i+9;
504  jacStamp[i+9].resize(4); // ca
505  jacStamp[i+9][0] = i;
506  jacStamp[i+9][1] = i+6;
507  jacStamp[i+9][2] = i+7;
508  jacStamp[i+9][3] = i+9;
509 
510  }
511 
512  }
513 
514  /*
515  // print out jacStamp
516  int numRows = jacStamp.size();
517  for( int i=0; i< numRows; i++ )
518  {
519  int numCol = jacStamp[i].size();
520  Xyce::dout() << "jacStamp[ " << i << " ] = { ";
521  for(int j=0; j<numCol; j++)
522  {
523  Xyce::dout() << jacStamp[i][j] << " ";
524  }
525  Xyce::dout() << " } " << std::endl;
526  }
527  Xyce::dout() << std::endl;
528  */
529 
530  // calculate segment conductivities used in load calls:
531  // Note: conductivity to the previous and next segment is not symmetric if the segment length and/or radius is not are not equal
532  // the full formula is:
533  // g(n,n') = radius * (radius')^2 / ( rInt segLength * ( segLength * (radius')^2 + segLength' * (radius)^2 ) )
534  //
535  // equation 6.30 Theoretical neuroscience: computational and mathematical modeling of neural systems, Peter Dayan and L. F. Abbot 2001
536  // If we allow variable segment lengths and radii then we'll need to update this calculation
537  //
538  // Note: the above equation has the wrong units unless rInt (which is Ohm Length) is rLong (which is Ohm/Length).
539  //
540  gForward.resize(nSeg);
541  gBackward.resize(nSeg);
542  double segLength = length / nSeg;
543  double rLong = rInt / (M_PI * radius * radius); // longitudinal resistivity (ohm/length)
544  gBackward[0] = radius * (radiusPrevious * radiusPrevious) / (rLong * segLength * ( segLength * radiusPrevious * radiusPrevious + lengthPrevious * radius * radius ));
545  gForward[0] = radius * (radius * radius) / (rLong * segLength * ( segLength * radius * radius + segLength * radius * radius ));
546  gBackward[nSeg-1] = radius * (radius * radius) / (rLong * segLength * ( segLength * radius * radius + segLength * radius * radius ));
547  gForward[nSeg-1] = radius * (radiusNext * radiusNext) / (rLong * segLength * ( segLength * radiusNext * radiusNext + lengthNext * radius * radius ));
548  for(int i=1; i<(nSeg-1); i++)
549  {
550  gBackward[i] = radius * (radius * radius) / (rLong * segLength * ( segLength * radius * radius + segLength * radius * radius ));
551  gForward[i] = gBackward[i];
552  }
553  // gForward.resize(nSeg);
554  // gBackward.resize(nSeg);
555  // double segLength = length / nSeg;
556  // gBackward[0] = radius * (radiusPrevious * radiusPrevious) / (rInt * segLength * ( segLength * radiusPrevious * radiusPrevious + lengthPrevious * radius * radius ));
557  // gForward[0] = radius * (radius * radius) / (rInt * segLength * ( segLength * radius * radius + segLength * radius * radius ));
558  // gBackward[nSeg-1] = radius * (radius * radius) / (rInt * segLength * ( segLength * radius * radius + segLength * radius * radius ));
559  // gForward[nSeg-1] = radius * (radiusNext * radiusNext) / (rInt * segLength * ( segLength * radiusNext * radiusNext + lengthNext * radius * radius ));
560  // for(int i=1; i<(nSeg-1); i++)
561  // {
562  // gBackward[i] = radius * (radius * radius) / (rInt * segLength * ( segLength * radius * radius + segLength * radius * radius ));
563  // gForward[i] = gBackward[i];
564  // }
565 
566  // allocate space for load and jacobian terms per segment
567  // variable indecies loads
568  li_Vol.resize(nSeg);
569  li_nPro.resize(nSeg);
570  li_mPro.resize(nSeg);
571  li_hPro.resize(nSeg);
572  li_aPro.resize(nSeg);
573  li_bPro.resize(nSeg);
574  li_MPro.resize(nSeg);
575  li_HPro.resize(nSeg);
576  li_cPro.resize(nSeg);
577  li_CaPro.resize(nSeg);
578  li_KCurrentState.resize(nSeg);
579  li_NaCurrentState.resize(nSeg);
580  segFvalue.resize(nSeg);
581  segQvalue.resize(nSeg);
582  segNEquFvalue.resize(nSeg);
583  segNEquQvalue.resize(nSeg);
584  segMEquFvalue.resize(nSeg);
585  segMEquQvalue.resize(nSeg);
586  segHEquFvalue.resize(nSeg);
587  segHEquQvalue.resize(nSeg);
588  segAEquFvalue.resize(nSeg);
589  segAEquQvalue.resize(nSeg);
590  segBEquFvalue.resize(nSeg);
591  segBEquQvalue.resize(nSeg);
592  segM_EquFvalue.resize(nSeg);
593  segM_EquQvalue.resize(nSeg);
594  segH_EquFvalue.resize(nSeg);
595  segH_EquQvalue.resize(nSeg);
596  segCEquFvalue.resize(nSeg);
597  segCEquQvalue.resize(nSeg);
598  segCaEquFvalue.resize(nSeg);
599  segCaEquQvalue.resize(nSeg);
600 
601  // jacobian elements
602  segF_dVp.resize(nSeg);
603  segF_dV.resize(nSeg);
604  segF_dVn.resize(nSeg);
605  segF_dn.resize(nSeg);
606  segF_dm.resize(nSeg);
607  segF_dh.resize(nSeg);
608  segF_da.resize(nSeg);
609  segF_db.resize(nSeg);
610  segF_dM.resize(nSeg);
611  segF_dH.resize(nSeg);
612  segF_dc.resize(nSeg);
613  segQ_dV.resize(nSeg);
614  dnF_dV.resize(nSeg);
615  dnF_dn.resize(nSeg);
616  dnQ_dn.resize(nSeg);
617  dmF_dV.resize(nSeg);
618  dmF_dm.resize(nSeg);
619  dmQ_dm.resize(nSeg);
620  dhF_dV.resize(nSeg);
621  dhF_dh.resize(nSeg);
622  dhQ_dh.resize(nSeg);
623  daF_dV.resize(nSeg);
624  daF_da.resize(nSeg);
625  daQ_da.resize(nSeg);
626  dbF_dV.resize(nSeg);
627  dbF_db.resize(nSeg);
628  dbQ_db.resize(nSeg);
629  dMF_dV.resize(nSeg);
630  dMF_dM.resize(nSeg);
631  dMQ_dM.resize(nSeg);
632  dHF_dV.resize(nSeg);
633  dHF_dH.resize(nSeg);
634  dHQ_dH.resize(nSeg);
635  dcF_dV.resize(nSeg);
636  dcF_dc.resize(nSeg);
637  dcF_dCa.resize(nSeg);
638  dcQ_dc.resize(nSeg);
639  dCaF_dV.resize(nSeg);
640  dCaF_dM.resize(nSeg);
641  dCaF_dH.resize(nSeg);
642  dCaF_dCa.resize(nSeg);
643  dCaQ_dCa.resize(nSeg);
644 
645  // state vars
646  potassiumCurrent.resize(nSeg);
647  sodiumCurrent.resize(nSeg);
648 
649 }
650 
651 //-----------------------------------------------------------------------------
652 // Function : Instance::~Instance
653 // Purpose : destructor
654 // Special Notes :
655 // Scope : public
656 // Creator : Richard Schiek, Electrical and Microsytem Modeling
657 // Creation Date : 06/10/09
658 //-----------------------------------------------------------------------------
660 {
661 }
662 
663 //-----------------------------------------------------------------------------
664 // Function : Instance::registerLIDs
665 // Purpose :
666 // Special Notes :
667 // Scope : public
668 // Creator : Richard Schiek, Electrical and Microsytem Modeling
669 // Creation Date : 06/10/09
670 //-----------------------------------------------------------------------------
671 void Instance::registerLIDs(const std::vector<int> & intLIDVecRef,
672  const std::vector<int> & extLIDVecRef)
673 {
674  AssertLIDs(intLIDVecRef.size() == numIntVars);
675  AssertLIDs(extLIDVecRef.size() == numExtVars);
676 
677 #ifdef Xyce_DEBUG_DEVICE
678  if (getDeviceOptions().debugLevel > 0)
679  {
680  Xyce::dout() << std::endl << section_divider << std::endl;
681  Xyce::dout() << " Instance::registerLIDs" << std::endl;
682  Xyce::dout() << " name = " << getName() << std::endl;
683  }
684 #endif
685 
686  // copy over the global ID lists.
687  intLIDVec = intLIDVecRef;
688  extLIDVec = extLIDVecRef;
689 
690  li_Pos = extLIDVec[0];
691  li_Neg = extLIDVec[1];
692  for( int i=0, j=0; i<nSeg; i++, j+=10)
693  {
694  li_Vol[i] = intLIDVec[j];
695  li_nPro[i] = intLIDVec[j+1];
696  li_mPro[i] = intLIDVec[j+2];
697  li_hPro[i] = intLIDVec[j+3];
698  li_aPro[i] = intLIDVec[j+4];
699  li_bPro[i] = intLIDVec[j+5];
700  li_MPro[i] = intLIDVec[j+6];
701  li_HPro[i] = intLIDVec[j+7];
702  li_cPro[i] = intLIDVec[j+8];
703  li_CaPro[i] = intLIDVec[j+9];
704  }
705 
706 #ifdef Xyce_DEBUG_DEVICE
707  if (getDeviceOptions().debugLevel > 0 )
708  {
709  Xyce::dout() << " li_Pos = " << li_Pos << std::endl
710  << " li_Neg = " << li_Neg << std::endl;
711  for( int i=0; i<nSeg; i++ )
712  {
713  Xyce::dout() << " li_Vol[ " << i << " ] = " << li_Vol[i] << std::endl
714  << " li_nPro[ " << i << " ] = " << li_nPro[i] << std::endl
715  << " li_mPro[ " << i << " ] = " << li_mPro[i] << std::endl
716  << " li_hPro[ " << i << " ] = " << li_hPro[i] << std::endl
717  << " li_aPro[ " << i << " ] = " << li_aPro[i] << std::endl
718  << " li_bPro[ " << i << " ] = " << li_bPro[i] << std::endl
719  << " li_MPro[ " << i << " ] = " << li_MPro[i] << std::endl
720  << " li_HPro[ " << i << " ] = " << li_HPro[i] << std::endl
721  << " li_cPro[ " << i << " ] = " << li_cPro[i] << std::endl
722  << " li_CaPro[ " << i << " ] = " << li_CaPro[i] << std::endl;
723  }
724  }
725 #endif
726 
727 #ifdef Xyce_DEBUG_DEVICE
728  if (getDeviceOptions().debugLevel > 0 )
729  {
730  Xyce::dout() << section_divider << std::endl;
731  }
732 #endif
733 
734 }
735 
736 //-----------------------------------------------------------------------------
737 // Function : Instance::getIntNameMap
738 // Purpose :
739 // Special Notes :
740 // Scope : public
741 // Creator : Richard Schiek, Electrical and Microsytem Modeling
742 // Creation Date : 06/10/09
743 //-----------------------------------------------------------------------------
744 std::map<int,std::string> & Instance::getIntNameMap ()
745 {
746  // set up the internal name map, if it hasn't been already.
747  if (intNameMap.empty ())
748  {
749  std::string tmpstr;
750  for( int i=0; i<nSeg; i++)
751  {
752  std::ostringstream segNumber;
753  segNumber << i;
754  std::string segNumStr = segNumber.str();
755 
756  tmpstr = getName() + "_" + "V" + segNumStr;
757  spiceInternalName (tmpstr);
758  intNameMap[ li_Vol[i] ] = tmpstr;
759 
760  tmpstr = getName() + "_" + "N" + segNumStr;
761  spiceInternalName (tmpstr);
762  intNameMap[ li_nPro[i] ] = tmpstr;
763 
764  tmpstr = getName() + "_" + "M" + segNumStr;
765  spiceInternalName (tmpstr);
766  intNameMap[ li_mPro[i] ] = tmpstr;
767 
768  tmpstr = getName() + "_" + "H" + segNumStr;
769  spiceInternalName (tmpstr);
770  intNameMap[ li_hPro[i] ] = tmpstr;
771 
772  tmpstr = getName() + "_" + "A" + segNumStr;
773  spiceInternalName (tmpstr);
774  intNameMap[ li_aPro[i] ] = tmpstr;
775 
776  tmpstr = getName() + "_" + "B" + segNumStr;
777  spiceInternalName (tmpstr);
778  intNameMap[ li_bPro[i] ] = tmpstr;
779 
780  tmpstr = getName() + "_" + "M_" + segNumStr;
781  spiceInternalName (tmpstr);
782  intNameMap[ li_MPro[i] ] = tmpstr;
783 
784  tmpstr = getName() + "_" + "H_" + segNumStr;
785  spiceInternalName (tmpstr);
786  intNameMap[ li_HPro[i] ] = tmpstr;
787 
788  tmpstr = getName() + "_" + "C" + segNumStr;
789  spiceInternalName (tmpstr);
790  intNameMap[ li_cPro[i] ] = tmpstr;
791 
792  tmpstr = getName() + "_" + "Ca" + segNumStr;
793  spiceInternalName (tmpstr);
794  intNameMap[ li_CaPro[i] ] = tmpstr;
795 
796  }
797  }
798 
799  return intNameMap;
800 }
801 
802 //-----------------------------------------------------------------------------
803 // Function : Instance::registerStateLIDs
804 // Purpose :
805 // Special Notes :
806 // Scope : public
807 // Creator : Richard Schiek, Electrical and Microsytem Modeling
808 // Creation Date : 06/10/09
809 //-----------------------------------------------------------------------------
810 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
811 {
812  AssertLIDs(staLIDVecRef.size() == numStateVars);
813 
814  // copy over the global ID lists.
815  staLIDVec = staLIDVecRef;
816 
817  for( int i=0, j=0; i<nSeg; i++, j+=2)
818  {
819  li_KCurrentState[i] = staLIDVec[j];
820  li_NaCurrentState[i] = staLIDVec[j+1];
821  }
822 
823 }
824 
825 //-----------------------------------------------------------------------------
826 // Function : Instance::loadDeviceMask
827 //
828 // Purpose : Loads the zero elements of the device mask
829 //
830 // Special Notes : elements of the error vector associated with zero
831 // elements of the mask will not be included in weighted
832 // norms by the time integrator.
833 //
834 // Scope : public
835 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
836 // Creation Date : 06/10/09
837 //-----------------------------------------------------------------------------
839 {
840  bool returnVal=false;
841  N_LAS_Vector * maskVectorPtr = extData.deviceMaskVectorPtr;
842 
843 // Xyce::dout() << "Masking n, m and h" << std::endl;
844 // (*maskVectorPtr)[li_nPro] = 0.0;
845 // (*maskVectorPtr)[li_mPro] = 0.0;
846 // (*maskVectorPtr)[li_hPro] = 0.0;
847 // returnVal = true;
848 
849  return (returnVal);
850 }
851 
852 //-----------------------------------------------------------------------------
853 // Function : Instance::jacobianStamp
854 // Purpose :
855 // Special Notes :
856 // Scope : public
857 // Creator : Richard Schiek, Electrical and Microsytem Modeling
858 // Creation Date : 06/10/09
859 //-----------------------------------------------------------------------------
860 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
861 {
862  return jacStamp;
863 }
864 
865 //-----------------------------------------------------------------------------
866 // Function : Instance::registerJacLIDs
867 // Purpose :
868 // Special Notes :
869 // Scope : public
870 // Creator : Richard Schiek, Electrical and Microsytem Modeling
871 // Creation Date : 06/10/09
872 //-----------------------------------------------------------------------------
873 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
874 {
875  DeviceInstance::registerJacLIDs( jacLIDVec );
876 
877  // external terminals
878  APosEquPosNodeOffset = jacLIDVec[0][0];
879  APosEquNextNodeOffset = jacLIDVec[0][1];
880  ANegEquNegNodeOffset = jacLIDVec[1][0];
881  ANegEquLastNodeOffset = jacLIDVec[1][1];
882  /*
883  Xyce::dout() << "APosEquPosNodeOffset = " << APosEquPosNodeOffset << std::endl;
884  Xyce::dout() << "APosEquNextNodeOffset = " << APosEquNextNodeOffset << std::endl;
885  Xyce::dout() << "ANegEquNegNodeOffset = " << ANegEquNegNodeOffset << std::endl;
886  Xyce::dout() << "ANegEquLastNodeOffset = " << ANegEquLastNodeOffset << std::endl;
887  */
888 
889  // internal variables
890  SegVEqnVpreOffset.resize(nSeg);
891  SegVEqnVsegOffset.resize(nSeg);
892  SegVEqnVnexOffset.resize(nSeg);
893  SegVEqnNOffset.resize(nSeg);
894  SegVEqnMOffset.resize(nSeg);
895  SegVEqnHOffset.resize(nSeg);
896  NEquVNodeOffset.resize(nSeg);
897  NEquNNodeOffset.resize(nSeg);
898  MEquVNodeOffset.resize(nSeg);
899  MEquMNodeOffset.resize(nSeg);
900  HEquVNodeOffset.resize(nSeg);
901  HEquHNodeOffset.resize(nSeg);
902  AEquVNodeOffset.resize(nSeg);
903  AEquANodeOffset.resize(nSeg);
904  BEquVNodeOffset.resize(nSeg);
905  BEquBNodeOffset.resize(nSeg);
906  M_EquVNodeOffset.resize(nSeg);
907  M_EquM_NodeOffset.resize(nSeg);
908  H_EquVNodeOffset.resize(nSeg);
909  H_EquH_NodeOffset.resize(nSeg);
910  CEquVNodeOffset.resize(nSeg);
911  CEquCNodeOffset.resize(nSeg);
912  CEquCaNodeOffset.resize(nSeg);
913  CaEquVNodeOffset.resize(nSeg);
914  CaEquM_NodeOffset.resize(nSeg);
915  CaEquH_NodeOffset.resize(nSeg);
916  CaEquCaNodeOffset.resize(nSeg);
917 
918  for(int i=0, j=2; i<nSeg; i++, j+=10 )
919  {
920  SegVEqnVpreOffset[i] = jacLIDVec[j][0];
921  SegVEqnVsegOffset[i] = jacLIDVec[j][1];
922  SegVEqnNOffset[i] = jacLIDVec[j][2];
923  SegVEqnMOffset[i] = jacLIDVec[j][3];
924  SegVEqnHOffset[i] = jacLIDVec[j][4];
925  SegVEqnVnexOffset[i] = jacLIDVec[j][5];
926 
927  NEquVNodeOffset[i] = jacLIDVec[j+1][0];
928  NEquNNodeOffset[i] = jacLIDVec[j+1][1];
929  MEquVNodeOffset[i] = jacLIDVec[j+2][0];
930  MEquMNodeOffset[i] = jacLIDVec[j+2][1];
931  HEquVNodeOffset[i] = jacLIDVec[j+3][0];
932  HEquHNodeOffset[i] = jacLIDVec[j+3][1];
933  AEquVNodeOffset[i] = jacLIDVec[j+4][0];
934  AEquANodeOffset[i] = jacLIDVec[j+4][1];
935  BEquVNodeOffset[i] = jacLIDVec[j+5][0];
936  BEquBNodeOffset[i] = jacLIDVec[j+5][1];
937  M_EquVNodeOffset[i] = jacLIDVec[j+6][0];
938  M_EquM_NodeOffset[i] = jacLIDVec[j+6][1];
939  H_EquVNodeOffset[i] = jacLIDVec[j+7][0];
940  H_EquH_NodeOffset[i] = jacLIDVec[j+7][1];
941  CEquVNodeOffset[i] = jacLIDVec[j+8][0];
942  CEquCNodeOffset[i] = jacLIDVec[j+8][1];
943  CEquCaNodeOffset[i] = jacLIDVec[j+8][2];
944  CaEquVNodeOffset[i] = jacLIDVec[j+9][0];
945  CaEquM_NodeOffset[i] = jacLIDVec[j+9][1];
946  CaEquH_NodeOffset[i] = jacLIDVec[j+9][2];
947  CaEquCaNodeOffset[i] = jacLIDVec[j+9][3];
948 
949  /*
950  Xyce::dout() << SegVEqnVpreOffset[i] << ", "
951  << SegVEqnVsegOffset[i] << ", "
952  << SegVEqnNOffset[i] << ", "
953  << SegVEqnMOffset[i] << ", "
954  << SegVEqnHOffset[i] << ", "
955  << SegVEqnVnexOffset[i] << ", "
956  << NEquVNodeOffset[i] << ", "
957  << NEquNNodeOffset[i] << ", "
958  << MEquVNodeOffset[i] << ", "
959  << MEquMNodeOffset[i] << ", "
960  << HEquVNodeOffset[i] << ", "
961  << HEquHNodeOffset[i] << std::endl;
962  */
963  }
964 }
965 
966 
967 //-----------------------------------------------------------------------------
968 // Function : Instance::updateIntermediateVars
969 // Purpose :
970 // Special Notes :
971 // Scope : public
972 // Creator : Richard Schiek, Electrical and Microsytem Modeling
973 // Creation Date : 06/10/09
974 //-----------------------------------------------------------------------------
976 {
977  bool bsuccess = true;
978 
979  // here we take the current solutions for V1, V2, n, m and h
980  // and use those to calculate all the terms needed for the next
981  // load cycle (F, Q, dFdX, dQdX)
982  N_LAS_Vector * solVectorPtr = extData.nextSolVectorPtr;
983 
984  double vIn = (*solVectorPtr)[li_Pos];
985  double vOut = (*solVectorPtr)[li_Neg];
986 
987  // take care of the input and output nodes as they are different
988  kcl1Fvalue = gForward[0] * ((*solVectorPtr)[li_Vol[0]] - vIn );
989  dkcl1F_dVin = -gForward[0];
990  dkcl1F_dVs0 = gForward[0];
991  kcl2Fvalue = gBackward[nSeg-1] * ((*solVectorPtr)[li_Vol[nSeg-1]] - vOut );
994 
995  // loop over segments getting all the load and jacobian terms for each segment
996  for( int i=0; i<nSeg; i++ )
997  {
998  // for this segment get the values of the local vars
999  double vSeg = (*solVectorPtr)[li_Vol[i]];
1000  double vNext = 0.0;
1001  if (i == (nSeg - 1))
1002  {
1003  vNext = vOut;
1004  }
1005  else
1006  {
1007  vNext = (*solVectorPtr)[li_Vol[i+1]];
1008  }
1009  double vPrev = 0.0;
1010  if (i == 0 )
1011  {
1012  vPrev = vIn;
1013  }
1014  else
1015  {
1016  vPrev = (*solVectorPtr)[li_Vol[i-1]];
1017  }
1018  double nVarSeg = (*solVectorPtr)[li_nPro[i]];
1019  double mVarSeg = (*solVectorPtr)[li_mPro[i]];
1020  double hVarSeg = (*solVectorPtr)[li_hPro[i]];
1021  double aVarSeg = (*solVectorPtr)[li_aPro[i]];
1022  double bVarSeg = (*solVectorPtr)[li_bPro[i]];
1023  double M_VarSeg = (*solVectorPtr)[li_MPro[i]];
1024  double H_VarSeg = (*solVectorPtr)[li_HPro[i]];
1025  double cVarSeg = (*solVectorPtr)[li_cPro[i]];
1026  double CaVarSeg = (*solVectorPtr)[li_CaPro[i]];
1027 
1028  // do the voltage equation for this node
1029  // get function and derivative values as we go.
1030  {
1031  // F part
1032  // use scoping to avoid lots of similar variable names
1033  const int numDeriv = 11;
1034  Sacado::Fad::SFad<double,11> vVar ( numDeriv, 0, vSeg );
1035  Sacado::Fad::SFad<double,11> vVpr ( numDeriv, 1, vPrev );
1036  Sacado::Fad::SFad<double,11> vVne ( numDeriv, 2, vNext );
1037  Sacado::Fad::SFad<double,11> nVar ( numDeriv, 3, nVarSeg );
1038  Sacado::Fad::SFad<double,11> mVar ( numDeriv, 4, mVarSeg );
1039  Sacado::Fad::SFad<double,11> hVar ( numDeriv, 5, hVarSeg );
1040  Sacado::Fad::SFad<double,11> aVar ( numDeriv, 6, aVarSeg );
1041  Sacado::Fad::SFad<double,11> bVar ( numDeriv, 7, bVarSeg );
1042  Sacado::Fad::SFad<double,11> M_Var( numDeriv, 8, M_VarSeg );
1043  Sacado::Fad::SFad<double,11> H_Var( numDeriv, 9, H_VarSeg );
1044  Sacado::Fad::SFad<double,11> cVar ( numDeriv, 10, cVarSeg );
1045 
1046  // parameters
1047  Sacado::Fad::SFad<double,11> gPrev( gBackward[i] );
1048  Sacado::Fad::SFad<double,11> gNext( gForward[i] );
1049  Sacado::Fad::SFad<double,11> gMemVar( model_.gMem * segArea );
1050  Sacado::Fad::SFad<double,11> vRestVar( model_.vRest );
1051  Sacado::Fad::SFad<double,11> gKVar( model_.gK * segArea );
1052  Sacado::Fad::SFad<double,11> eKVar( model_.eK );
1053  Sacado::Fad::SFad<double,11> gNaVar( model_.gNa * segArea );
1054  Sacado::Fad::SFad<double,11> eNaVar( model_.eNa );
1055  Sacado::Fad::SFad<double,11> gAVar( model_.gA * segArea );
1056  Sacado::Fad::SFad<double,11> eAVar( model_.eA );
1057  Sacado::Fad::SFad<double,11> gCaVar( model_.gCa * segArea );
1058  Sacado::Fad::SFad<double,11> eCaVar( model_.eCa );
1059  Sacado::Fad::SFad<double,11> gKCaVar( model_.gKCa * segArea );
1060  Sacado::Fad::SFad<double,11> CaInitVar( model_.CaInit );
1061  Sacado::Fad::SFad<double,11> CaGammaVar( model_.CaGamma );
1062  Sacado::Fad::SFad<double,11> CaTauVar( model_.CaTau );
1063 
1064  // compute the vaud and derivative terms for KCL 1 F
1065  Sacado::Fad::SFad<double,11> resultFad;
1066  resultFad = kcl1EquF( vVar, vVpr, vVne, nVar, mVar, hVar, aVar, bVar, M_Var, H_Var, cVar, gPrev, gNext, gMemVar, vRestVar, gKVar, eKVar, gNaVar, eNaVar, gAVar, eAVar, gCaVar, eCaVar, gKCaVar);
1067 
1068  segFvalue[i] = resultFad.val();
1069  segF_dV[i] = resultFad.dx(0);
1070  segF_dVp[i] = resultFad.dx(1);
1071  segF_dVn[i] = resultFad.dx(2);
1072  segF_dn[i] = resultFad.dx(3);
1073  segF_dm[i] = resultFad.dx(4);
1074  segF_dh[i] = resultFad.dx(5);
1075  segF_da[i] = resultFad.dx(6);
1076  segF_db[i] = resultFad.dx(7);
1077  segF_dM[i] = resultFad.dx(8);
1078  segF_dH[i] = resultFad.dx(9);
1079  segF_dc[i] = resultFad.dx(10);
1080  }
1081  {
1082  // Q part
1083  const int numDeriv = 1;
1084  Sacado::Fad::SFad<double,1> vVar( numDeriv, 0, vSeg );
1085 
1086  // parameters
1087  Sacado::Fad::SFad<double,1> cMemVar( model_.cMem * segArea );
1088 
1089  Sacado::Fad::SFad<double,1> resultFad;
1090  resultFad = kcl1EquQ( vVar, cMemVar );
1091  segQvalue[i] = resultFad.val();
1092  segQ_dV[i] = resultFad.dx(0);
1093 
1094  }
1095 
1096  // n - equation
1097  {
1098  const int numDeriv = 2;
1099  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
1100  Sacado::Fad::SFad<double,2> nVar( numDeriv, 1, nVarSeg );
1101  // parameter
1102  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1103 
1104  Sacado::Fad::SFad<double,2> resultFad = nEquF( vVar, nVar, vRestVar);
1105  segNEquFvalue[i] = resultFad.val();
1106  dnF_dV[i] = resultFad.dx(0);
1107  dnF_dn[i] = resultFad.dx(1);
1108  }
1109  {
1110  const int numDeriv = 1;
1111  Sacado::Fad::SFad<double,1> nVar( numDeriv, 0, nVarSeg );
1112 
1113  Sacado::Fad::SFad<double,1> resultFad = nEquQ( nVar );
1114  segNEquQvalue[i] = resultFad.val();
1115  dnQ_dn[i] = resultFad.dx(0);
1116  }
1117 
1118  // m - equation
1119  {
1120  const int numDeriv = 2;
1121  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
1122  Sacado::Fad::SFad<double,2> mVar( numDeriv, 1, mVarSeg );
1123  // parameter
1124  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1125 
1126  Sacado::Fad::SFad<double,2> resultFad = mEquF( vVar, mVar, vRestVar );
1127  segMEquFvalue[i] = resultFad.val();
1128  dmF_dV[i] = resultFad.dx(0);
1129  dmF_dm[i] = resultFad.dx(1);
1130  }
1131  {
1132  const int numDeriv = 1;
1133  Sacado::Fad::SFad<double,1> mVar( numDeriv, 0, mVarSeg );
1134 
1135  Sacado::Fad::SFad<double,1> resultFad = mEquQ( mVar );
1136  segMEquQvalue[i] = resultFad.val();
1137  dmQ_dm[i] = resultFad.dx(0);
1138  }
1139 
1140  // h - equation
1141  {
1142  const int numDeriv = 2;
1143  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
1144  Sacado::Fad::SFad<double,2> hVar( numDeriv, 1, hVarSeg );
1145  // parameter
1146  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1147 
1148  Sacado::Fad::SFad<double,2> resultFad = hEquF( vVar, hVar, vRestVar );
1149  segHEquFvalue[i] = resultFad.val();
1150  dhF_dV[i] = resultFad.dx(0);
1151  dhF_dh[i] = resultFad.dx(1);
1152  }
1153  {
1154  const int numDeriv = 1;
1155  Sacado::Fad::SFad<double,1> hVar( numDeriv, 0, hVarSeg );
1156 
1157  Sacado::Fad::SFad<double,1> resultFad = hEquQ( hVar );
1158  segHEquQvalue[i] = resultFad.val();
1159  dhQ_dh[i] = resultFad.dx(0);
1160  }
1161 
1162  // a - equation
1163  {
1164  const int numDeriv = 2;
1165  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
1166  Sacado::Fad::SFad<double,2> aVar( numDeriv, 1, aVarSeg );
1167  // parameter
1168  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1169 
1170  Sacado::Fad::SFad<double,2> resultFad = aEquF( vVar, aVar, vRestVar );
1171  segAEquFvalue[i] = resultFad.val();
1172  daF_dV[i] = resultFad.dx(0);
1173  daF_da[i] = resultFad.dx(1);
1174  }
1175  {
1176  const int numDeriv = 1;
1177  Sacado::Fad::SFad<double,1> aVar( numDeriv, 0, aVarSeg );
1178 
1179  Sacado::Fad::SFad<double,1> resultFad = aEquQ( aVar );
1180  segAEquQvalue[i] = resultFad.val();
1181  daQ_da[i] = resultFad.dx(0);
1182  }
1183 
1184  // b - equation
1185  {
1186  const int numDeriv = 2;
1187  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
1188  Sacado::Fad::SFad<double,2> bVar( numDeriv, 1, bVarSeg );
1189  // parameter
1190  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1191 
1192  Sacado::Fad::SFad<double,2> resultFad = bEquF( vVar, bVar, vRestVar );
1193  segBEquFvalue[i] = resultFad.val();
1194  dbF_dV[i] = resultFad.dx(0);
1195  dbF_db[i] = resultFad.dx(1);
1196  }
1197  {
1198  const int numDeriv = 1;
1199  Sacado::Fad::SFad<double,1> bVar( numDeriv, 0, bVarSeg );
1200 
1201  Sacado::Fad::SFad<double,1> resultFad = bEquQ( bVar );
1202  segBEquQvalue[i] = resultFad.val();
1203  dbQ_db[i] = resultFad.dx(0);
1204  }
1205 
1206  // M - equation
1207  {
1208  const int numDeriv = 2;
1209  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
1210  Sacado::Fad::SFad<double,2> M_Var( numDeriv, 1, M_VarSeg );
1211  // parameter
1212  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1213 
1214  Sacado::Fad::SFad<double,2> resultFad = M_EquF( vVar, M_Var, vRestVar );
1215  segM_EquFvalue[i] = resultFad.val();
1216  dMF_dV[i] = resultFad.dx(0);
1217  dMF_dM[i] = resultFad.dx(1);
1218  }
1219  {
1220  const int numDeriv = 1;
1221  Sacado::Fad::SFad<double,1> M_Var( numDeriv, 0, M_VarSeg );
1222 
1223  Sacado::Fad::SFad<double,1> resultFad = M_EquQ( M_Var );
1224  segM_EquQvalue[i] = resultFad.val();
1225  dMQ_dM[i] = resultFad.dx(0);
1226  }
1227 
1228  // H - equation
1229  {
1230  const int numDeriv = 2;
1231  Sacado::Fad::SFad<double,2> vVar( numDeriv, 0, vSeg );
1232  Sacado::Fad::SFad<double,2> H_Var( numDeriv, 1, H_VarSeg );
1233  // parameter
1234  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1235 
1236  Sacado::Fad::SFad<double,2> resultFad = H_EquF( vVar, H_Var, vRestVar );
1237  segH_EquFvalue[i] = resultFad.val();
1238  dHF_dV[i] = resultFad.dx(0);
1239  dHF_dH[i] = resultFad.dx(1);
1240  }
1241  {
1242  const int numDeriv = 1;
1243  Sacado::Fad::SFad<double,1> H_Var( numDeriv, 0, H_VarSeg );
1244 
1245  Sacado::Fad::SFad<double,1> resultFad = H_EquQ( H_Var );
1246  segH_EquQvalue[i] = resultFad.val();
1247  dHQ_dH[i] = resultFad.dx(0);
1248  }
1249 
1250  // c - equation
1251  {
1252  const int numDeriv = 3;
1253  Sacado::Fad::SFad<double,3> vVar( numDeriv, 0, vSeg );
1254  Sacado::Fad::SFad<double,3> cVar( numDeriv, 1, cVarSeg );
1255  Sacado::Fad::SFad<double,3> CaVar( numDeriv, 2, CaVarSeg );
1256  // parameter
1257  Sacado::Fad::SFad<double,3> vRestVar( model_.vRest );
1258 
1259  Sacado::Fad::SFad<double,3> resultFad = C_EquF( vVar, cVar, CaVar, vRestVar );
1260  segCEquFvalue[i] = resultFad.val();
1261  dcF_dV[i] = resultFad.dx(0);
1262  dcF_dc[i] = resultFad.dx(1);
1263  dcF_dCa[i] = resultFad.dx(2);
1264  }
1265  {
1266  const int numDeriv = 1;
1267  Sacado::Fad::SFad<double,1> cVar( numDeriv, 0, cVarSeg );
1268 
1269  Sacado::Fad::SFad<double,1> resultFad = C_EquQ( cVar );
1270  segCEquQvalue[i] = resultFad.val();
1271  dcQ_dc[i] = resultFad.dx(0);
1272  }
1273 
1274  // Ca - equation
1275  {
1276  const int numDeriv = 4;
1277  Sacado::Fad::SFad<double,4> vVar( numDeriv, 0, vSeg );
1278  Sacado::Fad::SFad<double,4> M_Var( numDeriv, 1, M_VarSeg );
1279  Sacado::Fad::SFad<double,4> H_Var( numDeriv, 2, H_VarSeg );
1280  Sacado::Fad::SFad<double,4> CaVar( numDeriv, 3, CaVarSeg );
1281  // parameter
1282  Sacado::Fad::SFad<double,4> gCaVar( model_.gCa );
1283  Sacado::Fad::SFad<double,4> eCaVar( model_.gCa );
1284  Sacado::Fad::SFad<double,4> CaGammaVar( model_.CaGamma );
1285  Sacado::Fad::SFad<double,4> CaTauVar( model_.CaTau );
1286 
1287  Sacado::Fad::SFad<double,4> resultFad = Ca_EquF( vVar, M_Var, H_Var, CaVar, gCaVar, eCaVar, CaGammaVar, CaTauVar );
1288  segCaEquFvalue[i] = resultFad.val();
1289  dCaF_dV[i] = resultFad.dx(0);
1290  dCaF_dM[i] = resultFad.dx(1);
1291  dCaF_dH[i] = resultFad.dx(2);
1292  dCaF_dCa[i] = resultFad.dx(3);
1293  }
1294  {
1295  const int numDeriv = 1;
1296  Sacado::Fad::SFad<double,1> CaVar( numDeriv, 0, CaVarSeg );
1297 
1298  Sacado::Fad::SFad<double,1> resultFad = Ca_EquQ( CaVar );
1299  segCaEquQvalue[i] = resultFad.val();
1300  dCaQ_dCa[i] = resultFad.dx(0);
1301  }
1302 
1303 
1304  }
1305 
1306 #if 0
1307  //Xyce::dout() << "Instance::updateIntermediateVars()" << std::endl;
1308 
1309  bool bsuccess = true;
1310 
1311  // here we take the current solutions for V1, V2, n, m and h
1312  // and use those to calculate all the terms needed for the next
1313  // load cycle (F, Q, dFdX, dQdX)
1314 
1315  N_LAS_Vector * solVectorPtr = extData.nextSolVectorPtr;
1316 
1317  // use suffix "now" to to clarify that this for the latest solution
1318  double v1Now = (*solVectorPtr)[li_Pos];
1319  double v2Now = (*solVectorPtr)[li_Neg];
1320  double nNow = (*solVectorPtr)[li_nPro];
1321  double mNow = (*solVectorPtr)[li_mPro];
1322  double hNow = (*solVectorPtr)[li_hPro];
1323  double aNow = (*solVectorPtr)[li_aPro];
1324  double bNow = (*solVectorPtr)[li_bPro];
1325  double M_Now = (*solVectorPtr)[li_M_Pro];
1326  double H_Now = (*solVectorPtr)[li_H_Pro];
1327  double cNow = (*solVectorPtr)[li_cPro];
1328  double CaNow = (*solVectorPtr)[li_CaPro];
1329 
1330  // get function and derivative values
1331  // independent variables
1332  // use scoping to avoid lots of similar variable names
1333  {
1334  Sacado::Fad::SFad<double,10> v1Var( 10, 0, v1Now );
1335  Sacado::Fad::SFad<double,10> v2Var( 10, 1, v2Now );
1336  Sacado::Fad::SFad<double,10> nVar( 10, 2, nNow );
1337  Sacado::Fad::SFad<double,10> mVar( 10, 3, mNow );
1338  Sacado::Fad::SFad<double,10> hVar( 10, 4, hNow );
1339  Sacado::Fad::SFad<double,10> aVar( 10, 5, aNow );
1340  Sacado::Fad::SFad<double,10> bVar( 10, 6, bNow );
1341  Sacado::Fad::SFad<double,10> M_Var( 10, 7, M_Now );
1342  Sacado::Fad::SFad<double,10> H_Var( 10, 8, H_Now );
1343  Sacado::Fad::SFad<double,10> cVar( 10, 9, cNow );
1344 
1345  // parameters from the model that we'll need.
1346  Sacado::Fad::SFad<double,10> gMemVar( model_.gMem );
1347  Sacado::Fad::SFad<double,10> vRestVar( model_.vRest );
1348  Sacado::Fad::SFad<double,10> gKVar( model_.gK );
1349  Sacado::Fad::SFad<double,10> eKVar( model_.eK );
1350  Sacado::Fad::SFad<double,10> gNaVar( model_.gNa );
1351  Sacado::Fad::SFad<double,10> eNaVar( model_.eNa );
1352  Sacado::Fad::SFad<double,10> gAVar( model_.gA );
1353  Sacado::Fad::SFad<double,10> eAVar( model_.eA );
1354  Sacado::Fad::SFad<double,10> gCaVar( model_.gCa );
1355  Sacado::Fad::SFad<double,10> eCaVar( model_.gCa );
1356  Sacado::Fad::SFad<double,10> gKCaVar( model_.gKCa );
1357  Sacado::Fad::SFad<double,10> CaInitVar( model_.CaInit );
1358  Sacado::Fad::SFad<double,10> CaGammaVar( model_.CaGamma );
1359  Sacado::Fad::SFad<double,10> CaTauVar( model_.CaTau );
1360 
1361  // compute the vaud and derivative terms for KCL 1 F
1362  Sacado::Fad::SFad<double,10> resultFad;
1363  resultFad = kcl1EquF( v1Var, v2Var, nVar, mVar, hVar, aVar, bVar, M_Var, H_Var, cVar, gMemVar, vRestVar, gKVar, eKVar, gNaVar, eNaVar, gAVar, eAVar, gCaVar, eCaVar, gKCaVar);
1364  kcl1Fvalue = resultFad.val();
1365  dkcl1F_dV1 = resultFad.dx(0);
1366  dkcl1F_dV2 = resultFad.dx(1);
1367  dkcl1F_dn = resultFad.dx(2);
1368  dkcl1F_dm = resultFad.dx(3);
1369  dkcl1F_dh = resultFad.dx(4);
1370  dkcl1F_da = resultFad.dx(5);
1371  dkcl1F_db = resultFad.dx(6);
1372  dkcl1F_dM = resultFad.dx(7);
1373  dkcl1F_dH = resultFad.dx(8);
1374  dkcl1F_dc = resultFad.dx(9);
1375 
1376  // compute the vaud and derivative terms for KCL 2 F
1377  resultFad = kcl2EquF( v1Var, v2Var, nVar, mVar, hVar, aVar, bVar, M_Var, H_Var, cVar, gMemVar, vRestVar, gKVar, eKVar, gNaVar, eNaVar, gAVar, eAVar, gCaVar, eCaVar, gKCaVar);
1378  kcl2Fvalue = resultFad.val();
1379  dkcl2F_dV1 = resultFad.dx(0);
1380  dkcl2F_dV2 = resultFad.dx(1);
1381  dkcl2F_dn = resultFad.dx(2);
1382  dkcl2F_dm = resultFad.dx(3);
1383  dkcl2F_dh = resultFad.dx(4);
1384  dkcl2F_da = resultFad.dx(5);
1385  dkcl2F_db = resultFad.dx(6);
1386  dkcl2F_dM = resultFad.dx(7);
1387  dkcl2F_dH = resultFad.dx(8);
1388  dkcl2F_dc = resultFad.dx(9);
1389  }
1390 
1391  {
1392  Sacado::Fad::SFad<double,2> v1Var( 2, 0, v1Now );
1393  Sacado::Fad::SFad<double,2> v2Var( 2, 1, v2Now );
1394 
1395  // parameters
1396  Sacado::Fad::SFad<double,2> cMemVar( model_.cMem );
1397 
1398  Sacado::Fad::SFad<double,2> resultFad;
1399  resultFad = kcl1EquQ( v1Var, v2Var, cMemVar );
1400  kcl1Qvalue = resultFad.val();
1401  dkcl1Q_dV1 = resultFad.dx(0);
1402  dkcl1Q_dV2 = resultFad.dx(1);
1403 
1404  resultFad = kcl2EquQ( v1Var, v2Var, cMemVar );
1405  kcl2Qvalue = resultFad.val();
1406  dkcl2Q_dV1 = resultFad.dx(0);
1407  dkcl2Q_dV2 = resultFad.dx(1);
1408  }
1409 
1410  // n - equation
1411  {
1412  Sacado::Fad::SFad<double,2> v1Var( 2, 0, v1Now );
1413  Sacado::Fad::SFad<double,2> nVar( 2, 1, nNow );
1414  // parameter
1415  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1416 
1417  Sacado::Fad::SFad<double,2> resultFad = nEquF( v1Var, nVar, vRestVar);
1418  nEquFvalue = resultFad.val();
1419  dnF_dV1 = resultFad.dx(0);
1420  dnF_dn = resultFad.dx(1);
1421  }
1422 
1423  {
1424  Sacado::Fad::SFad<double,1> nVar( 1, 0, nNow );
1425 
1426  Sacado::Fad::SFad<double,1> resultFad = nEquQ( nVar );
1427  nEquQvalue = resultFad.val();
1428  dnQ_dn = resultFad.dx(0);
1429  }
1430 
1431  // m - equation
1432  {
1433  Sacado::Fad::SFad<double,2> v1Var( 2, 0, v1Now );
1434  Sacado::Fad::SFad<double,2> mVar( 2, 1, mNow );
1435  // parameter
1436  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1437 
1438  Sacado::Fad::SFad<double,2> resultFad = mEquF( v1Var, mVar, vRestVar );
1439  mEquFvalue = resultFad.val();
1440  dmF_dV1 = resultFad.dx(0);
1441  dmF_dm = resultFad.dx(1);
1442  }
1443  {
1444  Sacado::Fad::SFad<double,1> mVar( 1, 0, mNow );
1445 
1446  Sacado::Fad::SFad<double,1> resultFad = mEquQ( mVar );
1447  mEquQvalue = resultFad.val();
1448  dmQ_dm = resultFad.dx(0);
1449  }
1450 
1451  // h - equation
1452  {
1453  Sacado::Fad::SFad<double,2> v1Var( 2, 0, v1Now );
1454  Sacado::Fad::SFad<double,2> hVar( 2, 1, hNow );
1455  // parameter
1456  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1457 
1458  Sacado::Fad::SFad<double,2> resultFad = hEquF( v1Var, hVar, vRestVar );
1459  hEquFvalue = resultFad.val();
1460  dhF_dV1 = resultFad.dx(0);
1461  dhF_dh = resultFad.dx(1);
1462  }
1463  {
1464  Sacado::Fad::SFad<double,1> hVar( 1, 0, hNow );
1465 
1466  Sacado::Fad::SFad<double,1> resultFad = hEquQ( hVar );
1467  hEquQvalue = resultFad.val();
1468  dhQ_dh = resultFad.dx(0);
1469  }
1470 
1471  // a - equation
1472  {
1473  Sacado::Fad::SFad<double,2> v1Var( 2, 0, v1Now );
1474  Sacado::Fad::SFad<double,2> aVar( 2, 1, aNow );
1475  // parameter
1476  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1477 
1478  Sacado::Fad::SFad<double,2> resultFad = aEquF( v1Var, aVar, vRestVar );
1479  aEquFvalue = resultFad.val();
1480  daF_dV1 = resultFad.dx(0);
1481  daF_da = resultFad.dx(1);
1482  }
1483  {
1484  Sacado::Fad::SFad<double,1> aVar( 1, 0, aNow );
1485 
1486  Sacado::Fad::SFad<double,1> resultFad = aEquQ( aVar );
1487  aEquQvalue = resultFad.val();
1488  daQ_da = resultFad.dx(0);
1489  }
1490 
1491  // b - equation
1492  {
1493  Sacado::Fad::SFad<double,2> v1Var( 2, 0, v1Now );
1494  Sacado::Fad::SFad<double,2> bVar( 2, 1, bNow );
1495  // parameter
1496  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1497 
1498  Sacado::Fad::SFad<double,2> resultFad = bEquF( v1Var, bVar, vRestVar );
1499  bEquFvalue = resultFad.val();
1500  dbF_dV1 = resultFad.dx(0);
1501  dbF_db = resultFad.dx(1);
1502  }
1503  {
1504  Sacado::Fad::SFad<double,1> bVar( 1, 0, bNow );
1505 
1506  Sacado::Fad::SFad<double,1> resultFad = aEquQ( bVar );
1507  bEquQvalue = resultFad.val();
1508  dbQ_db = resultFad.dx(0);
1509  }
1510 
1511  // M - equation
1512  {
1513  Sacado::Fad::SFad<double,2> v1Var( 2, 0, v1Now );
1514  Sacado::Fad::SFad<double,2> M_Var( 2, 1, M_Now );
1515  // parameter
1516  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1517 
1518  Sacado::Fad::SFad<double,2> resultFad = M_EquF( v1Var, M_Var, vRestVar );
1519  M_EquFvalue = resultFad.val();
1520  dMF_dV1 = resultFad.dx(0);
1521  dMF_dM = resultFad.dx(1);
1522  }
1523  {
1524  Sacado::Fad::SFad<double,1> M_Var( 1, 0, M_Now );
1525 
1526  Sacado::Fad::SFad<double,1> resultFad = aEquQ( M_Var );
1527  M_EquQvalue = resultFad.val();
1528  dMQ_dM = resultFad.dx(0);
1529  }
1530 
1531  // H - equation
1532  {
1533  Sacado::Fad::SFad<double,2> v1Var( 2, 0, v1Now );
1534  Sacado::Fad::SFad<double,2> H_Var( 2, 1, H_Now );
1535  // parameter
1536  Sacado::Fad::SFad<double,2> vRestVar( model_.vRest );
1537 
1538  Sacado::Fad::SFad<double,2> resultFad = H_EquF( v1Var, H_Var, vRestVar );
1539  H_EquFvalue = resultFad.val();
1540  dHF_dV1 = resultFad.dx(0);
1541  dHF_dH = resultFad.dx(1);
1542  }
1543  {
1544  Sacado::Fad::SFad<double,1> H_Var( 1, 0, H_Now );
1545 
1546  Sacado::Fad::SFad<double,1> resultFad = H_EquQ( H_Var );
1547  H_EquQvalue = resultFad.val();
1548  dHQ_dH = resultFad.dx(0);
1549  }
1550 
1551  // c - equation
1552  {
1553  Sacado::Fad::SFad<double,3> v1Var( 3, 0, v1Now );
1554  Sacado::Fad::SFad<double,3> cVar( 3, 1, cNow );
1555  Sacado::Fad::SFad<double,3> CaVar( 3, 2, CaNow );
1556  // parameter
1557  Sacado::Fad::SFad<double,3> vRestVar( model_.vRest );
1558 
1559  Sacado::Fad::SFad<double,3> resultFad = C_EquF( v1Var, cVar, CaVar, vRestVar );
1560  cEquFvalue = resultFad.val();
1561  dcF_dV1 = resultFad.dx(0);
1562  dcF_dc = resultFad.dx(1);
1563  dcF_dCa = resultFad.dx(2);
1564  }
1565  {
1566  Sacado::Fad::SFad<double,1> cVar( 1, 0, cNow );
1567 
1568  Sacado::Fad::SFad<double,1> resultFad = C_EquQ( cVar );
1569  cEquQvalue = resultFad.val();
1570  dcQ_dc = resultFad.dx(0);
1571  }
1572 
1573  // Ca - equation
1574  {
1575  Sacado::Fad::SFad<double,5> v1Var( 5, 0, v1Now );
1576  Sacado::Fad::SFad<double,5> v2Var( 5, 1, v2Now );
1577  Sacado::Fad::SFad<double,5> M_Var( 5, 2, M_Now );
1578  Sacado::Fad::SFad<double,5> H_Var( 5, 3, H_Now );
1579  Sacado::Fad::SFad<double,5> CaVar( 5, 4, CaNow );
1580 
1581  // parameter
1582  Sacado::Fad::SFad<double,5> gCaVar( model_.gCa );
1583  Sacado::Fad::SFad<double,5> eCaVar( model_.gCa );
1584  Sacado::Fad::SFad<double,5> CaGammaVar( model_.CaGamma );
1585  Sacado::Fad::SFad<double,5> CaTauVar( model_.CaTau );
1586 
1587  Sacado::Fad::SFad<double,5> resultFad = Ca_EquF( v1Var, v2Var, M_Var, H_Var, CaVar, gCaVar, eCaVar, CaGammaVar, CaTauVar );
1588  CaEquFvalue = resultFad.val();
1589  dCaF_dV1 = resultFad.dx(0);
1590  dCaF_dV2 = resultFad.dx(1);
1591  dCaF_dM = resultFad.dx(2);
1592  dCaF_dH = resultFad.dx(3);
1593  dCaF_dCa = resultFad.dx(4);
1594  }
1595  {
1596  Sacado::Fad::SFad<double,1> CaVar( 1, 0, CaNow );
1597 
1598  Sacado::Fad::SFad<double,1> resultFad = Ca_EquQ( CaVar );
1599  CaEquQvalue = resultFad.val();
1600  dCaQ_dCa = resultFad.dx(0);
1601  }
1602  // calculate potassium current
1603  potassiumCurrent = model_.gK * pow(nNow, 4.0) * (v1Now - v2Now - model_.eK);
1604 
1605  // calculate sodium current
1606  sodiumCurrent = model_.gNa * pow(mNow, 3.0) * hNow * (v1Now - v2Now - model_.eNa);
1607 
1608 
1609 #ifdef Xyce_DEBUG_DEVICE
1611  {
1612  Xyce::dout() << "Instance::updateIntermediateVars()" << std::endl
1613  << "v1 = " << v1Now << std::endl
1614  << "v2 = " << v2Now << std::endl
1615  << "nNow = " << nNow << std::endl
1616  << "mNow = " << mNow << std::endl
1617  << "hNow = " << hNow << std::endl
1618  << "aNow = " << aNow << std::endl
1619  << "bNow = " << bNow << std::endl
1620  << "M_Now = " << M_Now << std::endl
1621  << "H_Now = " << H_Now << std::endl
1622  << "cNow = " << cNow << std::endl
1623  << "CaNow = " << CaNow << std::endl
1624  << "kcl1Fvalue = " << kcl1Fvalue << std::endl
1625  << "dkcl1F_dV1 = " << dkcl1F_dV1 << std::endl
1626  << "dkcl1F_dV2 = " << dkcl1F_dV2 << std::endl
1627  << "dkcl1F_dn = " << dkcl1F_dn << std::endl
1628  << "dkcl1F_dm = " << dkcl1F_dm << std::endl
1629  << "dkcl1F_dh = " << dkcl1F_dh << std::endl
1630  << "kcl2Fvalue = " << kcl2Fvalue << std::endl
1631  << "dkcl2F_dV1 = " << dkcl2F_dV1 << std::endl
1632  << "dkcl2F_dV2 = " << dkcl2F_dV2 << std::endl
1633  << "dkcl2F_dn = " << dkcl2F_dn << std::endl
1634  << "dkcl2F_dm = " << dkcl2F_dm << std::endl
1635  << "dkcl2F_dh = " << dkcl2F_dh << std::endl
1636  << "alphaN = " << alphaN<double>( v1Now ) << std::endl
1637  << "betaN = " << betaN<double>( v1Now ) << std::endl
1638  << "nEquFvalue = " << nEquFvalue << std::endl
1639  << "dnF_dV1 = " << dnF_dV1 << std::endl
1640  << "dnF_dn = " << dnF_dn << std::endl
1641  << "nEquQvalue = " << nEquQvalue << std::endl
1642  << "dnQ_dn = " << dnQ_dn << std::endl
1643  << "alphaM = " << alphaM<double>( v1Now ) << std::endl
1644  << "betaM = " << betaM<double>( v1Now ) << std::endl
1645  << "mEquFvalue = " << mEquFvalue << std::endl
1646  << "dmF_dV1 = " << dmF_dV1 << std::endl
1647  << "dmF_dm = " << dmF_dm << std::endl
1648  << "mEquQvalue = " << mEquQvalue << std::endl
1649  << "dmQ_dm = " << dmQ_dm << std::endl
1650  << "alphaH = " << alphaH<double>( v1Now ) << std::endl
1651  << "betaH = " << betaH<double>( v1Now ) << std::endl
1652  << "hEquFvalue = " << hEquFvalue << std::endl
1653  << "dhF_dV1 = " << dhF_dV1 << std::endl
1654  << "dhF_dh = " << dhF_dh << std::endl
1655  << "hEquQvalue = " << hEquQvalue << std::endl
1656  << "dhQ_dh = " << dhQ_dh << std::endl
1657 
1658  << "aInf = " << aInf<double>( v1Now ) << std::endl
1659  << "aTau = " << aTau<double>( v1Now ) << std::endl
1660  << "aEquFvalue = " << aEquFvalue << std::endl
1661  << "daF_dV1 = " << daF_dV1 << std::endl
1662  << "daF_da = " << daF_da << std::endl
1663  << "aEquQvalue = " << aEquQvalue << std::endl
1664  << "daQ_da = " << daQ_da << std::endl
1665 
1666  << "bInf = " << bInf<double>( v1Now ) << std::endl
1667  << "bTau = " << bTau<double>( v1Now ) << std::endl
1668  << "bEquFvalue = " << bEquFvalue << std::endl
1669  << "dbF_dV1 = " << dbF_dV1 << std::endl
1670  << "dbF_db = " << dbF_db << std::endl
1671  << "bEquQvalue = " << bEquQvalue << std::endl
1672  << "dbQ_db = " << dbQ_db << std::endl
1673 
1674  << "M_Inf = " << M_Inf<double>( v1Now ) << std::endl
1675  << "M_Tau = " << M_Tau<double>( v1Now ) << std::endl
1676  << "M_EquFvalue = " << M_EquFvalue << std::endl
1677  << "dMF_dV1 = " << dMF_dV1 << std::endl
1678  << "dMF_dM = " << dMF_dM << std::endl
1679  << "M_EquQvalue = " << M_EquQvalue << std::endl
1680  << "dMQ_dM = " << dMQ_dM << std::endl
1681 
1682  << "H_Inf = " << H_Inf<double>( v1Now ) << std::endl
1683  << "H_Tau = " << H_Tau<double>( v1Now ) << std::endl
1684  << "H_EquFvalue = " << H_EquFvalue << std::endl
1685  << "dHF_dV1 = " << dHF_dV1 << std::endl
1686  << "dHF_dH = " << dHF_dH << std::endl
1687  << "H_EquQvalue = " << H_EquQvalue << std::endl
1688  << "dHQ_dH = " << dHQ_dH << std::endl
1689 
1690  << "cEquFvalue = " << cEquFvalue << std::endl
1691  << "dcF_dV1 = " << dcF_dV1 << std::endl
1692  << "dcF_dc = " << dcF_dc << std::endl
1693  << "cEquQvalue = " << cEquQvalue << std::endl
1694  << "dcQ_dc = " << dcQ_dc << std::endl
1695 
1696  << "CaEquFvalue = " << CaEquFvalue << std::endl
1697  << "dCaF_dV1 = " << dCaF_dV1 << std::endl
1698  << "dCaF_dV2 = " << dCaF_dV2 << std::endl
1699  << "dCaF_dM = " << dCaF_dM << std::endl
1700  << "dCaF_dH = " << dCaF_dH << std::endl
1701  << "dCaF_dCa = " << dCaF_dCa << std::endl
1702  << "CaEquQvalue = " << CaEquQvalue << std::endl
1703  << "dCaQ_dCa = " << dCaQ_dCa << std::endl
1704 
1705  << std::endl;
1706  }
1707 #endif
1708 
1709 #endif
1710  return bsuccess;
1711 }
1712 //-----------------------------------------------------------------------------
1713 // Function : Instance::updatePrimaryState
1714 // Purpose :
1715 // Special Notes :
1716 // Scope : public
1717 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1718 // Creation Date : 06/10/09
1719 //-----------------------------------------------------------------------------
1721 {
1722  bool bsuccess = true;
1723 
1725 
1726  N_LAS_Vector * solVectorPtr = extData.nextSolVectorPtr;
1727  N_LAS_Vector * staVectorPtr = extData.nextStaVectorPtr;
1728 
1729  for( int i=0; i<nSeg; i++)
1730  {
1731  (*staVectorPtr)[li_KCurrentState[i]] = potassiumCurrent[i];
1732  (*staVectorPtr)[li_NaCurrentState[i]] = sodiumCurrent[i];
1733  }
1734 
1735  return bsuccess;
1736 }
1737 
1738 //-----------------------------------------------------------------------------
1739 // Function : Instance::updateSecondaryState
1740 // Purpose :
1741 // Special Notes :
1742 // Scope : public
1743 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1744 // Creation Date : 06/10/09
1745 //-----------------------------------------------------------------------------
1747 {
1748  bool bsuccess = true;
1749 
1750  return bsuccess;
1751 }
1752 
1753 //-----------------------------------------------------------------------------
1754 // Function : Instance::loadDAEQVector
1755 //
1756 // Purpose : Loads the Q-vector contributions for a single
1757 // Neuron 4 instance.
1758 //
1759 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1760 // which the system of equations is represented as:
1761 //
1762 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1763 //
1764 // Scope : public
1765 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1766 // Creation Date : 06/10/09
1767 //-----------------------------------------------------------------------------
1769 {
1770  bool bsuccess = true;
1771 
1772  N_LAS_Vector * daeQVecPtr = extData.daeQVectorPtr;
1773 
1774  for( int i=0; i<nSeg ; i++)
1775  {
1776  (*daeQVecPtr)[li_Vol[i]] += segQvalue[i];
1777  (*daeQVecPtr)[li_nPro[i]] += segNEquQvalue[i];
1778  (*daeQVecPtr)[li_mPro[i]] += segMEquQvalue[i];
1779  (*daeQVecPtr)[li_hPro[i]] += segHEquQvalue[i];
1780  (*daeQVecPtr)[li_aPro[i]] += segAEquQvalue[i];
1781  (*daeQVecPtr)[li_bPro[i]] += segBEquQvalue[i];
1782  (*daeQVecPtr)[li_MPro[i]] += segM_EquQvalue[i];
1783  (*daeQVecPtr)[li_HPro[i]] += segH_EquQvalue[i];
1784  (*daeQVecPtr)[li_cPro[i]] += segCEquQvalue[i];
1785  (*daeQVecPtr)[li_CaPro[i]] += segCaEquQvalue[i];
1786  }
1787 
1788  return bsuccess;
1789 }
1790 
1791 
1792 
1793 //-----------------------------------------------------------------------------
1794 // Function : Instance::loadDAEFVector
1795 //
1796 // Purpose : Loads the F-vector contributions for a single
1797 // instance.
1798 //
1799 // Special Notes :
1800 //
1801 // Scope : public
1802 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1803 // Creation Date : 06/10/09
1804 //-----------------------------------------------------------------------------
1806 {
1807  bool bsuccess=true;
1808 
1809  N_LAS_Vector * daeFVecPtr = extData.daeFVectorPtr;
1810 
1811  (*daeFVecPtr)[li_Pos] += kcl1Fvalue;
1812  (*daeFVecPtr)[li_Neg] += kcl2Fvalue;
1813 
1814  for( int i=0; i<nSeg ; i++)
1815  {
1816  (*daeFVecPtr)[li_Vol[i]] += segFvalue[i];
1817  (*daeFVecPtr)[li_nPro[i]] += segNEquFvalue[i];
1818  (*daeFVecPtr)[li_mPro[i]] += segMEquFvalue[i];
1819  (*daeFVecPtr)[li_hPro[i]] += segHEquFvalue[i];
1820  (*daeFVecPtr)[li_aPro[i]] += segAEquFvalue[i];
1821  (*daeFVecPtr)[li_bPro[i]] += segBEquFvalue[i];
1822  (*daeFVecPtr)[li_MPro[i]] += segM_EquFvalue[i];
1823  (*daeFVecPtr)[li_HPro[i]] += segH_EquFvalue[i];
1824  (*daeFVecPtr)[li_cPro[i]] += segCEquFvalue[i];
1825  (*daeFVecPtr)[li_CaPro[i]] += segCaEquFvalue[i];
1826  }
1827 
1828  return bsuccess;
1829 }
1830 
1831 //-----------------------------------------------------------------------------
1832 // Function : Instance::loadDAEdQdx
1833 //
1834 // Purpose : Loads the Q-vector contributions for a single
1835 // instance.
1836 // Scope : public
1837 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1838 // Creation Date : 06/10/09
1839 //-----------------------------------------------------------------------------
1841 {
1842  bool bsuccess = true;
1843 
1844  N_LAS_Matrix * dQdxMatPtr = extData.dQdxMatrixPtr;
1845 
1846  for( int i=0; i<nSeg ; i++)
1847  {
1848  (*dQdxMatPtr)[li_Vol[i]][SegVEqnVsegOffset[i]] += segQ_dV[i];
1849  (*dQdxMatPtr)[li_nPro[i]][NEquNNodeOffset[i]] += dnQ_dn[i];
1850  (*dQdxMatPtr)[li_mPro[i]][MEquMNodeOffset[i]] += dmQ_dm[i];
1851  (*dQdxMatPtr)[li_hPro[i]][HEquHNodeOffset[i]] += dhQ_dh[i];
1852  (*dQdxMatPtr)[li_aPro[i]][AEquANodeOffset[i]] += daQ_da[i];
1853  (*dQdxMatPtr)[li_bPro[i]][BEquBNodeOffset[i]] += dbQ_db[i];
1854  (*dQdxMatPtr)[li_MPro[i]][M_EquM_NodeOffset[i]] += dMQ_dM[i];
1855  (*dQdxMatPtr)[li_HPro[i]][H_EquH_NodeOffset[i]] += dHQ_dH[i];
1856  (*dQdxMatPtr)[li_cPro[i]][CEquCNodeOffset[i]] += dcQ_dc[i];
1857  (*dQdxMatPtr)[li_CaPro[i]][CaEquCaNodeOffset[i]] += dCaQ_dCa[i];
1858  }
1859 
1860  return bsuccess;
1861 }
1862 
1863 
1864 
1865 //-----------------------------------------------------------------------------
1866 // Function : Instance::loadDAEdFdx ()
1867 //
1868 // Purpose : Loads the F-vector contributions for a single
1869 // Neuron 4 instance.
1870 //
1871 // Special Notes : This is an algebraic constaint.
1872 //
1873 // Scope : public
1874 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1875 // Creation Date : 06/10/09
1876 //-----------------------------------------------------------------------------
1878 {
1879  bool bsuccess = true;
1880 
1881  N_LAS_Matrix * dFdxMatPtr = extData.dFdxMatrixPtr;
1882 
1883  (*dFdxMatPtr)[li_Pos][APosEquPosNodeOffset] += dkcl1F_dVin;
1884  (*dFdxMatPtr)[li_Pos][APosEquNextNodeOffset] += dkcl1F_dVs0;
1885 
1886  (*dFdxMatPtr)[li_Neg][ANegEquNegNodeOffset] += dkcl2F_dVout;
1887  (*dFdxMatPtr)[li_Neg][ANegEquLastNodeOffset] += dkcl2F_dVsn;
1888 
1889  for( int i=0; i<nSeg ; i++)
1890  {
1891  (*dFdxMatPtr)[li_Vol[i]][SegVEqnVpreOffset[i]] += segF_dVp[i];
1892  (*dFdxMatPtr)[li_Vol[i]][SegVEqnVsegOffset[i]] += segF_dV[i];
1893  (*dFdxMatPtr)[li_Vol[i]][SegVEqnVnexOffset[i]] += segF_dVn[i];
1894  (*dFdxMatPtr)[li_Vol[i]][SegVEqnNOffset[i]] += segF_dn[i];
1895  (*dFdxMatPtr)[li_Vol[i]][SegVEqnMOffset[i]] += segF_dm[i];
1896  (*dFdxMatPtr)[li_Vol[i]][SegVEqnHOffset[i]] += segF_dh[i];
1897 
1898  (*dFdxMatPtr)[li_nPro[i]][NEquVNodeOffset[i]] += dnF_dV[i];
1899  (*dFdxMatPtr)[li_nPro[i]][NEquNNodeOffset[i]] += dnF_dn[i];
1900  (*dFdxMatPtr)[li_mPro[i]][MEquVNodeOffset[i]] += dmF_dV[i];
1901  (*dFdxMatPtr)[li_mPro[i]][MEquMNodeOffset[i]] += dmF_dm[i];
1902  (*dFdxMatPtr)[li_hPro[i]][HEquVNodeOffset[i]] += dhF_dV[i];
1903  (*dFdxMatPtr)[li_hPro[i]][HEquHNodeOffset[i]] += dhF_dh[i];
1904 
1905  (*dFdxMatPtr)[li_aPro[i]][AEquVNodeOffset[i]] += daF_dV[i];
1906  (*dFdxMatPtr)[li_aPro[i]][AEquANodeOffset[i]] += daF_da[i];
1907 
1908  (*dFdxMatPtr)[li_bPro[i]][BEquVNodeOffset[i]] += dbF_dV[i];
1909  (*dFdxMatPtr)[li_bPro[i]][BEquBNodeOffset[i]] += dbF_db[i];
1910 
1911  (*dFdxMatPtr)[li_MPro[i]][M_EquVNodeOffset[i]] += dMF_dV[i];
1912  (*dFdxMatPtr)[li_MPro[i]][M_EquM_NodeOffset[i]] += dMF_dM[i];
1913 
1914  (*dFdxMatPtr)[li_HPro[i]][H_EquVNodeOffset[i]] += dHF_dV[i];
1915  (*dFdxMatPtr)[li_HPro[i]][H_EquH_NodeOffset[i]] += dHF_dH[i];
1916 
1917  (*dFdxMatPtr)[li_cPro[i]][CEquVNodeOffset[i]] += dcF_dV[i];
1918  (*dFdxMatPtr)[li_cPro[i]][CEquCNodeOffset[i]] += dcF_dc[i];
1919  (*dFdxMatPtr)[li_cPro[i]][CEquCaNodeOffset[i]] += dcF_dCa[i];
1920 
1921  (*dFdxMatPtr)[li_CaPro[i]][CaEquVNodeOffset[i]] += dCaF_dV[i];
1922  (*dFdxMatPtr)[li_CaPro[i]][CaEquM_NodeOffset[i]] += dCaF_dM[i];
1923  (*dFdxMatPtr)[li_CaPro[i]][CaEquH_NodeOffset[i]] += dCaF_dH[i];
1924  (*dFdxMatPtr)[li_CaPro[i]][CaEquCaNodeOffset[i]] += dCaF_dCa[i];
1925 
1926  }
1927 
1928  return bsuccess;
1929 }
1930 
1931 //-----------------------------------------------------------------------------
1932 // Function : Instance::setIC
1933 // Purpose :
1934 // Special Notes :
1935 // Scope : public
1936 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1937 // Creation Date : 06/10/09
1938 //-----------------------------------------------------------------------------
1940 {
1941  bool bsuccess = true;
1942 
1943  return bsuccess;
1944 }
1945 
1946 //-----------------------------------------------------------------------------
1947 // Function : Instance::varTypes
1948 // Purpose :
1949 // Special Notes :
1950 // Scope : public
1951 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1952 // Creation Date : 06/10/09
1953 //-----------------------------------------------------------------------------
1954 void Instance::varTypes( std::vector<char> & varTypeVec )
1955 {
1956  //varTypeVec.resize(1);
1957  //varTypeVec[0] = 'I';
1958 }
1959 
1960 
1961 //-----------------------------------------------------------------------------
1962 // Function : Model::processParams
1963 // Purpose :
1964 // Special Notes :
1965 // Scope : public
1966 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1967 // Creation Date : 06/10/09
1968 //-----------------------------------------------------------------------------
1970 {
1971  return true;
1972 }
1973 
1974 //----------------------------------------------------------------------------
1975 // Function : Model::processInstanceParams
1976 // Purpose :
1977 // Special Notes :
1978 // Scope : public
1979 // Creator : Richard Schiek, Electrical and Microsytem Modeling
1980 // Creation Date : 06/10/09
1981 //----------------------------------------------------------------------------
1983 {
1984 
1985  std::vector<Instance*>::iterator iter;
1986  std::vector<Instance*>::iterator first = instanceContainer.begin();
1987  std::vector<Instance*>::iterator last = instanceContainer.end();
1988 
1989  for (iter=first; iter!=last; ++iter)
1990  {
1991  (*iter)->processParams();
1992  }
1993 
1994  return true;
1995 }
1996 
1997 //-----------------------------------------------------------------------------
1998 // Function : Model::Model
1999 // Purpose : block constructor
2000 // Special Notes :
2001 // Scope : public
2002 // Creator : Richard Schiek, Electrical and Microsytem Modeling
2003 // Creation Date : 06/10/09
2004 //-----------------------------------------------------------------------------
2006  const Configuration & configuration,
2007  const ModelBlock & MB,
2008  const FactoryBlock & factory_block)
2009  : DeviceModel(MB, configuration.getModelParameters(), factory_block)
2010 {
2011 
2012  // Set params to constant default values:
2013  setDefaultParams ();
2014 
2015  // Set params according to .model line and constant defaults from metadata:
2016  setModParams (MB.params);
2017 
2018  // Set any non-constant parameter defaults:
2019  //if (!given("TNOM"))
2020  // tnom = getDeviceOptions().tnom;
2021 
2022  // Calculate any parameters specified as expressions:
2024 
2025  // calculate dependent (ie computed) params and check for errors:
2026  processParams ();
2027 }
2028 
2029 //-----------------------------------------------------------------------------
2030 // Function : Model::~Model
2031 // Purpose : destructor
2032 // Special Notes :
2033 // Scope : public
2034 // Creator : Richard Schiek, Electrical and Microsytem Modeling
2035 // Creation Date : 06/10/09
2036 //-----------------------------------------------------------------------------
2038 {
2039  std::vector<Instance*>::iterator iter;
2040  std::vector<Instance*>::iterator first = instanceContainer.begin();
2041  std::vector<Instance*>::iterator last = instanceContainer.end();
2042 
2043  for (iter=first; iter!=last; ++iter)
2044  {
2045  delete (*iter);
2046  }
2047 
2048 }
2049 
2050 // additional Declarations
2051 
2052 //-----------------------------------------------------------------------------
2053 // Function : Model::printOutInstances
2054 // Purpose : debugging tool.
2055 // Special Notes :
2056 // Scope : public
2057 // Creator : Richard Schiek, Electrical and Microsytem Modeling
2058 // Creation Date : 06/10/09
2059 //-----------------------------------------------------------------------------
2060 std::ostream &Model::printOutInstances(std::ostream &os) const
2061 {
2062  std::vector<Instance*>::const_iterator iter;
2063  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
2064  std::vector<Instance*>::const_iterator last = instanceContainer.end();
2065 
2066  int i, isize;
2067  isize = instanceContainer.size();
2068 
2069  os << std::endl;
2070  os << "Number of Neuron instances: " << isize << std::endl;
2071  os << " name=\t\tmodelName\tParameters" << std::endl;
2072  for (i=0, iter=first; iter!=last; ++iter, ++i)
2073  {
2074  os << " " << i << ": " << (*iter)->getName() << "\t";
2075  os << getName();
2076  os << std::endl;
2077  }
2078 
2079  os << std::endl;
2080  return os;
2081 }
2082 
2083 //-----------------------------------------------------------------------------
2084 // Function : Model::forEachInstance
2085 // Purpose :
2086 // Special Notes :
2087 // Scope : public
2088 // Creator : David Baur
2089 // Creation Date : 2/4/2014
2090 //-----------------------------------------------------------------------------
2091 /// Apply a device instance "op" to all instances associated with this
2092 /// model
2093 ///
2094 /// @param[in] op Operator to apply to all instances.
2095 ///
2096 ///
2097 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
2098 {
2099  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
2100  op(*it);
2101 }
2102 
2103 
2104 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
2105 {
2106 
2107  return new DeviceMaster<Traits>( configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
2108 }
2109 
2111 {
2113  .registerDevice("neuron", 4)
2114  .registerModelType("neuron", 4);
2115 }
2116 
2117 } // namespace Neuron4
2118 } // namespace Device
2119 } // namespace Xyce