Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_Synapse2.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_Synapse2.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Christy Warrender, SNL, Cognitive Modeling
33 //
34 // Creation Date : 11/18/10
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.36 $
40 //
41 // Revision Date : $Date: 2014/05/13 14:50:39 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //----------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 
49 // ---------- Standard Includes ----------
50 
51 // ---------- Xyce Includes ----------
52 //
53 #include <N_DEV_Const.h>
54 #include <N_DEV_DeviceOptions.h>
55 #include <N_DEV_DeviceMaster.h>
56 #include <N_DEV_ExternData.h>
57 #include <N_DEV_MatrixLoadData.h>
58 #include <N_DEV_SolverState.h>
59 #include <N_DEV_Synapse2.h>
60 #include <N_DEV_Message.h>
61 #include <N_ERH_ErrorMgr.h>
62 
63 #include <N_DEV_Synapse.h>
64 
65 #include <N_LAS_Matrix.h>
66 #include <N_LAS_Vector.h>
67 
68 namespace Xyce {
69 namespace Device {
70 
71 
72 namespace Synapse2 {
73 
74 
76 {
77  // Set up configuration constants:
78 }
79 
81 {
82  // Set up map for double precision variables:
83  // Default values are taken from Destexhe 98, values for AMPA receptor
84  // although since this Synapse2::Model is different, those values may not have the same meaning
85  p.addPar ("GMAX", 1.0E-9, &Synapse2::Model::gMax)
86  .setUnit(U_OHMM1)
87  .setDescription("Maximal Synaptic Conductance");
88 
89  p.addPar ("EREV", 0.0, &Synapse2::Model::eRev)
90  .setUnit(U_VOLT)
91  .setDescription("Reversal Potential");
92 
93  p.addPar ("ALPHA", 1.1E-6, &Synapse2::Model::alpha)
94  .setUnit(U_SECM1)
95  .setDescription("Forward rate constant for receptor opening");
96 
97  p.addPar ("BETA", 190.0, &Synapse2::Model::beta)
98  .setUnit(U_SECM1)
99  .setDescription("Backward rate constant for receptor opening");
100 
101  p.addPar ("VP", 0.002, &Synapse2::Model::vP)
102  .setUnit(U_VOLT)
103  .setDescription("Presynaptic voltage that activates postsynaptic current");
104 
105  p.addPar ("TMAX", 0.001, &Synapse2::Model::tMax)
106  .setDescription("Maximal neurotransmitter concentration");
107 
108  // NOTE: not including concentration units - TMAX should be in moles/liter, and
109  // alpha has concentration in the denominator; they cancel out
110 }
111 
112 
113 std::vector< std::vector<int> > Instance::jacStamp;
114 
115 // Class Instance
116 //-----------------------------------------------------------------------------
117 // Function : Instance::processParams
118 // Purpose :
119 // Special Notes :
120 // Scope : public
121 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
122 // Creation Date : 6/03/02
123 //-----------------------------------------------------------------------------
125 {
126  // now set the temperature related stuff.
127  //updateTemperature(temp);
128 
129  return true;
130 }
131 
132 //-----------------------------------------------------------------------------
133 // Function : Instance::Instance
134 // Purpose : instance block constructor
135 // Special Notes :
136 // Scope : public
137 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
138 // Creation Date : 3/16/00
139 //-----------------------------------------------------------------------------
141  const Configuration & configuration,
142  const InstanceBlock & IB,
143  Model & Riter,
144  const FactoryBlock & factory_block)
145 
146  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
147  model_(Riter),
148  li_Prev(-1),
149  li_Post(-1),
150  APostEquPostNodeOffset(-1),
151  APostEquRNodeOffset(-1),
152  AREquPostNodeOffset(-1),
153  AREquRNodeOffset(-1),
154  f_PostEquPostNodePtr(0),
155  f_PostEquRNodePtr(0),
156  f_REquPostNodePtr(0),
157  f_REquRNodePtr(0)
158 {
159  numIntVars = 1;
160  numExtVars = 2;
161  numStateVars = 0;
162 
163  if( jacStamp.empty() )
164  {
165  // Vpre, Vpost, r
166  jacStamp.resize(3);
167  jacStamp[0].resize(0);
168  jacStamp[1].resize(2);
169  jacStamp[2].resize(2);
170  jacStamp[1][0] = 1; // Vpost PostPostVar
171  jacStamp[1][1] = 2; // r PostRVar
172  jacStamp[2][0] = 0; // Vpre RVpre
173  jacStamp[2][1] = 2; // r RR
174  }
175 
176 
177  // Set up mapping from param names to class variables:
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  // Calculate any parameters specified as expressions:
189 
190  // calculate dependent (ie computed) params and check for errors:
191  processParams ();
192 }
193 
194 //-----------------------------------------------------------------------------
195 // Function : Instance::~Instance
196 // Purpose : destructor
197 // Special Notes :
198 // Scope : public
199 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
200 // Creation Date : 3/16/00
201 //-----------------------------------------------------------------------------
203 {
204 }
205 
206 //-----------------------------------------------------------------------------
207 // Function : Instance::registerLIDs
208 // Purpose :
209 // Special Notes :
210 // Scope : public
211 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
212 // Creation Date : 6/12/02
213 //-----------------------------------------------------------------------------
214 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
215  const std::vector<int> & extLIDVecRef )
216 {
217  AssertLIDs(intLIDVecRef.size() == numIntVars);
218  AssertLIDs(extLIDVecRef.size() == numExtVars);
219 
220 #ifdef Xyce_DEBUG_DEVICE
221  if (getDeviceOptions().debugLevel > 0)
222  {
223  Xyce::dout() << std::endl << section_divider << std::endl;
224  Xyce::dout() << " SynapseInstance::registerLIDs" << std::endl;
225  Xyce::dout() << " name = " << getName() << std::endl;
226  }
227 #endif
228 
229  // copy over the global ID lists.
230  intLIDVec = intLIDVecRef;
231  extLIDVec = extLIDVecRef;
232 
233  li_Prev = extLIDVec[0];
234  li_Post = extLIDVec[1];
235 
236 #ifdef Xyce_DEBUG_DEVICE
237  if (getDeviceOptions().debugLevel > 0 )
238  {
239  Xyce::dout() << " li_Prev = " << li_Prev << std::endl;
240  Xyce::dout() << " li_Post = " << li_Post << std::endl;
241  }
242 #endif
243 
244  li_rVar = intLIDVec[0];
245 
246 #ifdef Xyce_DEBUG_DEVICE
247  if (getDeviceOptions().debugLevel > 0 )
248  {
249  Xyce::dout() << section_divider << std::endl;
250  }
251 #endif
252 }
253 
254 //-----------------------------------------------------------------------------
255 // Function : Instance::getIntNameMap
256 // Purpose :
257 // Special Notes :
258 // Scope : public
259 // Creator : Christina Warrender, SNL, Cognitive Modeling
260 // Creation Date : 10/17/11
261 //-----------------------------------------------------------------------------
262 std::map<int,std::string> & Instance::getIntNameMap ()
263 {
264  // set up the internal name map, if it hasn't been already.
265  if (intNameMap.empty ())
266  {
268  }
269  return intNameMap;
270 }
271 
272 //-----------------------------------------------------------------------------
273 // Function : Instance::registerStateLIDs
274 // Purpose : Note that the Synapse2 does not have any state vars.
275 // Special Notes :
276 // Scope : public
277 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
278 // Creation Date : 06/12/02
279 //-----------------------------------------------------------------------------
280 void Instance::registerStateLIDs(const std::vector<int> & staLIDVecRef )
281 {
282  AssertLIDs(staLIDVecRef.size() == numStateVars);
283 }
284 
285 //-----------------------------------------------------------------------------
286 // Function : Instance::jacobianStamp
287 // Purpose :
288 // Special Notes :
289 // Scope : public
290 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
291 // Creation Date : 08/20/01
292 //-----------------------------------------------------------------------------
293 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
294 {
295  return jacStamp;
296 }
297 
298 //-----------------------------------------------------------------------------
299 // Function : Instance::registerJacLIDs
300 // Purpose :
301 // Special Notes :
302 // Scope : public
303 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
304 // Creation Date : 08/27/01
305 //-----------------------------------------------------------------------------
306 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
307 {
308  DeviceInstance::registerJacLIDs( jacLIDVec );
309 
310  APostEquPostNodeOffset = jacLIDVec[1][0];
311  APostEquRNodeOffset = jacLIDVec[1][1];
312  AREquPostNodeOffset = jacLIDVec[2][0];
313  AREquRNodeOffset = jacLIDVec[2][1];
314 }
315 
316 //-----------------------------------------------------------------------------
317 // Function : Instance::setupPointers
318 // Purpose :
319 // Special Notes :
320 // Scope : public
321 // Creator : Eric Keiter, SNL
322 // Creation Date : 11/30/08
323 //-----------------------------------------------------------------------------
325 {
326 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
327  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
332 #endif
333 }
334 
335 //-----------------------------------------------------------------------------
336 // Function : Instance::updateIntermediateVars
337 // Purpose : update intermediate variables for one diode instance
338 // Special Notes :
339 // Scope : public
340 // Creator : Eric R. Keiter, Dept. 9233.
341 // Creation Date : 3/05/04
342 //-----------------------------------------------------------------------------
344 {
345  bool bsuccess = true;
346 
347  N_LAS_Vector * solVecPtr = extData.nextSolVectorPtr;
348 
349  if( getSolverState().dcopFlag )
350  {
351  // no firing during DCOP; r=0, so postsynaptic current is 0 and unchanging
352  ipost = 0.0;
353  didVpost = 0.0;
354  didr = 0.0;
355  rFval = 0.0;
356  drFdVpre = 0.0;
357  drFdr = 0.0;
358  }
359  else
360  {
361  double vPre = (*solVecPtr)[li_Prev];
362  double vPost = (*solVecPtr)[li_Post];
363  double rVar = (*solVecPtr)[li_rVar];
364 
365  // Load RHS vector element for the positive circuit node KCL equ.
366  {
367  Sacado::Fad::SFad<double,2> vPostVar( 2, 0, vPost );
368  Sacado::Fad::SFad<double,2> rVarS( 2, 1, rVar);
369 
370  // parameters
371  Sacado::Fad::SFad<double,2> gMaxVar( model_.gMax );
372  Sacado::Fad::SFad<double,2> eRevVar( model_.eRev );
373 
374  Sacado::Fad::SFad<double,2> resultFad;
375  resultFad = PostCurrentEqu( vPostVar, rVarS, gMaxVar, eRevVar );
376  ipost = resultFad.val();
377  didVpost = resultFad.dx(0);
378  didr = resultFad.dx(1);
379  }
380  {
381  Sacado::Fad::SFad<double,2> vPreVar( 2, 0, vPre );
382  Sacado::Fad::SFad<double,2> rVarS( 2, 1, rVar);
383 
384  // parameters
385  Sacado::Fad::SFad<double,2> alphaVar( model_.alpha );
386  Sacado::Fad::SFad<double,2> betaVar( model_.beta );
387  Sacado::Fad::SFad<double,2> tMaxVar( model_.tMax );
388  Sacado::Fad::SFad<double,2> vPVar( model_.vP );
389 
390  Sacado::Fad::SFad<double,2> resultFad;
391  resultFad = rEquF( vPreVar, rVarS, alphaVar, betaVar, tMaxVar, vPVar);
392  rFval = resultFad.val();
393  drFdVpre = resultFad.dx(0);
394  drFdr = resultFad.dx(1);
395  }
396  }
397 
398  return bsuccess;
399 }
400 
401 //-----------------------------------------------------------------------------
402 // Function : Instance::updatePrimaryState
403 // Purpose :
404 // Special Notes :
405 // Scope : public
406 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
407 // Creation Date : 01/29/01
408 //-----------------------------------------------------------------------------
410 {
411  bool bsuccess = updateIntermediateVars();
412  return bsuccess;
413 }
414 
415 //-----------------------------------------------------------------------------
416 // Function : Instance::updateSecondaryState
417 // Purpose :
418 // Special Notes :
419 // Scope : public
420 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
421 // Creation Date : 01/29/01
422 //-----------------------------------------------------------------------------
424 {
425  return true;
426 }
427 
428 //-----------------------------------------------------------------------------
429 // Function : Instance::loadDAEQVector
430 //
431 // Purpose : Loads the Q-vector contributions for a single
432 // Synapse2
433 //
434 // Special Notes : The "Q" vector is part of a standard DAE formalism in
435 // which the system of equations is represented as:
436 //
437 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
438 //
439 // Scope : public
440 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
441 // Creation Date : 8/31/2010
442 //-----------------------------------------------------------------------------
444 {
445  N_LAS_Vector * qVecPtr = extData.daeQVectorPtr;
446  N_LAS_Vector * solVecPtr = extData.nextSolVectorPtr;
447  double rVar = (*solVecPtr)[li_rVar];
448  (*qVecPtr)[li_rVar] -= rVar;
449 
450  return true;
451 }
452 //-----------------------------------------------------------------------------
453 // Function : Instance::loadDAEFVector
454 //
455 // Purpose : Loads the F-vector contributions for a single
456 // Synapse2 instance.
457 //
458 // Special Notes : This is an algebraic constaint, and as such the Synapse2
459 // does make a contribution to it.
460 //
461 // Scope : public
462 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
463 // Creation Date : 01/24/03
464 //-----------------------------------------------------------------------------
466 {
467  N_LAS_Vector * fVecPtr = extData.daeFVectorPtr;
468  (*fVecPtr)[li_Prev] += 0.0;
469  (*fVecPtr)[li_Post] += ipost;
470  (*fVecPtr)[li_rVar] += rFval;
471  return true;
472 }
473 
474 //-----------------------------------------------------------------------------
475 // Function : Instance::loadDAEdQdx
476 //
477 // Purpose : Loads the dQdx-matrix contributions for a single
478 // Synapse2 instance.
479 //
480 // Special Notes : The "Q" vector is part of a standard DAE formalism in
481 // which the system of equations is represented as:
482 //
483 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
484 //
485 // The "Q" vector contains charges and fluxes, mostly.
486 // However, it is ordered like the solution vector, and as
487 // it is part of the KCL formulation, the terms in Q will
488 // actually be *sums* of charges, rather than single
489 // distinct charges.
490 //
491 // This function assumes that updatePrimaryState has been
492 // called recently enough for the contents of q0 to be
493 // valid.
494 //
495 // Scope : public
496 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
497 // Creation Date : 03/05/04
498 //-----------------------------------------------------------------------------
500 {
501  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
502  dQdx[li_rVar][AREquRNodeOffset] += -1.0;
503 
504  return true;
505 }
506 
507 //-----------------------------------------------------------------------------
508 // Function : Instance::loadDAEdFdx ()
509 //
510 // Purpose : Loads the F-vector contributions for a single
511 // Synapse2 instance.
512 //
513 // Special Notes : This is an algebraic constaint, and as such the Synapse2
514 // does make a contribution to it.
515 //
516 // Scope : public
517 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
518 // Creation Date : 03/05/04
519 //-----------------------------------------------------------------------------
521 {
522  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
524  dFdx[li_Post][APostEquRNodeOffset] += didr;
526  dFdx[li_rVar][AREquRNodeOffset] += drFdr;
527 
528  return true;
529 }
530 
531 //-----------------------------------------------------------------------------
532 // Function : Instance::updateTemperature
533 // Purpose :
534 // Special Notes :
535 // Scope : public
536 // Creator : Tom Russo, Component Information and Models
537 // Creation Date : 02/27/01
538 //-----------------------------------------------------------------------------
539 bool Instance::updateTemperature ( const double & temp_tmp)
540 {
541  bool bsuccess = true;
542  return bsuccess;
543 }
544 
545 //-----------------------------------------------------------------------------
546 // Function : Model::processParams
547 // Purpose :
548 // Special Notes :
549 // Scope : public
550 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
551 // Creation Date : 6/03/02
552 //-----------------------------------------------------------------------------
554 {
555 
556  return true;
557 }
558 
559 //----------------------------------------------------------------------------
560 // Function : Model::processInstanceParams
561 // Purpose :
562 // Special Notes :
563 // Scope : public
564 // Creator : Dave Shirely, PSSI
565 // Creation Date : 03/23/06
566 //----------------------------------------------------------------------------
568 {
569 
570  std::vector<Instance*>::iterator iter;
571  std::vector<Instance*>::iterator first = instanceContainer.begin();
572  std::vector<Instance*>::iterator last = instanceContainer.end();
573 
574  for (iter=first; iter!=last; ++iter)
575  {
576  (*iter)->processParams();
577  }
578 
579  return true;
580 }
581 
582 //-----------------------------------------------------------------------------
583 // Function : Model::Model
584 // Purpose : model block constructor
585 // Special Notes :
586 // Scope : public
587 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
588 // Creation Date : 5/16/00
589 //-----------------------------------------------------------------------------
591  const Configuration & configuration,
592  const ModelBlock & MB,
593  const FactoryBlock & factory_block)
594  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
595  gMax(0.0),
596  eRev(0.0),
597  alpha(0.0),
598  beta(0.0),
599  vP(0.0),
600  tMax(0.0)
601 {
602 
603  // Set up mapping from param names to class variables:
604 
605  // Set params to constant default values:
606  setDefaultParams ();
607 
608  // Set params according to .model line and constant defaults from metadata:
609  setModParams (MB.params);
610 
611  // Set any non-constant parameter defaults:
612 
613  // Calculate any parameters specified as expressions:
615 
616  // calculate dependent (ie computed) params and check for errors:
617  processParams();
618 }
619 
620 //-----------------------------------------------------------------------------
621 // Function : Model::~Model
622 // Purpose : destructor
623 // Special Notes :
624 // Scope : public
625 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
626 // Creation Date : 3/16/00
627 //-----------------------------------------------------------------------------
629 {
630  std::vector<Instance*>::iterator iter;
631  std::vector<Instance*>::iterator first = instanceContainer.begin();
632  std::vector<Instance*>::iterator last = instanceContainer.end();
633 
634  for (iter=first; iter!=last; ++iter)
635  {
636  delete (*iter);
637  }
638 }
639 
640 //-----------------------------------------------------------------------------
641 // Function : Model::printOutInstances
642 // Purpose : debugging tool.
643 // Special Notes :
644 // Scope : public
645 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
646 // Creation Date : 4/03/00
647 //-----------------------------------------------------------------------------
648 std::ostream &Model::printOutInstances(std::ostream &os) const
649 {
650  std::vector<Instance*>::const_iterator iter;
651  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
652  std::vector<Instance*>::const_iterator last = instanceContainer.end();
653 
654  int i,isize;
655  isize = instanceContainer.size();
656  os << std::endl;
657  os << "Number of Synapse2 Instances: " << isize << std::endl;
658  os << " name model name Parameters" << std::endl;
659  for (i=0, iter=first; iter!=last; ++iter, ++i)
660  {
661  os << " " << i << ": " << (*iter)->getName() << "\t";
662  os << getName();
663  os << std::endl;
664  }
665 
666  os << std::endl;
667  return os;
668 }
669 
670 //-----------------------------------------------------------------------------
671 // Function : Model::forEachInstance
672 // Purpose :
673 // Special Notes :
674 // Scope : public
675 // Creator : David Baur
676 // Creation Date : 2/4/2014
677 //-----------------------------------------------------------------------------
678 /// Apply a device instance "op" to all instances associated with this
679 /// model
680 ///
681 /// @param[in] op Operator to apply to all instances.
682 ///
683 ///
684 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
685 {
686  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
687  op(*it);
688 }
689 
690 
691 // Synapse2 Master functions:
692 
693 //-----------------------------------------------------------------------------
694 // Function : Master::updateState
695 // Purpose :
696 // Special Notes :
697 // Scope : public
698 // Creator : Eric Keiter, SNL
699 // Creation Date : 11/26/08
700 //-----------------------------------------------------------------------------
701 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
702 {
703  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
704  {
705  (*it)->updateIntermediateVars();
706  }
707 
708  return true;
709 }
710 
711 //-----------------------------------------------------------------------------
712 // Function : Master::updateSecondaryState
713 // Purpose :
714 // Special Notes :
715 // Scope : public
716 // Creator : Eric Keiter, SNL
717 // Creation Date : 11/26/08
718 //-----------------------------------------------------------------------------
719 bool Master::updateSecondaryState ( double * staDerivVec, double * stoVec )
720 {
721  return true;
722 }
723 
724 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
725 {
726 
727  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
728 }
729 
731 {
733  .registerDevice("synapse", 2)
734  .registerModelType("synapse", 2);
735 }
736 
737 } // namespace Synapse2
738 } // namespace Device
739 } // namespace Xyce