📄 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) { 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 + -