Xyce  6.1
N_DEV_Synapse4.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-2015 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //----------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_Synapse4.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Christina Warrender, SNL, Cognitive Modeling
33 //
34 // Creation Date : 10/12/11
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.59.2.1 $
40 //
41 // Revision Date : $Date: 2015/04/02 18:29:38 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //----------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 //#define Xyce_FullSynapseJac 1
48 
49 // ---------- Standard Includes ----------
50 // used to get time in seconds to seed random number generator.
51 #include<time.h>
52 
53 // ---------- Xyce Includes ----------
54 //
55 #include <N_DEV_Const.h>
56 #include <N_DEV_DeviceOptions.h>
57 #include <N_DEV_DeviceMaster.h>
58 #include <N_DEV_ExternData.h>
59 #include <N_DEV_MatrixLoadData.h>
60 #include <N_DEV_SolverState.h>
61 #include <N_DEV_Synapse4.h>
62 #include <N_DEV_Message.h>
63 #include <N_ERH_ErrorMgr.h>
64 
65 #include <N_DEV_Synapse.h>
66 
67 #include <N_LAS_Matrix.h>
68 #include <N_LAS_Vector.h>
69 #include <N_UTL_FeatureTest.h>
70 
71 namespace Xyce {
72 namespace Device {
73 
74 namespace Synapse4 {
75 
77 {
78  p.addPar ("GMAX",0.01,&Synapse4::Instance::gMax)
79  .setGivenMember(&Synapse4::Instance::gMaxGiven)
80  .setUnit(U_OHMM1)
81  .setCategory(CAT_NONE)
82  .setDescription("Maximal Synaptic Conductance");
83 }
84 
86 {
87  p.addPar ("VTHRESH",0.01,&Synapse4::Model::vThresh)
88  .setUnit(U_VOLT)
89  .setDescription("Presynaptic voltage spike threhsold");
90 
91  p.addPar ("DELAY",0.001,&Synapse4::Model::delay)
92  .setUnit(U_SECOND)
93  .setDescription("Time delay between presynaptic signal and postsynaptic response");
94 
95  p.addPar ("GMAX",0.01,&Synapse4::Model::gMax)
96  .setUnit(U_OHMM1)
97  .setDescription("Maximal Synaptic Conductance");
98 
99  p.addPar ("EREV",0.0,&Synapse4::Model::eRev)
100  .setUnit(U_VOLT)
101  .setDescription("Postsynaptic Reversal Potential");
102 
103  p.addPar ("TAU1",0.0001,&Synapse4::Model::tau1)
104  .setUnit(U_SECM1)
105  .setDescription("Rise time constant");
106 
107  p.addPar ("TAU2",0.01,&Synapse4::Model::tau2)
108  .setUnit(U_SECM1)
109  .setDescription("Decay time constant");
110 }
111 
112 std::vector< std::vector<int> > Instance::jacStamp;
113 
114 // Class Instance
115 //-----------------------------------------------------------------------------
116 // Function : Instance::processParams
117 // Purpose :
118 // Special Notes :
119 // Scope : public
120 // Creator : Christina Warrender, SNL,
121 // Creation Date : 10/12/11
122 //-----------------------------------------------------------------------------
124 {
125  // initialization
126  respondTime = std::numeric_limits<double>::max( );
127  ready = true;
128  //active = false;
129 
130  return true;
131 }
132 
133 //-----------------------------------------------------------------------------
134 // Function : Instance::Instance
135 // Purpose : instance block constructor
136 // Special Notes :
137 // Scope : public
138 // Creator : Christina Warrender, SNL,
139 // Creation Date : 10/12/11
140 //-----------------------------------------------------------------------------
142  const Configuration & configuration,
143  const InstanceBlock & IB,
144  Model & Riter,
145  const FactoryBlock & factory_block)
146  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
147  model_(Riter),
148  li_Prev(-1),
149  li_Post(-1),
150  li_A0_store(-1),
151  li_B0_store(-1),
152  li_t0_store(-1),
153  li_store_dev_i(-1),
154 #ifdef Xyce_FullSynapseJac
155  APostEquPostNodeOffset(-1),
156  f_PostEquPostNodePtr(0),
157 #endif
158  ipost(0),
159  didVpost(0),
160  randInitialized(false)
161 {
162  numIntVars = 0; // A and B 2
163  numExtVars = 2; // presynaptic V and postsynaptic V
164  setNumStoreVars(3); // A0, B0, t0
166 
167  if( jacStamp.empty() )
168  {
169  jacStamp.resize(2);
170  jacStamp[0].resize(0); // presynaptic V not changed
171 #ifdef Xyce_FullSynapseJac
172  jacStamp[1].resize(1); // postsynaptic V depends on itself
173 #else
174  jacStamp[1].resize(0); // postsynaptic V depends on itself
175 #endif
176  }
177 
178 
179  // Set params to constant default values:
180  setDefaultParams ();
181 
182  // Set params according to instance line and constant defaults from metadata:
183  setParams (IB.params);
184 
185  // Set any non-constant parameter defaults:
186 
187  if (!gMaxGiven )
188  {
189  gMax = model_.gMax;
190  }
191 
192  // Calculate any parameters specified as expressions:
194 
195  // calculate dependent (ie computed) params and check for errors:
196  processParams ();
197 }
198 
199 //-----------------------------------------------------------------------------
200 // Function : Instance::~Instance
201 // Purpose : destructor
202 // Special Notes :
203 // Scope : public
204 // Creator : Christina Warrender, SNL,
205 // Creation Date : 10/12/11
206 //-----------------------------------------------------------------------------
208 {
209 }
210 
211 //-----------------------------------------------------------------------------
212 // Function : Instance::registerLIDs
213 // Purpose :
214 // Special Notes :
215 // Scope : public
216 // Creator : Christina Warrender, SNL,
217 // Creation Date : 10/12/11
218 //-----------------------------------------------------------------------------
219 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
220  const std::vector<int> & extLIDVecRef )
221 {
222  AssertLIDs(intLIDVecRef.size() == numIntVars);
223  AssertLIDs(extLIDVecRef.size() == numExtVars);
224 
225  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
226  {
227  Xyce::dout() << std::endl << section_divider << std::endl;
228  Xyce::dout() << " SynapseInstance::registerLIDs" << std::endl;
229  Xyce::dout() << " name = " << getName() << std::endl;
230  }
231 
232  // copy over the global ID lists.
233  intLIDVec = intLIDVecRef;
234  extLIDVec = extLIDVecRef;
235 
236  li_Prev = extLIDVec[0];
237  li_Post = extLIDVec[1];
238 
239  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
240  {
241  Xyce::dout() << " li_Prev = " << li_Prev << std::endl;
242  Xyce::dout() << " li_Post = " << li_Post << std::endl;
243  }
244 
245  /*
246  li_AVar = intLIDVec[0];
247  li_BVar = intLIDVec[1];
248  */
249 
250  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
251  {
252  Xyce::dout() << section_divider << std::endl;
253  }
254 }
255 
256 //-----------------------------------------------------------------------------
257 // Function : Instance::loadNodeSymbols
258 // Purpose :
259 // Special Notes :
260 // Scope : public
261 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
262 // Creation Date : 05/13/05
263 //-----------------------------------------------------------------------------
264 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
265 {
266  addStoreNode(symbol_table, li_A0_store, getName().getEncodedName() + "_A0");
267  addStoreNode(symbol_table, li_B0_store, getName().getEncodedName() + "_B0");
268  addStoreNode(symbol_table, li_t0_store, getName().getEncodedName() + "_T0");
269 
270  if (loadLeadCurrent)
271  addStoreNode(symbol_table, li_store_dev_i, getName(), "DEV_I");
272 }
273 
274 //-----------------------------------------------------------------------------
275 // Function : Instance::registerStoreLIDs
276 // Purpose :
277 // Special Notes :
278 // Scope : public
279 // Creator : Christina Warrender, SNL,
280 // Creation Date : 10/12/11
281 //-----------------------------------------------------------------------------
282 void Instance::registerStoreLIDs(const std::vector<int> & stoLIDVecRef )
283 {
284  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
285 
286  // copy over the global ID lists.
287  stoLIDVec = stoLIDVecRef;
288 
289  li_A0_store = stoLIDVec[0];
290  li_B0_store = stoLIDVec[1];
291  li_t0_store = stoLIDVec[2];
292  if( loadLeadCurrent )
293  {
294  li_store_dev_i = stoLIDVec[3];
295  }
296 
297 }
298 
299 //-----------------------------------------------------------------------------
300 // Function : Instance::jacobianStamp
301 // Purpose :
302 // Special Notes :
303 // Scope : public
304 // Creator : Christina Warrender, SNL,
305 // Creation Date : 10/12/11
306 //-----------------------------------------------------------------------------
307 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
308 {
309  return jacStamp;
310 }
311 
312 //-----------------------------------------------------------------------------
313 // Function : Instance::registerJacLIDs
314 // Purpose :
315 // Special Notes :
316 // Scope : public
317 // Creator : Christina Warrender, SNL,
318 // Creation Date : 10/12/11
319 //-----------------------------------------------------------------------------
320 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
321 {
322  DeviceInstance::registerJacLIDs( jacLIDVec );
323 #ifdef Xyce_FullSynapseJac
324  APostEquPostNodeOffset = jacLIDVec[1][0];
325 #endif
326 }
327 
328 //-----------------------------------------------------------------------------
329 // Function : Instance::setupPointers
330 // Purpose :
331 // Special Notes :
332 // Scope : public
333 // Creator : Christina Warrender, SNL
334 // Creation Date : 10/12/11
335 //-----------------------------------------------------------------------------
337 {
338 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
339 #ifdef Xyce_FullSynapseJac
340  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
341  f_PostEquPostNodePtr = &(dFdx[li_Post][APostEquPostNodeOffset]);
342 #endif
343 #endif
344 }
345 
346 //-----------------------------------------------------------------------------
347 // Function : Instance::updateIntermediateVars
348 // Purpose : update intermediate variables for one synapse instance
349 // Special Notes :
350 // Scope : public
351 // Creator : Christina Warrender, SNL
352 // Creation Date : 10/12/11
353 //-----------------------------------------------------------------------------
355 {
356  bool bsuccess = true;
357 
358  double * lastSolVecPtr = extData.lastSolVectorRawPtr;
359  double * stoVector = extData.nextStoVectorRawPtr;
360  double * lastStoVec = extData.lastStoVectorRawPtr;
361 
362  // initialized random number generator if needed
363  if( !randInitialized )
364  {
365  if( getDeviceOptions().randomSeed != 0 )
366  {
367  devSupport.SetSeed( getDeviceOptions().randomSeed );
368  }
369  else
370  {
371  unsigned int aSeed = static_cast<unsigned int>(time( NULL ) ) ;
372  devSupport.SetSeed( aSeed );
373  }
374  randInitialized=true;
375  }
376 
377  // This check need to
378  // Check for presynaptic spike start, set time to respond
379  double vPre = lastSolVecPtr[li_Prev];
380  double vPost = lastSolVecPtr[li_Post];
381  double time = getSolverState().currTime;
382  double vThresh = model_.vThresh;
383  double delay = model_.delay;
384  if (ready)
385  {
386  if (vPre > vThresh)
387  {
388  ready=false;
389  respondTime = time + delay;
390  }
391  }
392  else // already had spike start, looking for end
393  {
394  if (vPre < vThresh)
395  {
396  ready=true;
397  }
398  }
399 
400  // only need to update state variables and synaptic current when synapse active
401  // disabling testing for this because determining the point at which the synaptic current
402  // becomes negligible is somewhat problematic, and there don't appear to be significant savings
403  // from avoiding loads when synapse is inactive
404  //if (active)
405  {
406  // handle decay of A and B
407  double tau1 = model_.tau1;
408  double tau2 = model_.tau2;
409 
410  double t0 = stoVector[li_t0_store];
411  double Anow = stoVector[li_A0_store] * exp( - ( time - t0 ) / tau1 );
412  double Bnow = stoVector[li_B0_store] * exp( - ( time - t0 ) / tau2 );
413 
414  // set up variables for load methods
415  // current equation is the same whether we're responding to spike or not,
416  // assuming current A and B values set appropriately above
417  // ipost = (B-A)*(V-Erev)
418 
419  double eRev = model_.eRev;
420  double cond = Bnow-Anow;
421  ipost = cond*(vPost-eRev);
422  didVpost = cond;
423 
424  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
425  {
426  Xyce::dout() << std::endl << section_divider << std::endl;
427  Xyce::dout() << " SynapseInstance::updateIntermediateVars" << std::endl;
428  Xyce::dout() << "Anow: " << Anow << std::endl;
429  Xyce::dout() << "Bnow: " << Bnow << std::endl;
430  Xyce::dout() << "vPost: " << vPost << std::endl;
431  Xyce::dout() << "eRev: " << eRev << std::endl;
432  Xyce::dout() << "ipost: " << ipost << std::endl;
433  Xyce::dout() << "didVpost: " << didVpost << std::endl;
434  }
435 
436  } // end if synapse active
437 
438  return bsuccess;
439 }
440 
441 //-----------------------------------------------------------------------------
442 // Function : Instance::updatePrimaryState
443 // Purpose :
444 // Special Notes :
445 // Scope : public
446 // Creator : Christina Warrender, SNL,
447 // Creation Date : 10/12/11
448 //-----------------------------------------------------------------------------
450 {
451  bool bsuccess = updateIntermediateVars();
452  return bsuccess;
453 }
454 
455 //-----------------------------------------------------------------------------
456 // Function : Instance::updateSecondaryState
457 // Purpose :
458 // Special Notes :
459 // Scope : public
460 // Creator : Christina Warrender, SNL,
461 // Creation Date : 10/12/11
462 //-----------------------------------------------------------------------------
464 {
465  return true;
466 }
467 
468 //-----------------------------------------------------------------------------
469 // Function : Instance::loadDAEQVector
470 //
471 // Purpose : Loads the Q-vector contributions for a single
472 // Synapse4
473 //
474 // Special Notes : The "Q" vector is part of a standard DAE formalism in
475 // which the system of equations is represented as:
476 //
477 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
478 //
479 // The "Q" vector contains charges and fluxes, mostly.
480 // However, it is ordered like the solution vector, and as
481 // it is part of the KCL formulation, the terms in Q will
482 // actually be *sums* of charges, rather than single
483 // distinct charges.
484 //
485 // Scope : public
486 // Creator : Christina Warrender, SNL,
487 // Creation Date : 10/12/11
488 //-----------------------------------------------------------------------------
490 {
491  return true;
492 }
493 //-----------------------------------------------------------------------------
494 // Function : Instance::loadDAEFVector
495 //
496 // Purpose : Loads the F-vector contributions for a single
497 // Synapse4 instance.
498 //
499 // Special Notes : This is an algebraic constaint, and as such the Synapse4
500 // does make a contribution to it.
501 //
502 // Scope : public
503 // Creator : Christina Warrender, SNL,
504 // Creation Date : 10/12/11
505 //-----------------------------------------------------------------------------
507 {
508  Linear::Vector * fVecPtr = extData.daeFVectorPtr;
509  (*fVecPtr)[li_Prev] += 0.0;
510  (*fVecPtr)[li_Post] += ipost;
511  if( loadLeadCurrent )
512  {
513  double * stoVec = extData.nextStoVectorRawPtr;
514  stoVec[li_store_dev_i] = ipost;
515  }
516  return true;
517 }
518 
519 //-----------------------------------------------------------------------------
520 // Function : Instance::loadDAEdQdx
521 //
522 // Purpose : Loads the dQdx-matrix contributions for a single
523 // Synapse4 instance.
524 //
525 // Special Notes : The "Q" vector is part of a standard DAE formalism in
526 // which the system of equations is represented as:
527 //
528 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
529 //
530 // The "Q" vector contains charges and fluxes, mostly.
531 // However, it is ordered like the solution vector, and as
532 // it is part of the KCL formulation, the terms in Q will
533 // actually be *sums* of charges, rather than single
534 // distinct charges.
535 //
536 // Scope : public
537 // Creator : Christina Warrender, SNL,
538 // Creation Date : 10/12/11
539 //-----------------------------------------------------------------------------
541 {
542  return true;
543 }
544 
545 //-----------------------------------------------------------------------------
546 // Function : Instance::loadDAEdFdx ()
547 //
548 // Purpose : Loads the F-vector contributions for a single
549 // Synapse4 instance.
550 //
551 // Special Notes : This is an algebraic constaint, and as such the Synapse4
552 // does make a contribution to it.
553 //
554 // Scope : public
555 // Creator : Christina Warrender, SNL,
556 // Creation Date : 10/12/11
557 //-----------------------------------------------------------------------------
559 {
560 #ifdef Xyce_FullSynapseJac
561  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
562  dFdx[li_Post][APostEquPostNodeOffset] += didVpost;
563 #endif
564  return true;
565 }
566 
567 //-----------------------------------------------------------------------------
568 // Function : InstanceInstance::outputPlotFiles
569 // Purpose : If requested by the user output all the variables
570 // associated with the population
571 // Special Notes : We're actually using this method not for output, but because
572 // it's called after the system has converged. In this case,
573 // that let us mark the end of handling a presynaptic event.
574 // Scope : public
575 // Creator : Christina Warrender, SNL, Cognitive Modeling
576 // Creation Date : 10/25/2011
577 //-----------------------------------------------------------------------------
579 {
580  bool bsuccess = true;
581 
582  // cew 11/3/11: changing this back to just storing A0 and B0 for updateIntermediateVars
583  // to use in calculating A, B, and ipost
584  // But when incrementing A0 (B0), current value of A (B) must be used.
585 
586  double time = getSolverState().currTime;
587  //Linear::Vector * staVector = extData.nextStaVectorPtr;
588  double * stoVector = extData.nextStoVectorRawPtr;
589  if (time >= respondTime)
590  {
591  //Xyce::dout() << "Instance::outputPlotFiles() adjusting A0, B0 and t0 = " << getSolverState().currTime << std::endl;
592  // succesfully processed a step, so adjust the next
593  // respondTime to distant future
594  respondTime = std::numeric_limits<double>::max( );
595  //active = true;
596 
597  // now we also update the A0, B0 and t0 in the state vector
598  double factor = model_.factor;
599  double deltaAB = factor*gMax;
600  double tau1 = model_.tau1;
601  double tau2 = model_.tau2;
602  double t0 = stoVector[li_t0_store];
603  double Anow = stoVector[li_A0_store] * exp( - ( time - t0 ) / tau1 );
604  double Bnow = stoVector[li_B0_store] * exp( - ( time - t0 ) / tau2 );
605  stoVector[li_A0_store] = Anow + deltaAB;
606  stoVector[li_B0_store] = Bnow + deltaAB;
607  stoVector[li_t0_store] = getSolverState().currTime;
608  //Xyce::dout() << "A: " << (*staVector)[li_A0_state] << " B: " << (*staVector)[li_B0_state] << std::endl;
609  }
610 
611 /* disabling this because determining the point at which the synaptic current becomes negligible
612  is somewhat problematic, and there don't appear to be significant savings from avoiding loads
613  when synapse is inactive
614  if (active)
615  {
616  // determine when we can stop updating synaptic current, when it's negligible
617  // can't use magnitude of current, because it starts off small initially
618  // instead, determine whether time since last spike is greater than reasonable multiple of
619  // larger time constant
620  if ( (time-(*staVector)[li_t0_state])>3.0*model_.maxtau )
621  {
622  active = false;
623  ipost = 0.0;
624  didVpost = 0.0;
625  }
626  }
627 */
628 
629  return bsuccess;
630 }
631 
632 //-----------------------------------------------------------------------------
633 // Function : Instance::updateTemperature
634 // Purpose :
635 // Special Notes :
636 // Scope : public
637 // Creator : Tom Russo, Component Information and Models
638 // Creation Date : 10/12/11
639 //-----------------------------------------------------------------------------
640 bool Instance::updateTemperature ( const double & temp_tmp)
641 {
642  bool bsuccess = true;
643  return bsuccess;
644 }
645 
646 //-----------------------------------------------------------------------------
647 // Function : Model::processParams
648 // Purpose :
649 // Special Notes :
650 // Scope : public
651 // Creator : Christina Warrender, SNL,
652 // Creation Date : 10/12/11
653 //-----------------------------------------------------------------------------
655 {
656  // initialize variables needed to calculate synaptic dynamics
657  if (tau1/tau2 > .9999) {
658  tau1 = .9999*tau2;
659  }
660  tp = (tau1*tau2)/(tau2 - tau1) * log(tau2/tau1);
661  factor = -exp(-tp/tau1) + exp(-tp/tau2);
662  factor = 1/factor;
663  maxtau = (tau1>tau2)?tau1:tau2;
664 
665  return true;
666 }
667 
668 //----------------------------------------------------------------------------
669 // Function : Model::processInstanceParams
670 // Purpose :
671 // Special Notes :
672 // Scope : public
673 // Creator : Dave Shirely, PSSI
674 // Creation Date : 10/12/11
675 //----------------------------------------------------------------------------
677 {
678 
679  std::vector<Instance*>::iterator iter;
680  std::vector<Instance*>::iterator first = instanceContainer.begin();
681  std::vector<Instance*>::iterator last = instanceContainer.end();
682 
683  for (iter=first; iter!=last; ++iter)
684  {
685  (*iter)->processParams();
686  }
687 
688  return true;
689 }
690 
691 //-----------------------------------------------------------------------------
692 // Function : Model::Model
693 // Purpose : model block constructor
694 // Special Notes :
695 // Scope : public
696 // Creator : Christina Warrender, SNL,
697 // Creation Date : 10/12/11
698 //-----------------------------------------------------------------------------
700  const Configuration & configuration,
701  const ModelBlock & MB,
702  const FactoryBlock & factory_block)
703  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
704  vThresh(0.0),
705  delay(0.0),
706  gMax(0.0),
707  eRev(0.0),
708  tau1(0.0),
709  tau2(0.0)
710 {
711 
712  // Set params to constant default values:
713  setDefaultParams ();
714 
715  // Set params according to .model line and constant defaults from metadata:
716  setModParams (MB.params);
717 
718  // Set any non-constant parameter defaults:
719 
720  // Calculate any parameters specified as expressions:
722 
723  // calculate dependent (ie computed) params and check for errors:
724  processParams();
725 }
726 
727 //-----------------------------------------------------------------------------
728 // Function : Model::~Model
729 // Purpose : destructor
730 // Special Notes :
731 // Scope : public
732 // Creator : Christina Warrender, SNL,
733 // Creation Date : 10/12/11
734 //-----------------------------------------------------------------------------
736 {
737  std::vector<Instance*>::iterator iter;
738  std::vector<Instance*>::iterator first = instanceContainer.begin();
739  std::vector<Instance*>::iterator last = instanceContainer.end();
740 
741  for (iter=first; iter!=last; ++iter)
742  {
743  delete (*iter);
744  }
745 }
746 
747 //-----------------------------------------------------------------------------
748 // Function : Model::printOutInstances
749 // Purpose : debugging tool.
750 // Special Notes :
751 // Scope : public
752 // Creator : Christina Warrender, SNL,
753 // Creation Date : 10/12/11
754 //-----------------------------------------------------------------------------
755 std::ostream &Model::printOutInstances(std::ostream &os) const
756 {
757  std::vector<Instance*>::const_iterator iter;
758  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
759  std::vector<Instance*>::const_iterator last = instanceContainer.end();
760 
761  int i,isize;
762  isize = instanceContainer.size();
763  os << std::endl;
764  os << "Number of Synapse4 Instances: " << isize << std::endl;
765  os << " name model name Parameters" << std::endl;
766  for (i=0, iter=first; iter!=last; ++iter, ++i)
767  {
768  os << " " << i << ": " << (*iter)->getName() << "\t";
769  os << getName();
770  os << std::endl;
771  }
772 
773  os << std::endl;
774  return os;
775 }
776 
777 //-----------------------------------------------------------------------------
778 // Function : Model::forEachInstance
779 // Purpose :
780 // Special Notes :
781 // Scope : public
782 // Creator : David Baur
783 // Creation Date : 2/4/2014
784 //-----------------------------------------------------------------------------
785 /// Apply a device instance "op" to all instances associated with this
786 /// model
787 ///
788 /// @param[in] op Operator to apply to all instances.
789 ///
790 ///
791 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
792 {
793  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
794  op(*it);
795 }
796 
797 
798 //-----------------------------------------------------------------------------
799 // Function : Master::updateState
800 // Purpose :
801 // Special Notes :
802 // Scope : public
803 // Creator : Christina Warrender, SNL, Cognitive Modeling
804 // Creation Date : 07/18/12
805 //-----------------------------------------------------------------------------
806 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
807 {
808  if( getSolverState().dcopFlag )
809  {
810  // no synaptic activity during dcop
811  return true;
812  }
813 
814  bool bsuccess = true;
815 
816 #ifdef _OMP
817 #pragma omp parallel for reduction (&&:bsuccess)
818 #endif
819 
820  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
821  {
822  bool tmpBool = (*it)->updateIntermediateVars(); // skipping call to updatePrimaryState
823  bsuccess = bsuccess && tmpBool;
824  }
825 
826  return bsuccess;
827 }
828 
829 //-----------------------------------------------------------------------------
830 // Function : Master::updateSecondaryState
831 // Purpose :
832 // Special Notes :
833 // Scope : public
834 // Creator : Christina Warrender, SNL, Cognitive Modeling
835 // Creation Date : 7/18/12
836 //-----------------------------------------------------------------------------
837 bool Master::updateSecondaryState (double * staDerivVec, double *stoVec)
838 {
839  // not used for this device
840  return true;
841 }
842 
843 
844 //-----------------------------------------------------------------------------
845 // Function : Master::loadDAEVectors
846 // Purpose :
847 // Special Notes :
848 // Scope : public
849 // Creator : Christina Warrender, SNL, Cognitive Modeling
850 // Creation Date : 07/16/12
851 //-----------------------------------------------------------------------------
852 bool Master::loadDAEVectors(double * solVec, double * fVec, double * qVec, double * bVec, double * storeLeadF, double * storeLeadQ, double * leadF, double * leadQ, double * junctionV)
853 {
854  if( getSolverState().dcopFlag )
855  {
856  // no synaptic activity during dcop
857  return true;
858  }
859 
860  bool bsuccess = true;
861 
862  // We don't need Q loads for this synapse device at all
863  // Only need to do F loads if there's a nonzero synaptic current
864  // disabling testing for the latter because determining the point at which the synaptic current
865  // becomes negligible is somewhat problematic, and there don't appear to be significant savings
866  // from avoiding loads when synapse is inactive
867 
868  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
869  {
870  bool tmpBool = (*it)->loadDAEFVector();
871  bsuccess = bsuccess && tmpBool;
872  }
873 
874  return bsuccess;
875 }
876 
877 //-----------------------------------------------------------------------------
878 // Function : Master::loadDAEMatrices
879 // Purpose :
880 // Special Notes :
881 // Scope : public
882 // Creator : Christina Warrender, SNL, Cognitive Modeling
883 // Creation Date : 07/16/12
884 //-----------------------------------------------------------------------------
885 bool Master::loadDAEMatrices (Linear::Matrix & dFdx, Linear::Matrix & dQdx)
886 {
887  if( getSolverState().dcopFlag )
888  {
889  // no synaptic activity during dcop
890  return true;
891  }
892 
893  bool bsuccess = true;
894 
895  // We don't need Q loads for this synapse device at all
896  // Only need to do F loads if there's a nonzero synaptic current
897  // disabling testing for the latter because determining the point at which the synaptic current
898  // becomes negligible is somewhat problematic, and there don't appear to be significant savings
899  // from avoiding loads when synapse is inactive
900 
901  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
902  {
903  bool tmpBool = (*it)->loadDAEdFdx();
904  bsuccess = bsuccess && tmpBool;
905  }
906 
907  return bsuccess;
908 }
909 
910 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
911 {
912 
913  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
914 }
915 
917 {
919  .registerDevice("synapse", 4)
920  .registerModelType("synapse", 4);
921 }
922 
923 } // namespace Synapse4
924 } // namespace Device
925 } // namespace Xyce
const InstanceName & getName() const
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
bool updateTemperature(const double &temp_tmp)
virtual bool updateState(double *solVec, double *staVec, double *stoVec)
Updates the devices state information.
static std::vector< std::vector< int > > jacStamp
const DeviceOptions & deviceOptions_
Descriptor & addPar(const char *parName, T default_value, T U::*varPtr)
Adds the parameter description to the parameter map.
Definition: N_DEV_Pars.h:1429
static void loadModelParameters(ParametricData< Model > &model_parameters)
virtual bool loadDAEVectors(double *solVec, double *fVec, double *qVec, double *bVec, double *storeLeadF, double *storeLeadQ, double *leadF, double *leadQ, double *junctionV)
Populates the device's ExternData object with these pointers.
Pure virtual class to augment a linear system.
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
void setNumStoreVars(int num_store_vars)
InstanceVector::const_iterator getInstanceEnd() const
Returns an iterator to the ending of the vector of all instances created for this device...
#define AssertLIDs(cmp)
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
InstanceVector::const_iterator getInstanceBegin() const
Returns an iterator to the beginning of the vector of all instances created for this device...
int SetSeed(unsigned int seedIn)
std::vector< Param > params
Parameters from the line.
void setParams(const std::vector< Param > &params)
const std::string & getName() const
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
void registerStoreLIDs(const std::vector< int > &stoLIDVecRef)
const DeviceOptions & getDeviceOptions() const
virtual bool updateSecondaryState(double *staDeriv, double *stoVec)
Updates the devices secondary state information.
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
Linear::Matrix * dFdxMatrixPtr
bool processParams()
processParams
The Device class is an interface for device implementations.
Definition: N_DEV_Device.h:101
void addStoreNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
bool processInstanceParams()
processInstanceParams
const SolverState & solverState_
Class Configuration contains device configuration data.
std::vector< Instance * > instanceContainer
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &Riter, const FactoryBlock &factory_block)
const SolverState & getSolverState() const
virtual std::ostream & printOutInstances(std::ostream &os) const
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
Linear::Vector * daeFVectorPtr
virtual bool loadDAEMatrices(Linear::Matrix &dFdx, Linear::Matrix &dQdx)
Populates the device's Jacobian object with these pointers.
const std::vector< std::vector< int > > & jacobianStamp() const
ModelBlock represents a .MODEL line from the netlist.
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
InstanceBlock represent a device instance line from the netlist.
std::vector< Param > params
const SolverState & getSolverState() const
Returns the solver state given during device construction.
void setModParams(const std::vector< Param > &params)