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