📄 ltraacct.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 "suffix.h"intLTRAaccept(ckt, inModel) register CKTcircuit *ckt; GENmodel *inModel;{ register LTRAmodel *model = (LTRAmodel *) inModel; register LTRAinstance *here; register int i = 0, j; double v1, v2, v3, v4; double v5, v6, d1, d2, d3, d4; double *from, *to; int tmp_test; int error; int compact = 1; /* loop through all the transmission line models */ for (; model != NULL; model = model->LTRAnextModel) { if (ckt->CKTmode & MODEINITTRAN) {#define LTRAmemMANAGE(a,b) \ if ( a != NULL) FREE(a);\ a = (double *) MALLOC( b * sizeof(double)); model->LTRAmodelListSize = 10; LTRAmemMANAGE(model->LTRAh1dashCoeffs, model->LTRAmodelListSize) LTRAmemMANAGE(model->LTRAh2Coeffs, model->LTRAmodelListSize) LTRAmemMANAGE(model->LTRAh3dashCoeffs, model->LTRAmodelListSize) } if (ckt->CKTtimeIndex >= model->LTRAmodelListSize) { /* need more space */ model->LTRAmodelListSize += ckt->CKTsizeIncr; model->LTRAh1dashCoeffs = (double *) REALLOC((char *) model->LTRAh1dashCoeffs, sizeof(double) * model->LTRAmodelListSize); model->LTRAh2Coeffs = (double *) REALLOC((char *) model->LTRAh2Coeffs, sizeof(double) * model->LTRAmodelListSize); model->LTRAh3dashCoeffs = (double *) REALLOC((char *) model->LTRAh3dashCoeffs, sizeof(double) * model->LTRAmodelListSize); } /* loop through all the instances of the model */ for (here = model->LTRAinstances; here != NULL; here = here->LTRAnextInstance) { if (here->LTRAowner != ARCHme) continue; /* XXX */ if (ckt->CKTmode & MODEINITTRAN) { here->LTRAinstListSize = 10; LTRAmemMANAGE(here->LTRAv1, here->LTRAinstListSize) LTRAmemMANAGE(here->LTRAi1, here->LTRAinstListSize) LTRAmemMANAGE(here->LTRAv2, here->LTRAinstListSize) LTRAmemMANAGE(here->LTRAi2, here->LTRAinstListSize) } /* * why is this here? ask TQ * * if (ckt->CKTtimeIndex == 0? 1: (ckt->CKTtime- * (ckt->CKTtimePoints+ckt->CKTtimeIndex-1) > ckt->CKTminBreak)) { * */ if (ckt->CKTtimeIndex >= here->LTRAinstListSize) { /* need more space */ here->LTRAinstListSize += ckt->CKTsizeIncr; here->LTRAv1 = (double *) REALLOC((char *) here->LTRAv1, sizeof(double) * (here->LTRAinstListSize)); here->LTRAi1 = (double *) REALLOC((char *) here->LTRAi1, sizeof(double) * (here->LTRAinstListSize)); here->LTRAi2 = (double *) REALLOC((char *) here->LTRAi2, sizeof(double) * (here->LTRAinstListSize)); here->LTRAv2 = (double *) REALLOC((char *) here->LTRAv2, sizeof(double) * (here->LTRAinstListSize)); } *(here->LTRAv1 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld + here->LTRAposNode1) - *(ckt->CKTrhsOld + here->LTRAnegNode1); *(here->LTRAv2 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld + here->LTRAposNode2) - *(ckt->CKTrhsOld + here->LTRAnegNode2); *(here->LTRAi1 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld + here->LTRAbrEq1); *(here->LTRAi2 + ckt->CKTtimeIndex) = *(ckt->CKTrhsOld + here->LTRAbrEq2); if (ckt->CKTtryToCompact && (ckt->CKTtimeIndex >= 2)) { /* * figure out if the last 3 points lie on a st. line for all the * terminal variables */ { double t1, t2, t3; t1 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2); t2 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1); t3 = *(ckt->CKTtimePoints + ckt->CKTtimeIndex); if (compact) { compact = LTRAstraightLineCheck(t1, *(here->LTRAv1 + ckt->CKTtimeIndex - 2), t2, *(here->LTRAv1 + ckt->CKTtimeIndex - 1), t3, *(here->LTRAv1 + ckt->CKTtimeIndex), model->LTRAstLineReltol, model->LTRAstLineAbstol); } if (compact) { compact = LTRAstraightLineCheck(t1, *(here->LTRAv2 + ckt->CKTtimeIndex - 2), t2, *(here->LTRAv2 + ckt->CKTtimeIndex - 1), t3, *(here->LTRAv2 + ckt->CKTtimeIndex), model->LTRAstLineReltol, model->LTRAstLineAbstol); } if (compact) { compact = LTRAstraightLineCheck(t1, *(here->LTRAi1 + ckt->CKTtimeIndex - 2), t2, *(here->LTRAi1 + ckt->CKTtimeIndex - 1), t3, *(here->LTRAi1 + ckt->CKTtimeIndex), model->LTRAstLineReltol, model->LTRAstLineAbstol); } if (compact) { compact = LTRAstraightLineCheck(t1, *(here->LTRAi2 + ckt->CKTtimeIndex - 2), t2, *(here->LTRAi2 + ckt->CKTtimeIndex - 1), t3, *(here->LTRAi2 + ckt->CKTtimeIndex), model->LTRAstLineReltol, model->LTRAstLineAbstol); } } } if (ckt->CKTtimeIndex > 0) {#ifdef NOTDEF v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) + *(here->LTRAi1 + ckt->CKTtimeIndex) * model->LTRAimped) * model->LTRAattenuation; v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) + *(here->LTRAi1 + ckt->CKTtimeIndex - 1) * model->LTRAimped) * model->LTRAattenuation; v3 = (*(here->LTRAv2 + ckt->CKTtimeIndex) + *(here->LTRAi2 + ckt->CKTtimeIndex) * model->LTRAimped) * model->LTRAattenuation; v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) + *(here->LTRAi2 + ckt->CKTtimeIndex - 1) * model->LTRAimped) * model->LTRAattenuation; if ((FABS(v1 - v2) >= 50 * ckt->CKTreltol * MAX(FABS(v1), FABS(v2)) + 50 * ckt->CKTvoltTol) || (FABS(v3 - v4) >= 50 * ckt->CKTreltol * MAX(FABS(v3), FABS(v4)) + 50 * ckt->CKTvoltTol)) { /* changing - need to schedule after delay */ /* * don't really need this error = * CKTsetBreak(ckt,ckt->CKTtime+model->LTRAtd); if(error) * return(error); */ /* the PREVIOUS point is the real breakpoint */ error = CKTsetBreak(ckt, *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) + model->LTRAtd); CKTbreakDump(ckt); if (error) return (error); }#else /* * remove the hack here - store the total inputs for the last 2 or 3 * timesteps */ v1 = (*(here->LTRAv1 + ckt->CKTtimeIndex) + *(here->LTRAi1 + ckt->CKTtimeIndex) * model->LTRAimped) * model->LTRAattenuation; v2 = (*(here->LTRAv1 + ckt->CKTtimeIndex - 1) + *(here->LTRAi1 + ckt->CKTtimeIndex - 1) * model->LTRAimped) * model->LTRAattenuation; v3 = ckt->CKTtimeIndex < 2 ? v2 : (*(here->LTRAv1 + ckt->CKTtimeIndex - 2) + *(here->LTRAi1 + ckt->CKTtimeIndex - 2) * model->LTRAimped) * model->LTRAattenuation; v4 = (*(here->LTRAv2 + ckt->CKTtimeIndex) + *(here->LTRAi2 + ckt->CKTtimeIndex) * model->LTRAimped) * model->LTRAattenuation; v5 = (*(here->LTRAv2 + ckt->CKTtimeIndex - 1) + *(here->LTRAi2 + ckt->CKTtimeIndex - 1) * model->LTRAimped) * model->LTRAattenuation; v6 = ckt->CKTtimeIndex < 2 ? v5 : (*(here->LTRAv2 + ckt->CKTtimeIndex - 2) + *(here->LTRAi2 + ckt->CKTtimeIndex - 2) * model->LTRAimped) * model->LTRAattenuation; d1 = (v1 - v2) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) - *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1)); d2 = (v2 - v3) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) - *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2)); d3 = (v4 - v5) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex) - *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1)); d4 = (v5 - v6) / (*(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) - *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 2)); /* * here we have a big problem with the scheme boxed by the *s below. * Note the following: if LTRAreltol == 1, (assuming LTRAabstol==0) * then breakpoints are set if and only if d1 and d2 have opposite * signs or one is zero. If LTRAreltol > 2, breakpoints are never * set. The problem is that when the waveform is steady at a value, * small random numerical inaccuracies may produce derivatives of * opposite sign, and breakpoints get set. This can, in practice, get * quite killing... To alleviate this, we try to determine if the * waveform is actually steady using the following tests: 1. Check if * the maximum difference between v1,v2 and v3 is less than * 50*CKTreltol*(the average of v1,v2,and v3) + 50*ckt->CKTabstol * (the 50 has been taken from the NOTDEF section above, reason * unknown - hopefully there is a good reason for it - ask TQ) * * 2. Criterion 1 may be satisfied by a legitimate breakpoint. To * further check, find one more derivative one timepoint ago and see * if that is close to d2. If not, then the likelihood of numerical * inaccuracies is greater... */ /********************************************************************* 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) ) { *********************************************************************/#define CHECK(a,b,c) (MAX(MAX(a,b),c)-MIN(MIN(a,b),c) >= \ FABS(50.0*(ckt->CKTreltol/3.0*(a+b+c) +\ ckt->CKTabstol))) tmp_test = (FABS(d1 - d2) >= model->LTRAreltol * MAX(FABS(d1), FABS(d2)) + model->LTRAabstol) && CHECK(v1, v2, v3); if (tmp_test || ((FABS(d3 - d4) >= model->LTRAreltol * MAX(FABS(d3), FABS(d4)) + model->LTRAabstol) && CHECK(v4, v5, v6))) { /* criterion 2 not implemented yet... */ error = CKTsetBreak(ckt, *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) + model->LTRAtd); /* * this is not necessary - the previous timepoint was the * breakpoint error = CKTsetBreak(ckt, ckt->CKTtime + * model->LTRAtd); */#ifdef LTRADEBUG fprintf(stdout, "\nbreakpoints set at %14.14g at %14.14g at time %14.14g\n", ckt->CKTtime + model->LTRAtd, *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) + model->LTRAtd, ckt->CKTtime); fprintf(stdout, "d1 through d4 are %14.14g %14.14g %14.14g %14.14g\n\n", d1, d2, d3, d4);#endif if (error) return (error); } /* } */#endif /* NOTDEF */ } /* ask TQ } */ } /* instance */ } /* model */ if (ckt->CKTtryToCompact && compact && (ckt->CKTtimeIndex >= 2)) { /* * last three timepoints have variables lying on a straight line, do a * compaction */ model = (LTRAmodel *) inModel; for (; model != NULL; model = model->LTRAnextModel) { for (here = model->LTRAinstances; here != NULL; here = here->LTRAnextInstance) { *(here->LTRAv1 + ckt->CKTtimeIndex - 1) = *(here->LTRAv1 + ckt->CKTtimeIndex); *(here->LTRAv2 + ckt->CKTtimeIndex - 1) = *(here->LTRAv2 + ckt->CKTtimeIndex); *(here->LTRAi1 + ckt->CKTtimeIndex - 1) = *(here->LTRAi1 + ckt->CKTtimeIndex); *(here->LTRAi2 + ckt->CKTtimeIndex - 1) = *(here->LTRAi2 + ckt->CKTtimeIndex); } } *(ckt->CKTtimePoints + ckt->CKTtimeIndex - 1) = *(ckt->CKTtimePoints + ckt->CKTtimeIndex); ckt->CKTtimeIndex--;#ifdef LTRADEBUG fprintf(stdout, "compacted at time=%g\n", *(ckt->CKTtimePoints + ckt->CKTtimeIndex)); fflush(stdout);#endif } return (OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -