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