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