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