164 lines
4.2 KiB
C
164 lines
4.2 KiB
C
/**********
|
|
Copyright 1992 Regents of the University of California. All rights reserved.
|
|
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
|
Author: 1992 David A. Gates, U. C. Berkeley CAD Group
|
|
**********/
|
|
|
|
/*
|
|
* Miscellaneous routines culled from the oned directory so that the twod
|
|
* code will run without having to compile the oned code
|
|
*/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/numglobs.h"
|
|
#include "ngspice/numenum.h"
|
|
#include "ngspice/spmatrix.h"
|
|
#include "ngspice/cidersupt.h"
|
|
|
|
|
|
/* Used in Solution Projection Calculations */
|
|
double guessNewConc(double conc, double delta)
|
|
{
|
|
BOOLEAN acceptable = FALSE;
|
|
double fib, newConc, lambda, fibn, fibp;
|
|
lambda = 1.0;
|
|
fibn = 1.0;
|
|
fibp = 1.0;
|
|
newConc = 0.0;
|
|
for ( ; !acceptable ; ) {
|
|
fib = fibp;
|
|
fibp = fibn;
|
|
fibn += fib;
|
|
lambda *= fibp / fibn;
|
|
newConc = conc + delta * lambda;
|
|
if( newConc > 0.0 ) {
|
|
acceptable = TRUE;
|
|
}
|
|
else {
|
|
/* newConc is still negative but fibp and fibn are large */
|
|
if ( (fibp > 1e6) || (fibn > 1e6) ) {
|
|
acceptable = TRUE;
|
|
newConc = conc;
|
|
}
|
|
}
|
|
}
|
|
return( newConc );
|
|
}
|
|
|
|
/* Used in Doping Calculation */
|
|
/* compute the concentration at x given an array of data.
|
|
* The data is stored in a two-dimensional array x, N(x).
|
|
* x is assumed to be in ascending order. given an x
|
|
* a search is performed to determine the data points closest
|
|
* to it and linear interpolation is performed to generate N(x)
|
|
*/
|
|
|
|
/*
|
|
#define LOGSUPREM
|
|
*/
|
|
double lookup(double **dataTable, double x)
|
|
{
|
|
double conc=0.0, x0, x1, y0, y1;
|
|
#ifdef LOGSUPREM
|
|
double lnconc, lny0, lny1;
|
|
#endif
|
|
int index, numPoints;
|
|
BOOLEAN done = FALSE;
|
|
|
|
numPoints = (int)dataTable[ 0 ][ 0 ];
|
|
for( index = 2; index <= numPoints && (!done); index++ ) {
|
|
x1 = dataTable[ 0 ][ index ];
|
|
/* check if x1 > x */
|
|
if( x1 >= x ) {
|
|
/* found an x1 larger than x, so linear interpolate */
|
|
x0 = dataTable[ 0 ][ index - 1 ];
|
|
y0 = dataTable[ 1 ][ index - 1 ];
|
|
y1 = dataTable[ 1 ][ index ];
|
|
#ifdef LOGSUPREM
|
|
/* Ignore concentrations below 1.0 */
|
|
if ( ABS(y0) < 1.0 )
|
|
lny0 = 0.0;
|
|
else
|
|
lny0 = SGN(y0) * log( ABS(y0) );
|
|
if ( ABS(y1) < 1.0 )
|
|
lny1 = 0.0;
|
|
else
|
|
lny1 = SGN(y0) * log( ABS(y0) );
|
|
lnconc = lny0 + (lny1 - lny0) * (x - x0) / (x1 - x0);
|
|
conc = SGN(lnconc) * exp( ABS(lnconc) );
|
|
#else
|
|
conc = y0 + (y1 - y0) * (x - x0) / (x1 - x0);
|
|
#endif /* LOGSUPREM */
|
|
done = TRUE;
|
|
} else {
|
|
if( index == numPoints ) {
|
|
/* set to concentration of last node - due to roundoff errors */
|
|
conc = dataTable[ 1 ][ numPoints ];
|
|
}
|
|
}
|
|
}
|
|
return ( conc );
|
|
}
|
|
|
|
/* Used in admittance calculations */
|
|
/* this function returns TRUE is SOR iteration converges otherwise FALSE */
|
|
|
|
BOOLEAN hasSORConverged(double *oldSolution, double *newSolution,
|
|
int numEqns)
|
|
{
|
|
BOOLEAN converged = TRUE;
|
|
int index;
|
|
double xOld, xNew, tol;
|
|
double absTol = 1e-12;
|
|
double relTol = 1e-3;
|
|
for( index = 1 ; index <= numEqns ; index++ ) {
|
|
xOld = oldSolution[ index ];
|
|
xNew = newSolution[ index ];
|
|
tol = absTol + relTol * MAX( ABS( xOld ), ABS( xNew ));
|
|
if( ABS( xOld - xNew ) > tol ) {
|
|
converged = FALSE;
|
|
printf("hasSORconverged failed\n");
|
|
break;
|
|
}
|
|
}
|
|
return( converged );
|
|
}
|
|
|
|
/* Used to Check Sparse Matrix Errors */
|
|
BOOLEAN
|
|
foundError(int error)
|
|
{
|
|
BOOLEAN matrixError;
|
|
|
|
switch( error ) {
|
|
/* Removed for Spice3e1 Compatibility
|
|
case spSMALL_PIVOT:
|
|
printf( "Warning: LU Decomposition Problem - SMALL PIVOT\n" );
|
|
matrixError = FALSE;
|
|
break;
|
|
*/
|
|
case spPANIC:
|
|
printf( "Error: LU Decomposition Failed - PANIC\n" );
|
|
matrixError = TRUE;
|
|
break;
|
|
case spSINGULAR:
|
|
printf( "Error: LU Decomposition Failed - SINGULAR\n" );
|
|
matrixError = TRUE;
|
|
break;
|
|
/* Removed for Spice3e1 Compatibility
|
|
case spZERO_DIAG:
|
|
printf( "Error: LU Decomposition Failed - ZERO PIVOT\n" );
|
|
matrixError = TRUE;
|
|
break;
|
|
*/
|
|
case spNO_MEMORY:
|
|
printf( "Error: LU Decomposition Failed - NO MEMORY\n" );
|
|
matrixError = TRUE;
|
|
break;
|
|
default:
|
|
matrixError = FALSE;
|
|
break;
|
|
}
|
|
return( matrixError );
|
|
}
|