📄 ltratrun.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1990 Jaijeet S. Roychowdhury**********/#include "spice.h"#include <stdio.h>#include "util.h"#include "cktdefs.h"#include "ltradefs.h"#include "sperror.h"#include "util.h"#include "suffix.h"intLTRAtrunc(inModel, ckt, timeStep) GENmodel *inModel; register CKTcircuit *ckt; double *timeStep;{ register LTRAmodel *model = (LTRAmodel *) inModel; register LTRAinstance *here; double i1, i2, i3, i4; double i5, i6, d1, d2, d3, d4; int i; double tmp; double tolerance; double current_lte; int maxiter = 2, iterations = 0; double x, y, change, deriv, deriv_delta; /* loop through all the transmission line models */ for (; model != NULL; model = model->LTRAnextModel) { /* loop through all the instances of the model */ for (here = model->LTRAinstances; here != NULL; here = here->LTRAnextInstance) { if (here->LTRAowner != ARCHme) continue; switch (model->LTRAspecialCase) { case LTRA_MOD_LC: case LTRA_MOD_RLC: if (model->LTRAstepLimit == LTRA_MOD_STEPLIMIT) { tmp = model->LTRAtd; *timeStep = MIN(*timeStep, tmp); } else { i1 = ((*(ckt->CKTrhsOld + here->LTRAposNode2) - *(ckt->CKTrhsOld + here->LTRAnegNode2)) * model->LTRAadmit + *(ckt->CKTrhsOld + here->LTRAbrEq2)) * model->LTRAattenuation; i2 = (*(here->LTRAv2 + ckt->CKTtimeIndex) * model->LTRAadmit + *(here->LTRAi2 + ckt->CKTtimeIndex)) * model->LTRAattenuation; i3 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) * model->LTRAadmit + *(here->LTRAi2 + ckt->CKTtimeIndex - 1)) * model->LTRAattenuation; i4 = ((*(ckt->CKTrhsOld + here->LTRAposNode1) - *(ckt->CKTrhsOld + here->LTRAnegNode1)) * model->LTRAadmit + *(ckt->CKTrhsOld + here->LTRAbrEq1)) * model->LTRAattenuation; i5 = (*(here->LTRAv1 + ckt->CKTtimeIndex) * model->LTRAadmit + *(here->LTRAi1 + ckt->CKTtimeIndex)) * model->LTRAattenuation; i6 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) * model->LTRAadmit + *(here->LTRAi1 + ckt->CKTtimeIndex - 1)) * model->LTRAattenuation; /* * d1 = (i1-i2)/ckt->CKTdeltaOld[1]; d2 = * (i2-i3)/ckt->CKTdeltaOld[2]; d3 = (i4-i5)/ckt->CKTdeltaOld[1]; * d4 = (i5-i6)/ckt->CKTdeltaOld[2]; */ d1 = (i1 - i2) / (ckt->CKTtime - *(ckt->CKTtimePoints + ckt->CKTtimeIndex)); d2 = (i2 - i3) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) - *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1)); d3 = (i4 - i5) / (ckt->CKTtime - *(ckt->CKTtimePoints + ckt->CKTtimeIndex)); d4 = (i5 - i6) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) - *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1)); if ((FABS(d1 - d2) >= model->LTRAreltol * MAX(FABS(d1), FABS(d2)) + model->LTRAabstol) || (FABS(d3 - d4) >= model->LTRAreltol * MAX(FABS(d3), FABS(d4)) + model->LTRAabstol)) { /* derivitive changing - need to schedule after delay */ /* the PREVIOUS point was the breakpoint */ /* the previous timepoint plus the delay */ /* * tmp = *(ckt->CKTtimePoints + ckt->CKTtimeIndex) + * model->LTRAtd; the work of a confused mind minus current time * tmp -= ckt->CKTtime; */ tmp = model->LTRAtd; *timeStep = MIN(*timeStep, tmp); } } break; case LTRA_MOD_RC: case LTRA_MOD_RG: break; default: return (E_BADPARM); } /* * the above was for the parts of the equations that resemble the * lossless equations. Now we need to estimate the local truncation * error in each of the three convolution equations, and if possible * adjust the timestep so that all of them remain within some bound. * Unfortunately, the expression for the LTE in a convolution operation * is complicated and costly to evaluate; in addition, no explicit * inverse exists. * * So what we do here (for the moment) is check to see the current error * is acceptable. If so, the timestep is not changed. If not, then an * estimate is made for the new timestep using a few iterations of the * newton-raphson method. * * modification: we change the timestep to half its previous value */ if ((model->LTRAspecialCase == LTRA_MOD_RLC) && (!model->LTRAtruncDontCut)) { *timeStep = MIN(*timeStep, model->LTRAmaxSafeStep); } if (model->LTRAlteConType != LTRA_MOD_NOCONTROL) { switch (model->LTRAspecialCase) { case LTRA_MOD_RLC: case LTRA_MOD_RC: tolerance = ckt->CKTtrtol * (ckt->CKTreltol * ( FABS(here->LTRAinput1) + FABS(here->LTRAinput2)) + ckt->CKTabstol); current_lte = LTRAlteCalculate(ckt, (GENmodel *) model, (GENinstance *) here, ckt->CKTtime); if (current_lte >= tolerance) { if (model->LTRAtruncNR) { x = ckt->CKTtime; y = current_lte; while (1) { deriv_delta = 0.01 * (x - *(ckt->CKTtimePoints + ckt->CKTtimeIndex));#ifdef LTRADEBUG if (deriv_delta <= 0.0) fprintf(stdout, "LTRAtrunc: error: timestep is now less than zero\n");#endif deriv = LTRAlteCalculate(ckt, (GENmodel *) model, (GENinstance *) here, x + deriv_delta) - y; deriv /= deriv_delta; change = (tolerance - y) / deriv; x += change; if (maxiter == 0) { if (FABS(change) <= FABS(deriv_delta)) break; } else { iterations++; if (iterations >= maxiter) break; } y = LTRAlteCalculate(ckt, (GENmodel *) model, (GENinstance *) here, x); } tmp = x - *(ckt->CKTtimePoints + ckt->CKTtimeIndex); *timeStep = MIN(*timeStep, tmp); } else *timeStep *= 0.5; } break; case LTRA_MOD_RG: case LTRA_MOD_LC: break; default: return (E_BADPARM); } } }#ifdef LTRADEBUG if (*timeStep >= model->LTRAtd) { fprintf(stdout, "LTRAtrunc: Warning: Timestep bigger than delay of line %s\n", model->LTRAmodName); fflush(stdout); }#endif } return (OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -