📄 miftrunc.c
字号:
/*============================================================================FILE MIFtrunc.cMEMBER OF process XSPICECopyright 1991Georgia Tech Research CorporationAtlanta, Georgia 30332All Rights ReservedPROJECT A-8503AUTHORS 9/12/91 Bill KuhnMODIFICATIONS <date> <person name> <nature of modifications>SUMMARY This file contains the function called by SPICE to check truncation error of an integration state used by a code model.INTERFACES MIFtrunc()REFERENCED FILES None.NON-STANDARD FEATURES None.============================================================================*//* #include "prefix.h" */#include "ngspice.h"#include <stdio.h>#include "cktdefs.h"#include "sperror.h"//#include "util.h"#include <math.h>#include "mifproto.h"#include "mifparse.h"#include "mifdefs.h"#include "mifcmdat.h"/* #include "suffix.h" */static void MIFterr(Mif_Intgr_t *intgr, CKTcircuit *ckt, double *timeStep);/*MIFtruncThis function is called by the CKTtrunc() driver function tocheck numerical integration truncation error of any integralsassociated with instances of a particular code model type. Ittraverses all models of that type and all instances of eachmodel. For each instance, it looks in the instance structure todetermine if any variables allocated by cm_analog_alloc() have been usedin a call to cm_analog_integrate(). If so, the truncation error of thatintegration is computed and used to set the maximum delta allowedfor the current timestep.*/intMIFtrunc( GENmodel *inModel, /* The head of the model list */ CKTcircuit *ckt, /* The circuit structure */ double *timeStep) /* The timestep delta */{ MIFmodel *model; MIFinstance *here; int i; /* Setup for access into MIF specific model data */ model = (MIFmodel *) inModel; /* loop through all models of this type */ for( ; model != NULL; model = model->MIFnextModel) { /* Loop through all instances of this model */ for(here = model->MIFinstances; here != NULL; here = here->MIFnextInstance) { /* Loop through all integration states on the instance */ for(i = 0; i < here->num_intgr; i++) { /* Limit timeStep according to truncation error */ MIFterr(&(here->intgr[i]), ckt, timeStep); } /* end for number of integration states */ } /* end for all instances */ } /* end for all models of this type */ return(OK);}/* * Copyright (c) 1985 Thomas L. Quarles * * This is a modified version of the function CKTterr(). It limits * timeStep according to computed truncation error. * * Modifications are Copyright 1991 Georgia Tech Research Institute * */static void MIFterr( Mif_Intgr_t *intgr, CKTcircuit *ckt, double *timeStep){ double volttol; double chargetol; double tol; double del; double diff[8]; double deltmp[8]; double factor; int i; int j; static double gearCoeff[] = { .5, .2222222222, .1363636364, .096, .07299270073, .05830903790 }; static double trapCoeff[] = { .5, .08333333333 }; /* Define new local variables. Dimension = number of states in ckt struct */ char *byte_aligned_state_ptr; double *state_ptr[8]; /* Set state pointers to the (possibly byte-aligned) states */ for(i = 0; i < 8; i++) { byte_aligned_state_ptr = (char *) ckt->CKTstates[i]; byte_aligned_state_ptr += intgr->byte_index; state_ptr[i] = (double *) byte_aligned_state_ptr; } /* Modify computation of volttol to not include current from previous timestep */ /* which is unavailable in this implementation. Note that this makes the */ /* the overall trunction error timestep smaller (which is better accuracy) */ /* Old code *//* volttol = ckt->CKTabstol + ckt->CKTreltol * MAX( fabs(*(ckt->CKTstate0+ccap)), fabs(*(ckt->CKTstate1+ccap)));*/ /* New code */ volttol = ckt->CKTabstol + ckt->CKTreltol * fabs(*(state_ptr[0]) - *(state_ptr[1])) / ckt->CKTdelta; /* Modify remaining references to qcap to access byte-aligned MIF state */ /* Otherwise, remaining code is same as SPICE3C1 ... */ chargetol = MAX(fabs(*(state_ptr[0])),fabs(*(state_ptr[1]))); chargetol = ckt->CKTreltol * MAX(chargetol,ckt->CKTchgtol)/ckt->CKTdelta; tol = MAX(volttol,chargetol); /* now divided differences */ for(i=ckt->CKTorder+1;i>=0;i--) { diff[i] = *(state_ptr[i]); } for(i=0 ; i <= ckt->CKTorder ; i++) { deltmp[i] = ckt->CKTdeltaOld[i]; } j = ckt->CKTorder; while(1) { for(i=0;i <= j;i++) { diff[i] = (diff[i] - diff[i+1])/deltmp[i]; } if (--j < 0) break; for(i=0;i <= j;i++) { deltmp[i] = deltmp[i+1] + ckt->CKTdeltaOld[i]; } } switch(ckt->CKTintegrateMethod) { case GEAR: default: factor = gearCoeff[ckt->CKTorder-1]; break; case TRAPEZOIDAL: factor = trapCoeff[ckt->CKTorder - 1] ; break; } del = ckt->CKTtrtol * tol/MAX(ckt->CKTabstol,factor * fabs(diff[0])); if(ckt->CKTorder == 2) { del = sqrt(del); } else if (ckt->CKTorder > 2) { del = exp(log(del)/ckt->CKTorder); } *timeStep = MIN(*timeStep,del); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -