Xyce  6.1
N_DEV_Synapse3.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_Synapse3.C,v $
27 //
28 // Purpose : Simple Clopath synapse
29 //
30 // Special Notes :
31 //
32 // Creator : Rich Schiek, SNL, Electrical Systems Modeling
33 //
34 // Creation Date : 01/25/2011
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.53.2.1 $
40 //
41 // Revision Date : $Date: 2015/04/02 18:29:38 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-------------------------------------------------------------------------
45 
46 
47 #include <Xyce_config.h>
48 //#define Xyce_FullSynapseJac 1
49 
50 // ---------- Standard Includes ----------
51 // used to get time in seconds to seed random number generator.
52 #include<time.h>
53 
54 // ---------- Xyce Includes ----------
55 //
56 #include <N_DEV_Const.h>
57 #include <N_DEV_DeviceOptions.h>
58 #include <N_DEV_DeviceMaster.h>
59 #include <N_DEV_ExternData.h>
60 #include <N_DEV_MatrixLoadData.h>
61 #include <N_DEV_SolverState.h>
62 #include <N_DEV_Synapse3.h>
63 #include <N_DEV_Message.h>
64 #include <N_ERH_ErrorMgr.h>
65 
66 #include <N_DEV_Synapse.h>
67 
68 #include <N_LAS_Matrix.h>
69 #include <N_LAS_Vector.h>
70 #include <N_UTL_FeatureTest.h>
71 
72 namespace Xyce {
73 namespace Device {
74 
75 namespace Synapse3 {
76 
78 {
79  p.addPar ("GMAX",0.01,&Synapse3::Instance::gMax)
80  .setGivenMember(&Synapse3::Instance::gMaxGiven)
81  .setUnit(U_OHMM1)
82  .setCategory(CAT_NONE)
83  .setDescription("Maximal Synaptic Conductance");
84 
87  .setUnit(U_NONE)
88  .setCategory(CAT_NONE)
89  .setDescription("Transmission Probability");
90 
93  .setUnit(U_NONE)
94  .setCategory(CAT_NONE)
95  .setDescription("Synaptic weight,initial value");
96 }
97 
99 {
100  p.addPar ("VTHRESH",0.01,&Synapse3::Model::vThresh)
101  .setUnit(U_VOLT)
102  .setDescription("Presynaptic voltage spike threhsold");
103 
104  p.addPar ("DELAY",0.001,&Synapse3::Model::delay)
105  .setUnit(U_SECOND)
106  .setDescription("Time delay between presynaptic signal and postsynaptic response");
107 
108  p.addPar ("GMAX",0.01,&Synapse3::Model::gMax)
109  .setUnit(U_OHMM1)
110  .setDescription("Maximal Synaptic Conductance");
111 
112  p.addPar ("EREV",0.0,&Synapse3::Model::eRev)
113  .setUnit(U_VOLT)
114  .setDescription("Postsynaptic Reversal Potential");
115 
116  p.addPar ("TAU1",0.0001,&Synapse3::Model::tau1)
117  .setUnit(U_SECM1)
118  .setDescription("Rise time constant");
119 
120  p.addPar ("TAU2",0.01,&Synapse3::Model::tau2)
121  .setUnit(U_SECM1)
122  .setDescription("Decay time constant");
123 
124  p.addPar ("S",0.01,&Synapse3::Model::sParam)
125  .setUnit(U_VOLT)
126  .setDescription("Voltage threshold for a spike event");
127 
128  p.addPar ("R",0.01,&Synapse3::Model::rParam)
129  .setUnit(U_VOLT)
130  .setDescription("Resting voltage for resting event");
131 
132  p.addPar ("WMIN",0.01,&Synapse3::Model::wMin)
133  .setDescription("Synaptic weight,minimum value");
134 
135  p.addPar ("WMAX",0.01,&Synapse3::Model::wMax)
136  .setDescription("Synaptic weight,maximum value");
137 
138  p.addPar ("WINIT",0.01,&Synapse3::Model::wInitialValue)
139  .setDescription("Synaptic weight,initial value");
140 
141  p.addPar ("L1TAU",0.01,&Synapse3::Model::vL1tau1)
142  .setUnit(U_SECOND)
143  .setDescription("Rate for Longterm potentiation factor (LPF) based on post-synaptic voltage (rate 1)");
144 
145  p.addPar ("L2TAU",0.01,&Synapse3::Model::vL2tau2)
146  .setUnit(U_SECOND)
147  .setDescription("Rate for Longterm potentiation factor (LPF) based on post-synaptic voltage (rate 2)");
148 
149  p.addPar ("L3TAU",0.01,&Synapse3::Model::vL3tau3)
150  .setUnit(U_SECOND)
151  .setDescription("Rate for Longterm potentiation factor (LPF) based on pre-synaptic voltage (rate 3)");
152 
153  p.addPar ("ALTD",0.01,&Synapse3::Model::aLTD)
154  .setDescription("Long term depression coefficient");
155 
156  p.addPar ("ALTP",0.01,&Synapse3::Model::aLTP)
157  .setDescription("Long term potentiation coefficient");
158 
160  .setDescription("Transmission Probability");
161 }
162 
163 std::vector< std::vector<int> > Instance::jacStamp;
164 
165 // Class Instance
166 //-----------------------------------------------------------------------------
167 // Function : Instance::processParams
168 // Purpose :
169 // Special Notes :
170 // Scope : public
171 // Creator : Christina Warrender, SNL,
172 // Creation Date : 10/12/11
173 //-----------------------------------------------------------------------------
175 {
176  // initialization
177  respondTime = std::numeric_limits<double>::max( );
178  ready = true;
179 
180  return true;
181 }
182 
183 //-----------------------------------------------------------------------------
184 // Function : Instance::Instance
185 // Purpose : instance block constructor
186 // Special Notes :
187 // Scope : public
188 // Creator : Christina Warrender, SNL,
189 // Creation Date : 10/12/11
190 //-----------------------------------------------------------------------------
192  const Configuration & configuration,
193  const InstanceBlock & IB,
194  Model & Riter,
195  const FactoryBlock & factory_block)
196 
197  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
198  model_(Riter),
199  li_Prev(-1),
200  li_Post(-1),
201  li_A0_store(-1),
202  li_B0_store(-1),
203  li_t0_store(-1),
204  li_weight_store(-1),
205  li_VL1_store(-1),
206  li_VL2_store(-1),
207  li_VL3_store(-1),
208  li_store_dev_i(-1),
209 #ifdef Xyce_FullSynapseJac
210  APostEquPostNodeOffset(-1),
211  f_PostEquPostNodePtr(0),
212 #endif
213  transmissionProbability(1.0),
214  transmissionFactor(1),
215  ipost(0),
216  didVpost(0),
217  randInitialized(false)
218 {
219  numIntVars = 0; // A and B 2
220  numExtVars = 2; // presynaptic V and postsynaptic V
221  setNumStoreVars(7); // A0, B0, t0, weight, vl1, vl2, vl3
223 
224  if( jacStamp.empty() )
225  {
226  jacStamp.resize(2);
227  jacStamp[0].resize(0); // presynaptic V not changed
228 #ifdef Xyce_FullSynapseJac
229  jacStamp[1].resize(1); // postsynaptic V depends on itself
230 #else
231  jacStamp[1].resize(0);
232 #endif
233  }
234 
235 
236  // Set params to constant default values:
237  setDefaultParams ();
238 
239  // Set params according to instance line and constant defaults from metadata:
240  setParams (IB.params);
241 
242  // Set any non-constant parameter defaults:
243 
244  if (!gMaxGiven )
245  {
246  gMax = model_.gMax;
247  }
248 
249  if( !wInitialValueGiven )
250  {
251  // no value for initial weighting given on instance line.
252  // set default from model value
254  }
255 
257  {
259  }
260 
261  // Calculate any parameters specified as expressions:
263 
264  // calculate dependent (ie computed) params and check for errors:
265  // TODO - should 'factor' initialization be here instead of in processParams?
266  processParams ();
267 }
268 
269 //-----------------------------------------------------------------------------
270 // Function : Instance::~Instance
271 // Purpose : destructor
272 // Special Notes :
273 // Scope : public
274 // Creator : Christina Warrender, SNL,
275 // Creation Date : 10/12/11
276 //-----------------------------------------------------------------------------
278 {
279 }
280 
281 //-----------------------------------------------------------------------------
282 // Function : Instance::registerLIDs
283 // Purpose :
284 // Special Notes :
285 // Scope : public
286 // Creator : Christina Warrender, SNL,
287 // Creation Date : 10/12/11
288 //-----------------------------------------------------------------------------
289 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
290  const std::vector<int> & extLIDVecRef )
291 {
292  AssertLIDs(intLIDVecRef.size() == numIntVars);
293  AssertLIDs(extLIDVecRef.size() == numExtVars);
294 
295  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
296  {
297  Xyce::dout() << std::endl << section_divider << std::endl;
298  Xyce::dout() << " SynapseInstance::registerLIDs" << std::endl;
299  Xyce::dout() << " name = " << getName() << std::endl;
300  }
301 
302  // copy over the global ID lists.
303  intLIDVec = intLIDVecRef;
304  extLIDVec = extLIDVecRef;
305 
306  li_Prev = extLIDVec[0];
307  li_Post = extLIDVec[1];
308 
309  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
310  {
311  Xyce::dout() << " li_Prev = " << li_Prev << std::endl;
312  Xyce::dout() << " li_Post = " << li_Post << std::endl;
313  }
314 
315  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
316  {
317  Xyce::dout() << section_divider << std::endl;
318  }
319 }
320 
321 //-----------------------------------------------------------------------------
322 // Function : Instance::loadNodeSymbols
323 // Purpose :
324 // Special Notes :
325 // Scope : public
326 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
327 // Creation Date : 05/13/05
328 //-----------------------------------------------------------------------------
329 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
330 {
331  addStoreNode(symbol_table, li_A0_store, getName().getEncodedName() + "_A0");
332  addStoreNode(symbol_table, li_B0_store, getName().getEncodedName() + "_B0");
333  addStoreNode(symbol_table, li_t0_store, getName().getEncodedName() + "_T0");
334  addStoreNode(symbol_table, li_weight_store, getName().getEncodedName() + "_W");
335  addStoreNode(symbol_table, li_VL1_store, getName().getEncodedName() + "_VL1");
336  addStoreNode(symbol_table, li_VL2_store, getName().getEncodedName() + "_VL2");
337  addStoreNode(symbol_table, li_VL3_store, getName().getEncodedName() + "_VL3");
338 
339  if (loadLeadCurrent)
340  addStoreNode(symbol_table, li_store_dev_i, getName(), "DEV_I");
341 }
342 
343 //-----------------------------------------------------------------------------
344 // Function : Instance::registerStoreLIDs
345 // Purpose : Note that the Synapse3 does not have any state vars.
346 // Special Notes :
347 // Scope : public
348 // Creator : Christina Warrender, SNL,
349 // Creation Date : 10/12/11
350 //-----------------------------------------------------------------------------
351 void Instance::registerStoreLIDs(const std::vector<int> & stoLIDVecRef )
352 {
353  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
354 
355 // copy over the global ID lists.
356  stoLIDVec = stoLIDVecRef;
357 
358  li_A0_store = stoLIDVec[0];
359  li_B0_store = stoLIDVec[1];
360  li_t0_store = stoLIDVec[2];
361  li_weight_store = stoLIDVec[3];
362  li_VL1_store = stoLIDVec[4];
363  li_VL2_store = stoLIDVec[5];
364  li_VL3_store = stoLIDVec[6];
365  if( loadLeadCurrent )
366  {
367  li_store_dev_i = stoLIDVec[7];
368  }
369 }
370 
371 
372 //-----------------------------------------------------------------------------
373 // Function : Instance::jacobianStamp
374 // Purpose :
375 // Special Notes :
376 // Scope : public
377 // Creator : Christina Warrender, SNL,
378 // Creation Date : 10/12/11
379 //-----------------------------------------------------------------------------
380 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
381 {
382  return jacStamp;
383 }
384 
385 //-----------------------------------------------------------------------------
386 // Function : Instance::registerJacLIDs
387 // Purpose :
388 // Special Notes :
389 // Scope : public
390 // Creator : Christina Warrender, SNL,
391 // Creation Date : 10/12/11
392 //-----------------------------------------------------------------------------
393 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
394 {
395  DeviceInstance::registerJacLIDs( jacLIDVec );
396 #ifdef Xyce_FullSynapseJac
397  APostEquPostNodeOffset = jacLIDVec[1][0];
398 #endif
399 }
400 
401 //-----------------------------------------------------------------------------
402 // Function : Instance::setupPointers
403 // Purpose :
404 // Special Notes :
405 // Scope : public
406 // Creator : Christina Warrender, SNL
407 // Creation Date : 10/12/11
408 //-----------------------------------------------------------------------------
410 {
411 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
412 #ifdef Xyce_FullSynapseJac
413  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
414  f_PostEquPostNodePtr = &(dFdx[li_Post][APostEquPostNodeOffset]);
415 #endif
416 #endif
417 }
418 
419 //-----------------------------------------------------------------------------
420 // Function : Instance::updateIntermediateVars
421 // Purpose : update intermediate variables for one diode instance
422 // Special Notes :
423 // Scope : public
424 // Creator : Christina Warrender, SNL
425 // Creation Date : 10/12/11
426 //-----------------------------------------------------------------------------
428 {
429  bool bsuccess = true;
430 
431  double * lastSolVecPtr = extData.lastSolVectorRawPtr;
432  double * stoVec = extData.nextStoVectorRawPtr;
433  double * lastStoVec = extData.lastStoVectorRawPtr;
434 
435  double vPre = lastSolVecPtr[li_Prev];
436  double vPost = lastSolVecPtr[li_Post];
437 
438  // initialized random number generator if needed
439  if( !randInitialized )
440  {
441  if( getDeviceOptions().randomSeed != 0 )
442  {
443  devSupport.SetSeed( getDeviceOptions().randomSeed );
444  }
445  else
446  {
447  unsigned int aSeed = static_cast<unsigned int>(time( NULL ) ) ;
448  devSupport.SetSeed( aSeed );
449  }
450  randInitialized=true;
451  }
452 
453  // to do: Need to adjust this conditional to do this same initialization
454  // if the dcop is being skipped and this is the first iteration.
455  if( getSolverState().dcopFlag )
456  {
457  // no firing during DCOP, so postsynaptic current is 0 and unchanging
458  ipost = 0.0;
459  didVpost = 0.0;
463  stoVec[li_A0_store] = 0.0;
464  stoVec[li_B0_store] = 0.0;
465  stoVec[li_VL1_store] = vPost;
466  stoVec[li_VL2_store] = vPost;
467  stoVec[li_VL3_store] = 0.0;
468  }
469  else
470  {
471  // Check for presynaptic spikes, set time to respond
472  double time = getSolverState().currTime;
473  double vThresh = model_.vThresh;
474  double delay = model_.delay;
475  if (ready)
476  {
477  if (vPre > vThresh)
478  {
479  ready=false;
480  respondTime = time + delay;
481  // check transmissionProbability to see if current is transmitted
483  if( transmissionProbability < 1.0 )
484  {
485  double arand = devSupport.getRandomPerturbation(); // get a number from [0, 1)
486  if( arand > transmissionProbability )
487  {
489  }
490  }
491  }
492  }
493  else // already had spike start, looking for end
494  {
495  // Need to improve the logic here so that no only is the pre snyapse going down (vPre < vThresh),
496  // but synapse must be done with its work. (tau1 + tau2) after delay?
497  if( (vPre < vThresh) && ((time - lastStoVec[li_t0_store]) > ( model_.tau1 + model_.tau2 )))
498  {
499  ready=true;
500  }
501  }
502 
503  // handle decay of A and B
504  double tau1 = model_.tau1;
505  double tau2 = model_.tau2;
506 
507  double t0 = stoVec[li_t0_store];
508  double Anow = stoVec[li_A0_store] * exp( - ( time - t0 ) / tau1 );
509  double Bnow = stoVec[li_B0_store] * exp( - ( time - t0 ) / tau2 );
510  double vl1Now = stoVec[li_VL1_store];
511  double vl2Now = stoVec[li_VL2_store];
512  double vl3Now = stoVec[li_VL3_store];
514 
515  // calculate update to synaptic weight
516  synapticWeightUpdate = 0.0;
517  // only if the synapse is transmitting should be update the synaptic weight.
518  // transmissionFactor is only 0 or 1
519  if( transmissionFactor == 1 )
520  {
522  {
523  // weight in in range so update may be non zero. Check LTD and LTP terms.
524  if( (vPre > model_.sParam) && (vl1Now > model_.rParam) )
525  {
526  synapticWeightUpdate += -(model_.aLTD) * (vl1Now - model_.rParam);
527  }
528  if( (vPost > model_.sParam) && (vl2Now > model_.rParam) )
529  {
530  synapticWeightUpdate += (model_.aLTP) * vl3Now * (vPost - model_.sParam) * (vl2Now - model_.rParam);
531  }
532  }
533 
534  double wMin = model_.wMin;
535  double wMax = model_.wMax;
536 
537  // enforce min/max bounds on weight
539  {
541  }
542  else if (synapticWeight+synapticWeightUpdate < wMin)
543  {
545  }
546  }
547 
548 
549  vl1Update = getSolverState().currTimeStep * (vPost - vl1Now) / model_.vL1tau1;
550  vl2Update = getSolverState().currTimeStep * (vPost - vl2Now) / model_.vL2tau2;
551  if( vPre > model_.sParam )
552  {
553  vl3Update = getSolverState().currTimeStep * (1.0 - vl3Now) / model_.vL3tau3;
554  }
555  else
556  {
558  }
559 
560  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
561  {
562  Xyce::dout() << std::endl << section_divider << std::endl;
563  Xyce::dout() << " SynapseInstance::updateIntermediateVars" << std::endl;
564  Xyce::dout() << "Anow: " << Anow << std::endl;
565  Xyce::dout() << "Bnow: " << Bnow << std::endl;
566  }
567 
568  // set up variables for load methods
569 
570  // current equation is the same whether we're responding to spike or not,
571  // assuming current A and B values set appropriately above
572  // ipost = (B-A)*(V-Erev)
573  double eRev = model_.eRev;
574  //ipost = (synapticWeight + synapticWeightUpdate) * (Bnow-Anow)*(vPost-eRev);
575  ipost = transmissionFactor * synapticWeight * (Bnow-Anow)*(vPost-eRev);
576 
577  //didVpost = (synapticWeight + synapticWeightUpdate) * (Bnow - Anow);
578  // update synaptic weight after time steps is successful.
579  didVpost = synapticWeight * (Bnow - Anow);
580 
581  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
582  {
583  Xyce::dout() << std::endl << section_divider << std::endl;
584  Xyce::dout() << "vPost: " << vPost << std::endl;
585  Xyce::dout() << "eRev: " << eRev << std::endl;
586  Xyce::dout() << "weight: " << synapticWeight << std::endl;
587  Xyce::dout() << "weight update: " << synapticWeightUpdate << std::endl;
588  Xyce::dout() << "ipost: " << ipost << std::endl;
589  Xyce::dout() << "didVpost: " << didVpost << std::endl;
590  }
591 
592  } // end else (!getSolverState().dcopFlag)
593 
594  return bsuccess;
595 }
596 
597 //-----------------------------------------------------------------------------
598 // Function : Instance::updatePrimaryState
599 // Purpose :
600 // Special Notes :
601 // Scope : public
602 // Creator : Christina Warrender, SNL,
603 // Creation Date : 10/12/11
604 //-----------------------------------------------------------------------------
606 {
607  bool bsuccess = updateIntermediateVars();
608  return bsuccess;
609 }
610 
611 //-----------------------------------------------------------------------------
612 // Function : Instance::updateSecondaryState
613 // Purpose :
614 // Special Notes :
615 // Scope : public
616 // Creator : Christina Warrender, SNL,
617 // Creation Date : 10/12/11
618 //-----------------------------------------------------------------------------
620 {
621  return true;
622 }
623 
624 //-----------------------------------------------------------------------------
625 // Function : Instance::loadDAEQVector
626 //
627 // Purpose : Loads the Q-vector contributions for a single
628 // Synapse4
629 //
630 // Special Notes : The "Q" vector is part of a standard DAE formalism in
631 // which the system of equations is represented as:
632 //
633 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
634 //
635 // The "Q" vector contains charges and fluxes, mostly.
636 // However, it is ordered like the solution vector, and as
637 // it is part of the KCL formulation, the terms in Q will
638 // actually be *sums* of charges, rather than single
639 // distinct charges.
640 //
641 // Scope : public
642 // Creator : Christina Warrender, SNL,
643 // Creation Date : 10/12/11
644 //-----------------------------------------------------------------------------
646 {
647  return true;
648 }
649 //-----------------------------------------------------------------------------
650 // Function : Instance::loadDAEFVector
651 //
652 // Purpose : Loads the F-vector contributions for a single
653 // Synapse3 instance.
654 //
655 // Special Notes : This is an algebraic constaint, and as such the Synapse3
656 // does make a contribution to it.
657 //
658 // Scope : public
659 // Creator : Christina Warrender, SNL,
660 // Creation Date : 10/12/11
661 //-----------------------------------------------------------------------------
663 {
664  Linear::Vector * fVecPtr = extData.daeFVectorPtr;
665  (*fVecPtr)[li_Prev] += 0.0;
666  (*fVecPtr)[li_Post] += ipost;
667 
668  if( loadLeadCurrent )
669  {
670  double * stoVec = extData.nextStoVectorRawPtr;
671  stoVec[li_store_dev_i] = ipost;
672  }
673 
674  return true;
675 }
676 
677 //-----------------------------------------------------------------------------
678 // Function : Instance::loadDAEdQdx
679 //
680 // Purpose : Loads the dQdx-matrix contributions for a single
681 // Synapse3 instance.
682 //
683 // Special Notes : The "Q" vector is part of a standard DAE formalism in
684 // which the system of equations is represented as:
685 //
686 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
687 //
688 // The "Q" vector contains charges and fluxes, mostly.
689 // However, it is ordered like the solution vector, and as
690 // it is part of the KCL formulation, the terms in Q will
691 // actually be *sums* of charges, rather than single
692 // distinct charges.
693 //
694 // Scope : public
695 // Creator : Christina Warrender, SNL,
696 // Creation Date : 10/12/11
697 //-----------------------------------------------------------------------------
699 {
700  return true;
701 }
702 
703 //-----------------------------------------------------------------------------
704 // Function : Instance::loadDAEdFdx ()
705 //
706 // Purpose : Loads the F-vector contributions for a single
707 // Synapse3 instance.
708 //
709 // Special Notes : This is an algebraic constaint, and as such the Synapse3
710 // does make a contribution to it.
711 //
712 // Scope : public
713 // Creator : Christina Warrender, SNL,
714 // Creation Date : 10/12/11
715 //-----------------------------------------------------------------------------
717 {
718 #ifdef Xyce_FullSynapseJac
719  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
720  dFdx[li_Post][APostEquPostNodeOffset] += didVpost;
721 #endif
722  return true;
723 }
724 
725 //-----------------------------------------------------------------------------
726 // Function : InstanceInstance::outputPlotFiles
727 // Purpose : If requested by the user output all the variables
728 // associated with the population
729 // Special Notes : We're actually using this method not for output, but because
730 // it's called after the system has converged. In this case,
731 // that let us mark the end of handling a presynaptic event.
732 // Scope : public
733 // Creator : Christina Warrender, SNL, Cognitive Modeling
734 // Creation Date : 10/25/2011
735 //-----------------------------------------------------------------------------
737 {
738  bool bsuccess = true;
739 
740  // cew 11/3/11: changing this back to just storing A0 and B0 for updateIntermediateVars
741  // to use in calculating A, B, and ipost
742  // But when incrementing A0 (B0), current value of A (B) must be used.
743 
744  double time = getSolverState().currTime;
745  double * stoVec = extData.nextStoVectorRawPtr;
746 
747  if (time >= respondTime)
748  {
749  //Xyce::dout() << "Instance::outputPlotFiles() adjusting A0, B0 and t0 = " << getSolverState().currTime << ", " << respondTime << std::endl;
750  // succesfully processed a step, so adjust the next
751  // respondTime to distant future
752  respondTime = std::numeric_limits<double>::max( );
753 
754  // now we also update the A0, B0 and t0 in the state vector
755  double factor = model_.factor;
756  double deltaAB = factor*gMax;
757  double tau1 = model_.tau1;
758  double tau2 = model_.tau2;
759 
760  double t0 = stoVec[li_t0_store];
761  double Anow = stoVec[li_A0_store] * exp( - ( time - t0 ) / tau1 );
762  double Bnow = stoVec[li_B0_store] * exp( - ( time - t0 ) / tau2 );
763  stoVec[li_A0_store] = Anow + deltaAB;
764  stoVec[li_B0_store] = Bnow + deltaAB;
765  stoVec[li_t0_store] = getSolverState().currTime;
766  } // end if time >= respondTime
767 
769  stoVec[li_VL1_store] += vl1Update;
770  stoVec[li_VL2_store] += vl2Update;
771  stoVec[li_VL3_store] += vl3Update;
772 
773  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
774  {
775  Xyce::dout() << std::endl << section_divider << std::endl;
776  Xyce::dout() << " SynapseInstance::outputPlotFiles" << std::endl;
777  Xyce::dout() << "time: " << getSolverState().currTime << std::endl;
778  Xyce::dout() << "weight in store: " << stoVec[li_weight_store] << std::endl;
779  }
780 
781 
782  return bsuccess;
783 }
784 
785 //-----------------------------------------------------------------------------
786 // Function : Instance::updateTemperature
787 // Purpose :
788 // Special Notes :
789 // Scope : public
790 // Creator : Tom Russo, Component Information and Models
791 // Creation Date : 10/12/11
792 //-----------------------------------------------------------------------------
793 bool Instance::updateTemperature ( const double & temp_tmp)
794 {
795  bool bsuccess = true;
796  return bsuccess;
797 }
798 
799 //-----------------------------------------------------------------------------
800 // Function : Model::processParams
801 // Purpose :
802 // Special Notes :
803 // Scope : public
804 // Creator : Christina Warrender, SNL,
805 // Creation Date : 10/12/11
806 //-----------------------------------------------------------------------------
808 {
809  // initialize variables needed to calculate synaptic dynamics
810  if (tau1/tau2 > .9999) {
811  tau1 = .9999*tau2;
812  }
813  tp = (tau1*tau2)/(tau2 - tau1) * log(tau2/tau1);
814  factor = -exp(-tp/tau1) + exp(-tp/tau2);
815  factor = 1/factor;
816 
817  return true;
818 }
819 
820 //----------------------------------------------------------------------------
821 // Function : Model::processInstanceParams
822 // Purpose :
823 // Special Notes :
824 // Scope : public
825 // Creator : Dave Shirely, PSSI
826 // Creation Date : 10/12/11
827 //----------------------------------------------------------------------------
829 {
830 
831  std::vector<Instance*>::iterator iter;
832  std::vector<Instance*>::iterator first = instanceContainer.begin();
833  std::vector<Instance*>::iterator last = instanceContainer.end();
834 
835  for (iter=first; iter!=last; ++iter)
836  {
837  (*iter)->processParams();
838  }
839 
840  return true;
841 }
842 
843 //-----------------------------------------------------------------------------
844 // Function : Model::Model
845 // Purpose : model block constructor
846 // Special Notes :
847 // Scope : public
848 // Creator : Christina Warrender, SNL,
849 // Creation Date : 10/12/11
850 //-----------------------------------------------------------------------------
852  const Configuration & configuration,
853  const ModelBlock & MB,
854  const FactoryBlock & factory_block)
855  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
856  vThresh(0.0),
857  delay(0.0),
858  gMax(0.0),
859  eRev(0.0),
860  tau1(0.0),
861  tau2(0.0)
862 {
863 
864  // Set params to constant default values:
865  setDefaultParams ();
866 
867  // Set params according to .model line and constant defaults from metadata:
868  setModParams (MB.params);
869 
870  // Set any non-constant parameter defaults:
871 
872  // Calculate any parameters specified as expressions:
874 
875  // calculate dependent (ie computed) params and check for errors:
876  processParams();
877 }
878 
879 //-----------------------------------------------------------------------------
880 // Function : Model::~Model
881 // Purpose : destructor
882 // Special Notes :
883 // Scope : public
884 // Creator : Christina Warrender, SNL,
885 // Creation Date : 10/12/11
886 //-----------------------------------------------------------------------------
888 {
889  std::vector<Instance*>::iterator iter;
890  std::vector<Instance*>::iterator first = instanceContainer.begin();
891  std::vector<Instance*>::iterator last = instanceContainer.end();
892 
893  for (iter=first; iter!=last; ++iter)
894  {
895  delete (*iter);
896  }
897 }
898 
899 //-----------------------------------------------------------------------------
900 // Function : Model::printOutInstances
901 // Purpose : debugging tool.
902 // Special Notes :
903 // Scope : public
904 // Creator : Christina Warrender, SNL,
905 // Creation Date : 10/12/11
906 //-----------------------------------------------------------------------------
907 std::ostream &Model::printOutInstances(std::ostream &os) const
908 {
909  std::vector<Instance*>::const_iterator iter;
910  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
911  std::vector<Instance*>::const_iterator last = instanceContainer.end();
912 
913  int i,isize;
914  isize = instanceContainer.size();
915  os << std::endl;
916  os << "Number of Synapse3 Instances: " << isize << std::endl;
917  os << " name model name Parameters" << std::endl;
918  for (i=0, iter=first; iter!=last; ++iter, ++i)
919  {
920  os << " " << i << ": " << (*iter)->getName() << "\t";
921  os << getName();
922  os << std::endl;
923  }
924 
925  os << std::endl;
926  return os;
927 }
928 
929 //-----------------------------------------------------------------------------
930 // Function : Model::forEachInstance
931 // Purpose :
932 // Special Notes :
933 // Scope : public
934 // Creator : David Baur
935 // Creation Date : 2/4/2014
936 //-----------------------------------------------------------------------------
937 /// Apply a device instance "op" to all instances associated with this
938 /// model
939 ///
940 /// @param[in] op Operator to apply to all instances.
941 ///
942 ///
943 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
944 {
945  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
946  op(*it);
947 }
948 
949 
950 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
951 {
952 
953  return new DeviceMaster<Traits>(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
954 }
955 
957 {
959  .registerDevice("synapse", 3)
960  .registerModelType("synapse", 3);
961 }
962 
963 } // namespace Synapse3
964 } // namespace Device
965 } // namespace Xyce
const InstanceName & getName() const
const std::vector< std::vector< int > > & jacobianStamp() const
const SolverState & solverState_
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)
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &Riter, const FactoryBlock &factory_block)
Pure virtual class to augment a linear system.
void setNumStoreVars(int num_store_vars)
void registerStoreLIDs(const std::vector< int > &storeLIDVecRef)
#define AssertLIDs(cmp)
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
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...
const DeviceOptions & getDeviceOptions() const
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
const DeviceOptions & deviceOptions_
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
Linear::Matrix * dFdxMatrixPtr
std::vector< Instance * > instanceContainer
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
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
Class Configuration contains device configuration data.
bool updateTemperature(const double &temp_tmp)
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
const SolverState & getSolverState() const
bool processParams()
processParams
static std::vector< std::vector< int > > jacStamp
Linear::Vector * daeFVectorPtr
virtual std::ostream & printOutInstances(std::ostream &os) const
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
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
void setModParams(const std::vector< Param > &params)