ngspice/src/ciderlib/support/misc.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 );
}