Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_LTRA.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-2014 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_LTRA.C,v $
27 //
28 // Purpose : lossy transmission line
29 //
30 // Special Notes :
31 //
32 // Creator : Eric Keiter, SNL
33 //
34 // Creation Date : 06/16/10
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.65 $
40 //
41 // Revision Date : $Date: 2014/05/22 17:40:29 $
42 //
43 // Current Owner : $Author: erkeite $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 #include <N_UTL_Misc.h>
49 #include <N_DEV_DeviceOptions.h>
50 #include <N_DEV_DeviceState.h>
51 #include <N_DEV_ExternData.h>
52 #include <N_DEV_LTRA.h>
53 #include <N_DEV_LTRA_Faddeeva.h>
54 #include <N_DEV_MatrixLoadData.h>
55 #include <N_DEV_Message.h>
56 #include <N_DEV_SolverState.h>
57 #include <N_ERH_ErrorMgr.h>
58 
59 #include <N_LAS_Matrix.h>
60 #include <N_LAS_Vector.h>
61 
62 #include <N_UTL_BreakPoint.h>
63 
64 #include <N_UTL_Functors.h>
65 
66 namespace Xyce {
67 namespace Device {
68 namespace LTRA {
69 
70 
72 {
73  p.addPar("V1", 0.0, &LTRA::Instance::initVolt1)
74  .setGivenMember(&LTRA::Instance::initVolt1Given)
75  .setUnit(U_VOLT)
76  .setDescription("Initial voltage at end 1");
77 
78  p.addPar("V2", 0.0, &LTRA::Instance::initVolt2)
79  .setGivenMember(&LTRA::Instance::initVolt2Given)
80  .setUnit(U_VOLT)
81  .setDescription("Initial voltage at end 2");
82 
83  p.addPar("I1", 0.0, &LTRA::Instance::initCur1)
84  .setGivenMember(&LTRA::Instance::initCur1Given)
85  .setUnit(U_AMP)
86  .setDescription("Initial current at end 1");
87 
88  p.addPar("I2", 0.0, &LTRA::Instance::initCur2)
89  .setGivenMember(&LTRA::Instance::initCur2Given)
90  .setUnit(U_AMP)
91  .setDescription("Initial current at end 2");
92 }
93 
95 {
96  p.addPar("R", 0.0, &LTRA::Model::resist)
97  .setGivenMember(&LTRA::Model::resistGiven)
98  .setUnit(U_OHMMM1)
99  .setDescription("Resistance per unit length");
100 
101  p.addPar("L", 0.0, &LTRA::Model::induct)
102  .setGivenMember(&LTRA::Model::inductGiven)
103  .setUnit(U_HMM1)
104  .setDescription("Inductance per unit length");
105 
106  p.addPar("G", 0.0, &LTRA::Model::conduct)
107  .setGivenMember(&LTRA::Model::conductGiven)
108  .setUnit(U_OHMM1MM1)
109  .setDescription("Conductance per unit length");
110 
111  p.addPar("C", 0.0, &LTRA::Model::capac)
112  .setGivenMember(&LTRA::Model::capacGiven)
113  .setUnit(U_FARADMM1)
114  .setDescription("Capacitance per unit length");
115 
116  p.addPar("LEN", 0.0, &LTRA::Model::length)
117  .setGivenMember(&LTRA::Model::lengthGiven)
118  .setUnit(U_METER)
119  .setDescription("length of line");
120 
121  p.addPar("REL", 1.0, &LTRA::Model::reltol)
122  .setGivenMember(&LTRA::Model::reltolGiven)
123  .setDescription("Rel. rate of change of deriv. for bkpt");
124 
125  p.addPar("ABS", 1.0, &LTRA::Model::abstol)
126  .setGivenMember(&LTRA::Model::abstolGiven)
127  .setDescription("Abs. rate of change of deriv. for bkpt");
128 
129  p.addPar("STEPLIMIT", true, &LTRA::Model::stepLimit)
130  .setGivenMember(&LTRA::Model::stepLimitGiven)
131  .setUnit(U_LOGIC)
132  .setDescription("limit timestep size based on the time constant of the line");
133 
134  p.addPar("NOSTEPLIMIT", false, &LTRA::Model::noStepLimit)
135  .setGivenMember(&LTRA::Model::noStepLimitGiven)
136  .setUnit(U_LOGIC)
137  .setDescription("don't limit timestep size based on the time constant of the line");
138 
139  p.addPar("COMPLEXSTEPCONTROL", false, &LTRA::Model::lteTimeStepControl)
140  .setGivenMember(&LTRA::Model::lteTimeStepControlGiven)
141  .setUnit(U_LOGIC)
142  .setDescription("do complex time step control using local truncation error estimation");
143 
144  p.addPar("LININTERP", false, &LTRA::Model::linInterp)
145  .setGivenMember(&LTRA::Model::linInterpGiven)
146  .setUnit(U_LOGIC)
147  .setDescription("use linear interpolation");
148 
149  p.addPar("QUADINTERP", true, &LTRA::Model::quadInterp)
150  .setGivenMember(&LTRA::Model::quadInterpGiven)
151  .setUnit(U_LOGIC)
152  .setDescription("use quadratic interpolation");
153 
154  p.addPar("MIXEDINTERP", false, &LTRA::Model::mixedInterp)
155  .setGivenMember(&LTRA::Model::mixedInterpGiven)
156  .setUnit(U_LOGIC)
157  .setDescription("use linear interpolation if quadratic results look unacceptable");
158 
159  p.addPar("COMPACTREL", 1.0e-3, &LTRA::Model::stLineReltol)
160  .setGivenMember(&LTRA::Model::stLineReltolGiven)
161  .setDescription("special reltol for straight line checking");
162 
163  p.addPar("COMPACTABS", 1.0e-12, &LTRA::Model::stLineAbstol)
164  .setGivenMember(&LTRA::Model::stLineAbstolGiven)
165  .setDescription("special abstol for straight line checking");
166 
167  p.addPar("TRUNCNR", false, &LTRA::Model::truncNR)
168  .setGivenMember(&LTRA::Model::truncNRGiven)
169  .setUnit(U_LOGIC)
170  .setDescription("use N-R iterations for step calculation in LTRAtrunc");
171 
172  p.addPar("TRUNCDONTCUT", false, &LTRA::Model::truncDontCut)
173  .setGivenMember(&LTRA::Model::truncDontCutGiven)
174  .setUnit(U_LOGIC)
175  .setDescription("don't limit timestep to keep impulse response calculation errors low");
176 }
177 
178 
179 
180 std::vector< std::vector<int> > Instance::jacStamp;
181 
182 
183 // Class Instance
184 //-----------------------------------------------------------------------------
185 // Function : Instance::Instance
186 // Purpose : "instance block" constructor
187 // Special Notes :
188 // Scope : public
189 // Creator : Eric Keiter, SNL
190 // Creation Date : 06/16/10
191 //-----------------------------------------------------------------------------
192 
194  const Configuration & configuration,
195  const InstanceBlock& instance_block,
196  Model & model,
197  const FactoryBlock & factory_block)
198  : DeviceInstance(instance_block, configuration.getInstanceParameters(), factory_block),
199  model_(model),
200  input1(0.0),
201  input2(0.0),
202  listSize(0),
203  initVolt1(0.0),
204  initVolt2(0.0),
205  initCur1(0.0),
206  initCur2(0.0),
207 
208  initVolt1Given(false),
209  initVolt2Given(false),
210  initCur1Given(false),
211  initCur2Given(false),
212 
213  li_Pos1(-1),
214  li_Neg1(-1),
215 
216  li_Pos2(-1),
217  li_Neg2(-1),
218 
219  li_Ibr1(-1),
220  li_Ibr2(-1),
221 
222  APos1EquPos1NodeOffset(-1),
223  APos1EquIbr1NodeOffset(-1),
224 
225  ANeg1EquNeg1NodeOffset(-1),
226  ANeg1EquIbr1NodeOffset(-1),
227 
228  APos2EquPos2NodeOffset(-1),
229  APos2EquIbr2NodeOffset(-1),
230 
231  ANeg2EquNeg2NodeOffset(-1),
232  ANeg2EquIbr2NodeOffset(-1),
233 
234  AIbr1EquPos1NodeOffset(-1),
235  AIbr1EquNeg1NodeOffset(-1),
236  AIbr1EquPos2NodeOffset(-1),
237  AIbr1EquNeg2NodeOffset(-1),
238  AIbr1EquIbr1NodeOffset(-1),
239  AIbr1EquIbr2NodeOffset(-1),
240 
241  AIbr2EquPos1NodeOffset(-1),
242  AIbr2EquNeg1NodeOffset(-1),
243  AIbr2EquPos2NodeOffset(-1),
244  AIbr2EquNeg2NodeOffset(-1),
245  AIbr2EquIbr1NodeOffset(-1),
246  AIbr2EquIbr2NodeOffset(-1),
247 
248  pos1Pos1Ptr(0),
249  pos1Ibr1Ptr(0),
250 
251  neg1Neg1Ptr(0),
252  neg1Ibr1Ptr(0),
253 
254  pos2Pos2Ptr(0),
255  pos2Ibr2Ptr(0),
256 
257  neg2Neg2Ptr(0),
258  neg2Ibr2Ptr(0),
259 
260  ibr1Pos1Ptr(0),
261  ibr1Neg1Ptr(0),
262  ibr1Pos2Ptr(0),
263  ibr1Neg2Ptr(0),
264  ibr1Ibr1Ptr(0),
265  ibr1Ibr2Ptr(0),
266 
267  ibr2Pos1Ptr(0),
268  ibr2Neg1Ptr(0),
269  ibr2Pos2Ptr(0),
270  ibr2Neg2Ptr(0),
271  ibr2Ibr1Ptr(0),
272  ibr2Ibr2Ptr(0),
273 
274  first_BP_call_done(false),
275  newBreakPoint(false),
276  newBreakPointTime(0.0)
277 {
278  numIntVars = 2;
279  numExtVars = 4;
280  numStateVars = 0;
281 
282  devConMap.resize(4);
283  devConMap[0] = 1;
284  devConMap[1] = 1;
285  devConMap[2] = 2;
286  devConMap[3] = 2;
287 
288  if( jacStamp.empty() )
289  {
290  jacStamp.resize(6);
291 
292  jacStamp[0].resize(2);
293  jacStamp[0][0] = 0;
294  jacStamp[0][1] = 4;
295 
296  jacStamp[1].resize(2);
297  jacStamp[1][0] = 1;
298  jacStamp[1][1] = 4;
299 
300  jacStamp[2].resize(2);
301  jacStamp[2][0] = 2;
302  jacStamp[2][1] = 5;
303 
304  jacStamp[3].resize(2);
305  jacStamp[3][0] = 3;
306  jacStamp[3][1] = 5;
307 
308  jacStamp[4].resize(6);
309  jacStamp[4][0] = 0;
310  jacStamp[4][1] = 1;
311  jacStamp[4][2] = 2;
312  jacStamp[4][3] = 3;
313  jacStamp[4][4] = 4;
314  jacStamp[4][5] = 5;
315 
316  jacStamp[5].resize(6);
317  jacStamp[5][0] = 0;
318  jacStamp[5][1] = 1;
319  jacStamp[5][2] = 2;
320  jacStamp[5][3] = 3;
321  jacStamp[5][4] = 4;
322  jacStamp[5][5] = 5;
323  }
324 
325 
326  // Set params to constant default values:
327  setDefaultParams ();
328 
329  // Set params according to instance line and constant defaults from metadata:
330  setParams (instance_block.params);
331 
332  // Set any non-constant parameter defaults:
333 
334  // Calculate any parameters specified as expressions:
336 
337  // calculate dependent (ie computed) params and check for errors:
338  processParams();
339 
340 }
341 
342 //-----------------------------------------------------------------------------
343 // Function : Instance::processParams
344 // Purpose :
345 // Special Notes :
346 // Scope : public
347 // Creator : Tom Russo, SNL, Component Information and Models
348 // Creation Date : 06/16/10
349 //-----------------------------------------------------------------------------
351 {
352  bool bsuccess = true;
353 
354  return bsuccess;
355 }
356 
357 //-----------------------------------------------------------------------------
358 // Function : Instance::~Instance
359 // Purpose : destructor
360 // Special Notes :
361 // Scope : public
362 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
363 // Creation Date : 06/16/10
364 //-----------------------------------------------------------------------------
366 {
367 }
368 
369 // Additional Declarations
370 
371 //-----------------------------------------------------------------------------
372 // Function : Instance::registerLIDs
373 // Purpose : function for registering, and setting up, local ID's.
374 // Special Notes :
375 // Scope : public
376 // Creator : Eric Keiter, SNL
377 // Creation Date : 06/16/10
378 //-----------------------------------------------------------------------------
379 void Instance::registerLIDs( const std::vector<int>& intLIDVecRef,
380  const std::vector<int>& extLIDVecRef )
381 {
382  AssertLIDs(intLIDVecRef.size() == numIntVars);
383  AssertLIDs(extLIDVecRef.size() == numExtVars);
384 
385 #if defined(Xyce_DEBUG_DEVICE)
386  if (getDeviceOptions().debugLevel > 0)
387  {
388  Xyce::dout() << std::endl << section_divider << std::endl;
389  Xyce::dout() << "[LTRA-DBG-DEV] In Instance::registerLIDs\n\n";
390  Xyce::dout() << "name = " << getName() << std::endl;
391  Xyce::dout() << "[LTRA-DBG-DEV] number of internal variables: " << numIntVars << std::endl;
392  Xyce::dout() << "[LTRA-DBG-DEV] number of external variables: " << numExtVars << std::endl;
393  }
394 #endif
395 
396  // copy over the global ID lists.
397  intLIDVec = intLIDVecRef;
398  extLIDVec = extLIDVecRef;
399 
400  // Now use these lists to obtain the indices into the linear algebra
401  // entities. This assumes an order.
402 
403  li_Pos1 = extLIDVec[0];
404  li_Neg1 = extLIDVec[1];
405  li_Pos2 = extLIDVec[2];
406  li_Neg2 = extLIDVec[3];
407 
408  // Now do the internal variables
409 
410  li_Ibr1 = intLIDVec[0];
411  li_Ibr2 = intLIDVec[1];
412 
413 #if defined(Xyce_DEBUG_DEVICE)
414  if (getDeviceOptions().debugLevel > 0)
415  {
416  Xyce::dout() << "[LTRA-DBG-DEV] VARIABLE Indicies " << std::endl;
417  Xyce::dout() << "li_Pos1 = " << li_Pos1 << std::endl;
418  Xyce::dout() << "li_Neg1 = " << li_Neg1 << std::endl;
419  Xyce::dout() << "li_Pos2 = " << li_Pos2 << std::endl;
420  Xyce::dout() << "li_Neg2 = " << li_Neg2 << std::endl;
421  Xyce::dout() << "li_Ibr1 = " << li_Ibr1 << std::endl;
422  Xyce::dout() << "li_Ibr1 = " << li_Ibr1 << std::endl;
423  Xyce::dout() << "li_Ibr2 = " << li_Ibr2 << std::endl;
424  Xyce::dout() << "li_Ibr2 = " << li_Ibr2 << std::endl;
425 
426  Xyce::dout() << "\nEnd of Instance::register LIDs\n";
427  Xyce::dout() << section_divider << std::endl;
428  }
429 #endif
430 }
431 //-----------------------------------------------------------------------------
432 // Function : Instance::getIntNameMap
433 // Purpose :
434 // Special Notes :
435 // Scope : public
436 // Creator : Eric R. Keiter, SNL
437 // Creation Date : 06/16/10
438 //-----------------------------------------------------------------------------
439 std::map<int,std::string>& Instance::getIntNameMap ()
440 {
441  // set up the internal name map, if it hasn't been already.
442  if (intNameMap.empty ())
443  {
444  intNameMap[ li_Ibr1 ] = spiceInternalName(getName(), "branch1");
445  intNameMap[ li_Ibr2 ] = spiceInternalName(getName(), "branch2");
446 
447  }
448 
449  return intNameMap;
450 }
451 
452 //-----------------------------------------------------------------------------
453 // Function : Instance::registerStateLIDs
454 // Purpose :
455 // Special Notes :
456 // Scope : public
457 // Creator : Eric Keiter, SNL
458 // Creation Date : 06/16/10
459 //-----------------------------------------------------------------------------
460 void Instance::registerStateLIDs( const std::vector<int>& staLIDVecRef)
461 {
462  AssertLIDs(staLIDVecRef.size() == numStateVars);
463 }
464 
465 //-----------------------------------------------------------------------------
466 // Function : Instance::jacobianStamp
467 // Purpose :
468 // Special Notes :
469 // Scope : public
470 // Creator : Eric Keiter, SNL
471 // Creation Date : 06/16/10
472 //-----------------------------------------------------------------------------
473 const std::vector< std::vector<int> >& Instance::jacobianStamp() const
474 {
475  return jacStamp;
476 }
477 
478 //-----------------------------------------------------------------------------
479 // Function : Instance::registerJacLIDs
480 // Purpose :
481 // Special Notes :
482 // Scope : public
483 // Creator : Eric Keiter, SNL
484 // Creation Date : 06/16/10
485 //-----------------------------------------------------------------------------
486 void Instance::registerJacLIDs( const std::vector< std::vector<int> >& jacLIDVec )
487 {
488 
489  DeviceInstance::registerJacLIDs( jacLIDVec );
490 
491  APos1EquPos1NodeOffset = jacLIDVec[0][0];
492  APos1EquIbr1NodeOffset = jacLIDVec[0][1];
493 
494  ANeg1EquNeg1NodeOffset = jacLIDVec[1][0];
495  ANeg1EquIbr1NodeOffset = jacLIDVec[1][1];
496 
497  APos2EquPos2NodeOffset = jacLIDVec[2][0];
498  APos2EquIbr2NodeOffset = jacLIDVec[2][1];
499 
500  ANeg2EquNeg2NodeOffset = jacLIDVec[3][0];
501  ANeg2EquIbr2NodeOffset = jacLIDVec[3][1];
502 
503  AIbr1EquPos1NodeOffset = jacLIDVec[4][0];
504  AIbr1EquNeg1NodeOffset = jacLIDVec[4][1];
505  AIbr1EquPos2NodeOffset = jacLIDVec[4][2];
506  AIbr1EquNeg2NodeOffset = jacLIDVec[4][3];
507  AIbr1EquIbr1NodeOffset = jacLIDVec[4][4];
508  AIbr1EquIbr2NodeOffset = jacLIDVec[4][5];
509 
510  AIbr2EquPos1NodeOffset = jacLIDVec[5][0];
511  AIbr2EquNeg1NodeOffset = jacLIDVec[5][1];
512  AIbr2EquPos2NodeOffset = jacLIDVec[5][2];
513  AIbr2EquNeg2NodeOffset = jacLIDVec[5][3];
514  AIbr2EquIbr1NodeOffset = jacLIDVec[5][4];
515  AIbr2EquIbr2NodeOffset = jacLIDVec[5][5];
516 
517 }
518 
519 //-----------------------------------------------------------------------------
520 // Function : Instance::setupPointers
521 //
522 // Purpose : Sets up pointers!?
523 //
524 // Special Notes :
525 //
526 // Scope : public
527 // Creator : Gary Hennigan, SNL
528 // Creation Date : 10/11/2012
529 //-----------------------------------------------------------------------------
531 {
532 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
533  N_LAS_Matrix& dFdx = *(extData.dFdxMatrixPtr);
534 
537 
540 
543 
546 
553 
560 #endif
561 }
562 
563 //-----------------------------------------------------------------------------
564 // Function : Instance::loadDAEFVector
565 //
566 // Purpose : Loads the F-vector contributions for a single
567 // LTRA instance.
568 //
569 // Special Notes :
570 //
571 // Scope : public
572 // Creator : Eric Keiter, SNL
573 // Creation Date : 06/16/10
574 //-----------------------------------------------------------------------------
576 {
577  return false;
578 }
579 
580 //-----------------------------------------------------------------------------
581 // Function : Instance::loadDAEdFdx ()
582 //
583 // Purpose : Loads the F-vector contributions for a single
584 //
585 // Scope : public
586 // Creator : Eric Keiter, SNL
587 // Creation Date : 06/16/10
588 //-----------------------------------------------------------------------------
590 {
591  return false;
592 }
593 
594 //-----------------------------------------------------------------------------
595 // Function : Instance::updatePrimaryState
596 // Purpose : update primary state for one LTRA instance
597 // Special Notes :
598 // Scope : public
599 // Creator : Eric Keiter, SNL
600 // Creation Date : 06/16/10
601 //-----------------------------------------------------------------------------
602 
604 {
605  return updateIntermediateVars ();
606 }
607 
608 //-----------------------------------------------------------------------------
609 // Function : Instance::updateSecondaryState
610 // Purpose : update secondary state for one LTRA instance
611 // Special Notes :
612 // Scope : public
613 // Creator : Eric Keiter, SNL
614 // Creation Date : 06/16/10
615 //-----------------------------------------------------------------------------
616 
618 {
619  return true;
620 }
621 
622 //-----------------------------------------------------------------------------
623 // Function : Instance::updateIntermediateVars
624 // Purpose : update intermediate variables for one LTRA instance
625 // Special Notes :
626 // Scope : public
627 // Creator : Eric Keiter, SNL
628 // Creation Date : 06/16/10
629 //-----------------------------------------------------------------------------
631 {
632  double* solVec = extData.nextSolVectorRawPtr;
633 
634  return true;
635 }
636 
637 //-----------------------------------------------------------------------------
638 // Function : Instance::getInstanceBreakPoints
639 // Purpose : This function adds break points to a vector of breakpoints.
640 //
641 // It does not bother to check them in any way, or put them
642 // in order. It only adds them in.
643 //
644 // Special Notes : The guts of this has been moved to acceptStep, which
645 // actually computes the breakpoints if needed. We only add
646 // them to the list here if necessary.
647 //
648 // Scope : public
649 // Creator : Eric Keiter, SNL
650 // Creation Date : 06/16/10
651 //-----------------------------------------------------------------------------
652 bool Instance::getInstanceBreakPoints ( std::vector<N_UTL_BreakPoint>& breakPointTimes )
653 {
654  bool bsuccess = true;
655 
656  double currentTime = getSolverState().currTime;
657  int timeStep = getSolverState().timeStepNumber;
658 
659  // We're called once prior to any newton iterations, not even the
660  // DC Op point. Never do anything if first_BP_call_done is false.
661 
662  if (timeStep != 0 && first_BP_call_done)
663  {
664  if (newBreakPoint)
665  {
666  breakPointTimes.push_back(newBreakPointTime);
667  newBreakPoint = false;
668  }
669  }
670  else
671  {
672 #if defined(Xyce_DEBUG_DEVICE)
673  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
674  {
675  Xyce::dout() << "[LTRA-DBG-DEV] In Instance::getBreakPoints "<<std::endl;
676  Xyce::dout() << " First time step, I don't get to set breakpoints. Time is ";
677  Xyce::dout() << currentTime << std::endl;
678  }
679 #endif
680  }
681 
682  first_BP_call_done=true;
683  return bsuccess;
684 }
685 
686 //-----------------------------------------------------------------------------
687 // Function : Instance::acceptStep
688 // Purpose :
689 //
690 // Special Notes :
691 //
692 // Scope : public
693 // Creator : Eric Keiter, SNL
694 // Creation Date : 06/16/10
695 //-----------------------------------------------------------------------------
697 {
698 
699  // This stores the voltage and current time history at the ports. Note
700  // that both the dc-op and first time step have timeStepNumber 0 so we
701  // have to distinguish between them. For the purposes of these
702  // histories the dc-op is stored in index 0 and the first time step is
703  // at index 1. This is consistent with NG-Spice.
704  if (getSolverState().dcopFlag && listSize == 0)
705  {
706  listSize = 10;
707 
708  v1.resize(listSize);
709  v2.resize(listSize);
710  i1.resize(listSize);
711  i2.resize(listSize);
712  }
713  else if (getSolverState().ltraTimeIndex >= listSize)
714  {
715  listSize += 10;
716 
717  v1.resize(listSize);
718  v2.resize(listSize);
719  i1.resize(listSize);
720  i2.resize(listSize);
721  }
722 
723  // because of DCOP at index 0
726 
729 
730  // Allocate storage for time history entities
731  if (getSolverState().initTranFlag && !getSolverState().dcopFlag)
732  {
733  model_.listSize = 10;
734 
736  model_.h2Coeffs.resize(model_.listSize);
738  }
739  else if (!getSolverState().dcopFlag && getSolverState().ltraTimeIndex >= model_.listSize)
740  {
741  model_.listSize += 10;
742 
744  model_.h2Coeffs.resize(model_.listSize);
746  }
747 
748  bool compact = false;
749  if (getDeviceOptions().tryToCompact && getSolverState().ltraTimeIndex >= 2) {
750 
751  // Figure out if the last 3 points line on a straight line for all
752  // the termainal variables
756 
757  compact = model_.straightLineCheck_(t1, v1[getSolverState().ltraTimeIndex-2],
758  t2, v1[getSolverState().ltraTimeIndex-1],
759  t3, v1[getSolverState().ltraTimeIndex],
762  if (compact) {
763  compact = model_.straightLineCheck_(t1, v2[getSolverState().ltraTimeIndex-2],
764  t2, v2[getSolverState().ltraTimeIndex-1],
765  t3, v2[getSolverState().ltraTimeIndex],
768  }
769  if (compact) {
770  compact = model_.straightLineCheck_(t1, i1[getSolverState().ltraTimeIndex-2],
771  t2, i1[getSolverState().ltraTimeIndex-1],
772  t3, i1[getSolverState().ltraTimeIndex],
775  }
776  if (compact) {
777  compact = model_.straightLineCheck_(t1, i2[getSolverState().ltraTimeIndex-2],
778  t2, i2[getSolverState().ltraTimeIndex-1],
779  t3, i2[getSolverState().ltraTimeIndex],
782  }
783  }
784 
785  if (getSolverState().ltraTimeIndex > 0)
786  {
789 
790  double v2_ = (v1[getSolverState().ltraTimeIndex - 1] +
793 
794  double v3_ = getSolverState().ltraTimeIndex < 2 ? v2_ : (v1[getSolverState().ltraTimeIndex-2] +
797  double v4_ = (v2[getSolverState().ltraTimeIndex] +
800 
801  double v5_ = (v2[getSolverState().ltraTimeIndex-1] +
804 
805  double v6_ = getSolverState().ltraTimeIndex < 2 ? v5_ : (v2[getSolverState().ltraTimeIndex-2] +
808 
809  double d1_ = (v1_ - v2_) / (getSolverState().ltraTimePoints[getSolverState().ltraTimeIndex]
811 
812  double d2_ = getSolverState().ltraTimeIndex < 2 ? d1_ :
815 
816  double d3_ = (v4_ - v5_) / (getSolverState().ltraTimePoints[getSolverState().ltraTimeIndex]
818 
819  double d4_ = getSolverState().ltraTimeIndex < 2 ? d3_ :
822 
823 #define CHECK(a,b,c) (Xycemax(Xycemax(a,b),c)-Xycemin(Xycemin(a,b),c) >= \
824  fabs(50.0*(getDeviceOptions().reltol/3.0*(a+b+c) + \
825  getDeviceOptions().abstol)))
826 
827  bool tmp_test = (fabs(d1_ - d2_) > model_.reltol * Xycemax(fabs(d1_), fabs(d2_)) +
828  model_.abstol) && CHECK(v1_,v2_,v3_);
829 
830  if (tmp_test || ((fabs(d3_ - d4_)
831  >= model_.reltol * Xycemax(fabs(d3_), fabs(d4_)) +
832  model_.abstol) && CHECK(v4_,v5_,v6_)))
833  {
834  // Set breakpoint here
835  newBreakPoint = true;
837 
838 #ifdef Xyce_DEBUG_DEVICE
839  Xyce::dout() << "[LTRA-DBG-DEV]: At simulation time " << getSolverState().currTime
840  << " adding a breakpoint at time " << newBreakPointTime
841  << std::endl;
842 #endif
843  }
844  }
845 
846  if (getDeviceOptions().tryToCompact && compact && getSolverState().ltraTimeIndex >= 2)
847  {
852 
853 
854  getSolverState().ltraDoCompact = true;
855  }
856 
858 
859 #ifdef Xyce_DEBUG_DEVICE
860  Xyce::dout() << "[LTRA-DBG-DEV]: At time: " << getSolverState().currTime
861  << " max time step set to: " << model_.maxTimeStep
862  << std::endl;
863 #endif
864 }
865 
866 //-----------------------------------------------------------------------------
867 // Function : Instance::calculateMaxTimeStep_
868 // Purpose : Calculates a maximum safe time step to avoid excessive
869 // errors
870 //
871 // Special Notes :
872 //
873 // Scope : private
874 // Creator : Gary Hennigan, SNL
875 // Creation Date : 12/04/2012
876 //-----------------------------------------------------------------------------
878 {
879 
880  Model& model = model_;
881  model.maxTimeStep = 1.0e99;
882 
883  if (getSolverState().ltraTimeIndex < 2)
884  {
885  model.maxTimeStep = Xycemin(model.td, model.maxSafeStep);
886  return;
887  }
888 
889  switch (model.specialCase)
890  {
891  case LTRA_MOD_LC:
892  case LTRA_MOD_RLC:
893 
894  if (model.stepLimitType == LTRA_MOD_STEPLIMIT)
895  {
896  model.maxTimeStep = model.td;
897  }
898  else
899  {
900  size_t ti = getSolverState().ltraTimeIndex;
901 
902  // Approximate derivative to detect changing slope and adjust
903  // time step accordingly
904  double i1_ = (v2[ti] * model.admit + i2[ti]) * model.attenuation;
905  double i2_ = (v2[ti-1] * model.admit + i2[ti-1]) * model.attenuation;
906  double i3_ = (v2[ti-2] * model.admit + i2[ti-2]) * model.attenuation;
907 
908  double i4_ = (v1[ti] * model.admit + i1[ti]) * model.attenuation;
909  double i5_ = (v1[ti-1] * model.admit + i1[ti-1]) * model.attenuation;
910  double i6_ = (v1[ti-2] * model.admit + i1[ti-2]) * model.attenuation;
911 
912  double d1_ = (i1_ - i2_) /
914 
915  double d2_ = (i2_ - i3_) /
917 
918  double d3_ = (i4_ - i5_) /
920 
921  double d4_ = (i5_ - i6_) /
923 
924  if ((fabs(d1_-d2_) >= model.reltol * Xycemax(fabs(d1_), fabs(d2_)) + model.abstol) ||
925  (fabs(d3_-d4_) >= model.reltol * Xycemax(fabs(d3_), fabs(d4_)) + model.abstol))
926  {
927  model.maxTimeStep = Xycemin(model.maxTimeStep, model.td);
928  }
929 
930  }
931  break;
932 
933  case LTRA_MOD_RC:
934  case LTRA_MOD_RG:
935  break;
936 
937  default:
938  std::ostringstream msg;
939  msg << "**********" << std::endl;
940  msg << ": Error. Case not handled in calculateMaxTimeStep_()";
941  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg.str());
942  return;
943 
944  }
945 
946  //
947  // the above was for the parts of the equations that resemble the
948  // lossless equations. Now we need to estimate the local truncation
949  // error in each of the three convolution equations, and if possible
950  // adjust the timestep so that all of them remain within some bound.
951  // Unfortunately, the expression for the LTE in a convolution
952  // operation is complicated and costly to evaluate; in addition, no
953  // explicit inverse exists.
954  //
955  // So what we do here (for the moment) is check to see the current
956  // error is acceptable. If so, the timestep is not changed. If not,
957  // then an estimate is made for the new timestep using a few
958  // iterations of the newton-raphson method.
959  //
960  // modification: we change the timestep to half its previous value
961  //
962  if ((model.specialCase == LTRA_MOD_RLC) && !(model.truncDontCut))
963  {
964  model.maxTimeStep = Xycemin(model.maxTimeStep, model.maxSafeStep);
965  }
966 
967  // NOTE-GLH: None of the following code has been tested. As far as I
968  // can tell there is no user option in Spice3 to turn this bit of code
969  // on and as such there is no Xyce option to turn it on. Just to
970  // reiterate it has NOT been tested or even run.
971  if (model.lteTimeStepControl) {
972 
973  double current_lte;
974  double tolerance;
975  switch (model.specialCase) {
976 
977  case LTRA_MOD_RLC:
978  case LTRA_MOD_RC:
979  tolerance = 7.0 *
980  (getDeviceOptions().reltol * (fabs(input1) + fabs(input2)) + getDeviceOptions().abstol);
981 
982  current_lte = model.lteCalculate_(*this, getSolverState().currTime);
983 
984  if (current_lte >= tolerance) {
985  if (model.truncNR) {
986 
987  double ti = getSolverState().ltraTimeIndex;
988  double x = getSolverState().ltraTimePoints[ti];
989  double y = current_lte;
990  for (;;)
991  {
992  double deriv_delta = 0.01 * (x - getSolverState().ltraTimePoints[ti-1]);
993 
994 #ifdef Xyce_DEBUG_DEVICE
995  if (deriv_delta <= 0.0)
996  Xyce::dout() << "LTRAtrunc: error: timestep is now less than zero" << std::endl;
997 #endif
998  double deriv = model.lteCalculate_(*this, x + deriv_delta) - y;
999 
1000  deriv /= deriv_delta;
1001  double change = (tolerance - y) / deriv;
1002  x += change;
1003 
1004  int maxiter=2;
1005  int iterations=0;
1006  if (maxiter == 0) {
1007  if (fabs(change) <= fabs(deriv_delta))
1008  break;
1009  } else {
1010  iterations++;
1011  if (iterations >= maxiter)
1012  break;
1013  }
1014  y = model.lteCalculate_(*this, x);
1015  }
1016 
1017  double tmp = x - getSolverState().ltraTimePoints[ti-1];
1018  model.maxTimeStep = Xycemin(model.maxTimeStep, tmp);
1019  }
1020  else
1021  model.maxTimeStep *= 0.5;
1022  }
1023  break;
1024 
1025  case LTRA_MOD_RG:
1026  case LTRA_MOD_LC:
1027  break;
1028 
1029  default:
1030  std::ostringstream msg;
1031  msg << "**********" << std::endl;
1032  msg << ": Error. Case not handled in calculateMaxTimeStep_() [2]";
1033  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg.str());
1034  return;
1035  }
1036  }
1037 }
1038 
1039 //-----------------------------------------------------------------------------
1040 // Function : Instance::getInternalState
1041 // Purpose : Generates an DeviceState object and populates
1042 // it with the contents of the history vector for use by
1043 // restarts.
1044 //
1045 // Special Notes :
1046 //
1047 // Scope : public
1048 // Creator : Eric Keiter, SNL
1049 // Creation Date : 06/16/10
1050 //-----------------------------------------------------------------------------
1052 {
1053  int i,j;
1054  // allocate obiect to return
1055  DeviceState * myState = new DeviceState;
1056 
1057  myState->ID=getName().getEncodedName();
1058 
1059  // stuff owned by the instance:
1060  myState->dataSizeT.resize(2);
1061  myState->dataSizeT[0] = listSize;
1062 
1063  int origSize = myState->data.size();
1064  myState->data.resize(origSize + 4*listSize + 6);
1065 
1066  myState->data[origSize ]=input1;
1067  myState->data[origSize+1]=input2;
1068  myState->data[origSize+2]= initVolt1 ;
1069  myState->data[origSize+3]= initVolt2 ;
1070  myState->data[origSize+4]= initCur1 ;
1071  myState->data[origSize+5]= initCur2 ;
1072 
1073 #ifdef Xyce_DEBUG_RESTART
1074  Xyce::dout().width(18); Xyce::dout().precision(10); Xyce::dout().setf(std::ios::scientific);
1075  Xyce::dout() << "LTRA::getInternalState: input1="<<input1<<" input2="<<input2<<std::endl;
1076  Xyce::dout() << "LTRA::getInternalState: initVolt11="<<initVolt1<<" initVolt2="<<initVolt2<<std::endl;
1077  Xyce::dout() << "LTRA::getInternalState: initCur11="<<initCur1<<" initCur2="<<initCur2<<std::endl;
1078 #endif
1079 
1080  for (i=0;i<listSize;++i)
1081  {
1082  j=(origSize+6)+i*4;
1083  myState->data[j ]=v1[i];
1084  myState->data[j+1]=v2[i];
1085  myState->data[j+2]=i1[i];
1086  myState->data[j+3]=i2[i];
1087 #ifdef Xyce_DEBUG_RESTART
1088  Xyce::dout().width(18); Xyce::dout().precision(10); Xyce::dout().setf(std::ios::scientific);
1089  Xyce::dout() <<
1090  "LTRA::getInternalState: v1["<<i<<"]="<<v1[i]
1091  <<" v2["<<i<<"]="<<v2[i]
1092  <<" i1["<<i<<"]="<<i1[i]
1093  <<" i2["<<i<<"]="<<i2[i]
1094  <<std::endl;
1095 #endif
1096  }
1097 
1098  // stuff owned by the model:
1099  //if (!(model_.restartStoredFlag))
1100  //{
1101  myState->dataSizeT[1] = model_.listSize;
1102 
1103  origSize = myState->data.size();
1104  myState->data.resize(origSize+model_.listSize*3);
1105  for (i=0;i<model_.listSize;++i)
1106  {
1107  j=origSize+i*3;
1108  myState->data[j]=model_.h1dashCoeffs[i];
1109  myState->data[j+1]=model_.h2Coeffs[i];
1110  myState->data[j+2]=model_.h3dashCoeffs[i];
1111 #ifdef Xyce_DEBUG_RESTART
1112  Xyce::dout().width(18); Xyce::dout().precision(10); Xyce::dout().setf(std::ios::scientific);
1113  Xyce::dout() <<
1114  "LTRA::getInternalState: h1dashCoeffs["<<i<<"] =" << model_.h1dashCoeffs[i]
1115  <<" h2Coeffs["<<i<<"] =" << model_.h2Coeffs[i]
1116  <<" h3dashCoeffs["<<i<<"] =" << model_.h3dashCoeffs[i]<<std::endl;
1117 #endif
1118  }
1119 
1120  //model_.restartStoredFlag=true;
1121  //}
1122 
1123  return myState;
1124 }
1125 
1126 //-----------------------------------------------------------------------------
1127 // Function : Instance::setInternalState
1128 // Purpose : Reload history data from restart
1129 //
1130 // Special Notes :
1131 //
1132 // Scope : public
1133 // Creator : Eric Keiter, SNL
1134 // Creation Date : 06/16/10
1135 //-----------------------------------------------------------------------------
1137 {
1138  int i,j;
1139  if (getName().getEncodedName() != state.ID)
1140  {
1141  DevelFatal(*this).in("LTRA::Instance::setInternalState") << "ID(" << state.ID << ") from restart does not match my name (" << getName() <<")";
1142  return false;
1143  }
1144 
1145  // stuff owned by the instance:
1146  listSize=state.dataSizeT[0];
1147  v1.clear(); v2.clear(); i1.clear(); i2.clear();
1148  v1.resize(listSize); v2.resize(listSize); i1.resize(listSize); i2.resize(listSize);
1149 
1150  input1=state.data[0];
1151  input2=state.data[1];
1152  initVolt1=state.data[2];
1153  initVolt2=state.data[3];
1154  initCur1=state.data[4];
1155  initCur2=state.data[5];
1156 
1157 #ifdef Xyce_DEBUG_RESTART
1158  Xyce::dout().width(18); Xyce::dout().precision(10); Xyce::dout().setf(std::ios::scientific);
1159  Xyce::dout() << "LTRA::setInternalState: input1="<<input1<<" input2="<<input2<<std::endl;
1160  Xyce::dout() << "LTRA::setInternalState: initVolt11="<<initVolt1<<" initVolt2="<<initVolt2<<std::endl;
1161  Xyce::dout() << "LTRA::setInternalState: initCur11="<<initCur1<<" initCur2="<<initCur2<<std::endl;
1162 #endif
1163 
1164  for ( i=0; i<listSize; ++i)
1165  {
1166  j=6+i*4;
1167  v1[i]= state.data[j ];
1168  v2[i]= state.data[j+1];
1169  i1[i]= state.data[j+2];
1170  i2[i]= state.data[j+3];
1171 #ifdef Xyce_DEBUG_RESTART
1172  Xyce::dout().width(18); Xyce::dout().precision(10); Xyce::dout().setf(std::ios::scientific);
1173  Xyce::dout() <<
1174  "LTRA::setInternalState: v1["<<i<<"]="<<v1[i]
1175  <<" v2["<<i<<"]="<<v2[i]
1176  <<" i1["<<i<<"]="<<i1[i]
1177  <<" i2["<<i<<"]="<<i2[i]
1178  <<std::endl;
1179 #endif
1180  }
1181 
1182  // stuff owned by the model:
1183  model_.listSize=state.dataSizeT[1];
1184 
1185  model_.h1dashCoeffs.clear();
1186  model_.h2Coeffs.clear();
1187  model_.h3dashCoeffs.clear();
1188 
1190  model_.h2Coeffs.resize(model_.listSize);
1192 
1193  for ( i=0; i<model_.listSize; ++i)
1194  {
1195  j=(listSize*4+6)+i*3;
1196  model_.h1dashCoeffs[i]= state.data[j];
1197  model_.h2Coeffs[i]= state.data[j+1];
1198  model_.h3dashCoeffs[i]= state.data[j+2];
1199 #ifdef Xyce_DEBUG_RESTART
1200  Xyce::dout().width(18); Xyce::dout().precision(10); Xyce::dout().setf(std::ios::scientific);
1201  Xyce::dout() <<
1202  "LTRA::setInternalState: h1dashCoeffs["<<i<<"] =" << model_.h1dashCoeffs[i]
1203  <<" h2Coeffs["<<i<<"] =" << model_.h2Coeffs[i]
1204  <<" h3dashCoeffs["<<i<<"] =" << model_.h3dashCoeffs[i]<<std::endl;
1205 #endif
1206  }
1207 
1208  return true;
1209 }
1210 
1211 // Class Model
1212 
1213 //-----------------------------------------------------------------------------
1214 // Function : Model::processParams
1215 // Purpose :
1216 // Special Notes :
1217 // Scope : public
1218 // Creator : Eric Keiter, SNL
1219 // Creation Date : 06/16/10
1220 //-----------------------------------------------------------------------------
1222 {
1223 
1224  return true;
1225 }
1226 
1227 //----------------------------------------------------------------------------
1228 // Function : Model::processInstanceParams
1229 // Purpose :
1230 // Special Notes :
1231 // Scope : public
1232 // Creator : Eric Keiter, SNL
1233 // Creation Date : 06/16/10
1234 //----------------------------------------------------------------------------
1236 {
1237 
1238  std::vector<Instance*>::iterator iter;
1239  std::vector<Instance*>::iterator first = instanceContainer.begin();
1240  std::vector<Instance*>::iterator last = instanceContainer.end();
1241 
1242  for (iter=first; iter!=last; ++iter)
1243  {
1244  (*iter)->processParams();
1245  }
1246 
1247  return true;
1248 }
1249 
1250 //-----------------------------------------------------------------------------
1251 // Function : Model::Model
1252 // Purpose : model block constructor
1253 // Special Notes :
1254 // Scope : public
1255 // Creator : Eric Keiter, SNL
1256 // Creation Date : 06/16/10
1257 //-----------------------------------------------------------------------------
1259  const Configuration & configuration,
1260  const ModelBlock& MB,
1261  const FactoryBlock & factory_block)
1262  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
1263 
1264  h1dashFirstVal(0.0),
1265  h2FirstVal(0.0),
1266  h3dashFirstVal(0.0),
1267  h1dashFirstCoeff(0.0),
1268  h2FirstCoeff(0.0),
1269  h3dashFirstCoeff(0.0),
1270  listSize(0),
1271  resist(0.0),
1272  induct(0.0),
1273  conduct(0.0),
1274  capac(0.0),
1275  length(0.0),
1276  reltol(0.0),
1277  abstol(0.0),
1278 
1279  noStepLimit(false),
1280  stepLimit(true),
1281  stepLimitType(LTRA_MOD_STEPLIMIT),
1282 
1283  linInterp(false),
1284  quadInterp(true),
1285  mixedInterp(false),
1286 
1287  stLineReltol(0.0),
1288  stLineAbstol(0.0),
1289 
1290  truncNR(false),
1291  truncDontCut(false),
1292 
1293  resistGiven(false),
1294  inductGiven(false),
1295  conductGiven(false),
1296  capacGiven(false),
1297  lengthGiven(false),
1298  reltolGiven(false),
1299  abstolGiven(false),
1300  noStepLimitGiven(false),
1301  stepLimitGiven(false),
1302  linInterpGiven(false),
1303  quadInterpGiven(false),
1304  mixedInterpGiven(false),
1305  stLineReltolGiven(false),
1306  stLineAbstolGiven(false),
1307  truncNRGiven(false),
1308  truncDontCutGiven(false),
1309 
1310  td(0.0),
1311  imped(0.0),
1312  admit(0.0),
1313  alpha(0.0),
1314  beta(0.0),
1315  attenuation(0.0),
1316  cByR(0.0),
1317  rclsqr(0.0),
1318  intH1dash(0.0),
1319  intH2(0.0),
1320  intH3dash(0.0),
1321 
1322  coshlrootGR(0.0),
1323  rRsLrGRorG(0.0),
1324  rGsLrGRorR(0.0),
1325  auxIndex(0),
1326  chopReltol(0.0),
1327  chopAbstol(0.0),
1328 
1329  maxSafeStep(1.0e99),
1330  maxTimeStep(1.0e99),
1331  lteTimeStepControl(false),
1332  howToInterp(LTRA_MOD_QUADINTERP),
1333  printFlag(false),
1334  specialCase(0),
1335  tdover(false),
1336  restartStoredFlag(false)
1337 
1338 {
1339 
1340  // Set params to constant default values:
1341  setDefaultParams ();
1342 
1343  // Set params according to .model line and constant defaults from metadata:
1344  setModParams (MB.params);
1345 
1346  // Calculate any parameters specified as expressions:
1348 
1349  processParams ();
1350 }
1351 
1352 //-----------------------------------------------------------------------------
1353 //-----------------------------------------------------------------------------
1355 {
1356 
1357  return true;
1358 }
1359 
1360 //-----------------------------------------------------------------------------
1361 // Function : Model::~Model
1362 // Purpose : destructor
1363 // Special Notes :
1364 // Scope : public
1365 // Creator : Eric Keiter, SNL
1366 // Creation Date : 06/16/10
1367 //-----------------------------------------------------------------------------
1369 {
1370  std::vector<Instance*>::iterator iter;
1371  std::vector<Instance*>::iterator first = instanceContainer.begin();
1372  std::vector<Instance*>::iterator last = instanceContainer.end();
1373 
1374  for (iter=first; iter!=last; ++iter)
1375  {
1376  delete (*iter);
1377  }
1378 }
1379 
1380 //-----------------------------------------------------------------------------
1381 // Function : Model::printOutInstances
1382 // Purpose : debugging tool.
1383 // Special Notes :
1384 // Scope : public
1385 // Creator : Eric Keiter, SNL
1386 // Creation Date : 06/16/10
1387 //-----------------------------------------------------------------------------
1388 std::ostream &Model::printOutInstances(std::ostream &os) const
1389 {
1390  std::vector<Instance*>::const_iterator iter;
1391  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
1392  std::vector<Instance*>::const_iterator last = instanceContainer.end();
1393 
1394  int i;
1395  os << std::endl;
1396  os << " name model name Parameters" << std::endl;
1397  for (i=0, iter=first; iter!=last; ++iter, ++i)
1398  {
1399  os << " " << i << ": " << (*iter)->getName() << " ";
1400  os << getName();
1401 
1402  os << std::endl;
1403 
1404  os << std::endl;
1405  }
1406  os << std::endl;
1407 
1408  return os;
1409 }
1410 
1411 //-----------------------------------------------------------------------------
1412 // Function : Model::forEachInstance
1413 // Purpose :
1414 // Special Notes :
1415 // Scope : public
1416 // Creator : David Baur
1417 // Creation Date : 2/4/2014
1418 //-----------------------------------------------------------------------------
1419 /// Apply a device instance "op" to all instances associated with this
1420 /// model
1421 ///
1422 /// @param[in] op Operator to apply to all instances.
1423 ///
1424 ///
1425 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
1426 {
1427  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1428  op(*it);
1429 }
1430 
1431 
1432 //-----------------------------------------------------------------------------
1433 // Function : Model::modelCalculations_
1434 // Purpose :
1435 // Special Notes :
1436 // Scope : private
1437 // Creator : Eric Keiter, SNL
1438 // Creation Date : 06/16/10
1439 //-----------------------------------------------------------------------------
1440 bool Model::modelCalculations_(int& isaved,
1441  double& qf1, double& qf2, double& qf3,
1442  double& lf2, double& lf3)
1443 {
1444  double t1(0.0),t2(0.0),t3(0.0);
1445  double v1d(0.0), v2d(0.0), i1d(0.0), i2d(0.0);
1446  double dummy1(0.0), dummy2(0.0);
1447 
1448  // Initialize index
1449  isaved = 0;
1450 
1451  if( getSolverState().dcopFlag)
1452  {
1453  switch (specialCase)
1454  {
1455  case LTRA_MOD_RG:
1456  dummy1 = length*sqrt(resist*conduct);
1457  dummy2 = exp(-dummy1);
1458  dummy1 = exp(dummy1); // warning: may overflow!
1459  coshlrootGR = 0.5*(dummy1 + dummy2);
1460 
1461  if (conduct <= 1.0e-10)
1462  { // hack!
1464  }
1465  else
1466  {
1467  rRsLrGRorG = 0.5*(dummy1 - dummy2)*sqrt(resist/conduct);
1468  }
1469 
1470  if (resist <= 1.0e-10)
1471  { // hack!
1473  }
1474  else
1475  {
1476  rGsLrGRorR = 0.5*(dummy1 - dummy2)*sqrt(conduct/resist);
1477  }
1478  break;
1479 
1480  case LTRA_MOD_RC:
1481  case LTRA_MOD_LC:
1482  case LTRA_MOD_RLC:
1483  // simple resistor-like behaviour nothing to set up
1484  break;
1485 
1486  default:
1487  std::ostringstream msg;
1488  msg << "**********" << std::endl;
1489  msg << ": Error. Case not handled in modelCalculations_()";
1490  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg.str());
1491  return false;
1492  }
1493  }
1494  else
1495  {
1496  switch (specialCase)
1497  {
1498  case LTRA_MOD_RLC:
1499  case LTRA_MOD_LC:
1500 
1501  if (getSolverState().currTime > td)
1502  tdover = true;
1503  else
1504  tdover = false;
1505 
1506  default:
1507  break;
1508  }
1509 
1510  switch (specialCase)
1511  {
1512  case LTRA_MOD_RLC:
1513 
1514  // set up lists of values of the functions at the
1515  // necessary timepoints.
1516 
1517  // set up coefficient lists LTRAh1dashCoeffs,
1518  // LTRAh2Coeffs, LTRAh3dashCoeffs for current
1519  // timepoint
1520 
1521  // NOTE: h1, h2 and h3 here actually refer to h1tilde,
1522  // h2tilde, h3tilde in the paper
1523 
1524  // Note: many function evaluations are saved by doing
1525  // the following all together in one procedure
1526 
1529  listSize,
1530  td, alpha, beta,
1534  chopReltol,
1535  &(auxIndex));
1536 
1537  case LTRA_MOD_LC:
1538  // setting up the coefficients for interpolation
1539  if (tdover)
1540  { // serious hack -fix!
1541  int i = 0;
1542  for (i = getSolverState().ltraTimeIndex; i >= 0; i--)
1543  {
1545  break;
1546 
1547  }
1548 #ifdef Xyce_DEBUG_DEVICE
1549  if (i == getSolverState().ltraTimeIndex)
1550  {
1551  Xyce::dout() << "[LTRA-DBG-DEV] LTRAload: Warning: timestep larger than delay of line" << std::endl;
1552  Xyce::dout() << "\tTime now: " << getSolverState().currTime << std::endl << std::endl;
1553  }
1554 #endif
1555 
1556  if (i == getSolverState().ltraTimeIndex)
1557  i--;
1558 
1559  if (i == -1)
1560  {
1561 #ifdef Xyce_DEBUG_DEVICE
1562  Xyce::dout() << "[LTRA-DBG-DEV] LTRAload: mistake: cannot find delayed timepoint" << std::endl;
1563 #endif
1564  std::ostringstream msg;
1565  msg << "************" << std::endl;
1566  msg << ": Error. Delayed time point not found.";
1567  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg.str());
1568  return false;
1569  }
1570 
1571  isaved = i;
1572 
1573  t2 = getSolverState().ltraTimePoints[i];
1574  t3 = getSolverState().ltraTimePoints[i+1];
1575 
1576  // quadratic interpolation
1577  if ((i != 0) && ((howToInterp == LTRA_MOD_QUADINTERP)|| (howToInterp == LTRA_MOD_MIXEDINTERP)))
1578  {
1579  t1 = getSolverState().ltraTimePoints[i-1];
1580  quadInterp_(getSolverState().currTime-td, t1, t2, t3, qf1, qf2, qf3);
1581  }
1582 
1583  // linear interpolation
1584  if ( (i == 0) || (howToInterp == LTRA_MOD_MIXEDINTERP) || (howToInterp == LTRA_MOD_LININTERP))
1585  {
1586  linInterp_(getSolverState().currTime-td, t2, t3, lf2, lf3);
1587  }
1588  }
1589 
1590  // interpolation coefficients set-up
1591  break;
1592 
1593  case LTRA_MOD_RC:
1594 
1595  //
1596  // set up lists of values of the coefficients at the
1597  // necessary timepoints.
1598  //
1599 
1600  // set up coefficient lists LTRAh1dashCoeffs, LTRAh2Coeffs,
1601  // LTRAh3dashCoeffs for current timepoint
1602 
1603  // Note: many function evaluations are saved by doing the
1604  // following all together in one procedure
1605  //
1606 
1607  (void)
1610  listSize,
1611  cByR, rclsqr,
1615  chopReltol);
1616 
1617  break;
1618 
1619  case LTRA_MOD_RG:
1620  break;
1621 
1622  default:
1623  return false;
1624  //return(E_BADPARM);
1625  }
1626  }
1627 
1628  return true;
1629 }
1630 
1631 //-----------------------------------------------------------------------------
1632 // Function : Model::quadInterp_
1633 // Purpose :
1634 //
1635 // quadratic interpolation function
1636 // t = timepoint where value wanted
1637 // t1, t2, t3 are three timepoints where the value is known
1638 // c1, c2, c3 are set to the proper coefficients by the function
1639 // the interpolated value is c1*v1 + c2*v2 + c3*v3; this should be
1640 // done in the calling program; (v1,v2,v3 are the known values at
1641 // t1,t2,t3)
1642 //
1643 // Special Notes :
1644 // Scope : public
1645 // Creator : Eric Keiter, SNL
1646 // Creation Date : 07/05/10
1647 //-----------------------------------------------------------------------------
1648 int Model::quadInterp_ (double t, double t1, double t2, double t3, double& c1, double& c2, double& c3)
1649 {
1650  double f1, f2, f3;
1651 
1652  if (t == t1)
1653  {
1654  c1 = 1.0;
1655  c2 = 0.0;
1656  c3 = 0.0;
1657  return(0);
1658  }
1659  if (t == t2)
1660  {
1661  c1 = 0.0;
1662  c2 = 1.0;
1663  c3 = 0.0;
1664  return(0);
1665  }
1666  if (t == t3)
1667  {
1668  c1 = 0.0;
1669  c2 = 0.0;
1670  c3 = 1.0;
1671  return(0);
1672  }
1673  if( (t2-t1)==0 || (t3-t2) == 0 || (t1 - t3) ==0) return(1);
1674 
1675  f1 = (t - t2) * (t - t3) ;
1676  f2 = (t - t1) * (t - t3) ;
1677  f3 = (t - t1) * (t - t2) ;
1678  if((t2-t1)==0)
1679  { // should never happen, but don't want
1680  // to divide by zero, EVER...
1681  f1=0;
1682  f2=0;
1683  }
1684  else
1685  {
1686  f1 /= (t1-t2);
1687  f2 /= (t2-t1);
1688  }
1689  if((t3-t2)==0)
1690  { // should never happen, but don't want
1691  // to divide by zero, EVER...
1692  f2=0;
1693  f3=0;
1694  }
1695  else
1696  {
1697  f2 /= (t2-t3);
1698  f3 /= (t2-t3);
1699  }
1700  if((t3-t1)==0)
1701  { // should never happen, but don't want
1702  // to divide by zero, EVER...
1703  f1=0;
1704  f2=0;
1705  }
1706  else
1707  {
1708  f1 /= (t1-t3);
1709  f3 /= (t1-t3);
1710  }
1711  c1 = f1;
1712  c2 = f2;
1713  c3 = f3;
1714  return(0);
1715 }
1716 
1717 //-----------------------------------------------------------------------------
1718 // Function : Model::linInterp_
1719 // Purpose : linear interpolation
1720 // Special Notes :
1721 // Scope : public
1722 // Creator : Eric Keiter, SNL
1723 // Creation Date : 07/05/10
1724 //-----------------------------------------------------------------------------
1725 int Model::linInterp_ (double t, double t1, double t2, double& c1, double& c2)
1726 {
1727  double temp;
1728 
1729  if (t1 == t2) return(1);
1730 
1731  if (t==t1)
1732  {
1733  c1 = 1.0;
1734  c2 = 0.0;
1735  return(0);
1736  }
1737 
1738  if (t==t2)
1739  {
1740  c1 = 0.0;
1741  c2 = 1.0;
1742  return(0);
1743  }
1744 
1745  temp = (t-t1)/(t2-t1);
1746  c2 = temp;
1747  c1 = 1-temp;
1748 
1749  return(0);
1750 }
1751 
1752 //-----------------------------------------------------------------------------
1753 // Function : Model::intlinfunc_
1754 // Purpose :
1755 //
1756 // intlinfunc returns \int_lolimit^hilimit h(\tau) d \tau, where
1757 // h(\tau) is assumed to be linear, with values lovalue and hivalue
1758 // \tau = t1 and t2 respectively
1759 // this is used only locally
1760 //
1761 // Special Notes :
1762 // Scope : public
1763 // Creator : Eric Keiter, SNL
1764 // Creation Date : 07/05/10
1765 //-----------------------------------------------------------------------------
1766 double Model::intlinfunc_ (double lolimit, double hilimit,
1767  double lovalue, double hivalue,
1768  double t1, double t2)
1769 {
1770  double width, m;
1771 
1772  width = t2 - t1;
1773  if (width == 0.0) return(0.0);
1774  m = (hivalue - lovalue)/width;
1775 
1776  return( (hilimit-lolimit)*lovalue + 0.5*m*((hilimit-t1)*(hilimit-t1)
1777  - (lolimit - t1)*(lolimit - t1)));
1778 }
1779 
1780 //-----------------------------------------------------------------------------
1781 // Function : Model::twiceintlinfunc_
1782 // Purpose :
1783 //
1784 // twiceintlinfunc returns \int_lolimit^hilimit \int_otherlolimit^\tau
1785 // h(\tau') d \tau' d \tau , where
1786 // h(\tau') is assumed to be linear, with values lovalue and hivalue
1787 // \tau = t1 and t2 respectively
1788 // this is used only locally
1789 //
1790 // Special Notes :
1791 // Scope : public
1792 // Creator : Eric Keiter, SNL
1793 // Creation Date : 07/05/10
1794 //-----------------------------------------------------------------------------
1795 double Model::twiceintlinfunc_(double lolimit, double hilimit,
1796  double otherlolimit, double lovalue,
1797  double hivalue, double t1, double t2)
1798 {
1799  double width, m, dummy;
1800  double temp1, temp2, temp3;
1801 
1802  width = t2 - t1;
1803  if (width == 0.0) return(0.0);
1804  m = (hivalue - lovalue)/width;
1805 
1806  temp1 = hilimit - t1;
1807  temp2 = lolimit - t1;
1808  temp3 = otherlolimit - t1;
1809  dummy = lovalue*((hilimit - otherlolimit)*(hilimit - otherlolimit) -
1810  (lolimit - otherlolimit)*(lolimit - otherlolimit));
1811  dummy += m*((temp1*temp1*temp1 - temp2*temp2*temp2)/3.0 -
1812  temp3*temp3*(hilimit - lolimit));
1813  return(dummy*0.5);
1814 }
1815 
1816 
1817 //-----------------------------------------------------------------------------
1818 // Function : Model::thriceintlinfunc_
1819 // Purpose :
1820 //
1821 // thriceintlinfunc returns \int_lolimit^hilimit \int_secondlolimit^\tau
1822 // \int_thirdlolimit^\tau' h(\tau'') d \tau'' d \tau' d \tau , where
1823 // h(\tau'') is assumed to be linear, with values lovalue and hivalue
1824 // \tau = t1 and t2 respectively
1825 // this is used only locally
1826 //
1827 // Special Notes :
1828 // Scope : public
1829 // Creator : Eric Keiter, SNL
1830 // Creation Date : 07/05/10
1831 //-----------------------------------------------------------------------------
1832 double Model::thriceintlinfunc_(double lolimit, double hilimit,
1833  double secondlolimit, double thirdlolimit,
1834  double lovalue, double hivalue, double t1, double t2)
1835 {
1836  double width, m, dummy;
1837  double temp1, temp2, temp3, temp4;
1838  double temp5, temp6, temp7, temp8, temp9, temp10;
1839 
1840 
1841  width = t2 - t1;
1842  if (width == 0.0) return(0.0);
1843  m = (hivalue - lovalue)/width;
1844 
1845  temp1 = hilimit - t1;
1846  temp2 = lolimit - t1;
1847  temp3 = secondlolimit - t1;
1848  temp4 = thirdlolimit - t1;
1849  temp5 = hilimit - thirdlolimit;
1850  temp6 = lolimit - thirdlolimit;
1851  temp7 = secondlolimit - thirdlolimit;
1852  temp8 = hilimit - lolimit;
1853  temp9 = hilimit - secondlolimit;
1854  temp10 = lolimit - secondlolimit;
1855  dummy = lovalue*((temp5*temp5*temp5 - temp6*temp6*temp6)/3 -
1856  temp7*temp5*temp8);
1857  dummy += m*(((temp1*temp1*temp1*temp1 - temp2*temp2*temp2*temp2)*0.25 -
1858  temp3*temp3*temp3*temp8)/3 - temp4*temp4*0.5*(temp9*temp9 -
1859  temp10*temp10));
1860  return(dummy*0.5);
1861 }
1862 
1863 // from numerical recipies in C:
1864 //-----------------------------------------------------------------------------
1865 // Function : Model::bessI0_
1866 // Purpose :
1867 // Special Notes :
1868 // Scope : public
1869 // Creator : Eric Keiter, SNL
1870 // Creation Date : 07/05/10
1871 //-----------------------------------------------------------------------------
1872 double Model::bessI0_(double x)
1873 {
1874  double ax,ans;
1875  double y;
1876 
1877  if ((ax=fabs(x)) < 3.75)
1878  {
1879  y=x/3.75;
1880  y*=y;
1881  ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492
1882  +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2)))));
1883  }
1884  else
1885  {
1886  y=3.75/ax;
1887  ans=(exp(ax)/sqrt(ax))*
1888  (0.39894228+y*(0.1328592e-1+y*(0.225319e-2+
1889  y*(-0.157565e-2+y*(0.916281e-2+
1890  y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1
1891  +y*0.392377e-2))))))));
1892  }
1893  return(ans);
1894 }
1895 
1896 //-----------------------------------------------------------------------------
1897 // Function : Model::bessI1_
1898 // Purpose :
1899 // Special Notes :
1900 // Scope : public
1901 // Creator : Eric Keiter, SNL
1902 // Creation Date : 07/05/10
1903 //-----------------------------------------------------------------------------
1904 double Model::bessI1_(double x)
1905 {
1906  double ax,ans;
1907  double y;
1908 
1909  if ((ax=fabs(x)) < 3.75)
1910  {
1911  y=x/3.75;
1912  y*=y;
1913  ans=ax*(0.5+y*(0.87890594+y*(0.51498869+y*(0.15084934
1914  +y*(0.2658733e-1+y*(0.301532e-2+y*0.32411e-3))))));
1915  }
1916  else
1917  {
1918  y=3.75/ax;
1919  ans=0.2282967e-1+y*(-0.2895312e-1+y*(0.1787654e-1
1920  -y*0.420059e-2));
1921  ans=0.39894228+y*(-0.3988024e-1+y*(-0.362018e-2
1922  +y*(0.163801e-2+y*(-0.1031555e-1+y*ans))));
1923  ans *= (exp(ax)/sqrt(ax));
1924  }
1925  return(x < 0.0 ? -ans : ans);
1926 }
1927 
1928 //-----------------------------------------------------------------------------
1929 // Function : Model::bessI1xOverX_
1930 // Purpose :
1931 // Special Notes :
1932 // Scope : public
1933 // Creator : Eric Keiter, SNL
1934 // Creation Date : 07/05/10
1935 //-----------------------------------------------------------------------------
1936 double Model::bessI1xOverX_(double x)
1937 {
1938  double ax,ans;
1939  double y;
1940 
1941  if ((ax=fabs(x)) < 3.75) {
1942  y=x/3.75;
1943  y*=y;
1944  ans=0.5+y*(0.87890594+y*(0.51498869+y*(0.15084934
1945  +y*(0.2658733e-1+y*(0.301532e-2+y*0.32411e-3)))));
1946  }
1947  else
1948  {
1949  y=3.75/ax;
1950  ans=0.2282967e-1+y*(-0.2895312e-1+y*(0.1787654e-1
1951  -y*0.420059e-2));
1952  ans=0.39894228+y*(-0.3988024e-1+y*(-0.362018e-2
1953  +y*(0.163801e-2+y*(-0.1031555e-1+y*ans))));
1954  ans *= (exp(ax)/(ax*sqrt(ax)));
1955  }
1956  return(ans);
1957 }
1958 
1959 //-----------------------------------------------------------------------------
1960 // Function : Model::rlcH1dashFunc_
1961 // Purpose :
1962 // Special Notes :
1963 // Scope : public
1964 // Creator : Eric Keiter, SNL
1965 // Creation Date : 07/05/10
1966 //-----------------------------------------------------------------------------
1967 double Model::rlcH1dashFunc_(double time, double T, double alpha, double beta)
1968 {
1969  double besselarg, exparg, returnval;
1970  // T is not used in this function
1971 
1972  // result = alpha * e^{- beta*time} * {I_1(alpha*time) -
1973  // I_0(alpha*time)}
1974  //
1975 
1976  if (alpha == 0.0) return(0.0);
1977 
1978  exparg = - beta * time;
1979  besselarg = alpha*time;
1980 
1981  returnval = (bessI1_(besselarg)-bessI0_(besselarg))* alpha * exp(exparg);
1982  return(returnval);
1983 }
1984 
1985 //-----------------------------------------------------------------------------
1986 // Function : Model::rlcH2Func_
1987 // Purpose : first impulse response function
1988 // Special Notes :
1989 // Scope : public
1990 // Creator : Eric Keiter, SNL
1991 // Creation Date : 07/05/10
1992 //-----------------------------------------------------------------------------
1993 double Model::rlcH2Func_(double time, double T, double alpha, double beta)
1994 {
1995  double besselarg, exparg, returnval;
1996 
1997  //
1998  // result = 0, time < T
1999  // = (alpha*T*e^{-beta*time})/sqrt(t^2 - T^2) *
2000  // I_1(alpha*sqrt(t^2 - T^2)), time >= T
2001  //
2002 
2003  if (alpha == 0.0) return(0.0);
2004  if (time < T) return(0.0);
2005 
2006  if (time != T) {
2007  besselarg = alpha*sqrt(time*time - T*T);
2008  } else {
2009  besselarg = 0.0;
2010  }
2011  exparg = -beta*time;
2012 
2013  returnval = alpha*alpha*T*exp(exparg)*bessI1xOverX_(besselarg);
2014  return(returnval);
2015 }
2016 
2017 //-----------------------------------------------------------------------------
2018 // Function : Model::rlcH3dashFunc_
2019 // Purpose :
2020 // Special Notes :
2021 // Scope : public
2022 // Creator : Eric Keiter, SNL
2023 // Creation Date : 07/05/10
2024 //-----------------------------------------------------------------------------
2025 double Model::rlcH3dashFunc_(double time, double T, double alpha, double beta)
2026 {
2027  double exparg,besselarg,returnval;
2028 
2029  //
2030  // result = 0, time < T
2031  // = alpha*e^{-beta*time}*(t/sqrt(t^2-T^2)*
2032  // I_1(alpha*sqrt(t^2-T^2)) - I_0(alpha*sqrt(t^2-T^2)))
2033  //
2034 
2035  if (alpha == 0.0) return(0.0);
2036  if (time < T) return(0.0);
2037 
2038  exparg = - beta*time;
2039  if (time != T) {
2040  besselarg = alpha*sqrt(time*time - T*T);
2041  } else {
2042  besselarg = 0.0;
2043  }
2044 
2045  returnval = alpha*time*bessI1xOverX_(besselarg) - bessI0_(besselarg);
2046  returnval *= alpha*exp(exparg);
2047  return(returnval);
2048 }
2049 
2050 //-----------------------------------------------------------------------------
2051 // Function : Model::rlcH1dashTwiceIntFunc_
2052 //
2053 // Purpose : Twice repeated integral of h1dash for the
2054 // special case of G = 0
2055 //
2056 // Special Notes :
2057 // Scope : public
2058 // Creator : Eric Keiter, SNL
2059 // Creation Date : 07/05/10
2060 //-----------------------------------------------------------------------------
2061 double Model::rlcH1dashTwiceIntFunc_(double time, double beta)
2062 {
2063  double arg, returnval;
2064 
2065  // result = time * e^{- beta*time} * {I_0(beta*time) +
2066  // I_1(beta*time)} - time
2067  //
2068 
2069  if (beta == 0.0) return(time);
2070  arg = beta*time;
2071  if (arg == 0.0) return(0.0);
2072 
2073  returnval = (bessI1_(arg)+bessI0_(arg))* time * exp(-arg) - time;
2074  return(returnval);
2075 }
2076 
2077 //-----------------------------------------------------------------------------
2078 // Function : Model::rlcH3dashIntFunc_
2079 //
2080 // Purpose : twice repeated integral of h1dash for the
2081 // special case of G = 0
2082 //
2083 // Special Notes :
2084 // Scope : public
2085 // Creator : Eric Keiter, SNL
2086 // Creation Date : 07/05/10
2087 //-----------------------------------------------------------------------------
2088 double Model::rlcH3dashIntFunc_(double time, double T, double beta)
2089 {
2090  double exparg, besselarg;
2091  double returnval;
2092 
2093  if (time <= T) return(0.0);
2094  if (beta == 0.0) return(0.0);
2095  exparg = -beta*time;
2096  besselarg = beta*sqrt(time*time-T*T);
2097  returnval = exp(exparg)* bessI0_(besselarg) - exp(-beta*T);
2098  return(returnval);
2099 }
2100 
2101 //-----------------------------------------------------------------------------
2102 // Function : Model::rcH1dashTwiceIntFunc_
2103 // Purpose :
2104 // Special Notes :
2105 // Scope : public
2106 // Creator : Eric Keiter, SNL
2107 // Creation Date : 07/05/10
2108 //-----------------------------------------------------------------------------
2109 double Model::rcH1dashTwiceIntFunc_(double time, double cbyr)
2110 {
2111  return(sqrt(4*cbyr*time/M_PI));
2112 }
2113 
2114 //-----------------------------------------------------------------------------
2115 // Function : Model::rcH2TwiceIntFunc_
2116 // Purpose :
2117 // Special Notes :
2118 // Scope : public
2119 // Creator : Eric Keiter, SNL
2120 // Creation Date : 07/05/10
2121 //-----------------------------------------------------------------------------
2122 double Model::rcH2TwiceIntFunc_(double time, double rclsqr)
2123 {
2124  double temp(0.0);
2125  if (time != 0.0)
2126  {
2127  temp = rclsqr/(4*time);
2128 
2129  // FIXME: The Intel compiler's location of erf/erfc requires an
2130  // include of mathimf.h, which is incompatible with math.h. This is
2131  // completely screwed, because math.h is used EVERYWHERE in Xyce.
2132  // Must either refactor all of Xyce not to depend everywhere on
2133  // math.h, or must refactor this device to provide an alternative
2134  // erf/erfc function on Windows. Right now I'm incorporating a
2135  // third-party implementation of erfc() to avoid this problem
2136 
2137  double erfc_res = Faddeeva::erfc(sqrt(temp));
2138 
2139  return((time + rclsqr*0.5)*erfc_res - sqrt(time*rclsqr/M_PI)*exp(- temp));
2140  }
2141  else
2142  {
2143  return(0.0);
2144  }
2145 }
2146 
2147 //-----------------------------------------------------------------------------
2148 // Function : Model::rcH3dashTwiceIntFunc_
2149 // Purpose :
2150 // Special Notes :
2151 // Scope : public
2152 // Creator : Eric Keiter, SNL
2153 // Creation Date : 07/05/10
2154 //-----------------------------------------------------------------------------
2155 double Model::rcH3dashTwiceIntFunc_(double time, double cbyr, double rclsqr)
2156 {
2157  double temp;
2158  if (time != 0.0)
2159  {
2160  temp = rclsqr/(4*time);
2161 
2162  // see note in rcH2TwiceIntFunc_ about intel compilers
2163  double erfc_res = Faddeeva::erfc(sqrt(temp));
2164 
2165  temp = 2*sqrt(time/M_PI)*exp(-temp) - sqrt(rclsqr)*erfc_res;
2166  return(sqrt(cbyr)*temp);
2167  }
2168  else
2169  {
2170  return(0.0);
2171  }
2172 }
2173 
2174 // coefficient setups:
2175 //-----------------------------------------------------------------------------
2176 // Function : Model::rcCoeffsSetup_
2177 // Purpose :
2178 //
2179 // Sets up the all coefficient lists for the special case where L=G=0
2180 //
2181 // Special Notes :
2182 // Scope : public
2183 // Creator : Eric Keiter, SNL
2184 // Creation Date : 07/05/10
2185 //-----------------------------------------------------------------------------
2187  double& h1dashfirstcoeff,
2188  double& h2firstcoeff,
2189  double& h3dashfirstcoeff,
2190  std::vector<double>& h1dashcoeffs,
2191  std::vector<double>& h2coeffs,
2192  std::vector<double>& h3dashcoeffs,
2193  size_t listsize, double cbyr, double rclsqr, double curtime,
2194  const std::vector<double>& timelist, int timeindex, double reltol)
2195 {
2196  double delta1, delta2;
2197  double h1dummy1, h1dummy2;
2198  double h2dummy1, h2dummy2;
2199  double h3dummy1, h3dummy2;
2200  double lolimit1,lolimit2, hilimit1, hilimit2;
2201  double h1lovalue1,h1lovalue2,h1hivalue1,h1hivalue2;
2202  double h2lovalue1,h2lovalue2,h2hivalue1,h2hivalue2;
2203  double h3lovalue1,h3lovalue2,h3hivalue1,h3hivalue2;
2204  double temp, temp2, temp3, temp4, temp5;
2205  double h1relval, h2relval, h3relval;
2206  int doh1=1, doh2=1, doh3=1;
2207  int i,auxindex;
2208 
2209  // coefflists should already have been allocated to the necessary size
2210 
2211 #ifdef Xyce_DEBUG_DEVICE
2212  if (listsize < timeindex) {
2213  Xyce::dout() << "[LTRA-DBG-DEV]: LTRAcoeffSetup: not enough space in coefflist" << std::endl;
2214  }
2215 #endif
2216 
2217  auxindex = timeindex;
2218 
2219  // the first coefficients
2220 
2221  delta1 = curtime - timelist[auxindex];
2222  lolimit1 = 0.0;
2223  hilimit1 = delta1;
2224 
2225  h1lovalue1 = 0.0;
2226  h1hivalue1 = // LTRArcH1dashTwiceIntFunc(hilimit1,cbyr);
2227  sqrt(4*cbyr*hilimit1/M_PI);
2228  h1dummy1 = h1hivalue1/delta1;
2229  h1dashfirstcoeff = h1dummy1;
2230  h1relval = fabs(h1dummy1*reltol);
2231 
2232  temp = rclsqr/(4*hilimit1);
2233 
2234  // see note in :rcH2TwiceIntFunc_ re intel compiler
2235  temp2 = (temp >= 100.0 ? 0.0 : Faddeeva::erfc(sqrt(temp)));
2236  temp3 = exp(-temp);
2237  temp4 = sqrt(rclsqr);
2238  temp5 = sqrt(cbyr);
2239 
2240  h2lovalue1 = 0.0;
2241  h2hivalue1 = // LTRArcH2TwiceIntFunc(hilimit1,rclsqr);
2242  (hilimit1 != 0.0? (hilimit1 + rclsqr*0.5)*temp2 - sqrt(hilimit1*rclsqr/M_PI)*temp3 : 0.0);
2243 
2244 
2245  h2dummy1 = h2hivalue1/delta1;
2246  h2firstcoeff = h2dummy1;
2247  h2relval = fabs(h2dummy1*reltol);
2248 
2249  h3lovalue1 = 0.0;
2250  h3hivalue1 = // LTRArcH3dashTwiceIntFunc(hilimit1,cbyr,rclsqr);
2251  (hilimit1 != 0.0? temp = 2*sqrt(hilimit1/M_PI)*temp3 - temp4*temp2, (temp5*temp): 0.0);
2252 
2253 
2254  h3dummy1 = h3hivalue1/delta1;
2255  h3dashfirstcoeff = h3dummy1;
2256  h3relval = fabs(h3dummy1*reltol);
2257 
2258  // the coefficients for the rest of the timepoints
2259 
2260  for (i=auxindex; i>0; i--)
2261  {
2262  delta2 = delta1; // previous delta1
2263  lolimit2 = lolimit1; // previous lolimit1
2264  hilimit2 = hilimit1; //previous hilimit1
2265 
2266  delta1 = timelist[i] - timelist[i - 1];
2267  lolimit1 = hilimit2;
2268  hilimit1 = curtime - timelist[i - 1];
2269 
2270  if (doh1)
2271  {
2272  h1lovalue2 = h1lovalue1; // previous lovalue1
2273  h1hivalue2 = h1hivalue1; //previous hivalue1
2274  h1dummy2 = h1dummy1; // previous dummy1
2275 
2276  h1lovalue1 = h1hivalue2;
2277  h1hivalue1 = // LTRArcH1dashTwiceIntFunc(hilimit1,cbyr);
2278  sqrt(4*cbyr*hilimit1/M_PI);
2279  h1dummy1 = (h1hivalue1 - h1lovalue1)/delta1;
2280  h1dashcoeffs[i] = h1dummy1 - h1dummy2;
2281  if (fabs(h1dashcoeffs[i]) < h1relval) doh1=0;
2282  }
2283  else
2284  {
2285  h1dashcoeffs[i] = 0.0;
2286  }
2287 
2288  if (doh2 || doh3) {
2289  temp = rclsqr/(4*hilimit1);
2290  // see note in :rcH2TwiceIntFunc_ re intel compiler
2291  temp2 = (temp >= 100.0 ? 0.0 : Faddeeva::erfc(sqrt(temp)));
2292  temp3 = exp(-temp);
2293  }
2294 
2295  if (doh2)
2296  {
2297  h2lovalue2 = h2lovalue1; // previous lovalue1
2298  h2hivalue2 = h2hivalue1; // previous hivalue1
2299  h2dummy2 = h2dummy1; // previous dummy1
2300 
2301  h2lovalue1 = h2hivalue2;
2302  h2hivalue1 = // LTRArcH2TwiceIntFunc(hilimit1,rclsqr);
2303  (hilimit1 != 0.0? (hilimit1 + rclsqr*0.5)*temp2 - sqrt(hilimit1*rclsqr/M_PI)*temp3 : 0.0);
2304  h2dummy1 = (h2hivalue1 - h2lovalue1)/delta1;
2305  h2coeffs[i] = h2dummy1 - h2dummy2;
2306  if (fabs(h2coeffs[i]) < h2relval) doh2=0;
2307  }
2308  else
2309  {
2310  h2coeffs[i] = 0.0;
2311  }
2312 
2313  if (doh3)
2314  {
2315  h3lovalue2 = h3lovalue1; // previous lovalue1
2316  h3hivalue2 = h3hivalue1; // previous hivalue1
2317  h3dummy2 = h3dummy1; // previous dummy1
2318 
2319  h3lovalue1 = h3hivalue2;
2320  h3hivalue1 = // LTRArcH3dashTwiceIntFunc(hilimit1,cbyr,rclsqr);
2321  (hilimit1 != 0.0? temp = 2*sqrt(hilimit1/M_PI)*temp3 - temp4*temp2, (temp5*temp): 0.0);
2322  h3dummy1 = (h3hivalue1 - h3lovalue1)/delta1;
2323  h3dashcoeffs[i] = h3dummy1 - h3dummy2;
2324  if (fabs(h3dashcoeffs[i]) < h3relval) doh3=0;
2325  }
2326  else
2327  {
2328  h3dashcoeffs[i] = 0.0;
2329  }
2330  }
2331 }
2332 
2333 //-----------------------------------------------------------------------------
2334 // Function : Model::rlcCoeffsSetup_
2335 // Purpose :
2336 // Special Notes :
2337 // Scope : public
2338 // Creator : Eric Keiter, SNL
2339 // Creation Date : 07/05/10
2340 //-----------------------------------------------------------------------------
2342  double& h1dashfirstcoeff,
2343  double& h2firstcoeff,
2344  double& h3dashfirstcoeff,
2345  std::vector<double>& h1dashcoeffs,
2346  std::vector<double>& h2coeffs,
2347  std::vector<double>& h3dashcoeffs,
2348  size_t listsize,
2349  double T, double alpha, double beta, double curtime,
2350  const std::vector<double>& timelist, int timeindex, double reltol, int* auxindexptr)
2351 {
2352  unsigned exact;
2353  double lolimit1,lolimit2,hilimit1,hilimit2;
2354  double delta1, delta2;
2355 
2356  double h1dummy1, h1dummy2;
2357  double h1lovalue1,h1lovalue2,h1hivalue1,h1hivalue2;
2358 
2359  double h2dummy1, h2dummy2;
2360  double h2lovalue1,h2lovalue2,h2hivalue1,h2hivalue2;
2361 
2362  double h3dummy1, h3dummy2;
2363  double h3lovalue1,h3lovalue2,h3hivalue1,h3hivalue2;
2364 
2365  double exparg, besselarg, expterm, bessi1overxterm, bessi0term;
2366  double expbetaTterm, alphasqTterm;
2367  double h1relval, h2relval, h3relval;
2368  int doh1=1, doh2=1, doh3=1;
2369 
2370  int i,auxindex;
2371 
2372  // coefflists should already have been allocated to the necessary size
2373 
2374 #ifdef Xyce_DEBUG_DEVICE
2375  if (listsize < timeindex) {
2376  Xyce::dout() << "[LTRA-DBG-DEV]: LTRArlcCoeffsSetup_: not enough space in coefflist" << std::endl;
2377  }
2378 #endif
2379 
2380 
2381  //
2382  // we assume a piecewise linear function, and we calculate the
2383  // coefficients using this assumption in the integration of the
2384  // function
2385 
2386 
2387  if (T == 0.0) {
2388  auxindex = timeindex;
2389  } else {
2390 
2391  if (curtime - T <= 0.0) {
2392  auxindex = 0;
2393  } else {
2394  exact = 0;
2395  for (i = timeindex; i>= 0; i--) {
2396  if (curtime - timelist[i] == T) {
2397  exact =1;
2398  break;
2399  }
2400  if (curtime - timelist[i] > T) break;
2401  }
2402 
2403 #ifdef Xyce_DEBUG_DEVICE
2404  if ((i < 0) || ((i==0) && (exact==1)))
2405  Xyce::dout() << "[LTRA-DBG-DEV]: LTRAcoeffSetup: i <= 0: some mistake!" << std::endl;
2406 #endif
2407 
2408  if (exact == 1) {
2409  auxindex = i-1;
2410  } else {
2411  auxindex = i;
2412  }
2413  }
2414  }
2415  // the first coefficient
2416 
2417  if (auxindex != 0)
2418  {
2419  lolimit1 = T;
2420  hilimit1 = curtime - timelist[auxindex];
2421  delta1 = hilimit1 - lolimit1;
2422 
2423  h2lovalue1 = rlcH2Func_(T,T,alpha,beta);
2424  besselarg = (hilimit1 > T) ? alpha*sqrt(hilimit1*hilimit1-T*T):0.0;
2425  exparg = -beta*hilimit1;
2426  expterm = exp(exparg);
2427  bessi1overxterm = bessI1xOverX_(besselarg);
2428  alphasqTterm = alpha*alpha*T;
2429  h2hivalue1 = // LTRArlcH2Func(hilimit1,T,alpha,beta);
2430  ((alpha == 0.0) || (hilimit1 < T)) ? 0.0: alphasqTterm*expterm*bessi1overxterm;
2431 
2432  h2dummy1 = twiceintlinfunc_(lolimit1,hilimit1,lolimit1,h2lovalue1,
2433  h2hivalue1,lolimit1,hilimit1)/delta1;
2434  h2firstcoeff = h2dummy1;
2435  h2relval = fabs(reltol*h2dummy1);
2436 
2437  h3lovalue1 = 0.0; // E3dash should be consistent with this
2438  bessi0term = bessI0_(besselarg);
2439  expbetaTterm = exp(-beta*T);
2440  h3hivalue1 = // LTRArlcH3dashIntFunc(hilimit1,T,beta);
2441  ((hilimit1 <= T) || (beta == 0.0)) ? 0.0: expterm* bessi0term-expbetaTterm;
2442  h3dummy1 = intlinfunc_(lolimit1,hilimit1,h3lovalue1,
2443  h3hivalue1,lolimit1,hilimit1)/delta1;
2444  h3dashfirstcoeff = h3dummy1;
2445  h3relval = fabs(h3dummy1*reltol);
2446  }
2447  else
2448  {
2449  h2firstcoeff = h3dashfirstcoeff = 0.0;
2450  }
2451 
2452  lolimit1 = 0.0;
2453  hilimit1 = curtime - timelist[timeindex];
2454  delta1 = hilimit1 - lolimit1;
2455  exparg = -beta*hilimit1;
2456  expterm = exp(exparg);
2457 
2458  h1lovalue1 = 0.0;
2459  h1hivalue1 = //LTRArlcH1dashTwiceIntFunc(hilimit1,beta);
2460  (beta == 0.0) ? hilimit1 : ((hilimit1 == 0.0) ? 0.0 :
2461  (bessI1_(-exparg)+bessI0_(-exparg))* hilimit1 * expterm - hilimit1);
2462  h1dummy1 = h1hivalue1/delta1;
2463  h1dashfirstcoeff = h1dummy1;
2464  h1relval = fabs(h1dummy1*reltol);
2465 
2466 
2467  // the coefficients for the rest of the timepoints
2468 
2469  for (i=timeindex; i>0; i--)
2470  {
2471  if (doh1 || doh2 || doh3)
2472  {
2473  lolimit2 = lolimit1; // previous lolimit1
2474  hilimit2 = hilimit1; // previous hilimit1
2475  delta2 = delta1; // previous delta1
2476 
2477  lolimit1 = hilimit2;
2478  hilimit1 = curtime - timelist[i - 1];
2479  delta1 = timelist[i] - timelist[i - 1];
2480 
2481  exparg = -beta*hilimit1;
2482  expterm = exp(exparg);
2483  }
2484 
2485  if (doh1)
2486  {
2487  h1lovalue2 = h1lovalue1; // previous lovalue1
2488  h1hivalue2 = h1hivalue1; // previous hivalue1
2489  h1dummy2 = h1dummy1; // previous dummy1
2490 
2491  h1lovalue1 = h1hivalue2;
2492  h1hivalue1 = // LTRArlcH1dashTwiceIntFunc(hilimit1,beta);
2493  (beta == 0.0) ? hilimit1 : ((hilimit1 == 0.0) ? 0.0 :
2494  (bessI1_(-exparg)+bessI0_(-exparg))* hilimit1 * expterm - hilimit1);
2495  h1dummy1 = (h1hivalue1 - h1lovalue1)/delta1;
2496 
2497  h1dashcoeffs[i] = h1dummy1 - h1dummy2;
2498  if (fabs(h1dashcoeffs[i]) <= h1relval) doh1 = 0;
2499  }
2500  else
2501  {
2502  h1dashcoeffs[i] = 0.0;
2503  }
2504 
2505  if (i <= auxindex)
2506  {
2507  // if (i == auxindex) {
2508  // lolimit2 = T;
2509  // delta2 = hilimit2 - lolimit2;
2510  // }
2511 
2512  if (doh2 || doh3)
2513  {
2514  besselarg = (hilimit1 > T) ? alpha*sqrt(hilimit1*hilimit1-T*T):0.0;
2515  }
2516 
2517  if (doh2)
2518  {
2519  h2lovalue2 = h2lovalue1; // previous lovalue1
2520  h2hivalue2 = h2hivalue1; // previous hivalue1
2521  h2dummy2 = h2dummy1; // previous dummy1
2522 
2523  h2lovalue1 = h2hivalue2;
2524  bessi1overxterm = bessI1xOverX_(besselarg);
2525  h2hivalue1 = // rlcH2Func(hilimit1,T,alpha,beta);
2526  ((alpha == 0.0) || (hilimit1 < T)) ? 0.0: alphasqTterm*expterm*bessi1overxterm;
2527  h2dummy1 = twiceintlinfunc_(lolimit1,hilimit1,lolimit1,
2528  h2lovalue1,h2hivalue1,lolimit1,hilimit1)/delta1;
2529 
2530  h2coeffs[i] = h2dummy1 - h2dummy2 + intlinfunc_(lolimit2,hilimit2,
2531  h2lovalue2,h2hivalue2,lolimit2,hilimit2);
2532  if (fabs(h2coeffs[i]) <= h2relval) doh2 = 0;
2533  }
2534  else
2535  {
2536  h2coeffs[i] = 0.0;
2537  }
2538 
2539  if (doh3)
2540  {
2541  h3lovalue2 = h3lovalue1; // previous lovalue1
2542  h3hivalue2 = h3hivalue1; //previous hivalue1
2543  h3dummy2 = h3dummy1; // previous dummy1
2544 
2545  h3lovalue1 = h3hivalue2;
2546  bessi0term = bessI0_(besselarg);
2547  h3hivalue1 = //LTRArlcH3dashIntFunc(hilimit1,T,beta);
2548  ((hilimit1 <= T) || (beta == 0.0)) ? 0.0: expterm* bessi0term-expbetaTterm;
2549  h3dummy1 = intlinfunc_(lolimit1,hilimit1,h3lovalue1,h3hivalue1,lolimit1,hilimit1)/delta1;
2550 
2551  h3dashcoeffs[i] = h3dummy1 - h3dummy2;
2552  if (fabs(h3dashcoeffs[i]) <= h3relval) doh3 = 0;
2553  }
2554  else
2555  {
2556  h3dashcoeffs[i] = 0.0;
2557  }
2558  }
2559  }
2560  *auxindexptr = auxindex;
2561 }
2562 
2563 //-----------------------------------------------------------------------------
2564 // Function : Model::straightLineCheck_
2565 // Purpose :
2566 //
2567 // takes the co-ordinates of three points,
2568 // finds the area of the triangle enclosed by these points and
2569 // compares this area with the area of the quadrilateral formed by
2570 // the line between the first point and the third point, the
2571 // perpendiculars from the first and third points to the x-axis, and
2572 // the x-axis. If within reltol, then it returns 1, else 0. The
2573 // purpose of this function is to determine if three points lie
2574 // acceptably close to a straight line. This area criterion is used
2575 // because it is related to integrals and convolution
2576 //
2577 // Special Notes :
2578 // Scope : public
2579 // Creator : Eric Keiter, SNL
2580 // Creation Date : 07/05/10
2581 //-----------------------------------------------------------------------------
2582 bool Model::straightLineCheck_(double x1, double y1,
2583  double x2, double y2,
2584  double x3, double y3,
2585  double reltol, double abstol)
2586 {
2587  // double asqr, bsqr, csqr, c, c1sqr;
2588  // double htsqr;
2589  double TRarea, QUADarea1,QUADarea2,QUADarea3, area;
2590 
2591  // asqr = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
2592  // bsqr = (x3-x2)*(x3-x2) + (y3-y2)*(y3-y2);
2593  // csqr = (x3-x1)*(x3-x1) + (y3-y1)*(y3-y1);
2594  // c = sqrt(csqr);
2595  // c1sqr = (asqr - bsqr + csqr)/(2*c);
2596  // c1sqr *= c1sqr;
2597  // htsqr = asqr - c1sqr;
2598  // TRarea = c*sqrt(htsqr)*0.5;
2599 
2600  // this should work if y1,y2,y3 all have the same sign and x1,x2,x3
2601  // are in increasing order
2602 
2603  QUADarea1 = (fabs(y2)+fabs(y1))*0.5*fabs(x2-x1);
2604  QUADarea2 = (fabs(y3)+fabs(y2))*0.5*fabs(x3-x2);
2605  QUADarea3 = (fabs(y3)+fabs(y1))*0.5*fabs(x3-x1);
2606  TRarea = fabs( QUADarea3 - QUADarea1 - QUADarea2);
2607  area = QUADarea1 + QUADarea2;
2608  if (area*reltol + abstol > TRarea)
2609  return(true);
2610  else
2611  return(false);
2612 }
2613 
2614 // i is the index of the latest value,
2615 // a,b,c values correspond to values at t_{i-2}, t{i-1} and t_i
2616 //
2617 // ERK: Note: check curtime.
2618 #define SECONDDERIV(i,a,b,c) \
2619  (oof = (i==getSolverState().ltraTimeIndex?getSolverState().currTime: \
2620  (getSolverState().ltraTimePoints[i])), \
2621  (( c - b )/(oof-(getSolverState().ltraTimePoints[i-1])) - \
2622  ( b - a )/((getSolverState().ltraTimePoints[i-1])- \
2623  (getSolverState().ltraTimePoints[i-2])))/(oof - \
2624  (getSolverState().ltraTimePoints[i-2])))
2625 
2626 
2627 //-----------------------------------------------------------------------------
2628 // Function : Model::SECONDDERIV_
2629 // Purpose :
2630 // Special Notes : see macro, above, modified from spice3
2631 // Scope : public
2632 // Creator : Eric Keiter, SNL
2633 // Creation Date : 07/05/10
2634 //-----------------------------------------------------------------------------
2635 double Model::SECONDDERIV_(int i, double a, double b, double c)
2636 {
2637  double oof=0.0;
2638  return SECONDDERIV(i,a,b,c);
2639 }
2640 
2641 //-----------------------------------------------------------------------------
2642 // Function : Model::lteCalculate_
2643 // Purpose :
2644 //
2645 // returns sum of the absolute values of the total
2646 // local truncation error of the 2 equations for the LTRAline
2647 //
2648 // Special Notes :
2649 // Scope : public
2650 // Creator : Eric Keiter, SNL
2651 // Creation Date : 07/05/10
2652 //-----------------------------------------------------------------------------
2654  Instance& instance,
2655  double curtime
2656  )
2657 {
2658  double h1dashTfirstCoeff;
2659  double h2TfirstCoeff;
2660  double h3dashTfirstCoeff;
2661  double dashdash;
2662  double hilimit1, lolimit1, hivalue1, lovalue1, f1i, g1i;
2663  double eq1LTE=0.0, eq2LTE=0.0;
2664  int auxindex, tdover, i, exact;
2665 
2666  switch(specialCase)
2667  {
2668  case LTRA_MOD_LC:
2669  case LTRA_MOD_RG:
2670  return(0.0);
2671  break;
2672 
2673  case LTRA_MOD_RLC:
2674 
2675  if (curtime > td)
2676  {
2677  tdover = 1;
2678 
2679  exact = 0;
2680 
2681  for (i=(getSolverState().ltraTimeIndex-1); i >= 0; i--)
2682  {
2683  if (curtime - getSolverState().ltraTimePoints[i] == td)
2684  {
2685  exact = 1;
2686  break;
2687  }
2688  if (curtime - getSolverState().ltraTimePoints[i] > td)
2689  {
2690  break;
2691  }
2692  }
2693 
2694 #ifdef Xyce_DEBUG_DEVICE
2695  if ((i < 0) || ((i==0) && (exact==1)))
2696  Xyce::dout() << "[LTRA-DBG-DEV]: lteCalculate_: i <= 0: some mistake!" << std::endl;
2697 #endif
2698 
2699  if (exact == 1)
2700  {
2701  auxindex = i-1;
2702  }
2703  else
2704  {
2705  auxindex = i;
2706  }
2707  }
2708  else
2709  {
2710  tdover = 0;
2711  }
2712 
2713  hilimit1 = curtime - getSolverState().ltraTimePoints[getSolverState().ltraTimeIndex-1];
2714  lolimit1 = 0.0;
2715  hivalue1 = rlcH1dashTwiceIntFunc_(hilimit1,beta);
2716  lovalue1 = 0.0;
2717 
2718  f1i = hivalue1;
2719  g1i = intlinfunc_(lolimit1,hilimit1,lovalue1,hivalue1,
2720  lolimit1,hilimit1);
2721  h1dashTfirstCoeff = 0.5 * f1i *
2722  (curtime - getSolverState().ltraTimePoints[getSolverState().ltraTimeIndex-1]) - g1i;
2723 
2724  if (tdover)
2725  {
2726  hilimit1 = curtime - getSolverState().ltraTimePoints[auxindex];
2728  lolimit1 = Xycemax(td,lolimit1);
2729 
2730  // are the following really doing the operations in the write-up?
2731  hivalue1 = rlcH2Func_(hilimit1,td,alpha,beta);
2732  lovalue1 = rlcH2Func_(lolimit1,td,alpha,beta);
2733  f1i = twiceintlinfunc_(lolimit1,hilimit1,lolimit1,lovalue1,hivalue1,lolimit1,
2734  hilimit1);
2735  g1i = thriceintlinfunc_(lolimit1,hilimit1,lolimit1,lolimit1,lovalue1,
2736  hivalue1,lolimit1,hilimit1);
2737 
2738  h2TfirstCoeff = 0.5*f1i*(curtime-td-getSolverState().ltraTimePoints[auxindex]) - g1i;
2739 
2740  hivalue1 = rlcH3dashIntFunc_(hilimit1,td,beta);
2741  lovalue1 = rlcH3dashIntFunc_(lolimit1,td,beta);
2742  f1i = intlinfunc_(lolimit1,hilimit1,lovalue1,hivalue1,lolimit1,
2743  hilimit1);
2744  g1i = twiceintlinfunc_(lolimit1,hilimit1,lolimit1,lovalue1,
2745  hivalue1,lolimit1,hilimit1);
2746  h3dashTfirstCoeff = 0.5*f1i*(curtime-td-getSolverState().ltraTimePoints[auxindex]) - g1i;
2747  }
2748 
2749 
2750  // LTEs for convolution with v1
2751  // get divided differences for v1 (2nd derivative estimates)
2752 
2753  // no need to subtract operating point values because
2754  // taking differences anyway
2755  //
2756 
2757 
2758  dashdash = SECONDDERIV_(getSolverState().ltraTimeIndex,
2759  instance.v1[getSolverState().ltraTimeIndex-2],
2760  instance.v1[getSolverState().ltraTimeIndex-1],
2761  instance.v1[getSolverState().ltraTimeIndex]);
2762  eq1LTE += admit*fabs(dashdash * h1dashTfirstCoeff);
2763 
2764  // not bothering to interpolate since everything is approximate
2765  // anyway
2766  if (tdover)
2767  {
2768  dashdash = SECONDDERIV_(auxindex+1,
2769  instance.v1[auxindex - 1],
2770  instance.v1[auxindex],
2771  instance.v1[auxindex + 1]) ;
2772 
2773  eq2LTE += admit*fabs(dashdash * h3dashTfirstCoeff);
2774  }
2775  // end LTEs for convolution with v1
2776 
2777  // LTEs for convolution with v2
2778  // get divided differences for v2 (2nd derivative estimates)
2779 
2780  dashdash = SECONDDERIV_(getSolverState().ltraTimeIndex,
2781  instance.v2[getSolverState().ltraTimeIndex-2],
2782  instance.v2[getSolverState().ltraTimeIndex-1],
2783  instance.v2[getSolverState().ltraTimeIndex]);
2784 
2785  eq2LTE += admit*fabs(dashdash * h1dashTfirstCoeff);
2786 
2787  if (tdover)
2788  {
2789  dashdash = SECONDDERIV_(auxindex+1,
2790  instance.v2[auxindex - 1],
2791  instance.v2[auxindex],
2792  instance.v2[auxindex + 1]);
2793 
2794  eq1LTE += admit*fabs(dashdash * h3dashTfirstCoeff);
2795  }
2796 
2797  // end LTEs for convolution with v2
2798 
2799  // LTE for convolution with i1
2800  // get divided differences for i1 (2nd derivative estimates)
2801 
2802  if (tdover)
2803  {
2804  dashdash = SECONDDERIV_(auxindex+1,
2805  instance.i1[auxindex - 1],
2806  instance.i1[auxindex],
2807  instance.i1[auxindex + 1]) ;
2808 
2809  eq2LTE += fabs(dashdash * h2TfirstCoeff);
2810  }
2811  // end LTE for convolution with i1
2812 
2813  // LTE for convolution with i2
2814  // get divided differences for i2 (2nd derivative estimates)
2815 
2816  if (tdover)
2817  {
2818  dashdash = SECONDDERIV_(auxindex+1,
2819  instance.i2[auxindex - 1],
2820  instance.i2[auxindex],
2821  instance.i2[auxindex + 1]) ;
2822 
2823  eq1LTE += fabs(dashdash * h2TfirstCoeff);
2824  }
2825 
2826  // end LTE for convolution with i1
2827 
2828  break;
2829 
2830  case LTRA_MOD_RC:
2831 
2832  hilimit1 = curtime - getSolverState().ltraTimePoints[getSolverState().ltraTimeIndex-1];
2833  lolimit1 = 0.0;
2834 
2835  hivalue1 = rcH1dashTwiceIntFunc_(hilimit1,cByR);
2836  lovalue1 = 0.0;
2837 
2838  f1i = hivalue1;
2839  g1i = intlinfunc_(lolimit1,hilimit1,lovalue1,hivalue1,lolimit1,hilimit1);
2840 
2841  h1dashTfirstCoeff = 0.5*f1i*(curtime-getSolverState().ltraTimePoints[getSolverState().ltraTimeIndex-1]) - g1i;
2842 
2843  hivalue1 = rcH2TwiceIntFunc_(hilimit1,rclsqr);
2844  lovalue1 = 0.0;
2845 
2846  f1i = hivalue1;
2847  g1i = intlinfunc_(lolimit1,hilimit1,lovalue1,hivalue1,lolimit1,hilimit1);
2848  h1dashTfirstCoeff = 0.5*f1i*(curtime-getSolverState().ltraTimePoints[getSolverState().ltraTimeIndex-1]) - g1i;
2849 
2850  hivalue1 = rcH2TwiceIntFunc_(hilimit1,rclsqr);
2851  lovalue1 = 0.0;
2852 
2853  f1i = hivalue1;
2854  g1i = intlinfunc_(lolimit1,hilimit1,lovalue1,
2855  hivalue1,lolimit1,hilimit1);
2856  h1dashTfirstCoeff = 0.5*f1i*(curtime-getSolverState().ltraTimePoints[getSolverState().ltraTimeIndex-1]) - g1i;
2857 
2858  // LTEs for convolution with v1
2859  // get divided differences for v1 (2nd derivative estimates)
2860 
2861  // no need to subtract operating point values because
2862  // taking differences anyway
2863 
2864  dashdash = SECONDDERIV_( getSolverState().ltraTimeIndex,
2865  instance.v1[getSolverState().ltraTimeIndex-2],
2866  instance.v1[getSolverState().ltraTimeIndex-1],
2867  instance.v1[getSolverState().ltraTimeIndex] );
2868 
2869  eq1LTE += fabs(dashdash * h1dashTfirstCoeff);
2870  eq2LTE += fabs(dashdash * h3dashTfirstCoeff);
2871 
2872  // end LTEs for convolution with v1
2873 
2874  // LTEs for convolution with v2
2875  // get divided differences for v2 (2nd derivative estimates)
2876 
2877  dashdash = SECONDDERIV_( getSolverState().ltraTimeIndex,
2878  instance.v2[getSolverState().ltraTimeIndex-2],
2879  instance.v2[getSolverState().ltraTimeIndex-1],
2880  instance.v2[getSolverState().ltraTimeIndex] );
2881 
2882  eq2LTE += fabs(dashdash * h1dashTfirstCoeff);
2883  eq1LTE += fabs(dashdash * h3dashTfirstCoeff);
2884 
2885  // end LTEs for convolution with v2
2886 
2887  // LTE for convolution with i1
2888  // get divided differences for i1 (2nd derivative estimates)
2889 
2890  dashdash = SECONDDERIV_( getSolverState().ltraTimeIndex,
2891  instance.i1[getSolverState().ltraTimeIndex-2],
2892  instance.i1[getSolverState().ltraTimeIndex-1],
2893  instance.i1[getSolverState().ltraTimeIndex] );
2894 
2895  eq2LTE += fabs(dashdash * h2TfirstCoeff);
2896 
2897  // end LTE for convolution with i1
2898 
2899  // LTE for convolution with i2
2900  // get divided differences for i2 (2nd derivative estimates)
2901 
2902  dashdash = SECONDDERIV_( getSolverState().ltraTimeIndex,
2903  instance.i2[getSolverState().ltraTimeIndex-2],
2904  instance.i2[getSolverState().ltraTimeIndex-1],
2905  instance.i2[getSolverState().ltraTimeIndex] );
2906 
2907  eq1LTE += fabs(dashdash * h2TfirstCoeff);
2908 
2909  // end LTE for convolution with i1
2910 
2911  break;
2912 
2913  default:
2914  return(1/*error*/);
2915  }
2916 
2917 #ifdef Xyce_DEBUG_DEVICE
2918  Xyce::dout() << "[LTRA-DBG-DEV] " << instance.getName() << ": LTE/input for Eq1 at time "
2919  << curtime << " is: " << eq1LTE/instance.input1 << std::endl;
2920 
2921  Xyce::dout() << "[LTRA-DBG-DEV] " << instance.getName() << ": LTE/input for Eq2 at time "
2922  << curtime << " is: " << eq2LTE/instance.input1 << std::endl;
2923 #endif
2924 
2925  return(fabs(eq1LTE) + fabs(eq2LTE));
2926 }
2927 
2928 //-----------------------------------------------------------------------------
2929 // Function : Instance::getMaxTimeStepSize
2930 // Purpose :
2931 // Special Notes :
2932 // Scope : public
2933 // Creator : Eric Keiter, SNL
2934 // Creation Date : 06/16/10
2935 //-----------------------------------------------------------------------------
2937 {
2938  return model_.maxTimeStep;
2939 }
2940 
2941 // LTRA Master functions:
2942 
2943 //-----------------------------------------------------------------------------
2944 // Function : Master::updateState
2945 // Purpose :
2946 // Special Notes :
2947 // Scope : public
2948 // Creator : Eric Keiter, SNL
2949 // Creation Date : 06/16/10
2950 //-----------------------------------------------------------------------------
2951 bool Master::updateState (double* solVec, double* staVec, double* stoVec)
2952 {
2953 
2954  // Compute some quantities derived from input parameters and do some
2955  // error checking.
2956  if (!vars_initialized)
2957  {
2958  initialize_vars_();
2959 
2960  // Set flag to avoid multiple invocations
2961  vars_initialized = true;
2962  }
2963 
2964  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
2965  {
2966  Instance& di = *(*it);
2967 
2968  // Update current state
2969  di.vpos1 = solVec[di.li_Pos1];
2970  di.vneg1 = solVec[di.li_Neg1];
2971 
2972  di.vpos2 = solVec[di.li_Pos2];
2973  di.vneg2 = solVec[di.li_Neg2];
2974 
2975  di.currp1 = solVec[di.li_Ibr1];
2976  di.currp2 = solVec[di.li_Ibr2];
2977 
2978  // Initial state, generally the end result of the DC-OP calculation
2979  if (getSolverState().dcopFlag)
2980  {
2981  di.initVolt1 = di.vpos1 - di.vneg1;
2982  di.initVolt2 = di.vpos2 - di.vneg2;
2983 
2984  di.initCur1 = di.currp1;
2985  di.initCur2 = di.currp2;
2986  }
2987  }
2988 
2989  return true;
2990 }
2991 
2992 //-----------------------------------------------------------------------------
2993 // Function : Model::Model
2994 // Purpose : Error check and set some variables derived from input
2995 // parameters.
2996 // Special Notes : This should only be invoked once after the parameters from
2997 // the input file have been initialized. This should be
2998 // invoked from a function only once after the paramater
2999 // initialization and before the solve starts.
3000 // Scope : private
3001 // Creator : Gary Hennigan
3002 // Creation Date : 10/25/2012
3003 //-----------------------------------------------------------------------------
3005 {
3006  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
3007  {
3008 
3009  Model& m = (*it)->getModel();
3010 
3011  // If tolerances for the line interpolation aren't given set them to
3012  // the same as the tolerances for the device options
3013  if (m.stLineReltol == 0.0)
3015  if (m.stLineAbstol == 0.0)
3017 
3018  // Initialize which case this is based on the nonzero user-specified
3019  // parameters.
3020  if ((m.resist == 0) && (m.conduct == 0) && (m.capac != 0) && (m.induct != 0))
3022 
3023  else if ((m.resist != 0) && (m.conduct == 0) && (m.capac != 0) && (m.induct != 0))
3025 
3026  else if ((m.resist != 0) && (m.conduct == 0) && (m.capac != 0) && (m.induct == 0))
3028 
3029  else if ((m.resist != 0) && (m.conduct == 0) && (m.capac == 0) && (m.induct != 0))
3031 
3032  else if ((m.resist != 0) && (m.conduct != 0) && (m.capac == 0) && (m.induct == 0))
3034 
3035  else if ((m.conduct != 0) && ((m.capac != 0) || (m.induct != 0)))
3036  {
3037  UserError0(m) << "RL line not supported. "
3038  << "Modes supported: RC, RG, LC, RLC";
3039 
3041  }
3042  else if ((m.resist != 0) && (m.conduct == 0) && (m.capac == 0) && (m.induct != 0))
3043  {
3044  UserError0(m) << "Nonzero G (except RG) transmission line not supported. "
3045  << "Modes supported: RC, RG, LC, RLC";
3046 
3048  }
3049 
3050  if ((m.resist == 0.0 ? 0 : 1) + (m.conduct == 0.0 ? 0 : 1) +
3051  (m.induct == 0.0 ? 0 : 1) + (m.capac == 0.0 ? 0 : 1) <= 1)
3052  {
3053  UserError0(m) << "Invalid specification. Specify at least "
3054  << "two of R, L, G, or C with nonzero values. "
3055  << "Modes supported: RC, RG, LC, RLC";
3056 
3058  }
3059 
3060  // Override the interpolation, either default or user specified, if
3061  // the TRYTOCOMPACT option is specified.
3062  if (getDeviceOptions().tryToCompact) {
3064  }
3065 
3066  if (m.stepLimit && m.noStepLimit)
3067  {
3068  UserWarning(*this) << "Conflicting options STEPLIMIT and NOSTEPLIMIT given. Using STEPLIMIT";
3070  }
3071  else if (m.stepLimit || !m.noStepLimit)
3072  {
3074  }
3075  else if (m.noStepLimit || !m.stepLimit)
3076  {
3078  }
3079  else
3080  { // default
3082  }
3083 
3084  // Calculate some derived parameters
3085  switch (m.specialCase)
3086  {
3087 
3088  case LTRA_MOD_LC:
3089  m.imped = sqrt(m.induct / m.capac);
3090  m.admit = 1.0 / m.imped;
3091  m.td = sqrt(m.induct*m.capac) * m.length;
3092  m.attenuation = 1.0;
3093  break;
3094 
3095  case LTRA_MOD_RLC:
3096  m.imped = sqrt(m.induct / m.capac);
3097  m.admit = 1.0 / m.imped;
3098  m.td = sqrt(m.induct * m.capac) * m.length;
3099  m.alpha = 0.5 * (m.resist / m.induct);
3100  m.beta = m.alpha;
3101  m.attenuation = exp(-m.beta * m.td);
3102 
3103  if (m.alpha > 0.0)
3104  {
3105  m.intH1dash = -1.0;
3106  m.intH2 = 1.0 - m.attenuation;
3107  m.intH3dash = -m.attenuation;
3108  }
3109  else
3110  {
3111  m.intH1dash = m.intH2 = m.intH3dash = 0.0;
3112  }
3113 
3114  // Sanity check
3115  if (m.alpha < 0.0) {
3116  UserError(m) << "Resistance and inductance must be greater than zero";
3117  return;
3118  }
3119 
3120  // Calculate the time step size limit in order to keep
3121  // impulse-response errors low
3122  if (!m.truncDontCut) {
3123  double xbig, xsmall, xmid, y1big, y1small, y1mid;
3124  double y2big, y2small, y2mid;
3125  int done = 0, maxiter = 50, iters = 0;
3126 
3127  xbig = 10.0 * m.td;
3128  xsmall = m.td;
3129  xmid = 0.5 * (xbig + xsmall);
3130  y1small = m.rlcH2Func_(xsmall, m.td, m.alpha, m.beta);
3131  y2small = m.rlcH3dashFunc_(xsmall, m.td, m.beta, m.beta);
3132  iters = 0;
3133  for (;;) {
3134 
3135  iters++;
3136  y1big = m.rlcH2Func_(xbig, m.td, m.alpha, m.beta);
3137  y1mid = m.rlcH2Func_(xmid, m.td, m.alpha, m.beta);
3138  y2big = m.rlcH3dashFunc_(xbig, m.td, m.beta, m.beta);
3139  y2mid = m.rlcH3dashFunc_(xmid, m.td, m.beta, m.beta);
3140  done = m.straightLineCheck_(xbig, y1big, xmid, y1mid, xsmall,
3141  y1small, m.stLineReltol,
3142  m.stLineAbstol) +
3143  m.straightLineCheck_(xbig, y1big, xmid, y1mid, xsmall,
3144  y1small, m.stLineReltol,
3145  m.stLineAbstol);
3146  if ((done == 2) || (iters > maxiter))
3147  break; // out of "for (;;)"
3148  xbig = xmid;
3149  xmid = 0.5 * (xbig + xsmall);
3150  }
3151  m.maxSafeStep = xbig - m.td;
3152  }
3153  break;
3154 
3155  case LTRA_MOD_RC:
3156  m.cByR = m.capac / m.resist;
3157  m.rclsqr = m.resist * m.capac * m.length * m.length;
3158  m.intH1dash = 0.0;
3159  m.intH2 = 1.0;
3160  m.intH3dash = 0.0;
3161  break;
3162 
3163  case LTRA_MOD_RG:
3164  break;
3165 
3166  default:
3167  {
3168  Report::DevelFatal().in("Master::initialize_vars_(void)") << "Unhandled LTRA special case encountered.";
3169  return;
3170  }
3171  }
3172  }
3173 
3174  return;
3175 }
3176 
3177 //-----------------------------------------------------------------------------
3178 // Function : Master::loadDAEVectors
3179 // Purpose :
3180 // Special Notes :
3181 // Scope : public
3182 // Creator : Eric Keiter, SNL
3183 // Creation Date : 06/16/10
3184 //-----------------------------------------------------------------------------
3185 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ)
3186 {
3187  double max(0.0),min(0.0);
3188  double v1d(0.0), v2d(0.0), i1d(0.0), i2d(0.0);
3189  double dummy1(0.0), dummy2(0.0);
3190  std::ostringstream msg;
3191 
3192  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
3193  {
3194  Instance& di = *(*it);
3195 
3197  {
3198  switch (di.getModel().specialCase)
3199  {
3200  case LTRA_MOD_RG:
3201  dummy1 = di.getModel().length * std::sqrt(di.getModel().resist *
3202  di.getModel().conduct);
3203  dummy2 = exp(-dummy1);
3204  dummy1 = exp(dummy1); // May overflow
3205  di.getModel().coshlrootGR = 0.5 * (dummy1 + dummy2);
3206 
3207  if (di.getModel().conduct <= 1.0e-10)
3208  { // Spice3 hack!
3209  di.getModel().rRsLrGRorG = di.getModel().length *
3210  di.getModel().resist;
3211  }
3212  else
3213  {
3214  di.getModel().rRsLrGRorG =
3215  0.5 * (dummy1 - dummy2) * sqrt(di.getModel().resist /
3216  di.getModel().conduct);
3217  }
3218 
3219  if (di.getModel().resist <= 1.0e-10)
3220  { // Spice3 hack!
3221  di.getModel().rGsLrGRorR = di.getModel().length *
3222  di.getModel().conduct;
3223  }
3224  else
3225  {
3226  di.getModel().rGsLrGRorR =
3227  0.5 * (dummy1 - dummy2) * sqrt(di.getModel().conduct /
3228  di.getModel().resist);
3229  }
3230 
3231  fVec[di.li_Ibr1] += (di.vpos1 -
3232  di.vneg1 -
3233  di.getModel().coshlrootGR * di.vpos2 +
3234  di.getModel().coshlrootGR * di.vneg2 +
3235  (1.0 + getDeviceOptions().gmin) * di.getModel().rRsLrGRorG * di.currp2);
3236 
3237  fVec[di.li_Ibr2] += (di.getModel().coshlrootGR * di.currp2 -
3238  (1.0 + getDeviceOptions().gmin) * di.getModel().rGsLrGRorR * di.vpos2 +
3239  (1.0 + getDeviceOptions().gmin) * di.getModel().rGsLrGRorR * di.vneg2 +
3240  di.currp1);
3241 
3242  break;
3243 
3244  // load a simple resistor (DC case, C=open, L=short). In the
3245  // lossless case (R=0.0) the port voltages are equal.
3246  case LTRA_MOD_LC:
3247  case LTRA_MOD_RC:
3248  case LTRA_MOD_RLC:
3249 
3250  // i_1 + i_2 = 0
3251  fVec[di.li_Ibr1] += (di.currp1 + di.currp2);
3252 
3253  // v_(n1+) - v_(n2+) - R_ltra * i_1 = 0
3254  fVec[di.li_Ibr2] += (di.vpos1 - di.vpos2 -
3255  di.currp1 *
3256  di.getModel().resist *
3257  di.getModel().length);
3258 
3259  break;
3260 
3261  default:
3262  UserError(di) << "Unknown LTRA configuration, " << di.getModel().specialCase << ". Must be one of RG, LC, RC, or RLC.";
3263  return false;
3264  }
3265 
3266  // These are common for all DC cases. They are just the residuals
3267  // that enforce that the current out of the positive terminal of
3268  // the TL is equal to the current in to the negative terminal at
3269  // the same end of the TL.
3270  fVec[di.li_Pos1] += di.currp1; // i_(n1+) = i_1
3271  fVec[di.li_Neg1] += -di.currp1; // i_(n1-) = -i_1
3272 
3273  fVec[di.li_Pos2] += di.currp2; // i_(n2+) = i_2
3274  fVec[di.li_Neg2] += -di.currp2; // i_(n2-) = -i_2
3275 
3276  }
3277  else
3278  {
3279  // all cases other than DC or the RG case
3280 
3281  int isaved = 0;
3282  double qf1, qf2, qf3;
3283  double lf2, lf3;
3284 
3285  qf1 = qf2 = qf3 = 0.0;
3286  lf2 = lf3 = 0.0;
3287 
3288  di.getModel().modelCalculations_(isaved, qf1, qf2, qf3, lf2, lf3);
3289 
3290  di.input1 = di.input2 = 0.0;
3291 
3292  switch (di.getModel().specialCase)
3293  {
3294  case LTRA_MOD_LC:
3295  case LTRA_MOD_RLC:
3296 
3297  if (di.getModel().tdover)
3298  {
3299  // have to interpolate values
3300  if ((isaved != 0) &&
3302  {
3303  v1d = di.v1[isaved-1] * qf1
3304  + di.v1[isaved] * qf2
3305  + di.v1[isaved+1] * qf3;
3306 
3307  max = Xycemax(di.v1[isaved-1], di.v1[isaved]);
3308  max = Xycemax(max,di.v1[isaved+1]);
3309  min = Xycemin(di.v1[isaved-1], di.v1[isaved]);
3310  min = Xycemin(min,di.v1[isaved+1]);
3311  }
3312 
3313  if ((di.getModel().howToInterp == LTRA_MOD_LININTERP) || (isaved == 0) ||
3314  ((isaved != 0) && ((di.getModel().howToInterp == LTRA_MOD_QUADINTERP) ||
3315  (di.getModel().howToInterp == LTRA_MOD_MIXEDINTERP)) && ((v1d > max) || (v1d < min))))
3316  {
3317  if ((isaved != 0) && (di.getModel().howToInterp == LTRA_MOD_QUADINTERP))
3318  {
3319 #ifdef Xyce_DEBUG_DEVICE
3320  Xyce::dout() << "[LTRA-DBG-DEV] load: warning: interpolated v1 is out of range after timepoint "
3321  << getSolverState().ltraTimeIndex << std::endl;
3322  Xyce::dout() << " values: "
3323  << di.v1[isaved-1] << " "
3324  << di.v1[isaved] << " "
3325  << di.v1[isaved+1] << "; interpolated: "
3326  << v1d << std::endl;
3327  Xyce::dout() << " timepoints are: "
3328  << getSolverState().currTime - di.getModel().td << std::endl;
3329 #endif
3330  }
3331  else
3332  {
3333  v1d = di.v1[isaved] * lf2 + di.v1[isaved+1] * lf3;
3334  }
3335  }
3336 
3337  if ((isaved != 0) &&
3340  {
3341  i1d = di.i1[isaved-1] * qf1
3342  + di.i1[isaved] * qf2
3343  + di.i1[isaved+1] * qf3;
3344 
3345  max = Xycemax(di.i1[isaved-1], di.i1[isaved]);
3346  max = Xycemax(max,di.i1[isaved+1]);
3347  min = Xycemin(di.i1[isaved-1], di.i1[isaved]);
3348  min = Xycemin(min,di.i1[isaved+1]);
3349  }
3350 
3351  if ((di.getModel().howToInterp == LTRA_MOD_LININTERP) || (isaved == 0) ||
3352  ((isaved != 0) && ((di.getModel().howToInterp == LTRA_MOD_QUADINTERP) ||
3354  ((i1d > max) || (i1d < min))))
3355  {
3356 
3357  if ((isaved != 0) && (di.getModel().howToInterp == LTRA_MOD_QUADINTERP))
3358  {
3359 #ifdef Xyce_DEBUG_DEVICE
3360  Xyce::dout() << "[LTRA-DBG-DEV] load: warning: interpolated i1 is out of range after timepoint "
3361  << getSolverState().ltraTimeIndex << std::endl;
3362  Xyce::dout() << " values: "
3363  << di.i1[isaved-1] << " "
3364  << di.i1[isaved] << " "
3365  << di.i1[isaved+1] << "; interpolated: "
3366  << i1d << std::endl;
3367  Xyce::dout() << " timepoints are: "
3368  << getSolverState().currTime - di.getModel().td << std::endl;
3369 #endif
3370  }
3371  else
3372  {
3373  i1d = di.i1[isaved] * lf2 + di.i1[isaved+1] * lf3;
3374  }
3375  }
3376 
3377  if ((isaved != 0) &&
3380  {
3381  v2d = di.v2[isaved-1] * qf1
3382  + di.v2[isaved] * qf2
3383  + di.v2[isaved+1] * qf3;
3384 
3385  max = Xycemax(di.v2[isaved-1], di.v2[isaved]);
3386  max = Xycemax(max,di.v2[isaved+1]);
3387  min = Xycemin(di.v2[isaved-1], di.v2[isaved]);
3388  min = Xycemin(min,di.v2[isaved+1]);
3389  }
3390 
3391  if ((di.getModel().howToInterp ==
3392  LTRA_MOD_LININTERP) || (isaved == 0) ||
3393  ((isaved != 0) &&
3396  ((v2d > max) || (v2d < min))))
3397  {
3398 
3399  if ((isaved != 0) &&
3401  {
3402 #ifdef Xyce_DEBUG_DEVICE
3403  Xyce::dout() << "[LTRA-DBG-DEV] load: warning: interpolated v2 is out of range after timepoint "
3404  << getSolverState().ltraTimeIndex << std::endl;
3405  Xyce::dout() << " values: "
3406  << di.v2[isaved-1] << " "
3407  << di.v2[isaved] << " "
3408  << di.v2[isaved+1] << "; interpolated: "
3409  << v2d << std::endl;
3410  Xyce::dout() << " timepoints are: "
3411  << getSolverState().currTime - di.getModel().td << std::endl;
3412 #endif
3413  }
3414  else
3415  {
3416  v2d = di.v2[isaved] * lf2
3417  + di.v2[isaved+1] *
3418  lf3;
3419  }
3420  }
3421 
3422  if ((isaved != 0) &&
3425  {
3426  i2d = di.i2[isaved-1] * qf1
3427  + di.i2[isaved] * qf2
3428  + di.i2[isaved+1] * qf3;
3429 
3430  max = Xycemax(di.i2[isaved-1], di.i2[isaved]);
3431  max = Xycemax(max,di.i2[isaved+1]); min = Xycemin(di.i2[isaved-1], di.i2[isaved]);
3432  min = Xycemin(min,di.i2[isaved+1]);
3433  }
3434 
3435  if ((di.getModel().howToInterp == LTRA_MOD_LININTERP) || (isaved == 0) ||
3436  ((isaved != 0) && ((di.getModel().howToInterp == LTRA_MOD_QUADINTERP) ||
3438  ((i2d > max) || (i2d < min))))
3439  {
3440  if ((isaved != 0) && (di.getModel().howToInterp == LTRA_MOD_QUADINTERP))
3441  {
3442 #ifdef Xyce_DEBUG_DEVICE
3443  Xyce::dout() << "[LTRA-DBG-DEV] load: warning: interpolated i2 is out of range after timepoint "
3444  << getSolverState().ltraTimeIndex << std::endl;
3445  Xyce::dout() << " values: "
3446  << di.i2[isaved-1] << " "
3447  << di.i2[isaved] << " "
3448  << di.i2[isaved+1] << "; interpolated: "
3449  << i2d << std::endl;
3450  Xyce::dout() << " timepoints are: "
3451  << getSolverState().currTime - di.getModel().td << std::endl;
3452 #endif
3453  }
3454  else
3455  {
3456  i2d = di.i2[isaved] * lf2 + di.i2[isaved+1] * lf3;
3457  }
3458  }
3459  }
3460 
3461  // interpolation done
3462  break;
3463 
3464  case LTRA_MOD_RC:
3465  break;
3466 
3467  default:
3468  return false;
3469  // return(E_BADPARM);
3470  }
3471 
3472  switch (di.getModel().specialCase)
3473  {
3474  case LTRA_MOD_RLC:
3475 
3476  // begin convolution parts
3477 
3478  // convolution of h1dash with v1 and v2
3479  // the matrix has already been loaded above
3480 
3481  dummy1 = dummy2 = 0.0;
3482  for (int j = getSolverState().ltraTimeIndex; j > 0; j--)
3483  {
3484  if (di.getModel().h1dashCoeffs[j] != 0.0)
3485  {
3486  dummy1 += di.getModel().h1dashCoeffs[j] * (di.v1[j] - di.initVolt1);
3487  dummy2 += di.getModel().h1dashCoeffs[j] * (di.v2[j] - di.initVolt2);
3488  }
3489  }
3490 
3491  dummy1 += di.initVolt1 * di.getModel().intH1dash;
3492  dummy2 += di.initVolt2 * di.getModel().intH1dash;
3493 
3494  dummy1 -= di.initVolt1 * di.getModel().h1dashFirstCoeff;
3495  dummy2 -= di.initVolt2 * di.getModel().h1dashFirstCoeff;
3496 
3497  di.input1 -= dummy1 * di.getModel().admit;
3498  di.input2 -= dummy2 * di.getModel().admit;
3499 
3500  // end convolution of h1dash with v1 and v2
3501 
3502  // convolution of h2 with i2 and i1
3503 
3504  dummy1 = dummy2 = 0.0;
3505  if (di.getModel().tdover)
3506  {
3507  // the term for ckt->CKTtime - di.getModel().td
3508  dummy1 = (i2d - di.initCur2)* di.getModel().h2FirstCoeff;
3509  dummy2 = (i1d - di.initCur1)* di.getModel().h2FirstCoeff;
3510 
3511  // the rest of the convolution
3512 
3513  for (int j= di.getModel().auxIndex; j > 0; j--)
3514  {
3515 
3516  if (di.getModel().h2Coeffs[j] != 0.0)
3517  {
3518  dummy1 += di.getModel().h2Coeffs[j] * (di.i2[j] - di.initCur2);
3519  dummy2 += di.getModel().h2Coeffs[j] * (di.i1[j] - di.initCur1);
3520  }
3521  }
3522  }
3523 
3524  // the initial-condition terms
3525 
3526  dummy1 += di.initCur2 * di.getModel().intH2;
3527  dummy2 += di.initCur1 * di.getModel().intH2;
3528 
3529  di.input1 += dummy1;
3530  di.input2 += dummy2;
3531 
3532  // end convolution of h2 with i2 and i1
3533  // convolution of h3dash with v2 and v1
3534  // the term for ckt->CKTtime - di.getModel().td
3535 
3536  dummy1 = dummy2 = 0.0;
3537  if (di.getModel().tdover)
3538  {
3539  dummy1 = (v2d - di.initVolt2)* di.getModel().h3dashFirstCoeff;
3540  dummy2 = (v1d - di.initVolt1)* di.getModel().h3dashFirstCoeff;
3541 
3542  // the rest of the convolution
3543 
3544  for (int j= di.getModel().auxIndex; j > 0; j--)
3545  {
3546  if (di.getModel().h3dashCoeffs[j] != 0.0)
3547  {
3548  dummy1 += di.getModel().h3dashCoeffs[j] * (di.v2[j] - di.initVolt2);
3549  dummy2 += di.getModel().h3dashCoeffs[j] * (di.v1[j] - di.initVolt1);
3550  }
3551  }
3552  }
3553 
3554  // the initial-condition terms
3555 
3556  dummy1 += di.initVolt2 * di.getModel().intH3dash;
3557  dummy2 += di.initVolt1 * di.getModel().intH3dash;
3558 
3559  di.input1 += di.getModel().admit*dummy1;
3560  di.input2 += di.getModel().admit*dummy2;
3561 
3562  // end convolution of h3dash with v2 and v1
3563 
3564  // NOTE: this switch passes through to following case
3565 
3566  case LTRA_MOD_LC:
3567  // begin lossless-like parts
3568 
3569  if (!di.getModel().tdover)
3570  {
3571  di.input1 += di.getModel().attenuation * (di.initVolt2*di.getModel().admit + di.initCur2);
3572  di.input2 += di.getModel().attenuation * (di.initVolt1*di.getModel().admit + di.initCur1);
3573  }
3574  else
3575  {
3576  di.input1 += di.getModel().attenuation * (v2d*di.getModel().admit + i2d);
3577  di.input2 += di.getModel().attenuation * (v1d*di.getModel().admit + i1d);
3578  }
3579 
3580  // Residuals for the internal equations. These are for both
3581  // the RLC and LC case.
3582  fVec[di.li_Ibr1] += ((di.getModel().admit * (di.getModel().h1dashFirstCoeff + 1.0)) *
3583  (di.vpos1-di.vneg1) - di.currp1) - di.input1;
3584 
3585  fVec[di.li_Ibr2] += ((di.getModel().admit * (di.getModel().h1dashFirstCoeff + 1.0)) *
3586  (di.vpos2-di.vneg2) - di.currp2) - di.input2;
3587 
3588  // end lossless-like parts
3589  break;
3590 
3591  case LTRA_MOD_RC:
3592 
3593  // begin convolution parts
3594 
3595  // convolution of h1dash with v1 and v2
3596  // the matrix has already been loaded above
3597 
3598  dummy1 = 0.0;
3599  dummy2 = 0.0;
3600  for (int j = getSolverState().ltraTimeIndex; j > 0; j--)
3601  {
3602  if (di.getModel().h1dashCoeffs[j]!= 0.0)
3603  {
3604  dummy1 += di.getModel().h1dashCoeffs[j] * (di.v1[j] - di.initVolt1);
3605  dummy2 += di.getModel().h1dashCoeffs[j] * (di.v2[j] - di.initVolt2);
3606  }
3607  }
3608 
3609  // the initial condition terms
3610 
3611  dummy1 += di.initVolt1 * di.getModel().intH1dash; dummy2 += di.initVolt2 * di.getModel().intH1dash;
3612 
3613  // the constant contributed by the init
3614  // condition and the latest timepoint
3615 
3616  dummy1 -= di.initVolt1* di.getModel().h1dashFirstCoeff;
3617  dummy2 -= di.initVolt2* di.getModel().h1dashFirstCoeff;
3618 
3619  di.input1 -= dummy1;
3620  di.input2 -= dummy2;
3621 
3622  // end convolution of h1dash with v1 and v2
3623  // convolution of h2 with i2 and i1
3624 
3625  dummy1=dummy2=0.0;
3626 
3627  for (int j = getSolverState().ltraTimeIndex; j > 0; j--)
3628  {
3629  if (di.getModel().h2Coeffs[j] != 0.0)
3630  {
3631  dummy1 += di.getModel().h2Coeffs[j] * (di.i2[j] - di.initCur2);
3632  dummy2 += di.getModel().h2Coeffs[j] * (di.i1[j] - di.initCur1);
3633  }
3634  }
3635 
3636  // the initial-condition terms
3637  dummy1 += di.initCur2 * di.getModel().intH2;
3638  dummy2 += di.initCur1 * di.getModel().intH2;
3639 
3640  dummy1 -= di.initCur2* di.getModel().h2FirstCoeff;
3641  dummy2 -= di.initCur1* di.getModel().h2FirstCoeff;
3642 
3643  di.input1 += dummy1;
3644  di.input2 += dummy2;
3645 
3646  // end convolution of h2 with i2 and i1
3647  // convolution of h3dash with v2 and v1
3648 
3649  dummy1 = dummy2 = 0.0;
3650 
3651  for (int j=getSolverState().ltraTimeIndex; j > 0; j--)
3652  {
3653  if (di.getModel().h3dashCoeffs[j] != 0.0)
3654  {
3655  dummy1 += di.getModel().h3dashCoeffs[j] * (di.v2[j] - di.initVolt2);
3656  dummy2 += di.getModel().h3dashCoeffs[j] * (di.v1[j] - di.initVolt1);
3657  }
3658  }
3659 
3660  // the initial-condition terms
3661 
3662  dummy1 += di.initVolt2 * di.getModel().intH3dash;
3663  dummy2 += di.initVolt1 * di.getModel().intH3dash;
3664 
3665  dummy1 -= di.initVolt2* di.getModel().h3dashFirstCoeff;
3666  dummy2 -= di.initVolt1* di.getModel().h3dashFirstCoeff;
3667 
3668  di.input1 += dummy1;
3669  di.input2 += dummy2;
3670 
3671  // Residuales for the internal equations.
3672  fVec[di.li_Ibr1] += ((di.getModel().h1dashFirstCoeff * (di.vpos1-di.vneg1) -
3673  di.getModel().h3dashFirstCoeff * (di.vpos2-di.vneg2) -
3674  di.getModel().h2FirstCoeff * di.currp2 -
3675  di.currp1) -
3676  di.input1);
3677 
3678  fVec[di.li_Ibr2] += ((di.getModel().h1dashFirstCoeff * (di.vpos2-di.vneg2) -
3679  di.getModel().h3dashFirstCoeff * (di.vpos1-di.vneg1) -
3680  di.getModel().h2FirstCoeff * di.currp1 -
3681  di.currp2) -
3682  di.input2);
3683 
3684  // end convolution of h3dash with v2 and v1
3685 
3686  break;
3687 
3688  default:
3689  return false;
3690  //return(E_BADPARM);
3691  }
3692 
3693  // Residuals (KCL) for "normal" nodes and common between all cases
3694  fVec[di.li_Pos1] += di.currp1;
3695  fVec[di.li_Neg1] -= di.currp1;
3696 
3697  fVec[di.li_Pos2] += di.currp2;
3698  fVec[di.li_Neg2] -= di.currp2;
3699 
3700  }
3701  }
3702 
3703  return true;
3704 }
3705 
3706 //-----------------------------------------------------------------------------
3707 // Function : Master::loadDAEMatrices
3708 // Purpose :
3709 // Special Notes :
3710 // Scope : public
3711 // Creator : Eric Keiter, SNL
3712 // Creation Date : 06/16/10
3713 //-----------------------------------------------------------------------------
3714 bool Master::loadDAEMatrices (N_LAS_Matrix& dFdx, N_LAS_Matrix& dQdx)
3715 {
3716  double dummy1(0.0), dummy2(0.0);
3717  std::ostringstream msg;
3718 
3719  // this is commented out for now because the loop contains return statements which
3720  // break the OMP threading on the loop -- RLS 8/20/2010
3721  // #ifdef _OMP
3722  // #pragma omp parallel for
3723  // #endif
3724  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
3725  {
3726  Instance& di = *(*it);
3727 
3729  {
3730  switch (di.getModel().specialCase)
3731  {
3732  case LTRA_MOD_RG:
3733  *(di.ibr1Pos1Ptr) += 1.0;
3734  *(di.ibr1Neg1Ptr) += -1.0;
3735  *(di.ibr1Pos2Ptr) += -di.getModel().coshlrootGR;
3736  *(di.ibr1Neg2Ptr) += di.getModel().coshlrootGR;
3737  *(di.ibr1Ibr2Ptr) += (1.0 + getDeviceOptions().gmin) * di.getModel().rRsLrGRorG;
3738 
3739  *(di.ibr2Ibr2Ptr) += di.getModel().coshlrootGR;
3740  *(di.ibr2Pos2Ptr) += -(1.0 + getDeviceOptions().gmin) * di.getModel().rGsLrGRorR;
3741  *(di.ibr2Neg2Ptr) += (1.0 + getDeviceOptions().gmin) * di.getModel().rGsLrGRorR;
3742  *(di.ibr2Ibr1Ptr) += 1.0;
3743 
3744  *(di.pos1Ibr1Ptr) += 1.0;
3745  *(di.neg1Ibr1Ptr) += -1.0;
3746  *(di.pos2Ibr2Ptr) += 1.0;
3747  *(di.neg2Ibr2Ptr) += -1.0;
3748 
3749  break;
3750 
3751  case LTRA_MOD_LC:
3752  case LTRA_MOD_RLC:
3753  case LTRA_MOD_RC: // load a simple resistor
3754 
3755  *(di.pos1Ibr1Ptr) += 1.0;
3756  *(di.neg1Ibr1Ptr) += -1.0;
3757 
3758  *(di.pos2Ibr2Ptr) += 1.0;
3759  *(di.neg2Ibr2Ptr) += -1.0;
3760 
3761  *(di.ibr1Ibr1Ptr) += 1.0;
3762  *(di.ibr1Ibr2Ptr) += 1.0;
3763 
3764  *(di.ibr2Pos1Ptr) += 1.0;
3765  *(di.ibr2Pos2Ptr) += -1.0;
3766  *(di.ibr2Ibr1Ptr) += -di.getModel().resist*di.getModel().length;
3767 
3768  break;
3769 
3770  default:
3771  UserError(di) << "Unknown LTRA configuration, " << di.getModel().specialCase << ". Must be one of RG, LC, RC, or RLC.";
3772 
3773  return false;
3774  }
3775 
3776  }
3777  else
3778  {
3779  // all cases other than DC or the RG case
3780 
3781  // matrix loading - done every time load is called
3782  switch (di.getModel().specialCase)
3783  {
3784  case LTRA_MOD_RLC:
3785  // loading for convolution parts' first terms
3786 
3787  dummy1 = di.getModel().admit * di.getModel().h1dashFirstCoeff;
3788 
3789  *(di.ibr1Pos1Ptr) += dummy1;
3790  *(di.ibr1Neg1Ptr) -= dummy1;
3791 
3792  *(di.ibr2Pos2Ptr) += dummy1;
3793  *(di.ibr2Neg2Ptr) -= dummy1;
3794  // end loading for convolution parts' first terms
3795 
3796  // NOTE: This case intentionally falls through to the next case
3797 
3798  case LTRA_MOD_LC:
3799  // this section loads for the parts of the equations that
3800  // resemble the lossless equations
3801 
3802  *(di.ibr1Pos1Ptr) += di.getModel().admit;
3803  *(di.ibr1Neg1Ptr) -= di.getModel().admit;
3804 
3805  *(di.ibr1Ibr1Ptr) -= 1.0;
3806 
3807  *(di.pos1Ibr1Ptr) += 1.0;
3808  *(di.neg1Ibr1Ptr) -= 1.0;
3809 
3810  *(di.ibr2Pos2Ptr) += di.getModel().admit;
3811  *(di.ibr2Neg2Ptr) -= di.getModel().admit;
3812 
3813  *(di.ibr2Ibr2Ptr) -= 1.0;
3814 
3815  *(di.pos2Ibr2Ptr) += 1.0;
3816  *(di.neg2Ibr2Ptr) -= 1.0;
3817 
3818  // loading for lossless-like parts over
3819  break;
3820 
3821  case LTRA_MOD_RC:
3822 
3823  // this section loads for the parts of the equations that
3824  // have no convolution
3825 
3826  *(di.ibr1Ibr1Ptr) -= 1.0;
3827 
3828  *(di.pos1Ibr1Ptr) += 1.0;
3829  *(di.neg1Ibr1Ptr) -= 1.0;
3830 
3831  *(di.ibr2Ibr2Ptr) -= 1.0;
3832 
3833  *(di.pos2Ibr2Ptr) += 1.0;
3834  *(di.neg2Ibr2Ptr) -= 1.0;
3835 
3836  // loading for non-convolution parts over
3837  // loading for convolution parts' first terms
3838 
3839  dummy1 = di.getModel().h1dashFirstCoeff;
3840 
3841  *(di.ibr1Pos1Ptr) += dummy1;
3842  *(di.ibr1Neg1Ptr) -= dummy1;
3843 
3844  *(di.ibr2Pos2Ptr) += dummy1;
3845  *(di.ibr2Neg2Ptr) -= dummy1;
3846 
3847  dummy1 = di.getModel().h2FirstCoeff;
3848 
3849  *(di.ibr1Ibr2Ptr) -= dummy1;
3850  *(di.ibr2Ibr1Ptr) -= dummy1;
3851 
3852  dummy1 = di.getModel().h3dashFirstCoeff;
3853 
3854  *(di.ibr1Pos2Ptr) -= dummy1;
3855  *(di.ibr1Neg2Ptr) += dummy1;
3856 
3857  *(di.ibr2Pos1Ptr) -= dummy1;
3858  *(di.ibr2Neg1Ptr) += dummy1;
3859 
3860  // end loading for convolution parts' first terms
3861 
3862  break;
3863 
3864  default:
3865  return false;
3866  }
3867  }
3868  }
3869 
3870  return true;
3871 }
3872 
3873 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
3874 {
3875 
3876  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
3877 }
3878 
3880 {
3882  .registerDevice("o", 1)
3883  .registerModelType("ltra", 1);
3884 }
3885 
3886 } // namespace LTRA
3887 } // namespace Device
3888 } // namespace Xyce