Jspice3
ltratrun.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3f2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1990 Jaijeet S. Roychowdhury
5  1993 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 #include "spice.h"
9 #include <stdio.h>
10 #include <math.h>
11 #include "ltradefs.h"
12 #include "sperror.h"
13 #include "util.h"
14 
15 
16 int
17 LTRAtrunc(inModel,ckt,timeStep)
18 
19 GENmodel *inModel;
20 CKTcircuit *ckt;
21 double *timeStep;
22 {
23  LTRAmodel* model = (LTRAmodel *)inModel;
24  LTRAinstance *here;
25  double i1,i2,i3;
26  double d1,d2;
27  double tmp;
28  double tolerance;
29  double current_lte;
30  double x, y, change, deriv, deriv_delta;
31  double A1, A2, A3;
32  double time_step;
33  int i;
34  int maxiter = 2, iterations = 0;
35 
36  /* in jspice3, the timeStep passed to the trunc functions is
37  * not normalized to integration order, which saves having to
38  * call an expensive math operation at each CKTterr() call.
39  * We have to undo this here.
40  */
41  if (ckt->CKTorder == 1)
42  time_step = *timeStep;
43  else if (ckt->CKTorder == 2)
44  time_step = sqrt(*timeStep);
45  else
46  time_step = exp(log(*timeStep)/ckt->CKTorder);
47 
48 
49  /* loop through all the transmission line models */
50  for ( ; model != NULL; model = model->LTRAnextModel) {
51 
52  /* loop through all the instances of the model */
53  for (here = model->LTRAinstances; here != NULL;
54  here = here->LTRAnextInstance) {
55 
56  switch (model->LTRAspecialCase) {
57 
58  case LTRA_MOD_LC:
59  case LTRA_MOD_RLC:
60 
61  if (model->LTRAstepLimit == LTRA_MOD_STEPLIMIT) {
62  tmp = model->LTRAtd;
63  time_step = MIN(time_step,tmp);
64  }
65  else {
66  i1 = ((*(ckt->CKTrhsOld + here->LTRAposNode2)
67  - *(ckt->CKTrhsOld + here->LTRAnegNode2))*
68  model->LTRAadmit +
69  *(ckt->CKTrhsOld + here->LTRAbrEq2))*
70  model->LTRAattenuation;
71  i2 = (*(here->LTRAv2+ ckt->CKTtimeIndex)*
72  model->LTRAadmit +
73  *(here->LTRAi2 + ckt->CKTtimeIndex))*
74  model->LTRAattenuation;
75  i3 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1)*
76  model->LTRAadmit +
77  *(here->LTRAi2 + ckt->CKTtimeIndex - 1))*
78  model->LTRAattenuation;
79  d1 = (i1-i2)/(ckt->CKTtime - *(ckt->CKTtimePoints +
80  ckt->CKTtimeIndex));
81  d2 = (i2-i3)/(*(ckt->CKTtimePoints + ckt->CKTtimeIndex)
82  - *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1));
83 
84  A1 = d1 - d2;
85  A2 = FABS(d1);
86  A3 = FABS(d2);
87 
88  if (FABS(A1) >= model->LTRAreltol*MAX(A2,A3) +
89  model->LTRAabstol) {
90  /* derivitive changing - need to schedule after delay */
91  /* the PREVIOUS point was the breakpoint*/
92  /* the previous timepoint plus the delay */
93 
94  tmp = model->LTRAtd;
95  time_step = MIN(time_step,tmp);
96  break;
97  }
98 
99  i1 = ((*(ckt->CKTrhsOld + here->LTRAposNode1) -
100  *(ckt->CKTrhsOld + here->LTRAnegNode1))*
101  model->LTRAadmit +
102  *(ckt->CKTrhsOld + here->LTRAbrEq1))*
103  model->LTRAattenuation;
104  i2 = (*(here->LTRAv1+ ckt->CKTtimeIndex)*
105  model->LTRAadmit +
106  *(here->LTRAi1 + ckt->CKTtimeIndex))*
107  model->LTRAattenuation;
108  i3 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1)*
109  model->LTRAadmit +
110  *(here->LTRAi1 + ckt->CKTtimeIndex - 1))*
111  model->LTRAattenuation;
112  d1 = (i1-i2)/(ckt->CKTtime - *(ckt->CKTtimePoints +
113  ckt->CKTtimeIndex));
114  d2 = (i2-i3)/(*(ckt->CKTtimePoints + ckt->CKTtimeIndex)
115  - *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1));
116 
117  A1 = d1 - d2;
118  A2 = FABS(d1);
119  A3 = FABS(d2);
120 
121  if (FABS(A1) >= model->LTRAreltol*MAX(A2,A3) +
122  model->LTRAabstol) {
123  /* derivitive changing - need to schedule after delay */
124  /* the PREVIOUS point was the breakpoint*/
125  /* the previous timepoint plus the delay */
126 
127  tmp = model->LTRAtd;
128  time_step = MIN(time_step,tmp);
129  }
130  }
131  break;
132 
133  case LTRA_MOD_RC:
134  case LTRA_MOD_RG:
135  break;
136 
137  default:
138  return(E_BADPARM);
139  }
140 
141  /*
142  * the above was for the parts of the equations that
143  * resemble the lossless equations. Now we need to
144  * estimate the local truncation error in each of the
145  * three convolution equations, and if possible adjust
146  * the timestep so that all of them remain within some
147  * bound. Unfortunately, the expression for the LTE in a
148  * convolution operation is complicated and costly to
149  * evaluate; in addition, no explicit inverse exists.
150  *
151  * So what we do here (for the moment) is check to see
152  * the current error is acceptable. If so, the timestep
153  * is not changed. If not, then an estimate is made for the
154  * new timestep using a few iterations of the
155  * newton-raphson method.
156  *
157  * modification: we change the timestep to half its
158  * previous value
159  */
160 
161  if ((model->LTRAspecialCase == LTRA_MOD_RLC) &&
162  (!model->LTRAtruncDontCut)) {
163  time_step = MIN(time_step, model->LTRAmaxSafeStep);
164  }
165 
166  if (model->LTRAlteConType != LTRA_MOD_NOCONTROL) {
167  switch(model->LTRAspecialCase) {
168 
169  case LTRA_MOD_RLC:
170  case LTRA_MOD_RC:
171  tolerance = ckt->CKTtrtol*(ckt->CKTreltol*(
172  FABS(here->LTRAinput1) + FABS(here->LTRAinput2))
173  + ckt->CKTabstol);
174 
175  current_lte = LTRAlteCalculate(ckt,(GENmodel *) model,
176  (GENinstance *) here, ckt->CKTtime);
177 
178  if (current_lte >= tolerance) {
179  if (model->LTRAtruncNR) {
180 
181  x = ckt->CKTtime;
182  y = current_lte;
183  for (;;) {
184  deriv_delta =
185  0.01 * (x - *(ckt->CKTtimePoints +
186  ckt->CKTtimeIndex));
187 
188 #ifdef LTRADEBUG
189  if (deriv_delta <= 0.0)
190  fprintf(stdout,
191  "LTRAtrunc: error: timestep is now less than zero\n");
192 #endif
193  deriv = LTRAlteCalculate(ckt,
194  (GENmodel *) model,
195  (GENinstance *) here,
196  x + deriv_delta) - y;
197  deriv /= deriv_delta;
198  change = (tolerance - y)/deriv;
199  x += change;
200  if (maxiter == 0) {
201  if (FABS(change) <= FABS(deriv_delta))
202  break;
203  }
204  else {
205  iterations++;
206  if (iterations >= maxiter) break;
207  }
208  y = LTRAlteCalculate(ckt, (GENmodel *) model,
209  (GENinstance *) here,x);
210  }
211 
212  tmp = x - *(ckt->CKTtimePoints +
213  ckt->CKTtimeIndex);
214  time_step = MIN(time_step,tmp);
215  }
216  else
217  time_step *= 0.5;
218  }
219  break;
220 
221  case LTRA_MOD_RG:
222  case LTRA_MOD_LC:
223  break;
224 
225  default:
226  return(E_BADPARM);
227  }
228  }
229 
230  }
231 #ifdef LTRADEBUG
232  if (time_step >= model->LTRAtd) {
233  fprintf(stdout,
234 "LTRAtrunc: Warning: Timestep bigger than delay of line %s\n",
235 model->LTRAmodName);
236  fflush(stdout);
237  }
238 #endif
239  }
240 
241  /* see note above regarding renormalization */
242  tmp = time_step;
243  for (i = ckt->CKTorder - 1; i > 0; i--)
244  tmp *= time_step;
245  *timeStep = tmp;
246 
247  return (OK);
248 }
double CKTtime
Definition: cktdefs.h:77
double LTRAinput2
Definition: ltradefs.h:32
int LTRAtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep)
Definition: ltratrun.c:17
#define MAX(a, b)
Definition: spdefs.h:135
#define MIN(a, b)
Definition: spdefs.h:136
int LTRAstepLimit
Definition: ltradefs.h:151
#define LTRA_MOD_RG
Definition: ltradefs.h:163
#define E_BADPARM
Definition: iferrmsg.h:26
int LTRAnegNode1
Definition: ltradefs.h:26
unsigned LTRAtruncDontCut
Definition: ltradefs.h:137
struct sLTRAinstance * LTRAnextInstance
Definition: ltradefs.h:21
double CKTreltol
Definition: cktdefs.h:183
double LTRAinput1
Definition: ltradefs.h:31
#define LTRA_MOD_LC
Definition: ltradefs.h:164
int CKTorder
Definition: cktdefs.h:87
double LTRAabstol
Definition: ltradefs.h:155
double CKTabstol
Definition: cktdefs.h:180
#define OK
Definition: iferrmsg.h:17
double * LTRAi2
Definition: ltradefs.h:42
double * CKTrhsOld
Definition: cktdefs.h:98
int CKTtimeIndex
Definition: cktdefs.h:223
double LTRAreltol
Definition: ltradefs.h:156
LTRAinstance * LTRAinstances
Definition: ltradefs.h:84
#define NULL
Definition: spdefs.h:121
double * LTRAv2
Definition: ltradefs.h:41
int LTRAbrEq1
Definition: ltradefs.h:29
int LTRAposNode1
Definition: ltradefs.h:25
IFuid LTRAmodName
Definition: ltradefs.h:86
double * LTRAi1
Definition: ltradefs.h:40
double LTRAmaxSafeStep
Definition: ltradefs.h:140
int LTRAlteConType
Definition: ltradefs.h:147
static char model[32]
Definition: subckt.c:76
double CKTtrtol
Definition: cktdefs.h:192
#define FABS(a)
Definition: util.h:41
int LTRAnegNode2
Definition: ltradefs.h:28
double * CKTtimePoints
Definition: cktdefs.h:218
double LTRAtd
Definition: ltradefs.h:111
double LTRAlteCalculate()
double LTRAadmit
Definition: ltradefs.h:113
#define LTRA_MOD_RLC
Definition: ltradefs.h:161
#define LTRA_MOD_NOCONTROL
Definition: ltradefs.h:192
struct sLTRAmodel * LTRAnextModel
Definition: ltradefs.h:82
int LTRAbrEq2
Definition: ltradefs.h:30
unsigned LTRAtruncNR
Definition: ltradefs.h:135
double LTRAattenuation
Definition: ltradefs.h:116
int LTRAposNode2
Definition: ltradefs.h:27
#define LTRA_MOD_RC
Definition: ltradefs.h:162
double * LTRAv1
Definition: ltradefs.h:39
#define LTRA_MOD_STEPLIMIT
Definition: ltradefs.h:195
int LTRAspecialCase
Definition: ltradefs.h:158