Xyce  6.1
N_DEV_SourceData.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_SourceData.C,v $
27 //
28 // Purpose : This file contains the member functions of the
29 // N_DEV_SourceData class, which is used by the Vsrc
30 // and ISRC devices.
31 //
32 // Special Notes :
33 //
34 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
35 //
36 // Creation Date : 02/28/00
37 //
38 // Revision Information:
39 // ---------------------
40 //
41 // Revision Number: $Revision: 1.145 $
42 //
43 // Revision Date : $Date: 2015/08/02 15:01:32 $
44 //
45 // Current Owner : $Author: peshola $
46 //-------------------------------------------------------------------------
47 
48 #include <Xyce_config.h>
49 
50 #include <N_DEV_DeviceInstance.h>
51 #include <N_DEV_DeviceOptions.h>
52 #include <N_DEV_Message.h>
53 #include <N_DEV_SolverState.h>
54 #include <N_DEV_SourceData.h>
55 #include <N_IO_DeviceBlock.h>
56 #include <N_IO_SpiceSeparatedFieldTool.h>
57 #include <N_UTL_BreakPoint.h>
58 #include <N_UTL_ExtendedString.h>
59 #include <N_UTL_FeatureTest.h>
60 #include <N_UTL_Math.h>
61 
62 namespace Xyce {
63 namespace Device {
64 
65 void
67 {
68  std::vector<Param> sourceFcnParamList;
69 
70  // Source function metadata.
71  sourceFcnParamList.resize(7);
72  sourceFcnParamList[0].set("V1", 0.0);
73  sourceFcnParamList[1].set("V2", 0.0);
74  sourceFcnParamList[2].set("TD", 0.0);
75  sourceFcnParamList[3].set("TR", 0.0);
76  sourceFcnParamList[4].set("TF", 0.0);
77  sourceFcnParamList[5].set("PW", 0.0);
78  sourceFcnParamList[6].set("PER", 0.0);
79  sourceFcnMap[ "PULSE" ] = sourceFcnParamList;
80 
81  sourceFcnParamList.resize(6);
82  sourceFcnParamList[0].set("V0", 0.0);
83  sourceFcnParamList[1].set("VA", 0.0);
84  sourceFcnParamList[2].set("FREQ", 0.0);
85  sourceFcnParamList[3].set("TD", 0.0);
86  sourceFcnParamList[4].set("THETA", 0.0);
87  sourceFcnParamList[5].set("PHASE", 0.0);
88  sourceFcnMap[ "SIN" ] = sourceFcnParamList;
89 
90  sourceFcnParamList.resize(6);
91  sourceFcnParamList[0].set("V1", 0.0);
92  sourceFcnParamList[1].set("V2", 0.0);
93  sourceFcnParamList[2].set("TD1", 0.0);
94  sourceFcnParamList[3].set("TAU1", 0.0);
95  sourceFcnParamList[4].set("TD2", 0.0);
96  sourceFcnParamList[5].set("TAU2", 0.0);
97  sourceFcnMap[ "EXP" ] = sourceFcnParamList;
98 
99  sourceFcnParamList.resize(5);
100  sourceFcnParamList[0].set("V0", 0.0);
101  sourceFcnParamList[1].set("VA", 0.0);
102  sourceFcnParamList[2].set("FC", 0.0);
103  sourceFcnParamList[3].set("MDI", 0.0);
104  sourceFcnParamList[4].set("FS", 0.0);
105  sourceFcnMap[ "SFFM" ] = sourceFcnParamList;
106 
107 // sourceFcnParamList is empty for source function "PWL" indicating
108  // that it needs special handling in NetlistHandler.C
109  sourceFcnParamList.clear();
110  sourceFcnMap[ "PWL" ] = sourceFcnParamList;
111 
112  sourceFcnParamList.resize(8);
113  sourceFcnParamList[0].set("V1", 0.0);
114  sourceFcnParamList[1].set("V2", 0.0);
115  sourceFcnParamList[2].set("TD", 0.0);
116  sourceFcnParamList[3].set("TR", 0.0);
117  sourceFcnParamList[4].set("TF", 0.0);
118  sourceFcnParamList[5].set("PW", 0.0);
119  sourceFcnParamList[6].set("PER", 0.0);
120  sourceFcnParamList[7].set("SF", 0.0);
121  sourceFcnMap[ "SMOOTHPULSE" ] = sourceFcnParamList;
122 }
123 
124 //----------------------------------------------------------------------------
125 // Function : CircuitMetadata::getSourceFunctionParameters
126 // Purpose :
127 // Special Notes :
128 // Scope : public
129 // Creator :
130 // Creation Date :
131 //----------------------------------------------------------------------------
132 const std::vector<Param> &
134  const std::string & sourceFcn)
135 {
136  static DeviceParamMap sourceFcnMap;
137 
138  if (sourceFcnMap.empty())
139  sourceFunctionMetadata(sourceFcnMap);
140 
141  DeviceParamMap::const_iterator it = sourceFcnMap.find(sourceFcn);
142  if (it == sourceFcnMap.end())
143  {
144  Report::DevelFatal() << "No such source function " << sourceFcn;
145  }
146 
147  return (*it).second;
148 }
149 
150 
151 //-----------------------------------------------------------------------------
152 // Function : getSourceFunctionID
153 // Purpose : Return the integer value corresponding to the
154 // given source function. Return NUM_SRC_DATA if the given string
155 // is unknown.
156 // Special Notes :
157 // Scope : public
158 // Creator : Lon Waters
159 // Creation Date : 09/30/2003
160 //-----------------------------------------------------------------------------
161 int
163  const std::string & sourceFcn)
164 {
165  if (sourceFcn == "PULSE") return _PULSE_DATA;
166  else if (sourceFcn == "SIN") return _SIN_DATA;
167  else if (sourceFcn == "EXP") return _EXP_DATA;
168  else if (sourceFcn == "SFFM") return _SFFM_DATA;
169  else if (sourceFcn == "PWL") return _PWL_DATA;
170  else if (sourceFcn == "DC") return _DC_DATA;
171  else if (sourceFcn == "SMOOTHPULSE") return _SMOOTH_PULSE_DATA;
172  else if (sourceFcn == "AC") return _AC_DATA; //tmei: 05/02
173  //else if (sourceFcn == "DISTOF1") return _DISTOF1_DATA;
174  //else if (sourceFcn == "DISTOF2") return _DISTOF2_DATA;
175  else return _NUM_SRC_DATA;
176 }
177 
178 //-----------------------------------------------------------------------------
179 // Function : SourceData::SourceData
180 // Purpose : constructor
181 // Special Notes :
182 // Scope : public
183 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
184 // Creation Date : 4/24/00
185 //-----------------------------------------------------------------------------
187  const DeviceOptions & do1)
188  : sourceName_(""),
189  typeName_(""),
190  defaultParamName_(""),
191  time(0.0),
192  SourceValue(0.0),
193  initializeFlag_(false),
194  resetFlag_(true),
195  solState_(ss1),
196  devOptions_(do1),
197  fastTimeScaleFlag_(false),
198  realFlag_(true)
199 {}
200 
201 //-----------------------------------------------------------------------------
202 // Function : SourceData::~SourceData
203 // Purpose : destructor
204 // Special Notes :
205 // Scope : public
206 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
207 // Creation Date : 4/24/00
208 //-----------------------------------------------------------------------------
210 {}
211 
212 //-----------------------------------------------------------------------------
213 // Function : SourceData::initializeSource
214 // Purpose : Base class initialization function.
215 // Special Notes :
216 // Scope : public
217 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
218 // Creation Date : 9/04/01
219 //-----------------------------------------------------------------------------
221 {
222  initializeFlag_ = true;
223  return true;
224 }
225 
226 //-----------------------------------------------------------------------------
227 // Function : SourceData::returnSource
228 // Purpose :
229 // Special Notes :
230 // Scope : public
231 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
232 // Creation Date : 4/24/00
233 //-----------------------------------------------------------------------------
235 {
236  return SourceValue;
237 }
238 
239 //-----------------------------------------------------------------------------
240 // Function : SourceData::returnSource
241 // Purpose :
242 // Special Notes :
243 // Scope : public
244 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
245 // Creation Date : 4/24/00
246 //-----------------------------------------------------------------------------
248 {
249  return typeName_;
250 }
251 
252 //-----------------------------------------------------------------------------
253 // Function : SourceData::printOutParams
254 // Purpose :
255 // Special Notes :
256 // Scope : public
257 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
258 // Creation Date : 6/21/00
259 //-----------------------------------------------------------------------------
261 {}
262 
263 //-----------------------------------------------------------------------------
264 // Function : SourceData::getMaxTimeStepSize
265 // Purpose :
266 // Special Notes :
267 // Scope : public
268 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
269 // Creation Date : 4/01/02
270 //-----------------------------------------------------------------------------
272 {
274 }
275 
276 //-----------------------------------------------------------------------------
277 // Function : SourceData::getTime_
278 // Purpose :
279 // Special Notes :
280 // Scope : protected
281 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
282 // Creation Date : 3/25/04
283 //-----------------------------------------------------------------------------
285 {
286  double tmpTime = 0.0;
287 
288  if (fastTimeScaleFlag_)
289  tmpTime = solState_.currFastTime_;
290  else
291  tmpTime = solState_.currTime_;
292 
293  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
294  {
295  Xyce::dout() << "SourceData::getTime. time = " << tmpTime << std::endl
296  << "SourceData::getTime. currFastTime = " << solState_.currFastTime_ << std::endl
297  << "SourceData::getTime. currTime = " << solState_.currTime_ << std::endl;
298  }
299 
300  return tmpTime;
301 }
302 
303 // Class SinData
304 
305 //-----------------------------------------------------------------------------
306 // Function : SinData::SinData
307 // Purpose : constructor
308 // Special Notes :
309 // Scope : public
310 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
311 // Creation Date : 3/16/00
312 //
313 // From 3f5: remember to incorporate this later:
314 //
315 //-----------------------------------------------------------------------------
316 #if 0
317  // this is from 3f5:
318  #define FREQ (((here->VSRCfunctionOrder >=3) && (*(here->VSRCcoeffs+2)))? \
319  (*(here->VSRCcoeffs+2)):(1/ckt->CKTfinalTime))
320 #endif
321 
323  const DeviceEntity & device,
324  const std::vector<Param> & paramRef,
325  const SolverState & ss1,
326  const DeviceOptions & do1)
327  : SourceData(ss1,do1),
328  V0(0.0),
329  VA(0.0),
330  FREQ(0.0),
331  TD(0.0),
332  THETA(0.0),
333  PHASE(0.0),
334  V0given(false),
335  VAgiven(false),
336  FREQgiven(false),
337  TDgiven(false),
338  THETAgiven(false),
339  PHASEgiven(false)
340 {
341  std::vector<Param>::const_iterator iter = paramRef.begin();
342  std::vector<Param>::const_iterator last = paramRef.end();
343 
344  for ( ; iter != last; ++iter)
345  {
346  const std::string & tmpname = iter->tag();
347 
348  if (tmpname == "V0") { V0 = iter->getImmutableValue<double>(); V0given = iter->given();}
349  if (tmpname == "VA") { VA = iter->getImmutableValue<double>(); VAgiven = iter->given();}
350  if (tmpname == "FREQ") { FREQ = iter->getImmutableValue<double>(); FREQgiven = iter->given();}
351  if (tmpname == "TD") { TD = iter->getImmutableValue<double>(); TDgiven = iter->given();}
352  if (tmpname == "THETA") { THETA = iter->getImmutableValue<double>(); THETAgiven = iter->given();}
353  if (tmpname == "PHASE") { PHASE = iter->getImmutableValue<double>(); PHASEgiven = iter->given();}
354  }
355 
356  if (!(V0given && VAgiven && FREQgiven))
357  UserError(device) << "V0, VA and FREQ are required for the SIN source function";
358 
359  typeName_ = "SIN";
360  defaultParamName_ = "V0";
361 }
362 
363 //-----------------------------------------------------------------------------
364 // Function : SinData::initializeSource
365 // Purpose :
366 // Special Notes :
367 // Scope : public
368 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
369 // Creation Date : 9/04/01
370 //-----------------------------------------------------------------------------
372 {
373 
374  // If neccessary, set defaults:
375  double tstop = solState_.finalTime_;
376 
377  if (!FREQgiven) FREQ = 1.0/tstop;
378  if (!TDgiven) TD = 0.0;
379  if (!THETAgiven) THETA = 0.0;
380 
381  initializeFlag_ = true;
382 
383  return true;
384 }
385 
386 //-----------------------------------------------------------------------------
387 // Function : SinData::~SinData
388 // Purpose : destructor
389 // Special Notes :
390 // Scope : public
391 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
392 // Creation Date : 3/16/00
393 //-----------------------------------------------------------------------------
395 {}
396 
397 //-----------------------------------------------------------------------------
398 // Function : SinData::printOutParams
399 // Purpose :
400 // Special Notes :
401 // Scope : public
402 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
403 // Creation Date : 6/21/00
404 //-----------------------------------------------------------------------------
405 
407 
408 {
409  Xyce::dout() << "SinData:\n";
410  Xyce::dout() << "V0 = " << V0 << std::endl;
411  Xyce::dout() << "VA = " << VA << std::endl;
412  Xyce::dout() << "FREQ = " << FREQ << std::endl;
413  Xyce::dout() << "TD = " << TD << std::endl;
414  Xyce::dout() << "THETA = " << THETA << std::endl;
415  Xyce::dout() << "PHASE = " << PHASE << std::endl;
416 }
417 
418 // Additional Declarations
419 
420 //-----------------------------------------------------------------------------
421 // Function : SinData::updateSource
422 // Purpose : Update the sinwave source.
423 // Special Notes :
424 //
425 // V0 - offset (V or A)
426 // VA - Amplitude (V or A)
427 // FREQ - frequency in Hz
428 // TD - delay in seconds
429 // THETA - damping factor (Hz).
430 // PHASE - phase (degrees)
431 //
432 // Scope : public
433 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
434 // Creation Date : 4/24/00
435 //-----------------------------------------------------------------------------
437 {
438  bool bsuccess = true;
439 
440  if (!initializeFlag_) bsuccess = initializeSource ();
441 
442  time = getTime_();
443 
444  time -= TD;
445  double mpi = M_PI;
446  if (time <= 0)
447  {
448  //SourceValue = V0;
449  SourceValue = V0 + VA * sin (2.0*mpi*(PHASE/360)) ;
450  }
451  else
452  {
453  // 2PI to convert from hz to radians/sec
454  SourceValue = V0 + VA * sin (2.0*mpi*(FREQ*time + PHASE/360)) *
455  exp( -(time*THETA));
456  }
457 
458  resetFlag_ = false;
459  return bsuccess;
460 }
461 
462 //-----------------------------------------------------------------------------
463 // Function : SinData::getParams
464 // Purpose : Pass back the sine source params.
465 // Special Notes : TD and FREQ are interchanged from their normal order
466 // to accomodate the storage layout in the device classes
467 //
468 // Scope : public
469 // Creator : Dave Shirley, PSSI
470 // Creation Date : 4/14/05
471 //-----------------------------------------------------------------------------
472 void SinData::getParams(double *params)
473 {
474  params[0] = V0;
475  params[1] = VA;
476  params[2] = TD;
477  params[3] = FREQ;
478  params[4] = THETA;
479  params[5] = PHASE;
480 }
481 
482 //-----------------------------------------------------------------------------
483 // Function : SinData::setParams
484 // Purpose : Update the sine source params.
485 // Special Notes : TD and FREQ are interchanged from their normal order
486 // to accomodate the storage layout in the device classes
487 //
488 // Scope : public
489 // Creator : Dave Shirley, PSSI
490 // Creation Date : 4/14/05
491 //-----------------------------------------------------------------------------
492 void SinData::setParams(double *params)
493 {
494  bool reset=false;
495  if (V0 != params[0])
496  {
497  V0 = params[0];
498  reset = true;
499  }
500  if (VA != params[1])
501  {
502  VA = params[1];
503  reset = true;
504  }
505  if (TD != params[2])
506  {
507  TD = params[2];
508  reset = true;
509  }
510  if (FREQ != params[3])
511  {
512  FREQ = params[3];
513  reset = true;
514  }
515  if (THETA != params[4])
516  {
517  THETA = params[4];
518  reset = true;
519  }
520  if (PHASE != params[5])
521  {
522  PHASE = params[5];
523  reset = true;
524  }
525  if (reset)
526  {
527  updateSource();
528  }
529 }
530 
531 // Class ExpData
532 
533 //-----------------------------------------------------------------------------
534 // Function : ExpData::ExpData
535 // Purpose : constructor
536 // Special Notes :
537 // Scope : public
538 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
539 // Creation Date : 3/16/00
540 //-----------------------------------------------------------------------------
542  const DeviceEntity & device,
543  const std::vector<Param> & paramRef,
544  const SolverState & ss1,
545  const DeviceOptions & do1)
546  : SourceData(ss1,do1),
547  V1 (0.0),
548  V2 (0.0),
549  TD1 (0.0),
550  TAU1 (0.0),
551  TD2 (0.0),
552  TAU2 (0.0),
553  V1given (false),
554  V2given (false),
555  TD1given (false),
556  TAU1given (false),
557  TD2given (false),
558  TAU2given (false)
559 {
560  // Set the user-defined params:
561  std::vector<Param>::const_iterator iter = paramRef.begin();
562  std::vector<Param>::const_iterator last = paramRef.end();
563 
564  for ( ; iter != last; ++iter)
565  {
566  const std::string & tmpname = iter->tag();
567 
568  if (tmpname == "V1") { V1 = iter->getImmutableValue<double>(); V1given = iter->given();}
569  if (tmpname == "V2") { V2 = iter->getImmutableValue<double>(); V2given = iter->given();}
570  if (tmpname == "TD1") { TD1 = iter->getImmutableValue<double>(); TD1given = iter->given();}
571  if (tmpname == "TAU1") { TAU1 = iter->getImmutableValue<double>(); TAU1given = iter->given();}
572  if (tmpname == "TD2") { TD2 = iter->getImmutableValue<double>(); TD2given = iter->given();}
573  if (tmpname == "TAU2") { TAU2 = iter->getImmutableValue<double>(); TAU2given = iter->given();}
574  }
575 
576  if (!(V1given && V2given))
577  UserError(device) << "V1 and V2 are required for the EXP source function";
578 
579  typeName_ = "EXP";
580  defaultParamName_ = "V1";
581 }
582 
583 //-----------------------------------------------------------------------------
584 // Function : ExpData::~ExpData
585 // Purpose : destructor
586 // Special Notes :
587 // Scope : public
588 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
589 // Creation Date : 3/16/00
590 //-----------------------------------------------------------------------------
592 {}
593 
594 // Additional Declarations
595 
596 //-----------------------------------------------------------------------------
597 // Function : ExpData::printOutParams
598 // Purpose :
599 // Special Notes :
600 // Scope : public
601 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
602 // Creation Date : 6/21/00
603 //-----------------------------------------------------------------------------
605 {
606  Xyce::dout() << "ExpData:\n";
607 
608  Xyce::dout() << "V1 = " << V1 << std::endl;
609  Xyce::dout() << "V2 = " << V2 << std::endl;
610 
611  Xyce::dout() << "TD1 = " << TD1 << std::endl;
612  Xyce::dout() << "TAU1 = " << TAU1 << std::endl;
613 
614  Xyce::dout() << "TD2 = " << TD2 << std::endl;
615  Xyce::dout() << "TAU2 = " << TAU2 << std::endl;
616 
617 }
618 
619 //-----------------------------------------------------------------------------
620 // Function : ExpData::initializeSource
621 // Purpose :
622 // Special Notes :
623 // Scope : public
624 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
625 // Creation Date : 9/04/01
626 //-----------------------------------------------------------------------------
628 {
629  // If neccessary, set defaults:
630  double tstep = solState_.startingTimeStep_;
631 
632  if (!TD1given) TD1 = 0.0;
633  if (!TAU1given) TAU1 = tstep;
634  if (!TD2given) TD2 = TD1 + tstep;
635  if (!TAU2given) TAU2 = tstep;
636 
637  initializeFlag_ = true;
638 
639  return true;
640 }
641 
642 //-----------------------------------------------------------------------------
643 // Function : ExpData::updateSource
644 // Purpose : Updates an exponential source:
645 // Special Notes :
646 //
647 // V1 - Initial value (V or A)
648 // V2 - Pulsed value (V or A).
649 // TD1 - Rise delay time (seconds).
650 // TAU1 - Rise time constant (seconds)
651 // TD2 - Fall delay time (seconds).
652 // TAU2 - Fall time constant (seconds)
653 //
654 // Scope : public
655 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
656 // Creation Date : 4/24/00
657 //-----------------------------------------------------------------------------
658 
660 
661 {
662  bool bsuccess = true;
663 
664  if (!initializeFlag_) bsuccess = initializeSource ();
665 
666  time = getTime_();
667 
668  if (time <= TD1)
669  {
670  SourceValue = V1;
671  }
672  else if (time <= TD2)
673  {
674  SourceValue = V1 + (V2-V1)*(1-exp(-(time-TD1)/TAU1));
675  }
676  else
677  {
678  SourceValue = V1 + (V2-V1)*(1-exp(-(time-TD1)/TAU1)) +
679  (V1-V2)*(1-exp(-(time-TD2)/TAU2)) ;
680  }
681 
682  resetFlag_ = false;
683 
684  return bsuccess;
685 
686 }
687 
688 //-----------------------------------------------------------------------------
689 // Function : ExpData::getParams
690 // Purpose : Pass back the exponential source params.
691 // Special Notes :
692 //
693 // Scope : public
694 // Creator : Dave Shirley, PSSI
695 // Creation Date : 4/14/05
696 //-----------------------------------------------------------------------------
697 void ExpData::getParams(double *params)
698 {
699  params[0] = V1;
700  params[1] = V2;
701  params[2] = TD1;
702  params[3] = TAU1;
703  params[4] = TD2;
704  params[5] = TAU2;
705 }
706 
707 //-----------------------------------------------------------------------------
708 // Function : ExpData::setParams
709 // Purpose : Update the exponential source params.
710 // Special Notes :
711 //
712 // Scope : public
713 // Creator : Dave Shirley, PSSI
714 // Creation Date : 4/14/05
715 //-----------------------------------------------------------------------------
716 void ExpData::setParams(double *params)
717 {
718  bool reset=false;
719  if (V1 != params[0])
720  {
721  V1 = params[0];
722  reset = true;
723  }
724  if (V2 != params[1])
725  {
726  V2 = params[1];
727  reset = true;
728  }
729  if (TD1 != params[2])
730  {
731  TD1 = params[2];
732  reset = true;
733  }
734  if (TAU1 != params[3])
735  {
736  TAU1 = params[3];
737  reset = true;
738  }
739  if (TD2 != params[4])
740  {
741  TD2 = params[4];
742  reset = true;
743  }
744  if (TAU2 != params[5])
745  {
746  TAU2 = params[5];
747  reset = true;
748  }
749  if (reset)
750  {
751  updateSource();
752  }
753 }
754 
755 // Class PulseData
756 
757 //-----------------------------------------------------------------------------
758 // Function : PulseData::PulseData
759 // Purpose : constructor
760 // Special Notes :
761 // Scope : public
762 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
763 // Creation Date : 3/16/00
764 //-----------------------------------------------------------------------------
766  const DeviceEntity & device,
767  const std::vector<Param> & paramRef,
768  const SolverState & ss1,
769  const DeviceOptions & do1)
770  : SourceData (ss1,do1),
771  V1 (0.0),
772  V2 (0.0),
773  TD (0.0),
774  TR (0.0),
775  TF (0.0),
776  PW (0.0),
777  PER (0.0),
778  V1given (false),
779  V2given (false),
780  TDgiven (false),
781  TRgiven (false),
782  TFgiven (false),
783  PWgiven (false),
784  PERgiven (false)
785 {
786 
787  // Get the user-defined values:
788  std::vector<Param>::const_iterator iter = paramRef.begin();
789  std::vector<Param>::const_iterator last = paramRef.end();
790 
791  for ( ; iter != last; ++iter)
792  {
793  const std::string & tmpname = iter->tag();
794 
795  if (tmpname == "V1") { V1 = iter->getImmutableValue<double>(); V1given = iter->given();}
796  if (tmpname == "V2") { V2 = iter->getImmutableValue<double>(); V2given = iter->given();}
797  if (tmpname == "TD") { TD = iter->getImmutableValue<double>(); TDgiven = iter->given();}
798  if (tmpname == "TR") { TR = iter->getImmutableValue<double>(); TRgiven = iter->given();}
799  if (tmpname == "TF") { TF = iter->getImmutableValue<double>(); TFgiven = iter->given();}
800  if (tmpname == "PW") { PW = iter->getImmutableValue<double>(); PWgiven = iter->given();}
801  if (tmpname == "PER") { PER = iter->getImmutableValue<double>(); PERgiven = iter->given();}
802  }
803 
804  typeName_ = "PULSE";
805  defaultParamName_ = "V2";
806 }
807 
808 //-----------------------------------------------------------------------------
809 // Function : PulseData::~PulseData
810 // Purpose : destructor
811 // Special Notes :
812 // Scope : public
813 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
814 // Creation Date : 3/16/00
815 //-----------------------------------------------------------------------------
817 {}
818 
819 // Additional Declarations
820 
821 //-----------------------------------------------------------------------------
822 // Function : PulseData::printOutParams
823 // Purpose :
824 // Special Notes :
825 // Scope : public
826 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
827 // Creation Date : 6/21/00
828 //-----------------------------------------------------------------------------
830 {
831  Xyce::dout() << std::endl;
832  Xyce::dout() << " PulseData::printOutParams\n";
833  Xyce::dout() << " V1 = " << V1 << std::endl;
834  Xyce::dout() << " V2 = " << V2 << std::endl;
835 
836  Xyce::dout() << " TD = " << TD << std::endl;
837  Xyce::dout() << " TR = " << TR << std::endl;
838  Xyce::dout() << " TF = " << TF << std::endl;
839  Xyce::dout() << " PW = " << PW << std::endl;
840  Xyce::dout() << " PER = " << PER << std::endl;
841  Xyce::dout() << std::endl;
842 
843 }
844 
845 //-----------------------------------------------------------------------------
846 // Function : PulseData::initializeSource
847 // Purpose :
848 // Special Notes :
849 // Scope : public
850 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
851 // Creation Date : 9/04/01
852 //-----------------------------------------------------------------------------
854 {
855  // If neccessary, set the defaults:
856 
857  double tstep = solState_.startingTimeStep_;
858  double tstop = solState_.finalTime_;
859 
860  if (!TDgiven) TD = 0.0;
861  if (!TRgiven) TR = tstep;
862  if (!TFgiven) TF = tstep;
863  if (!PWgiven) PW = tstop;
864  if (!PERgiven) PER = tstop;
865 
866  initializeFlag_ = true;
867 
868  return true;
869 }
870 
871 //-----------------------------------------------------------------------------
872 // Function : PulseData::updateSource
873 // Purpose :
874 // Special Notes :
875 // Scope : public
876 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
877 // Creation Date : 4/24/00
878 //-----------------------------------------------------------------------------
880 
881 {
882 //notused: double tstep = solState_.startingTimeStep;
883 //notused: double tstop = solState_.finalTime_;
884  bool bsuccess = true;
885 
886  if (!initializeFlag_) bsuccess = initializeSource ();
887 
888  double basetime = 0;
889  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
890  {
891  Xyce::dout() << " PulseData::updateSources\n";
892  printOutParams();
893  }
894 
895  time = getTime_();
896 
897  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
898  {
899  Xyce::dout() << " Time = " << time << std::endl;
900  }
901 
902  time -= TD;
903 
904  if (time > PER && PER != 0.0)
905  {
906  // repeating signal - figure out where we are in period
907  basetime = PER * floor(time/PER);
908  time -= basetime;
909  }
910 
911  // This section got ugly because of a nasty roundoff bug.
912  // Instead of doing "time > X" you need also check that time
913  // is not within bptol of X.
914  // So the following translation is used:
915  // Instead of: we do:
916  // time > X time>X && fabs(time-x)>bptol
917  // time <= X time<X || fabs(time-x)<bptol
918 
919  if (time <= 0 || (time > (TR + PW + TF) &&
920  (fabs (time - (TR+PW+TF)) > solState_.bpTol_) ) )
921  {
922  SourceValue = V1;
923  }
924  else if ((time > TR && fabs(time-TR) > solState_.bpTol_)
925  && (time < (TR + PW) || fabs (time-(TR+PW))<solState_.bpTol_) )
926  {
927  SourceValue = V2;
928  }
929  else if (time > 0 &&
930  (time < TR || fabs(time-TR) < solState_.bpTol_))
931  {
932  if (TR != 0.0)
933  {
934  SourceValue = V1 + (V2 - V1) * (time) / TR;
935  }
936  else
937  {
938  SourceValue = V1;
939  }
940  }
941  else
942  { // time > (TR + PW) && <= (TR + PW + TF)
943  if (TF != 0.0)
944  {
945  SourceValue = V2 + (V1 - V2) * (time - (TR + PW)) / TF;
946  }
947  else
948  {
949  SourceValue = V2; // SourceValue = 0.5 * (V1 + V2);
950  }
951  }
952 
953  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
954  {
955  Xyce::dout() << " SourceValue = " << SourceValue << std::endl;
956  }
957 
958  resetFlag_ = false;
959 
960  return bsuccess;
961 }
962 
963 //-----------------------------------------------------------------------------
964 // Function : PulseData::getParams
965 // Purpose : Pass back the pulse source params.
966 // Special Notes :
967 //
968 // Scope : public
969 // Creator : Dave Shirley, PSSI
970 // Creation Date : 4/14/05
971 //-----------------------------------------------------------------------------
972 void PulseData::getParams(double *params)
973 {
974  params[0] = V1;
975  params[1] = V2;
976  params[2] = TD;
977  params[3] = TR;
978  params[4] = TF;
979  params[5] = PW;
980  params[6] = PER;
981 }
982 
983 //-----------------------------------------------------------------------------
984 // Function : PulseData::setParams
985 // Purpose : Update the pulse source params.
986 // Special Notes :
987 //
988 // Scope : public
989 // Creator : Dave Shirley, PSSI
990 // Creation Date : 4/14/05
991 //-----------------------------------------------------------------------------
992 void PulseData::setParams(double *params)
993 {
994  bool reset=false;
995  if (V1 != params[0])
996  {
997  V1 = params[0];
998  reset = true;
999  }
1000  if (V2 != params[1])
1001  {
1002  V2 = params[1];
1003  reset = true;
1004  }
1005  if (TD != params[2])
1006  {
1007  TD = params[2];
1008  reset = true;
1009  }
1010  if (TR != params[3])
1011  {
1012  TR = params[3];
1013  reset = true;
1014  }
1015  if (TF != params[4])
1016  {
1017  TF = params[4];
1018  reset = true;
1019  }
1020  if (PW != params[5])
1021  {
1022  PW = params[5];
1023  reset = true;
1024  }
1025  if (PER != params[6])
1026  {
1027  PER = params[6];
1028  reset = true;
1029  }
1030  if (reset)
1031  {
1032  updateSource();
1033  }
1034 }
1035 
1036 //-----------------------------------------------------------------------------
1037 // Function : PulseData::getBreakPoints
1038 // Purpose : This function adds break points to a vector of breakpoints.
1039 //
1040 // It does not bother to check them in any way, or put them
1041 // in order. It only adds them in.
1042 //
1043 // Special Notes : Like much of this file, this is adapted from spice 3f5.
1044 // Some of the stuff in it is a little hokey, and may get
1045 // removed or modified later.
1046 //
1047 // Scope : public
1048 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1049 // Creation Date : 06/08/01
1050 //-----------------------------------------------------------------------------
1052  (std::vector<Util::BreakPoint> & breakPointTimes )
1053 {
1054  bool bsuccess = true;
1055 
1056  if (!initializeFlag_) bsuccess = initializeSource ();
1057 
1058  // currPeriodIndex is the integer index representing the period of
1059  // the current circuit time.
1060  int currPeriodIndex = 0;
1061 
1062  // subtract out the delay.
1063  double basetime = 0.0;
1064 
1065  time = getTime_() - TD;
1066 
1067  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1068  {
1069  Xyce::dout() << std::endl;
1070  Xyce::dout() << " In PulseData::getBreakPoints\n";
1071  Xyce::dout() << " time = " << time << std::endl;
1072  Xyce::dout() << " TD = " << TD << std::endl;
1073  Xyce::dout() << " PER = " << PER << std::endl;
1074  }
1075 
1076  // repeating signal - figure out where we are in period
1077  if(time >= PER)
1078  {
1079  if (PER != 0.0)
1080  {
1081  currPeriodIndex = (static_cast<int> (floor(time/PER)));
1082  basetime = PER * (static_cast<double> (currPeriodIndex));
1083  time -= basetime;
1084  }
1085  }
1086 
1087  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1088  {
1089  Xyce::dout() << " time = " << time << std::endl;
1090  Xyce::dout() << " basetime = " << basetime << std::endl;
1091  Xyce::dout() << " currPeriodIndex = " << currPeriodIndex << std::endl;
1092  Xyce::dout() << std::endl;
1093  }
1094 
1095  // now that we know which period this is, push_back all breakpoints
1096  // in this period and the next. If we are still in the delay, then
1097  // just use first two periods.
1098 
1099  // current period:
1100  breakPointTimes.push_back(basetime+TD);
1101  breakPointTimes.push_back(basetime+TD+TR);
1102  breakPointTimes.push_back(basetime+TD+TR+PW);
1103  breakPointTimes.push_back(basetime+TD+TR+PW+TF);
1104 
1105  if (PER != 0.0)
1106  {
1107  breakPointTimes.push_back(basetime+TD+PER);
1108 
1109  // next period:
1110  breakPointTimes.push_back(basetime+TD+PER+TR);
1111  breakPointTimes.push_back(basetime+TD+PER+TR+PW);
1112  breakPointTimes.push_back(basetime+TD+PER+TR+PW+TF);
1113  breakPointTimes.push_back(basetime+TD+PER+PER);
1114  }
1115 
1116  return bsuccess;
1117 }
1118 
1119 //-----------------------------------------------------------------------------
1120 // Function : PulseData::getMaxTimeStepSize
1121 // Purpose :
1122 // Special Notes :
1123 // Scope : public
1124 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1125 // Creation Date : 9/25/01
1126 //-----------------------------------------------------------------------------
1128 {
1129  double maxTimeStep = devOptions_.defaultMaxTimeStep;
1130 
1131  // check if we are still in the delay or not.
1132  time = getTime_();
1133 
1134  if (time < TD) maxTimeStep = (0.1*TD );
1135  else maxTimeStep = (0.1*PER);
1136 
1137  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1138  {
1139  Xyce::dout() << "\nIn PulseData::getMaxTimeStepSize. ";
1140  Xyce::dout() << " maxTimeStep = "<< maxTimeStep;
1141  Xyce::dout() << " TD = " << TD << " PER = " <<PER;
1142  Xyce::dout() << " time = "<< time << std::endl;
1143  }
1144 
1145  return maxTimeStep;
1146 }
1147 
1148 // Class PWLinData
1149 
1150 //-----------------------------------------------------------------------------
1151 // Function : PWLinData::PWLinData
1152 // Purpose : constructor
1153 // Special Notes :
1154 // Scope : public
1155 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1156 // Creation Date : 3/16/00
1157 //-----------------------------------------------------------------------------
1159  const DeviceEntity & device,
1160  const std::vector<Param> & paramRef,
1161  const SolverState & ss1,
1162  const DeviceOptions & do1)
1163  : SourceData(ss1,do1),
1164  NUM(0),
1165  REPEAT(false),
1166  REPEATTIME(0.0),
1167  TD(0.0),
1168  loc_(0),
1169  starttime_(0.0)
1170 {
1171  std::vector<Param>::const_iterator iter = paramRef.begin();
1172  std::vector<Param>::const_iterator last = paramRef.end();
1173 
1174  for ( ; iter != last; ++iter)
1175  {
1176  const std::string & tmpname = iter->tag();
1177  const bool & tmpgiven = iter->given();
1178 
1179  if (tmpname == "NUM") NUM = iter->getImmutableValue<int>();
1180  if (tmpname == "R" && tmpgiven == true)
1181  {
1182  REPEAT = true;
1183  REPEATTIME = iter->getImmutableValue<double>();
1184  }
1185  if (tmpname == "TD") TD = iter->getImmutableValue<double>();
1186 
1187  if ( tmpname == "T" && iter->given() )
1188  {
1189  time = iter->getImmutableValue<double>();
1190  ++iter;
1191 
1192  // The if statement handles the case where the first time-value pair is not (0,0).
1193  // It inserts a time-value pair at time=0, with the voltage level of the
1194  // first user specified time-voltage pair. This is compatible with what
1195  // PSpice and HSpice do. The number of time-value pairs (NUM) is also
1196  // incremented by 1, if that time-voltage pair at time=0 needs to be inserted.
1197  if ( TVVEC.empty() && time > 0.0 )
1198  {
1199  TVVEC.push_back(std::pair<double,double>(0.0,iter->getImmutableValue<double>()));
1200  NUM++;
1201  }
1202 
1203  TVVEC.push_back(std::pair<double,double>(time, iter->getImmutableValue<double>()));
1204  }
1205  }
1206 
1207  // an empty list of time-voltage pairs will likely fail parsing in
1208  // extractSourceFields(). So, this error test may never be used.
1209  if (NUM == 0)
1210  UserError(device) << "At least one time-voltage pair must be specified for the PWL source function";
1211 
1212  // only do this test if the REPEAT parameter (R) is true
1213  if ( REPEAT && (REPEATTIME < 0 || REPEATTIME >=TVVEC[NUM-1].first) )
1214  UserError(device) << "PWL source repeat value (R) must be >= 0 and < last value in time-voltage list";
1215 
1216  typeName_ = "PWL";
1217 }
1218 
1219 //-----------------------------------------------------------------------------
1220 // Function : PWLinData::PWLinData
1221 // Purpose : destructor
1222 // Special Notes :
1223 // Scope : public
1224 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1225 // Creation Date : 3/16/00
1226 //-----------------------------------------------------------------------------
1228 {}
1229 
1230 //-----------------------------------------------------------------------------
1231 // Function : PWLinData::printOutParams
1232 // Purpose :
1233 // Special Notes :
1234 // Scope : public
1235 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1236 // Creation Date : 6/21/00
1237 //-----------------------------------------------------------------------------
1239 {
1240  Xyce::dout() << std::endl;
1241  Xyce::dout() << " NUM = " << NUM << std::endl;
1242  Xyce::dout() << " REPEAT = " << REPEAT << std::endl;
1243  Xyce::dout() << " REPEATTIME = " << REPEATTIME << std::endl;
1244  Xyce::dout() << " TD = " << TD << std::endl;
1245  Xyce::dout() << " loc_ = " << loc_ << std::endl;
1246  Xyce::dout() << " starttime_ = " << starttime_ << std::endl;
1247 
1248  Xyce::dout() << " Time Voltage" << std::endl;
1249  for( int i = 0; i < NUM; ++i )
1250  Xyce::dout() << " " << TVVEC[i].first << " " << TVVEC[i].second << std::endl;
1251 
1252  Xyce::dout() << std::endl;
1253 }
1254 
1255 // Additional Declarations
1256 
1257 //-----------------------------------------------------------------------------
1258 // Function : PWLinData::updateSource
1259 // Purpose :
1260 // Special Notes :
1261 // Scope : public
1262 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1263 // Creation Date : 4/24/00
1264 //-----------------------------------------------------------------------------
1266 {
1267 
1268  bool bsuccess = true;
1269 
1270  if (!initializeFlag_) bsuccess = initializeSource ();
1271 
1272  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1273  {
1274  Xyce::dout() << std::endl;
1275  Xyce::dout() << " PWLinData::updateSource\n";
1276  printOutParams();
1277  }
1278 
1279  time = getTime_();
1280 
1281  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1282  {
1283  Xyce::dout() << Xyce::section_divider << std::endl;
1284  Xyce::dout() << " Time = " << time << std::endl;
1285  }
1286 
1287  double time1, time2, voltage1, voltage2;
1288 
1289  if( time >= TD )
1290  {
1291  time -= TD;
1292 
1293  if( time <= TVVEC[NUM-1].first )
1294  {
1295  for( int i = 0; i < NUM; ++i )
1296  if( time < TVVEC[i].first ) {loc_ = i;break;}
1297 
1298  if( loc_ == 0 )
1299  {
1300  time1 = 0.0;
1301  voltage1 = 0.0;
1302  }
1303  else
1304  {
1305  time1 = TVVEC[loc_-1].first;
1306  voltage1 = TVVEC[loc_-1].second;
1307  }
1308  time2 = TVVEC[loc_].first;
1309  voltage2 = TVVEC[loc_].second;
1310 
1311  }
1312  else if( !REPEAT )
1313  {
1314  // this has the net-effect of setting SourceValue = voltage2
1315  // when combined with the next if-else block
1316  time1 = 0.0;
1317  time2 = 1.0;
1318  voltage1 = voltage2 = TVVEC[NUM-1].second;
1319  }
1320  else
1321  {
1322  double looptime = TVVEC[NUM-1].first - REPEATTIME;
1323  time -= TVVEC[NUM-1].first;
1324  time -= looptime * floor(time / looptime);
1325  time += REPEATTIME;
1326 
1327  for( int i = 0; i < NUM; ++i )
1328  {
1329  if( time < TVVEC[i].first ) {loc_ = i;break;}
1330  }
1331  if (time == REPEATTIME)
1332  {
1333  time1 = 0.0;
1334  time2 = 1.0;
1335  voltage1 = voltage2 = TVVEC[NUM-1].second;
1336  }
1337  else
1338  {
1339  if( loc_ == 0 )
1340  {
1341  time1 = REPEATTIME;
1342  voltage1 = TVVEC[NUM-1].second;
1343  }
1344  else
1345  {
1346  time1 = TVVEC[loc_-1].first;
1347  voltage1 = TVVEC[loc_-1].second;
1348  }
1349  time2 = TVVEC[loc_].first;
1350  voltage2 = TVVEC[loc_].second;
1351  }
1352 
1353  }
1354 
1355  if( time1 == time2 )
1356  SourceValue = voltage2;
1357  else
1358  {
1359  double length = time2 - time1;
1360  SourceValue = ( time2 - time ) * voltage1 / length;
1361  SourceValue += ( -time1 + time ) * voltage2 / length;
1362  }
1363 
1364  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1365  {
1366  Xyce::dout() << "time: " << time << std::endl;
1367  Xyce::dout() << "time1: " << time1 << std::endl;
1368  Xyce::dout() << "time2: " << time2 << std::endl;
1369  Xyce::dout() << "voltage1: " << voltage1 << std::endl;
1370  Xyce::dout() << "voltage2: " << voltage2 << std::endl;
1371  Xyce::dout() << "Src: " << SourceValue << std::endl;
1372  Xyce::dout() << Xyce::section_divider << std::endl;
1373  }
1374  }
1375  else
1376  {
1377  SourceValue = 0.0;
1378  }
1379 
1380 
1381  resetFlag_ = false;
1382 
1383  return bsuccess;
1384 }
1385 
1386 //-----------------------------------------------------------------------------
1387 // Function : PWLinData::getBreakPoints
1388 // Purpose :
1389 // Special Notes :
1390 // Scope : public
1391 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1392 // Creation Date : 06/08/01
1393 //-----------------------------------------------------------------------------
1395  (std::vector<Util::BreakPoint> & breakPointTimes )
1396 {
1397  bool bsuccess = true;
1398 
1399  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1400  {
1401  Xyce::dout() << " In PWLinData::getBreakPoints\n";
1402  }
1403 
1404  if (!initializeFlag_) bsuccess = initializeSource ();
1405 
1406  time = solState_.currTime_;
1407 
1408  time -= TD;
1409 
1410  // if it's a repeating signal, figure out what period we are in
1411  if (REPEAT && time >= TVVEC[NUM - 1].first)
1412  {
1413  double loopBaseTime = 0.0;
1414  double bp_time;
1415 
1416  double looptime = TVVEC[NUM-1].first - REPEATTIME;
1417  loopBaseTime = looptime * (1.0 + floor((time - TVVEC[NUM - 1].first) / looptime));
1418  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1419  {
1420  Xyce::dout() << "loopBaseTime: " << loopBaseTime << std::endl;
1421  Xyce::dout() << "floor function: " << floor((time - TVVEC[NUM - 1].first) / (TVVEC[NUM - 1].first - REPEATTIME)) << std::endl;
1422  }
1423 
1424  for (int i = 0; i < NUM; ++i)
1425  {
1426  bp_time = TVVEC[i].first;
1427  if (bp_time >= REPEATTIME)
1428  {
1429  breakPointTimes.push_back(bp_time + loopBaseTime + TD);
1430  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1431  {
1432  Xyce::dout() << "bp_time + loopBaseTime + TD: " << bp_time + loopBaseTime + TD << std::endl;
1433  }
1434  }
1435  }
1436  }
1437  else
1438  {
1439  for (int i = 0; i < NUM; ++i)
1440  {
1441  double bp_time = TVVEC[i].first;
1442  breakPointTimes.push_back(bp_time+TD);
1443  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
1444  {
1445  Xyce::dout() << "bp_time + TD: " << bp_time + TD << std::endl;
1446  }
1447  }
1448  }
1449  // now that we know which period this is, push_back all breakpoints
1450  // in this period and the next.
1451 
1452  return bsuccess;
1453 }
1454 
1455 // Class SFFMData
1456 
1457 //-----------------------------------------------------------------------------
1458 // Function : SFFMData::SFFMData
1459 // Purpose : constructor
1460 // Special Notes :
1461 // Scope : public
1462 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1463 // Creation Date : 3/16/00
1464 //-----------------------------------------------------------------------------
1465 
1467  const DeviceEntity & device,
1468  const std::vector<Param> & paramRef,
1469  const SolverState & ss1,
1470  const DeviceOptions & do1)
1471  : SourceData(ss1,do1),
1472  V0 (0.0),
1473  VA (0.0),
1474  FC (0.0),
1475  MDI (0.0),
1476  FS (0.0),
1477  V0given (false),
1478  VAgiven (false),
1479  FCgiven (false),
1480  MDIgiven (false),
1481  FSgiven (false)
1482 
1483 {
1484  std::vector<Param>::const_iterator iter = paramRef.begin();
1485  std::vector<Param>::const_iterator last = paramRef.end();
1486 
1487  for ( ; iter != last; ++iter)
1488  {
1489  const std::string & tmpname = iter->tag();
1490 
1491  if (tmpname == "V0") { V0 = iter->getImmutableValue<double>(); V0given = iter->given(); }
1492  if (tmpname == "VA") { VA = iter->getImmutableValue<double>(); VAgiven = iter->given(); }
1493  if (tmpname == "FC") { FC = iter->getImmutableValue<double>(); FCgiven = iter->given(); }
1494  if (tmpname == "MDI") { MDI = iter->getImmutableValue<double>(); MDIgiven = iter->given(); }
1495  if (tmpname == "FS") { FS = iter->getImmutableValue<double>(); FSgiven = iter->given(); }
1496  }
1497 
1498  if (!(V0given && VAgiven))
1499  UserError(device) << "V0 and VA are required for the SFFM source function";
1500 
1501  typeName_ = "SFFM";
1502 }
1503 
1504 //-----------------------------------------------------------------------------
1505 // Function : SFFMData::~SFFMData
1506 // Purpose : destructor
1507 // Special Notes :
1508 // Scope : public
1509 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1510 // Creation Date : 3/16/00
1511 //-----------------------------------------------------------------------------
1513 {}
1514 
1515 // Additional Declarations
1516 
1517 //-----------------------------------------------------------------------------
1518 // Function : SFFMData::printOutParams
1519 // Purpose :
1520 // Special Notes :
1521 // Scope : public
1522 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1523 // Creation Date : 5/01/00
1524 //-----------------------------------------------------------------------------
1525 
1527 {
1528  Xyce::dout() << "SFFMData:\n";
1529  Xyce::dout() << "V0 = " << V0 << std::endl;
1530  Xyce::dout() << "VA = " << VA << std::endl;
1531  Xyce::dout() << "FC = " << FC << std::endl;
1532  Xyce::dout() << "MDI = " << MDI << std::endl;
1533  Xyce::dout() << "FS = " << FS << std::endl;
1534 }
1535 
1536 //-----------------------------------------------------------------------------
1537 // Function : SFFMData::initializeSource
1538 // Purpose :
1539 // Special Notes :
1540 // Scope : public
1541 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1542 // Creation Date : 9/04/01
1543 //-----------------------------------------------------------------------------
1544 
1546 {
1547  // If neccessary, set the defaults:
1548  double tstop = solState_.finalTime_;
1549 
1550  if (!FCgiven) FC = 1.0/tstop;
1551  if (!FSgiven) FS = 1.0/tstop;
1552 
1553  initializeFlag_ = true;
1554 
1555  return true;
1556 }
1557 
1558 //-----------------------------------------------------------------------------
1559 // Function : SFFMData::updateSource
1560 // Purpose :
1561 // Special Notes :
1562 //
1563 // V0 - offset (V or A)
1564 // VA - Amplitude (V or A)
1565 // FC - carrier frequency
1566 // MDI - modulation index
1567 // FS - signal frequency
1568 //
1569 // Scope : public
1570 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1571 // Creation Date : 4/24/00
1572 //-----------------------------------------------------------------------------
1573 
1575 {
1576  bool bsuccess = true;
1577 
1578  if (!initializeFlag_) bsuccess = initializeSource ();
1579 
1580  time = getTime_();
1581 
1582  double mpi = M_PI;
1583  SourceValue = V0 + VA * sin((2 * mpi * FC * time) +
1584  MDI * sin (2 * mpi * FS * time));
1585 
1586  resetFlag_ = false;
1587 
1588  return bsuccess;
1589 }
1590 
1591 //-----------------------------------------------------------------------------
1592 // Function : SFFMData::getParams
1593 // Purpose : Pass back the SFFM source params.
1594 // Special Notes :
1595 //
1596 // Scope : public
1597 // Creator : Dave Shirley, PSSI
1598 // Creation Date : 4/14/05
1599 //-----------------------------------------------------------------------------
1600 void SFFMData::getParams(double *params)
1601 {
1602  params[0] = V0;
1603  params[1] = VA;
1604  params[2] = FC;
1605  params[3] = MDI;
1606  params[4] = FS;
1607 }
1608 
1609 //-----------------------------------------------------------------------------
1610 // Function : SFFMData::setParams
1611 // Purpose : Update the SFFM source params.
1612 // Special Notes :
1613 //
1614 // Scope : public
1615 // Creator : Dave Shirley, PSSI
1616 // Creation Date : 4/14/05
1617 //-----------------------------------------------------------------------------
1618 void SFFMData::setParams(double *params)
1619 {
1620  bool reset=false;
1621  if (V0 != params[0])
1622  {
1623  V0 = params[0];
1624  reset = true;
1625  }
1626  if (VA != params[1])
1627  {
1628  VA = params[1];
1629  reset = true;
1630  }
1631  if (FC != params[2])
1632  {
1633  FC = params[2];
1634  reset = true;
1635  }
1636  if (MDI != params[3])
1637  {
1638  MDI = params[3];
1639  reset = true;
1640  }
1641  if (FS != params[4])
1642  {
1643  FS = params[4];
1644  reset = true;
1645  }
1646  if (reset)
1647  updateSource();
1648 }
1649 
1650 // Class ACData
1651 
1652 //-----------------------------------------------------------------------------
1653 // Function : ACData::ACData
1654 // Purpose : constructor
1655 // Special Notes :
1656 // Scope : public
1657 // Creator : Ting Mei, SNL
1658 // Creation Date :
1659 //-----------------------------------------------------------------------------
1660 
1662  const DeviceEntity & device,
1663  const std::vector<Param> & paramRef,
1664  const SolverState & ss1,
1665  const DeviceOptions & do1)
1666  : SourceData(ss1,do1),
1667  ACMAG(1.0),
1668  ACPHASE(0.0),
1669  ACMAGgiven(false),
1670  ACPHASEgiven(false)
1671 {
1672  std::vector<Param>::const_iterator iter = paramRef.begin();
1673  std::vector<Param>::const_iterator last = paramRef.end();
1674 
1675  for ( ; iter != last; ++iter)
1676  {
1677  const std::string & tmpname = iter->tag();
1678 
1679  if (tmpname == "ACMAG") { ACMAG = iter->getImmutableValue<double>(); ACMAGgiven = iter->given();}
1680  if (tmpname == "ACPHASE") { ACPHASE = iter->getImmutableValue<double>(); ACPHASEgiven = iter->given();}
1681  }
1682 
1683  typeName_ = "AC";
1684  defaultParamName_ = "ACMAG";
1685 }
1686 
1687 //-----------------------------------------------------------------------------
1688 // Function : ACData::~ACData
1689 // Purpose : destructor
1690 // Special Notes :
1691 // Scope : public
1692 // Creator : Ting Mei, SNL
1693 // Creation Date : 3/16/00
1694 //-----------------------------------------------------------------------------
1696 {}
1697 
1698 //-----------------------------------------------------------------------------
1699 // Function : ACData::printOutParams
1700 // Purpose :
1701 // Special Notes :
1702 // Scope : public
1703 // Creator : Ting Mei, SNL
1704 // Creation Date : 6/21/00
1705 //-----------------------------------------------------------------------------
1706 
1708 
1709 {
1710  Xyce::dout() << "ACData:\n";
1711  Xyce::dout() << "ACMAG = " << ACMAG << std::endl;
1712  Xyce::dout() << "ACPHASE = " << ACPHASE << std::endl;
1713 }
1714 
1715 //-----------------------------------------------------------------------------
1716 // Function : ACData::updateSource
1717 // Purpose : Update the sinwave source.
1718 // Special Notes :
1719 //
1720 // Scope : public
1721 // Creator : Ting Mei, SNL
1722 // Creation Date :
1723 //-----------------------------------------------------------------------------
1724 
1726 {
1727  bool bsuccess = true;
1728 
1729  double mpi = M_PI;
1730 
1731  if (!initializeFlag_) bsuccess = initializeSource ();
1732 
1733  if (realFlag_)
1734  {
1735  SourceValue = ACMAG * cos(2.0*mpi*ACPHASE/360);
1736  }
1737  else
1738  {
1739  SourceValue = ACMAG * sin(2.0*mpi*ACPHASE/360);
1740  }
1741 
1742  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1743  {
1744  Xyce::dout() << " SourceValue = " << SourceValue << std::endl;
1745  }
1746 
1747  resetFlag_ = false;
1748 
1749  return bsuccess;
1750 }
1751 
1752 //-----------------------------------------------------------------------------
1753 // Function : ACData::getParams
1754 // Purpose : Pass back the AC source params.
1755 // Special Notes :
1756 // Scope : public
1757 // Creator : Ting Mei
1758 // Creation Date :
1759 //-----------------------------------------------------------------------------
1760 void ACData::getParams(double *params)
1761 {
1762  params[0] = ACMAG;
1763  params[1] = ACPHASE;
1764 }
1765 
1766 //-----------------------------------------------------------------------------
1767 // Function : ACData::setParams
1768 // Purpose : Update the AC source params.
1769 // Special Notes :
1770 //
1771 // Scope : public
1772 // Creator : Ting Mei
1773 // Creation Date :
1774 //-----------------------------------------------------------------------------
1775 void ACData::setParams(double *params)
1776 {
1777  bool reset=false;
1778  if (ACMAG!= params[0])
1779  {
1780  ACMAG = params[0];
1781  reset = true;
1782  }
1783  if ( ACPHASE != params[1])
1784  {
1785  ACPHASE = params[1];
1786  reset = true;
1787  }
1788  if (reset)
1789  updateSource();
1790 }
1791 
1792 
1793 // Class ConstData
1794 
1795 //-----------------------------------------------------------------------------
1796 // Function : ConstData::ConstData
1797 // Purpose : constructor
1798 // Special Notes :
1799 // Scope : public
1800 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
1801 // Creation Date : 10/5/00
1802 //-----------------------------------------------------------------------------
1803 
1805  const DeviceEntity & device,
1806  const std::vector<Param> & paramRef,
1807  const SolverState & ss1,
1808  const DeviceOptions & do1)
1809  : SourceData(ss1,do1),
1810  V0(0.0)
1811 {
1812  std::vector<Param>::const_iterator iter = paramRef.begin();
1813  std::vector<Param>::const_iterator last = paramRef.end();
1814 
1815  for ( ; iter != last; ++iter)
1816  {
1817  const std::string & tmpname = iter->tag();
1818  if (tmpname == "DCV0")
1819  {
1820  V0 = iter->getImmutableValue<double>();
1821  }
1822  }
1823 
1824  typeName_ = "CONST";
1825  defaultParamName_ = "DCV0";
1826 // SourceValue = V0; // updateSource function is a no-op, essentially.
1827 }
1828 
1829 //-----------------------------------------------------------------------------
1830 // Function : ConstData::~ConstData
1831 // Purpose : destructor
1832 // Special Notes :
1833 // Scope : public
1834 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
1835 // Creation Date : 10/5/00
1836 //-----------------------------------------------------------------------------
1838 {}
1839 
1840 //-----------------------------------------------------------------------------
1841 // Function : ConstData::printOutParams
1842 // Purpose :
1843 // Special Notes :
1844 // Scope : public
1845 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
1846 // Creation Date : 10/5/00
1847 //-----------------------------------------------------------------------------
1848 
1850 
1851 {
1852  Xyce::dout() << "ConstData:\n";
1853  Xyce::dout() << "V0: " << V0 << std::endl;
1854 }
1855 
1856 // Additional Declarations
1857 
1858 //-----------------------------------------------------------------------------
1859 // Function : ConstData::updateSource
1860 // Purpose : Update the const source.
1861 // Special Notes : ERK: this is now a no-op, as the source value is set in
1862 // the constructor. The value for this source never changes,
1863 // so there isn't any point is re-setting the same value
1864 // over and over.
1865 //
1866 // Scope : public
1867 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
1868 // Creation Date : 10/5/00
1869 //-----------------------------------------------------------------------------
1871 {
1872 
1873  bool bsuccess = true;
1874 
1875  if (!initializeFlag_) bsuccess = initializeSource ();
1876 
1877  SourceValue = V0;
1878 
1879  resetFlag_ = false;
1880 
1881  return bsuccess;
1882 
1883 }
1884 
1885 //-----------------------------------------------------------------------------
1886 // Function : ConstData::getParams
1887 // Purpose : Pass back the const source params.
1888 // Special Notes :
1889 //
1890 // Scope : public
1891 // Creator : Dave Shirley, PSSI
1892 // Creation Date : 4/13/05
1893 //-----------------------------------------------------------------------------
1894 void ConstData::getParams(double *params)
1895 {
1896  params[0] = V0;
1897 }
1898 
1899 //-----------------------------------------------------------------------------
1900 // Function : ConstData::setParams
1901 // Purpose : Update the const source params.
1902 // Special Notes :
1903 //
1904 // Scope : public
1905 // Creator : Dave Shirley, PSSI
1906 // Creation Date : 4/13/05
1907 //-----------------------------------------------------------------------------
1908 void ConstData::setParams(double *params)
1909 {
1910  if (V0 != params[0])
1911  {
1912  V0 = params[0];
1913  updateSource();
1914  }
1915 }
1916 
1917 
1918 // Class SmoothPulseData
1919 
1920 //-----------------------------------------------------------------------------
1921 // Function : SmoothPulseData::SmoothPulseData
1922 // Purpose : constructor
1923 // Special Notes :
1924 // Scope : public
1925 // Creator : Richard Schiek, Electrical Systems Modeling
1926 // Creation Date : 04/13/11
1927 //-----------------------------------------------------------------------------
1928 
1930  const DeviceEntity & device,
1931  const std::vector<Param> & paramRef,
1932  const SolverState & ss1,
1933  const DeviceOptions & do1)
1934  : SourceData (ss1,do1),
1935  V1 (0.0),
1936  V2 (0.0),
1937  TD (0.0),
1938  TR (0.0),
1939  TF (0.0),
1940  PW (0.0),
1941  PER (0.0),
1942  riseScaleFactor_(0.0),
1943  fallScaleFactor_(0.0),
1944  functionScaleFactor_(20.0),
1945  V1given (false),
1946  V2given (false),
1947  TDgiven (false),
1948  TRgiven (false),
1949  TFgiven (false),
1950  PWgiven (false),
1951  PERgiven (false),
1952  functionScaleFactorGiven_(false)
1953 {
1954 
1955  // Get the user-defined values:
1956  std::vector<Param>::const_iterator iter = paramRef.begin();
1957  std::vector<Param>::const_iterator last = paramRef.end();
1958 
1959  for ( ; iter != last; ++iter)
1960  {
1961  const std::string & tmpname = iter->tag();
1962 
1963  if (tmpname == "V1") { V1 = iter->getImmutableValue<double>(); V1given = iter->given();}
1964  if (tmpname == "V2") { V2 = iter->getImmutableValue<double>(); V2given = iter->given();}
1965  if (tmpname == "TD") { TD = iter->getImmutableValue<double>(); TDgiven = iter->given();}
1966  if (tmpname == "TR") { TR = iter->getImmutableValue<double>(); TRgiven = iter->given();}
1967  if (tmpname == "TF") { TF = iter->getImmutableValue<double>(); TFgiven = iter->given();}
1968  if (tmpname == "PW") { PW = iter->getImmutableValue<double>(); PWgiven = iter->given();}
1969  if (tmpname == "PER") { PER = iter->getImmutableValue<double>(); PERgiven = iter->given();}
1970  if (tmpname == "SF") { functionScaleFactor_ = iter->getImmutableValue<double>(); functionScaleFactorGiven_ = iter->given();}
1971  }
1972 
1973  typeName_ = "SMOOTHPULSE";
1974  defaultParamName_ = "V2";
1975 }
1976 
1977 //-----------------------------------------------------------------------------
1978 // Function : SmoothPulseData::~SmoothPulseData
1979 // Purpose : destructor
1980 // Special Notes :
1981 // Scope : public
1982 // Creator : Richard Schiek, Electrical Systems Modeling
1983 // Creation Date : 04/13/11
1984 //-----------------------------------------------------------------------------
1986 {}
1987 
1988 // Additional Declarations
1989 
1990 //-----------------------------------------------------------------------------
1991 // Function : SmoothPulseData::printOutParams
1992 // Purpose :
1993 // Special Notes :
1994 // Scope : public
1995 // Creator : Richard Schiek, Electrical Systems Modeling
1996 // Creation Date : 04/13/11
1997 //-----------------------------------------------------------------------------
1998 
2000 {
2001 
2002  Xyce::dout() << std::endl;
2003  Xyce::dout() << " SmoothPulseData::printOutParams\n";
2004  Xyce::dout() << " V1 = " << V1 << std::endl;
2005  Xyce::dout() << " V2 = " << V2 << std::endl;
2006 
2007  Xyce::dout() << " TD = " << TD << std::endl;
2008  Xyce::dout() << " TR = " << TR << std::endl;
2009  Xyce::dout() << " TF = " << TF << std::endl;
2010  Xyce::dout() << " PW = " << PW << std::endl;
2011  Xyce::dout() << " PER = " << PER << std::endl;
2012  Xyce::dout() << " SF = " << functionScaleFactor_ << std::endl;
2013  Xyce::dout() << std::endl;
2014 
2015 }
2016 
2017 //-----------------------------------------------------------------------------
2018 // Function : SmoothPulseData::initializeSource
2019 // Purpose :
2020 // Special Notes :
2021 // Scope : public
2022 // Creator : Richard Schiek, Electrical Systems Modeling
2023 // Creation Date : 04/13/11
2024 //-----------------------------------------------------------------------------
2025 
2027 {
2028 
2029  // If neccessary, set the defaults:
2030 
2031  double tstep = solState_.startingTimeStep_;
2032  double tstop = solState_.finalTime_;
2033 
2034  if (!TDgiven) TD = 0.0;
2035  if (!TRgiven) TR = tstep;
2036  if (!TFgiven) TF = tstep;
2037  if (!PWgiven) PW = tstop;
2038  if (!PERgiven) PER = tstop;
2039  // scale the amplitude of the response so it better joins the low and hi value
2040  // riseFallScaleFactor_ = M_PI;
2041  riseScaleFactor_ = 2.0*fabs( atan(M_PI * functionScaleFactor_ * (0.5*TR) / TR) );
2042  fallScaleFactor_ = 2.0*fabs( atan(M_PI * functionScaleFactor_ * (0.5*TF) / TF) );
2043  initializeFlag_ = true;
2044 
2045  return true;
2046 }
2047 
2048 //-----------------------------------------------------------------------------
2049 // Function : SmoothPulseData::updateSource
2050 // Purpose :
2051 // Special Notes :
2052 // Scope : public
2053 // Creator : Richard Schiek, Electrical Systems Modeling
2054 // Creation Date : 04/13/11
2055 //-----------------------------------------------------------------------------
2056 
2058 
2059 {
2060  bool bsuccess = true;
2061 
2062  if (!initializeFlag_) bsuccess = initializeSource ();
2063 
2064  double basetime = 0;
2065 
2066  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
2067  {
2068  Xyce::dout() << " SmoothPulseData::updateSources\n";
2069  printOutParams();
2070  }
2071 
2072  time = getTime_();
2073 
2074  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
2075  {
2076  Xyce::dout() << " Time = " << time << std::endl;
2077  }
2078 
2079  time -= TD;
2080 
2081  if (time > PER && PER != 0.0)
2082  {
2083  // repeating signal - figure out where we are in period
2084  basetime = PER * floor(time/PER);
2085  time -= basetime;
2086  }
2087 
2088  // This section got ugly because of a nasty roundoff bug.
2089  // Instead of doing "time > X" you need also check that time
2090  // is not within bptol of X.
2091  // So the following translation is used:
2092  // Instead of: we do:
2093  // time > X time>X && fabs(time-x)>bptol
2094  // time <= X time<X || fabs(time-x)<bptol
2095 
2096  if (time <= 0 || (time > (TR + PW + TF) &&
2097  (fabs (time - (TR+PW+TF)) > solState_.bpTol_) ) )
2098  {
2099  SourceValue = V1;
2100  }
2101  else if ((time > TR && fabs(time-TR) > solState_.bpTol_)
2102  && (time < (TR + PW) || fabs (time-(TR+PW))<solState_.bpTol_) )
2103  {
2104  SourceValue = V2;
2105  }
2106  else if (time > 0 &&
2107  (time < TR || fabs(time-TR) < solState_.bpTol_))
2108  {
2109  if (TR != 0.0)
2110  SourceValue = V1 + (V2 - V1) *
2111  (((atan(M_PI * functionScaleFactor_ * (time-0.5*TR) / TR))/riseScaleFactor_) + 0.5);
2112  else
2113  SourceValue = V1;
2114  }
2115  else
2116  { // time > (TR + PW) && <= (TR + PW + TF)
2117  if (TF != 0.0)
2118  SourceValue = V2 + (V1 - V2) *
2119  (((atan(M_PI * functionScaleFactor_ * (time - (TR + PW + 0.5*TF)) / TF))/fallScaleFactor_) + 0.5);
2120  else
2121  SourceValue = V2;
2122  }
2123 
2124  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
2125  {
2126  Xyce::dout() << " SourceValue = " << SourceValue << std::endl;
2127  }
2128 
2129  resetFlag_ = false;
2130 
2131  return bsuccess;
2132 }
2133 
2134 //-----------------------------------------------------------------------------
2135 // Function : SmoothPulseData::getParams
2136 // Purpose : Pass back the pulse source params.
2137 // Special Notes :
2138 //
2139 // Scope : public
2140 // Creator : Richard Schiek, Electrical Systems Modeling
2141 // Creation Date : 04/13/11
2142 //-----------------------------------------------------------------------------
2143 void SmoothPulseData::getParams(double *params)
2144 {
2145  params[0] = V1;
2146  params[1] = V2;
2147  params[2] = TD;
2148  params[3] = TR;
2149  params[4] = TF;
2150  params[5] = PW;
2151  params[6] = PER;
2152 }
2153 
2154 //-----------------------------------------------------------------------------
2155 // Function : SmoothPulseData::setParams
2156 // Purpose : Update the pulse source params.
2157 // Special Notes :
2158 //
2159 // Scope : public
2160 // Creator : Richard Schiek, Electrical Systems Modeling
2161 // Creation Date : 04/13/11
2162 //-----------------------------------------------------------------------------
2163 void SmoothPulseData::setParams(double *params)
2164 {
2165  bool reset=false;
2166  if (V1 != params[0])
2167  {
2168  V1 = params[0];
2169  reset = true;
2170  }
2171  if (V2 != params[1])
2172  {
2173  V2 = params[1];
2174  reset = true;
2175  }
2176  if (TD != params[2])
2177  {
2178  TD = params[2];
2179  reset = true;
2180  }
2181  if (TR != params[3])
2182  {
2183  TR = params[3];
2184  reset = true;
2185  }
2186  if (TF != params[4])
2187  {
2188  TF = params[4];
2189  reset = true;
2190  }
2191  if (PW != params[5])
2192  {
2193  PW = params[5];
2194  reset = true;
2195  }
2196  if (PER != params[6])
2197  {
2198  PER = params[6];
2199  reset = true;
2200  }
2201  if (reset)
2202  updateSource();
2203 }
2204 
2205 //-----------------------------------------------------------------------------
2206 // Function : SmoothPulseData::getBreakPoints
2207 // Purpose : This function adds break points to a vector of breakpoints.
2208 //
2209 // It does not bother to check them in any way, or put them
2210 // in order. It only adds them in.
2211 //
2212 // Special Notes : Like much of this file, this is adapted from spice 3f5.
2213 // Some of the stuff in it is a little hokey, and may get
2214 // removed or modified later.
2215 //
2216 // Scope : public
2217 // Creator : Richard Schiek, Electrical Systems Modeling
2218 // Creation Date : 04/13/11
2219 //-----------------------------------------------------------------------------
2221  (std::vector<Util::BreakPoint> & breakPointTimes )
2222 {
2223  bool bsuccess = true;
2224 
2225  if (!initializeFlag_) bsuccess = initializeSource ();
2226 
2227  return bsuccess;
2228 }
2229 
2230 //-----------------------------------------------------------------------------
2231 // Function : SmoothPulseData::getMaxTimeStepSize
2232 // Purpose :
2233 // Special Notes :
2234 // Scope : public
2235 // Creator : Richard Schiek, Electrical Systems Modeling
2236 // Creation Date : 04/13/11
2237 //-----------------------------------------------------------------------------
2239 {
2240  double maxTimeStep = devOptions_.defaultMaxTimeStep;
2241 
2242  // check if we are still in the delay or not.
2243  time = getTime_();
2244 
2245  if (time < TD) maxTimeStep = (0.1*TD );
2246  else maxTimeStep = (0.1*PER);
2247 
2248  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState_.debugTimeFlag)
2249  {
2250  Xyce::dout() << "\nIn SmoothPulseData::getMaxTimeStepSize. ";
2251  Xyce::dout() << " maxTimeStep = "<< maxTimeStep;
2252  Xyce::dout() << " TD = " << TD << " PER = " <<PER;
2253  Xyce::dout() << " time = "<< time << std::endl;
2254  }
2255 
2256  return maxTimeStep;
2257 }
2258 
2259 
2260 //-----------------------------------------------------------------------------
2261 // Function : findSourceFieldPosition
2262 // Purpose : Find the position of a given field of an independent source
2263 // in parsedLine_. Return the position if the field is found,
2264 // otherwise return 0.
2265 // Special Notes :
2266 // Scope : public
2267 // Creator : Lon Waters, SNL
2268 // Creation Date : 10/02/2001
2269 //-----------------------------------------------------------------------------
2270 int
2272  const IO::TokenVector & parsed_line,
2273  const std::string & fieldToFind,
2274  int startPosition )
2275 {
2276  size_t numFields = parsed_line.size();
2277  int fieldPosition = 0;
2278 
2279  if ( fieldToFind == "SOURCEFCN" ) // any transient source type.
2280  {
2281  ExtendedString field("");
2282  for ( size_t i = startPosition; i < numFields; ++i )
2283  {
2284  // The test here checks the field at position i to see if it
2285  // corresponds to a source function type registered in metadata.
2286  field = parsed_line[i].string_;
2287  field.toUpper();
2288  if ( getSourceFunctionID(field) != _NUM_SRC_DATA && // ie, not found
2289  getSourceFunctionID(field) != _AC_DATA ) // AC
2290  {
2291  fieldPosition = i;
2292  break;
2293  }
2294  }
2295  }
2296  else
2297  {
2298  ExtendedString field("");
2299  for ( size_t i = startPosition; i < numFields; ++i )
2300  {
2301  field = parsed_line[i].string_;
2302  field.toUpper();
2303  if ( field == fieldToFind )
2304  {
2305  fieldPosition = i;
2306  break;
2307  }
2308  }
2309  }
2310 
2311  return fieldPosition;
2312 }
2313 
2314 //-----------------------------------------------------------------------------
2315 // Function : extractSourceData
2316 // Purpose : Extract the device data from parsedLine for independent
2317 // source devices.
2318 //
2319 // Special Notes : Independent sources have the general form:
2320 //
2321 // VXXXXXXX N+ N- <DC<> DC/TRAN VALUE> <AC <ACMAG <ACPHASE>>>
2322 // + <DISTOF1 <F1MAG <F1PHASE>>> <DISTOF2 <F2MAG <F2PHASE>>>
2323 //
2324 // N+ and N- are the positive and negative nodes, respectively.
2325 //
2326 // DC/TRAN is the dc and transient analysis value of the source.
2327 // The DC keyword is optional.
2328 //
2329 // ACMAG is the AC magnitude and ACPHASE is the AC phase. AC keyword and
2330 // values only present if this is an AC source.
2331 //
2332 // DISTOF1 and DISTOF2 are the keywords that specify that the independent
2333 // source has distortion inputs at the frequencies F1 and F2 respectively.
2334 // These are not supported yet.
2335 //
2336 // Any independent source can be assigned a time-dependent value for
2337 // transient analysis. If a source is assigned a time-dependent value,
2338 // the time-zero value is used for dc analysis. There are five independent
2339 // source functions: PULSE, EXP, SIN, PWL, and single-frequency FM (SFFM).
2340 //
2341 // Examples:
2342 // VCC 10 0 DC 6
2343 // VIN 13 2 0.001 AC 1 SIN(0 1 1MEG)
2344 // ISRC 23 21 AC 0.333 45.0 SFFM(0 1 10K 5 1K)
2345 // VMEAS 12 9
2346 // VCARRIER 1 0 DISTOF1 0.1 -90.0
2347 // VMODULATOR 2 0 DISTOF2 0.01
2348 // IIN1 1 5 AC 1 DISTOF1 DISTOF2 0.001
2349 //
2350 // Scope : public
2351 // Creator : Lon Waters, SNL
2352 // Creation Date : 09/25/2001
2353 //-----------------------------------------------------------------------------
2354 bool
2356  const IO::TokenVector & parsedInputLine,
2357  IO::DeviceBlock & device_block,
2358  const std::string & primaryDeviceParameter)
2359 {
2360  int numFields = parsedInputLine.size();
2361  bool tranGiven=false;
2362  bool acGiven=false;
2363  bool dcGiven=true;
2364 
2365  // Extract the source device nodes.
2366  device_block.extractNodes(parsedInputLine, -1, 0);
2367 
2368  // Set up the "primary" parameter. (for vsrc's this is V0 by default, and is DC)
2369  Util::Param primaryParameter( "", "" );
2370  primaryParameter.setTag(primaryDeviceParameter);
2371  primaryParameter.setVal("0");
2372  int tranSourceType = _DC_DATA;
2373 
2374  // Set position on line to first field after the nodes.
2375  int linePosition = device_block.getNumberOfNodes() + 1;
2376 
2377  // Check for DC field. If present, then reset DC parameter (default parameter)
2378  // to the value from the netlist. The DC value is "special" because
2379  // it doesn't require a DC keyword in front of it. Also, it is always the
2380  // first type specified on the instance line.
2381  //
2382  // All other src types require a keyword. So, the handling is different.
2383  if ( linePosition < numFields )
2384  {
2385  ExtendedString field(parsedInputLine[linePosition].string_);
2386  field.toUpper();
2387  int sourceID = getSourceFunctionID(field);
2388  // The field is the DC field, advance past "DC" keyword.
2389  if ( sourceID == _DC_DATA )
2390  {
2391  ++linePosition ;
2392 
2393  field = parsedInputLine[linePosition].string_;
2394  field.toUpper();
2395  sourceID = getSourceFunctionID(field);
2396  }
2397 
2398  // If the field is NOT related to any recognized non-DC
2399  // source, then proceed.
2400  if ( sourceID == _NUM_SRC_DATA ) // ie, type not found
2401  {
2402  // Get the DC value.
2403  if ( linePosition < numFields )
2404  {
2405  primaryParameter.setVal( parsedInputLine[linePosition].string_ );
2406  ++linePosition;
2407 
2408  // generate error message if DC value is invalid
2409  if( !( primaryParameter.isNumeric() || primaryParameter.hasExpressionValue() ) )
2410  {
2411  Report::UserError().at(device_block.getNetlistFilename(), device_block.getLineNumber())
2412  << "Invalid DC value \"" << primaryParameter.stringValue() << "\" for device " << device_block.getInstanceName();
2413  }
2414  }
2415  }
2416  else
2417  {
2418  // no-op. primary param was already set to zero.
2419  }
2420  }
2421 
2422  // Find the positions of the "AC", "DISTOF1", "DISTOF2", and source
2423  // function fields in parsedInputLine. Save names and positions of the
2424  // fields that appear in parsedLine in fieldNames and fieldPositions.
2425  std::vector<std::string> fieldNames;
2426  std::vector<int> fieldPositions;
2427 
2428  int fieldPosition = findSourceFieldPosition(parsedInputLine, "AC", linePosition );
2429  if ( fieldPosition > 0 )
2430  {
2431  fieldNames.push_back( "AC" );
2432  fieldPositions.push_back( fieldPosition );
2433  acGiven=true;
2434 // tranSourceType = getSourceFunctionID("AC"); //tmei: 05/02
2435 // ++linePosition;
2436  }
2437 
2438  fieldPosition = findSourceFieldPosition(parsedInputLine, "DISTOF1", linePosition );
2439  if ( fieldPosition > 0 )
2440  {
2441  fieldNames.push_back( "DISTOF1" );
2442  fieldPositions.push_back( fieldPosition );
2443  }
2444 
2445  fieldPosition = findSourceFieldPosition(parsedInputLine, "DISTOF2", linePosition );
2446  if ( fieldPosition > 0 )
2447  {
2448  fieldNames.push_back( "DISTOF2" );
2449  fieldPositions.push_back( fieldPosition );
2450  }
2451 
2452  fieldPosition = findSourceFieldPosition(parsedInputLine, "SOURCEFCN", linePosition );
2453  if ( fieldPosition > 0 )
2454  {
2455  fieldNames.push_back( "SOURCEFCN" );
2456  fieldPositions.push_back( fieldPosition );
2457  ExtendedString field( parsedInputLine[fieldPosition].string_ );
2458  field.toUpper();
2459  tranSourceType = getSourceFunctionID(field);
2460  tranGiven=true;
2461  }
2462  else
2463  {
2464  tranGiven=false;
2465  }
2466 
2467  // Set the type(s) of the source.
2468  Util::Param tranSourceTypeParameter( "TRANSIENTSOURCETYPE", tranSourceType );
2469  Util::Param acSourceTypeParameter( "ACSOURCETYPE", (int) _AC_DATA);
2470  Util::Param dcSourceTypeParameter( "DCSOURCETYPE", (int) _DC_DATA);
2471 
2472  // Add the device instance parameters and their default values
2473  // to instanceParameters and extract instance parameters from
2474  // parsedInputLine.
2475 
2476  int parameterStartPosition;
2477  int parameterEndPosition;
2478  device_block.extractInstanceParameters( parsedInputLine,
2479  linePosition,
2480  parameterStartPosition,
2481  parameterEndPosition,
2482  "continue");
2483  fieldNames.push_back( "PARAMS" );
2484  fieldPositions.push_back( parameterStartPosition );
2485 
2486  // ERK. Before extractSourceFields can be called, the field vectors
2487  // need to be in order of ascending field position.
2488  //
2489  // This loop below does a quick insertion sort.
2490  // (see the insort routine from: http://www.yendor.com/programming/sort/)
2491  //
2492  // It is quick // as long as the field arrays are less than 15 elements. I did
2493  // not use STL sort b/c I am sorting using the contents of fieldPositions,
2494  // but fieldNames must also be sorted the same way.
2495  int len = fieldPositions.size();
2496  for (int i = 1; i < len; i++)
2497  {
2498  int j = i;
2499  int temp = fieldPositions[j];
2500  std::string tmpName = fieldNames[j];
2501  while (j > 0 && (fieldPositions[j-1] > temp))
2502  {
2503  fieldPositions[j] = fieldPositions[j-1];
2504  fieldNames[j] = fieldNames[j-1];
2505  j--;
2506  }
2507  fieldPositions[j] = temp;
2508  fieldNames[j] = tmpName;
2509  }
2510 
2511  // Extract the "AC", "DISTOF1", "DISTOF2", and transient
2512  // source function fields if they appear in parsedInputLine.
2513  bool result = extractSourceFields(parsedInputLine, device_block, fieldNames, fieldPositions );
2514  if ( !result )
2515  {
2516  return false;
2517  }
2518 
2519  // Set the DC value.
2520  Param * parameterPtr;
2521  if ( primaryParameter.tag() != "" )
2522  {
2523  parameterPtr = device_block.findInstanceParameter( primaryParameter );
2524  parameterPtr->setVal( primaryParameter );
2525  parameterPtr->setGiven( true );
2526  }
2527 
2528  // Set the transient source type.
2529  parameterPtr = device_block.findInstanceParameter( tranSourceTypeParameter );
2530  parameterPtr->setVal( tranSourceTypeParameter );
2531  parameterPtr->setGiven( tranGiven );
2532 
2533  // Set the AC source type, if it was given
2534  parameterPtr = device_block.findInstanceParameter( acSourceTypeParameter );
2535  parameterPtr->setVal( acSourceTypeParameter );
2536  parameterPtr->setGiven( acGiven );
2537 
2538  // Set the DC source type, if it was given
2539  parameterPtr = device_block.findInstanceParameter( dcSourceTypeParameter );
2540  parameterPtr->setVal( dcSourceTypeParameter );
2541  parameterPtr->setGiven( dcGiven );
2542 
2543  return true; // Only get here on success.
2544 }
2545 
2546 //-----------------------------------------------------------------------------
2547 // Function : extractSourceFields
2548 //
2549 // Purpose : This function loops through the fields on a source instance
2550 // line, processes them, adding defaults when necessary, and
2551 // then adds them to the instance parameter database for
2552 // this device.
2553 //
2554 // Special Notes : ERK: this function does at least one really strange thing.
2555 // Instead of plugging values into existing metadata, the
2556 // parameters for the given source type are added to the
2557 // metadata container. So, for example, if the user has
2558 // set V1, and V1 is already in the metadata, this function
2559 // does not set the existing V1. It adds a new one so that
2560 // two instances of V1 are present.
2561 //
2562 // In practice, this still works, as the devices (vsrc and
2563 // isrc) will use the last value set for any parameter,
2564 // and the "added" version is the last value. However,
2565 // for a develoer it is confusing.
2566 //
2567 // I think the reason for the "adding" is the PWL source,
2568 // which can have an arbitrary number of entries.
2569 //
2570 // Scope : public
2571 // Creator : Lon Waters, SNL
2572 // Creation Date : 10/03/2001
2573 //-----------------------------------------------------------------------------
2574 bool
2576  const IO::TokenVector & parsedInputLine,
2577  IO::DeviceBlock & device_block,
2578  const std::vector<std::string> & fieldNames,
2579  const std::vector<int> & fieldPositions )
2580 {
2581  if ( fieldNames[0] == "PARAMS" )
2582  {
2583  // No fields to extract.
2584  return true;
2585  }
2586 
2587  // Iterate through the fieldNames and extract the corresponding data
2588  // for the field. The fieldPositions vector gives the position in
2589  // parsedLine at which the fieldNames appear.
2590  int i;
2591  int numFields = fieldNames.size();
2592  for ( i = 0; i < numFields; ++i )
2593  {
2594 // if ( fieldNames[i] == "AC" || fieldNames[i] == "DISTOF1" ||
2595 // fieldNames[i] == "DISTOF2" )
2596  if ( fieldNames[i] == "AC")
2597  {
2598  // The code here inserts instance parameters for magnitude and phase
2599  // of AC stimulus.
2600  Param mag("", "");
2601  Param phase("", "");
2602 
2603  int numTerms = fieldPositions[i+1] - fieldPositions[i] - 1;
2604 
2605  std::string magName(fieldNames[i] + "MAG");
2606  std::string phaseName(fieldNames[i] + "PHASE");
2607  mag.set( magName, "1.0" );
2608  phase.set( phaseName, "0.0" );
2609 
2610  if ( numTerms > 2 )
2611  {
2612  device_block.issueUnrecognizedParameterError(fieldNames[i]+" Too Many Terms");
2613  }
2614 
2615  if ( numTerms >= 1 )
2616  {
2617  mag.setVal( parsedInputLine[fieldPositions[i]+1].string_ );
2618  mag.setGiven( true );
2619  }
2620 
2621  if ( numTerms == 2 )
2622  {
2623  phase.setVal( parsedInputLine[fieldPositions[i]+2].string_ );
2624  phase.setGiven( true );
2625  }
2626 
2627  // Add magnitude and phase parameters to instanceParameters.
2628  device_block.addInstanceParameter( mag );
2629  device_block.addInstanceParameter( phase );
2630 
2631  }
2632  else if ( fieldNames[i] == "SOURCEFCN" )
2633  {
2634  // Determine the source function.
2635  const std::string &sourceFunction = parsedInputLine[ fieldPositions[i] ].string_;
2636 
2637  // Check for optional parentheses around source function parameters,
2638  // and set start and end position of source function parameters on
2639  // the input line (skip the initial parenthese).
2640  int sourceFunctionParamStart;
2641  int sourceFunctionParamEnd;
2642 
2643  // skip over nested parentheses
2644  int offset=1;
2645  while (fieldPositions[i] + offset < parsedInputLine.size() && parsedInputLine[ fieldPositions[i] + offset ].string_ == "(" )
2646  {
2647  ++offset;
2648  }
2649 
2650  sourceFunctionParamStart = fieldPositions[i] + offset;
2651  sourceFunctionParamEnd = fieldPositions[i + 1] - offset;
2652 
2653  if (!equal_nocase(sourceFunction, "PWL"))
2654  {
2655  // Get the source function parameters from metadata, set their
2656  // values to the given input value and add to the device instance
2657  // parameter list.
2658 
2659  // Set the number of parameters for this source function on
2660  // the input line.
2661  size_t numInputSourceFunctionParams = sourceFunctionParamEnd - sourceFunctionParamStart + 1;
2662 
2663  // const std::vector<Param> &sourceFunctionParameters = metadata_.getSourceFunctionParameters(sourceFunction);
2664  const std::vector<Param> &sourceFunctionParameters = getSourceFunctionParameters(sourceFunction);
2665  for ( size_t k = 0; k < sourceFunctionParameters.size(); ++k )
2666  {
2667  if ( k < numInputSourceFunctionParams )
2668  {
2669  Param parameter(sourceFunctionParameters[k].uTag(), 0.0);
2670  parameter.setVal( parsedInputLine[sourceFunctionParamStart + k].string_ );
2671  parameter.setGiven( true );
2672  device_block.addInstanceParameter( parameter );
2673  }
2674  }
2675  }
2676  else // PWL source
2677  {
2678  if ( parsedInputLine.size() <= sourceFunctionParamStart )
2679  {
2680  // this test handle instance lines of the form V1 1 0 PWL, without any other source data.
2681  // That instance line would cause a segfault later in this IF-ELSE block.
2682  Report::UserError().at(device_block.getNetlistFilename(), parsedInputLine[0].lineNumber_)
2683  << "PWL device missing source parameters: " << device_block.getInstanceName();
2684  }
2685  else
2686  {
2687  ExtendedString field(parsedInputLine[sourceFunctionParamStart].string_);
2688  if (field.toUpper() != "FILE")
2689  {
2690  // Xyce expects the "R" parameter to be tagged "REPEATTIME". Find
2691  // that parameter and rename it.
2692  //Param* parameterPtr = findInstanceParameter( Param("R", "") );
2693  //assert(parameterPtr != NULL);
2694  //parameterPtr->setTag( "REPEATTIME" );
2695 
2696  // Locate the start of the (time, value) pairs in the PWL source.
2697  int timeValPairStart = sourceFunctionParamStart;
2698  while ( parsedInputLine[timeValPairStart].string_ == "R" || parsedInputLine[timeValPairStart].string_ == "TD" )
2699  {
2700  timeValPairStart += 3;
2701  // next if statement accounts for a missing list of time-voltage pairs.
2702  // Otherwise the next iteration of the while loop will cause a seg-fault.
2703  if (timeValPairStart >= parsedInputLine.size()) {break;}
2704  }
2705 
2706  // In the PWL source case, sourceFunctionParamEnd could have been
2707  // miscaluated if the repeat time or time delay appeared with no
2708  // other tagged parameters (which are required to be at the end of
2709  // the line. In this case recalculate teh value of
2710  // sourceFunctionParamEnd.
2711  if ( sourceFunctionParamEnd < timeValPairStart )
2712  {
2713  //sourceFunctionParamEnd = (int) parsedInputLine.size() - 1;
2714  sourceFunctionParamEnd = static_cast<int> (parsedInputLine.size()) - 1;
2715  if ( parsedInputLine[sourceFunctionParamEnd].string_ == ")" )
2716  {
2717  --sourceFunctionParamEnd;
2718  }
2719  }
2720 
2721  // Add (time, value) pairs to the instance parameters. Also,
2722  // reset the parameter ("NUM") that indicates the number of
2723  // such pairs and "REPEAT" which is a boolean that indicates
2724  // that PWL function is periodic.
2725  Param time( "T", "" );
2726  Param value( "V", "" );
2727  int numTimeValuePairs = 0;
2728  int i = timeValPairStart;
2729  while ( i < sourceFunctionParamEnd )
2730  {
2731  ++numTimeValuePairs;
2732 
2733  time.setVal( parsedInputLine[i].string_ );
2734  time.setGiven( true );
2735  device_block.addInstanceParameter( time );
2736  ++i;
2737 
2738  value.setVal( parsedInputLine[i].string_ );
2739  value.setGiven( true );
2740  device_block.addInstanceParameter( value );
2741  ++i;
2742 
2743  // HSpice compatibility, where time-value pairs are
2744  // separated with a comma
2745  if ( i < sourceFunctionParamEnd )
2746  {
2747  if ( parsedInputLine[i].string_ == "," ) ++i;
2748  }
2749  }
2750 
2751  if ( numTimeValuePairs > 0 )
2752  {
2753  Param * parameterPtr = device_block.findInstanceParameter( Param("NUM", "") );
2754  assert(parameterPtr != NULL);
2755  parameterPtr->setVal( numTimeValuePairs );
2756  parameterPtr->setGiven( true );
2757  }
2758  else
2759  {
2760  // no FILE parameter given (that's the next else block)
2761  // so there should have been some time, value pairs given
2762  // however, numTimeValueParis == 0.
2763  Report::UserError().at(device_block.getNetlistFilename(), parsedInputLine[0].lineNumber_)
2764  << "Could not parse time/value pairs for piecewise linear function in device: " << device_block.getInstanceName();
2765  }
2766  }
2767  else
2768  {
2769  // PWL time value pairs are given in specified file. Get the
2770  // file name, open and read (time, value) pairs.
2771  std::string tvFileNameIN(parsedInputLine[sourceFunctionParamStart+1].string_);
2772 
2773  // If the file name is enclosed in double quotes, strip them.
2774  std::string tvFileName;
2775  if (tvFileNameIN[0] == '"' &&
2776  tvFileNameIN[tvFileNameIN.length()-1] =='"')
2777  {
2778  tvFileName = tvFileNameIN.substr(1, tvFileNameIN.length()-2);
2779  }
2780 
2781  std::ifstream tvDataIn;
2782  tvDataIn.open(tvFileName.c_str(), std::ios::in);
2783  if ( !tvDataIn.is_open() )
2784  {
2785  Report::UserError().at(device_block.getNetlistFilename(), parsedInputLine[0].lineNumber_)
2786  << "Could not find file " << tvFileName;
2787  }
2788 
2789  Param time( "T", "" );
2790  Param value( "V", "" );
2791 
2792  int numTimeValuePairs = 0;
2793  double timeIn;
2794  double valueIn;
2795  while (tvDataIn >> timeIn)
2796  {
2797  char ch;
2798  tvDataIn.get(ch);
2799 
2800  if (tvDataIn >> valueIn)
2801  {
2802  ++numTimeValuePairs;
2803 
2804  time.setVal(timeIn);
2805  time.setGiven( true );
2806  device_block.addInstanceParameter(time);
2807 
2808  value.setVal(valueIn);
2809  value.setGiven( true );
2810  device_block.addInstanceParameter(value);
2811  }
2812  else
2813  {
2814  Report::UserError() << "Problem reading " << tvFileName << std::endl
2815  << "File format must be comma, tab or space separated value. There should be no extra spaces or tabs "
2816  << "around the comma if it is used as the separator.";
2817  }
2818  }
2819 
2820  tvDataIn.close();
2821 
2822  if ( numTimeValuePairs > 0 )
2823  {
2824  Param* parameterPtr = device_block.findInstanceParameter( Param("NUM", "") );
2825  assert(parameterPtr != NULL);
2826  parameterPtr->setVal( numTimeValuePairs );
2827  parameterPtr->setGiven( true );
2828  }
2829 
2830  else
2831  {
2832  Report::UserError() << "Failed to successfully read " << tvFileName;
2833  }
2834  }
2835  }
2836  }
2837  }
2838  }
2839 
2840  return true; // Only get here on success.
2841 }
2842 
2843 } // namespace Device
2844 } // namespace Xyce
void setParams(double *)
bool extractSourceFields(const IO::TokenVector &parsedInputLine, IO::DeviceBlock &device_block, const std::vector< std::string > &fieldNames, const std::vector< int > &fieldPositions)
virtual bool updateSource()
void setParams(double *)
Pure virtual class to augment a linear system.
double startingTimeStep_
SourceData devices.
std::vector< std::pair< double, double > > TVVEC
const T & value(const ParameterBase &entity, const Descriptor &descriptor)
Returns the value of the parameter for the entity.
Definition: N_DEV_Pars.h:1224
double finalTime_
Analysis final time, SourceData devices.
void getParams(double *)
#define THETA
const DeviceOptions & devOptions_
double bpTol_
Break point tolerance, SourceData devices, Neuron devices.
bool getBreakPoints(std::vector< Util::BreakPoint > &breakPointTimes)
bool getBreakPoints(std::vector< Util::BreakPoint > &breakPointTimes)
int findSourceFieldPosition(const IO::TokenVector &parsed_line, const std::string &fieldToFind, int startPosition)
virtual double getMaxTimeStepSize()
SFFMData(const DeviceEntity &device, const std::vector< Param > &paramRef, const SolverState &ss1, const DeviceOptions &do1)
void getParams(double *)
void setParams(double *)
ExpData(const DeviceEntity &device, const std::vector< Param > &paramRef, const SolverState &ss1, const DeviceOptions &do1)
ACData(const DeviceEntity &device, const std::vector< Param > &paramRef, const SolverState &ss1, const DeviceOptions &do1)
bool getBreakPoints(std::vector< Util::BreakPoint > &breakPointTimes)
std::map< std::string, std::vector< Param >, LessNoCase > DeviceParamMap
bool extractSourceData(const IO::TokenVector &parsedInputLine, IO::DeviceBlock &device_block, const std::string &primaryDeviceParameter)
SinData(const DeviceEntity &device, const std::vector< Param > &paramRef, const SolverState &ss1, const DeviceOptions &do1)
PWLinData(const DeviceEntity &device, const std::vector< Param > &paramRef, const SolverState &ss1, const DeviceOptions &do1)
SmoothPulseData(const DeviceEntity &device, const std::vector< Param > &paramRef, const SolverState &ss1, const DeviceOptions &do1)
virtual bool updateSource()
virtual bool initializeSource()
void setGiven(bool is_given)
Definition: N_DEV_Param.h:104
ConstData(const DeviceEntity &device, const std::vector< Param > &paramRef, const SolverState &ss1, const DeviceOptions &do1)
double defaultMaxTimeStep
mosfet homotopy:
virtual bool updateSource()
#define M_PI
const std::vector< Param > & getSourceFunctionParameters(const std::string &sourceFcn)
const SolverState & solState_
void getParams(double *)
PulseData(const DeviceEntity &device, const std::vector< Param > &paramRef, const SolverState &ss1, const DeviceOptions &do1)
double currTime_
DeviceEntity for expression time, breakpoints DeviceMgr for dependent parameters, breakpoints...
double currFastTime_
Source devices,.
int getSourceFunctionID(const std::string &sourceFcn)
void sourceFunctionMetadata(DeviceParamMap &map)