You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
5.9 KiB
208 lines
5.9 KiB
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1985 Thomas L. Quarles
|
|
**********/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/cktdefs.h"
|
|
#include "ngspice/sperror.h"
|
|
#include "ngspice/cpextern.h"
|
|
|
|
/* xmu=0: Backward Euler
|
|
* xmu=0.5: trapezoidal (standard)
|
|
*/
|
|
|
|
|
|
int
|
|
NIcomCof(CKTcircuit *ckt)
|
|
{
|
|
|
|
double mat[8][8]; /* matrix to compute the gear coefficients in */
|
|
int i,j,k; /* generic loop indicies */
|
|
double arg;
|
|
double arg1;
|
|
|
|
/* this routine calculates the timestep-dependent terms used in the
|
|
* numerical integration.
|
|
*/
|
|
|
|
/*
|
|
* compute coefficients for particular integration method
|
|
*/
|
|
switch(ckt->CKTintegrateMethod) {
|
|
|
|
case TRAPEZOIDAL:
|
|
switch(ckt->CKTorder) {
|
|
|
|
case 1:
|
|
ckt->CKTag[0] = 1/ckt->CKTdelta;
|
|
ckt->CKTag[1] = -1/ckt->CKTdelta;
|
|
break;
|
|
|
|
case 2:
|
|
ckt->CKTag[0] = 1.0 / ckt->CKTdelta / (1.0 - ckt->CKTxmu);
|
|
ckt->CKTag[1] = ckt->CKTxmu / (1.0 - ckt->CKTxmu);
|
|
break;
|
|
|
|
default:
|
|
return(E_ORDER);
|
|
}
|
|
break;
|
|
|
|
case GEAR:
|
|
switch(ckt->CKTorder) {
|
|
|
|
case 1:
|
|
/* ckt->CKTag[0] = 1/ckt->CKTdelta;
|
|
ckt->CKTag[1] = -1/ckt->CKTdelta;
|
|
break;*/
|
|
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
memset(ckt->CKTag, 0, 7*sizeof(double));
|
|
ckt->CKTag[1] = -1/ckt->CKTdelta;
|
|
/* first, set up the matrix */
|
|
arg=0;
|
|
for(i=0;i<=ckt->CKTorder;i++) { mat[0][i]=1; }
|
|
for(i=1;i<=ckt->CKTorder;i++) { mat[i][0]=0; }
|
|
/* SPICE2 difference warning
|
|
* the following block builds the corrector matrix
|
|
* using (sum of h's)/h(final) instead of just (sum of h's)
|
|
* because the h's are typically ~1e-10, so h^7 is an
|
|
* underflow on many machines, but the ratio is ~1
|
|
* and produces much better results
|
|
*/
|
|
for(i=1;i<=ckt->CKTorder;i++) {
|
|
arg += ckt->CKTdeltaOld[i-1];
|
|
arg1 = 1;
|
|
for(j=1;j<=ckt->CKTorder;j++) {
|
|
arg1 *= arg/ckt->CKTdelta;
|
|
mat[j][i]=arg1;
|
|
}
|
|
}
|
|
/* lu decompose */
|
|
/* weirdness warning!
|
|
* The following loop (and the first one after the forward
|
|
* substitution comment) start at one instead of zero
|
|
* because of a SPECIAL CASE - the first column is 1 0 0 ...
|
|
* thus, the first iteration of both loops does nothing,
|
|
* so it is skipped
|
|
*/
|
|
for(i=1;i<=ckt->CKTorder;i++) {
|
|
for(j=i+1;j<=ckt->CKTorder;j++) {
|
|
mat[j][i] /= mat[i][i];
|
|
for(k=i+1;k<=ckt->CKTorder;k++) {
|
|
mat[j][k] -= mat[j][i]*mat[i][k];
|
|
}
|
|
}
|
|
}
|
|
/* forward substitution */
|
|
for(i=1;i<=ckt->CKTorder;i++) {
|
|
for(j=i+1;j<=ckt->CKTorder;j++) {
|
|
ckt->CKTag[j]=ckt->CKTag[j]-mat[j][i]*ckt->CKTag[i];
|
|
}
|
|
}
|
|
/* backward substitution */
|
|
ckt->CKTag[ckt->CKTorder] /= mat[ckt->CKTorder][ckt->CKTorder];
|
|
for(i=ckt->CKTorder-1;i>=0;i--) {
|
|
for(j=i+1;j<=ckt->CKTorder;j++) {
|
|
ckt->CKTag[i]=ckt->CKTag[i]-mat[i][j]*ckt->CKTag[j];
|
|
}
|
|
ckt->CKTag[i] /= mat[i][i];
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
return(E_ORDER);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return(E_METHOD);
|
|
}
|
|
|
|
#ifdef PREDICTOR
|
|
/* ok, have the coefficients for corrector, now for the predictor */
|
|
|
|
switch(ckt->CKTintegrateMethod) {
|
|
|
|
default:
|
|
return(E_METHOD);
|
|
|
|
case TRAPEZOIDAL:
|
|
/* ADAMS-BASHFORD PREDICTOR FOR TRAPEZOIDAL CORRECTOR
|
|
* MAY BE SUPPLEMENTED BY SECOND ORDER GEAR CORRECTOR
|
|
* AGP(1) STORES b0 AND AGP(2) STORES b1
|
|
*/
|
|
arg = ckt->CKTdelta/(2*ckt->CKTdeltaOld[1]);
|
|
ckt->CKTagp[0] = 1+arg;
|
|
ckt->CKTagp[1] = -arg;
|
|
break;
|
|
|
|
case GEAR:
|
|
|
|
/*
|
|
* CONSTRUCT GEAR PREDICTOR COEFICENT MATRIX
|
|
* MUST STILL ACCOUNT FOR ARRAY AGP()
|
|
* KEEP THE SAME NAME FOR GMAT
|
|
*/
|
|
memset(ckt->CKTagp, 0, 7*sizeof(double));
|
|
/* SET UP RHS OF EQUATIONS */
|
|
ckt->CKTagp[0]=1;
|
|
for(i=0;i<=ckt->CKTorder;i++) {
|
|
mat[0][i] = 1;
|
|
}
|
|
arg = 0;
|
|
for(i=0;i<=ckt->CKTorder;i++){
|
|
arg += ckt->CKTdeltaOld[i];
|
|
arg1 = 1;
|
|
for(j=1;j<=ckt->CKTorder;j++) {
|
|
arg1 *= arg/ckt->CKTdelta;
|
|
mat[j][i]=arg1;
|
|
}
|
|
}
|
|
/*
|
|
* SOLVE FOR GEAR COEFFICIENTS AGP(*)
|
|
*/
|
|
|
|
/*
|
|
* LU DECOMPOSITION
|
|
*/
|
|
for(i=0;i<=ckt->CKTorder;i++) {
|
|
for(j=i+1;j<=ckt->CKTorder;j++) {
|
|
mat[j][i] /= mat[i][i];
|
|
for(k=i+1;k<=ckt->CKTorder;k++) {
|
|
mat[j][k] -= mat[j][i]*mat[i][k];
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
* FORWARD SUBSTITUTION
|
|
*/
|
|
for(i=0;i<=ckt->CKTorder;i++) {
|
|
for(j=i+1;j<=ckt->CKTorder;j++) {
|
|
ckt->CKTagp[j] -= mat[j][i]*ckt->CKTagp[i];
|
|
}
|
|
}
|
|
/*
|
|
* BACKWARD SUBSTITUTION
|
|
*/
|
|
ckt->CKTagp[ckt->CKTorder] /= mat[ckt->CKTorder][ckt->CKTorder];
|
|
for(i=ckt->CKTorder-1;i>=0;i--) {
|
|
for(j=i+1;j<=ckt->CKTorder;j++) {
|
|
ckt->CKTagp[i] -= mat[i][j]*ckt->CKTagp[j];
|
|
}
|
|
ckt->CKTagp[i] /= mat[i][i];
|
|
}
|
|
/*
|
|
* FINISHED
|
|
*/
|
|
break;
|
|
}
|
|
#endif /* PREDICTOR */
|
|
return(OK);
|
|
}
|