Add EXITPOINTs, if reading inputs etc. fails

This commit is contained in:
Holger Vogt 2020-04-25 18:54:22 +02:00
parent 18e6ca15c1
commit 3ad93a50e8
8 changed files with 480 additions and 257 deletions

View File

@ -4,18 +4,19 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
Modifed: 2001 Paolo Nenzi
**********/
#include "ngspice/ngspice.h"
#include "ngspice/carddefs.h"
#include "ngspice/cidersupt.h"
#include "ngspice/cktdefs.h"
#include "ngspice/numenum.h"
#include "ngspice/ciderinp.h"
#include "ngspice/cpextern.h"
#include "ngspice/dopdefs.h"
#include "ngspice/meshext.h"
#include "ngspice/ngspice.h"
#include "ngspice/numenum.h"
#include "ngspice/profile.h"
#include "ngspice/gendev.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
#include "ngspice/cidersupt.h"
#include "ngspice/carddefs.h"
#include "ngspice/ciderinp.h"
/*
@ -234,17 +235,29 @@ DOPsetup(DOPcard *cardList, DOPprofile **profileList, DOPtable **tableList,
break;
case DOP_SUPREM3:
newProfile->type = LOOKUP;
readSupremData( card->DOPinFile, 0, card->DOPimpurityType, tableList );
if (readSupremData( card->DOPinFile, 0, card->DOPimpurityType,
tableList) != 0) {
(void) fprintf(cp_err, "Doping setup failed.\n");
return -1;
}
newProfile->IMPID = ++impurityId;
break;
case DOP_SUPASCII:
newProfile->type = LOOKUP;
readSupremData( card->DOPinFile, 1, card->DOPimpurityType, tableList );
if (readSupremData( card->DOPinFile, 1, card->DOPimpurityType,
tableList) != 0) {
(void) fprintf(cp_err, "Doping setup failed.\n");
return -1;
}
newProfile->IMPID = ++impurityId;
break;
case DOP_ASCII:
newProfile->type = LOOKUP;
readAsciiData( card->DOPinFile, card->DOPimpurityType, tableList );
if (readAsciiData(card->DOPinFile, card->DOPimpurityType,
tableList) != 0) {
(void) fprintf(cp_err, "Doping setup failed.\n");
return -1;
}
newProfile->IMPID = ++impurityId;
break;
default:

View File

@ -40,7 +40,7 @@ NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd)
int index, i;
double yReal, yImag;
double *solutionReal, *solutionImag;
SPcomplex yAc, cOmega;
SPcomplex yAc_adm, cOmega;
SPcomplex *y;
BOOLEAN SORFailed;
double startTime;
@ -146,13 +146,13 @@ NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd)
startTime = SPfrontEnd->IFseconds();
pNode = pDevice->elemArray[1]->pLeftNode;
y = computeAdmittance(pNode, FALSE, solutionReal, solutionImag, &cOmega);
CMPLX_ASSIGN_VALUE(yAc, -y->real, -y->imag);
CMPLX_ASSIGN(*yd, yAc);
CMPLX_ASSIGN_VALUE(yAc_adm, -y->real, -y->imag);
CMPLX_ASSIGN(*yd, yAc_adm);
CMPLX_MULT_SELF_SCALAR(*yd, GNorm * pDevice->area);
pDevice->pStats->miscTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
return (AcAnalysisMethod);
}
} /* end of function NUMDadmittance */
int

View File

@ -77,6 +77,7 @@ ONEdopingValue(DOPprofile *pProfile, DOPtable *pTable, double x)
} else {
value = pProfile->PEAK_CONC * exp(-argP);
}
break;
case EXP:
argP = ABS(argP);
if (argP > 80.0) {

View File

@ -5,26 +5,36 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
**********/
/* Functions to read SUPREM (Binary or Ascii) & ASCII input files */
#include <errno.h>
#include <string.h>
#include "ngspice/cidersupt.h"
#include "ngspice/cpextern.h"
#include "ngspice/ngspice.h"
#include "ngspice/profile.h"
#include "ngspice/cidersupt.h"
void
readAsciiData( char *fileName, int impType, DOPtable **ppTable )
static void free_profile_data(double **p);
static double **alloc_profile_data(size_t n);
int readAsciiData(const char *fileName, int impType, DOPtable **ppTable)
{
FILE *fpAscii;
int xrc = 0;
FILE *fpAscii = (FILE *) NULL;
int index;
double x, y;
int numPoints;
DOPtable *tmpTable;
double **profileData;
DOPtable *tmpTable = (DOPtable *) NULL;
double **profileData = (double **) NULL;
double sign;
/* Open Input File */
if ((fpAscii = fopen( fileName, "r" )) == NULL) {
perror( fileName );
exit(-1);
(void) fprintf(cp_err, "unable to open SUPREM file \"%s\": %s\n",
fileName, strerror(errno));
xrc = -1;
goto EXITPOINT;
}
/* Get sign of concentrations */
@ -35,31 +45,43 @@ readAsciiData( char *fileName, int impType, DOPtable **ppTable )
}
/* read the number of points */
fscanf( fpAscii, "%d", &numPoints );
if (fscanf(fpAscii, "%d", &numPoints) != 1) {
(void) fprintf(cp_err, "unable to read point count "
"from SUPREM file \"%s\"\n",
fileName);
xrc = -1;
goto EXITPOINT;
}
/* allocate 2-D array to read in data of x-coordinate and N(x) */
XCALLOC( profileData, double *, 2 );
for( index = 0; index <= 1; index++ ) {
XCALLOC( profileData[ index ], double, 1 + numPoints );
}
profileData = alloc_profile_data((size_t) numPoints + 1);
/* the number of points is stored as profileData[0][0] */
profileData[0][0] = numPoints;
for( index = 1; index <= numPoints; index++ ) {
fscanf( fpAscii, "%lf %lf ", &x, &y );
profileData[ 0 ][ index ] = x;
profileData[ 1 ][ index ] = sign * ABS(y);
}
for (index = 1; index <= numPoints; index++ ) {
if (fscanf(fpAscii, "%lf %lf ", &x, &y) != 2) {
(void) fprintf(cp_err, "unable to read point %d"
"from SUPREM file \"%s\"\n",
index + 1, fileName);
xrc = -1;
goto EXITPOINT;
}
profileData[0][index] = x;
profileData[1][index] = sign * ABS(y);
} /* end of loop over points */
/* Now create a new lookup table */
XCALLOC( tmpTable, DOPtable, 1 );
if ( *ppTable == NULL ) {
XCALLOC(tmpTable, DOPtable, 1);
if (*ppTable == NULL) {
/* First Entry */
tmpTable->impId = 1;
tmpTable->dopData = profileData;
tmpTable->next = NULL;
*ppTable = tmpTable;
} else {
}
else {
tmpTable->impId = (*ppTable)->impId + 1;
tmpTable->dopData = profileData;
tmpTable->next = *ppTable;
@ -72,9 +94,21 @@ readAsciiData( char *fileName, int impType, DOPtable **ppTable )
printf("\n %e %e", profileData[ 0 ][ index ], profileData[ 1 ][ index ]);
}
*/
fclose(fpAscii);
return;
}
EXITPOINT:
if (fpAscii != (FILE *) NULL) { /* close data file if open */
fclose(fpAscii);
}
/* Free resources on error */
if (xrc != 0) {
free_profile_data(profileData);
free(tmpTable);
}
return xrc;
} /* end of function readAsciiData */
/* interface routine based on notes provided by Steve Hansen of Stanford */
@ -108,40 +142,45 @@ readAsciiData( char *fileName, int impType, DOPtable **ppTable )
*/
void
readSupremData(char *fileName, int fileType, int impType, DOPtable **ppTable)
int readSupremData(const char *fileName, int fileType, int impType,
DOPtable **ppTable)
{
int xrc = 0;
#define MAX_GRID 500
float x[ MAX_GRID ], conc[ MAX_GRID ];
int index;
DOPtable *tmpTable;
double **profileData;
DOPtable *tmpTable = (DOPtable *) NULL;
double **profileData = (double **) NULL;
int numNodes;
/* read the Suprem data file */
if ( fileType == 0 ) { /* BINARY FILE */
SUPbinRead( fileName, x, conc, &impType, &numNodes );
const int rc = SUPbinRead(fileName, x, conc, &impType,
&numNodes);
if (rc != 0) {
(void) fprintf(cp_err, "Data input failed.\n");
xrc = -1;
goto EXITPOINT;
}
}
else {
SUPascRead( fileName, x, conc, &impType, &numNodes );
}
/* allocate 2-D array to read in data of x-coordinate and N(x) */
XCALLOC( profileData, double *, 2 );
for( index = 0; index <= 1; index++ ) {
XCALLOC( profileData[ index ], double, 1 + numNodes );
}
profileData = alloc_profile_data((size_t) numNodes + 1);
/* the number of points is stored as profileData[0][0] */
profileData[0][0] = numNodes;
for( index = 1; index <= numNodes; index++ ) {
profileData[ 0 ][ index ] = x[ index ];
profileData[ 1 ][ index ] = conc[ index ];
profileData[ 0 ][ index ] = x[ index ];
profileData[ 1 ][ index ] = conc[ index ];
}
/* Now create a new lookup table */
XCALLOC( tmpTable, DOPtable, 1 );
XCALLOC(tmpTable, DOPtable, 1);
if ( *ppTable == NULL ) {
/* First Entry */
tmpTable->impId = 1;
@ -161,8 +200,46 @@ readSupremData(char *fileName, int fileType, int impType, DOPtable **ppTable)
printf("%e %e\n", profileData[ 0 ][ index ], profileData[ 1 ][ index ]);
}
*/
return;
}
EXITPOINT:
if (xrc != 0) {
free_profile_data(profileData);
free(tmpTable);
}
return xrc;
} /* end of function readSupremData */
/* Allocate a profile data */
static double **alloc_profile_data(size_t n)
{
double **p;
XCALLOC(p, double *, 2);
XCALLOC(p[0], double, n);
XCALLOC(p[1], double, n);
return p;
} /* end of function alloc_profile_data */
/* Free a profile data */
static void free_profile_data(double **p)
{
/* Immediate exit if no allocation */
if (p == (double **) NULL) {
return;
}
free(p[0]);
free(p[1]);
free(p);
} /* end of function alloc_profile_data */
/* main program to debug readSupremData */

View File

@ -8,25 +8,31 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
* the data is read and stored in two arrays x and conc
*/
#include <errno.h>
#include <string.h>
#include "ngspice/ngspice.h"
#include "ngspice/cidersupt.h"
#include "ngspice/cpextern.h"
#include "ngspice/ngspice.h"
#define MAXMAT 10
#define MAXIMP 4
#define MAXLAYER 10
#define MAXGRID 500
#define GFREAD( fp, ptr, type, num ) if (num && (fread( ptr,\
sizeof(type), (unsigned)num, fp ) != (unsigned)num)) {\
return;\
}
#define GFREAD( fp, ptr, type, num )\
if (num && (fread( ptr, sizeof(type), (size_t) num,\
fp ) != (size_t) num)) {\
xrc = -1;\
goto EXITPOINT;\
}
#define DEBUG if (0)
void
SUPbinRead(char *inFile, float *x, float *conc, int *impId, int *numNod)
int SUPbinRead(const char *inFile, float *x, float *conc, int *impId,
int *numNod)
{
int xrc = 0;
int idata, recordMark;
int ldata;
int i, j;
@ -37,18 +43,20 @@ SUPbinRead(char *inFile, float *x, float *conc, int *impId, int *numNod)
float xStart;
float layerTh[10];
float con[500];
FILE *fpSuprem;
FILE *fpSuprem = (FILE *) NULL;
/* Clear Concentration Array */
for ( i=0; i < MAXGRID; i++ ) {
conc[i] = 0.0;
}
/* Open Input File */
if ((fpSuprem = fopen( inFile, "r" )) == NULL) {
perror(inFile);
return;
}
/* Open Input File */
if ((fpSuprem = fopen( inFile, "r" )) == NULL) {
(void) fprintf(cp_err, "Unable to read file \"%s\": %s.\n",
inFile, strerror(errno));
xrc = -1;
goto EXITPOINT;
}
/*
* The first record contains the number of layers (I4), the number of
@ -199,17 +207,27 @@ SUPbinRead(char *inFile, float *x, float *conc, int *impId, int *numNod)
DEBUG fprintf(stderr," %d\n", ldata );
GFREAD( fpSuprem, &recordMark, int, 1 );
fclose( fpSuprem );
if (fclose(fpSuprem) != 0) {
(void) fprintf(cp_err, "Unable to close file \"%s\": %s.\n",
inFile, strerror(errno));
xrc = -1;
goto EXITPOINT;
}
fpSuprem = (FILE *) NULL;
/* shift silicon layer to beginning of array */
for ( j=numLay; --j >= 0; )
if (matTyp[ j ] == 1)
break;
/* shift silicon layer to beginning of array */
for (j = numLay; --j >= 0; ) {
if (matTyp[j] == 1) {
break;
}
}
if (j < 0) {
(void) fprintf(cp_err, "internal error in %s!\n", __FUNCTION__);
xrc = -1;
goto EXITPOINT;
}
if(j < 0) {
fprintf(stderr, "internal error in %s, bye !\n", __FUNCTION__);
controlled_exit(1);
}
siIndex = j;
@ -223,15 +241,26 @@ SUPbinRead(char *inFile, float *x, float *conc, int *impId, int *numNod)
/* Store number of valid nodes using pointer */
*numNod = numGrid;
return;
}
void
SUPascRead(char *inFile, float *x, float *conc, int *impId, int *numNod)
EXITPOINT:
if (fpSuprem != (FILE *) NULL) {
if (fclose(fpSuprem) != 0) {
(void) fprintf(cp_err, "Unable to close \"%s\" at exit: %s\n",
inFile, strerror(errno));
xrc = -1;
}
}
return xrc;
} /* end of function SUPbinRead */
int SUPascRead(const char *inFile, float *x, float *conc, int *impId,
int *numNod)
{
int idata;
int xrc = 0;
int i, j;
float rdata;
char cdata[21];
int numLay, numImp, numGrid;
int impTyp[4], matTyp[10], topNod[10], siIndex, offset;
@ -245,119 +274,196 @@ SUPascRead(char *inFile, float *x, float *conc, int *impId, int *numNod)
conc[i] = 0.0;
}
/* Open Input File */
if ((fpSuprem = fopen( inFile, "r" )) == NULL) {
perror(inFile);
return;
}
/* Open Input File */
if ((fpSuprem = fopen( inFile, "r" )) == NULL) {
(void) fprintf(cp_err, "Unable to open file \"%s\": %s.\n",
inFile, strerror(errno));
xrc = -1;
goto EXITPOINT;
}
/*
* The first line contains the number of layers (I4), the number of
* impurities (I4), and the number of nodes (I4) present in the structure.
*/
fscanf( fpSuprem, "%d %d %d\n", &numLay, &numImp, &numGrid );
if (fscanf( fpSuprem, "%d %d %d\n", &numLay, &numImp, &numGrid) != 3) {
(void) fprintf(cp_err, "Unable to read file first line of \"%s\"\n",
inFile);
xrc = -1;
goto EXITPOINT;
}
DEBUG fprintf( stderr, "set 1: %d %d %d\n", numLay, numImp, numGrid);
/*
* The second set of lines contains, for each layer, the material name (A20),
* the material type (I4), the layer thickness (R4), and the pointer to
* the top node of the layer (I4), and an unknown int and unknown float.
* The material type code:
* 1 - Si
* 2 - SiO2
* 3 - Poly
* 4 - Si3N4
* 5 - Alum
*/
for ( i=0; i < numLay; i++ ) {
fscanf( fpSuprem, "%s\n %d %e %d %d %e\n",
cdata, &matTyp[i], &layerTh[i], &topNod[i], &idata, &rdata );
DEBUG fprintf(stderr,"set 2: %s: %d %f %d\n",
cdata, matTyp[i], layerTh[i], topNod[i] );
}
/*
* The second set of lines contains, for each layer, the material name
* (A20), the material type (I4), the layer thickness (R4), and the
* pointer to the top node of the layer (I4), and an unknown int and
* unknown float.
*
* The material type code:
* 1 - Si
* 2 - SiO2
* 3 - Poly
* 4 - Si3N4
* 5 - Alum
*/
for (i = 0; i < numLay; ++i) {
int idata;
float rdata;
if (fscanf(fpSuprem, "%s\n %d %e %d %d %e\n",
cdata, &matTyp[i], &layerTh[i], &topNod[i],
&idata, &rdata) != 6) {
(void) fprintf(cp_err, "Unable to read layer %d "
"from file \"%s\".\n",
i + 1, inFile);
xrc = -1;
goto EXITPOINT;
}
/*
* The third set of lines contains, for each impurity, the name of the
* impurity (A20) and the type of impurity (I4).
*/
for ( i=0; i < numImp; i++ ) {
fscanf( fpSuprem, "%s\n %d\n", cdata, &impTyp[i] );
DEBUG fprintf(stderr,"set 3: %s: %d\n", cdata, impTyp[i] );
}
DEBUG fprintf(stderr,"set 2: %s: %d %f %d\n",
cdata, matTyp[i], layerTh[i], topNod[i]);
} /* end of loop over layers */
/*
* The fourth set of lines contains, for each layer by each impurity, the
* integrated dopant (R4), and the interior concentration of the
* polysilicon grains (R4).
*/
for ( j=0; j < numLay; j++ ) {
for ( i=0; i < numImp; i++ ) {
fscanf( fpSuprem, "%e", &rdata );
fscanf( fpSuprem, "%e", &rdata );
/*
* The third set of lines contains, for each impurity, the name of the
* impurity (A20) and the type of impurity (I4).
*/
for (i = 0; i < numImp; ++i) {
if (fscanf( fpSuprem, "%s\n %d\n", cdata, &impTyp[i]) != 2) {
(void) fprintf(cp_err, "Unable to read impurity %d "
"from file \"%s\".\n",
i + 1, inFile);
xrc = -1;
goto EXITPOINT;
}
DEBUG fprintf(stderr,"set 3: %s: %d\n", cdata, impTyp[i]);
} /* end of loop over impurities */
/*
* The fourth set of lines contains, for each layer by each impurity,
* the integrated dopant (R4), and the interior concentration of the
* polysilicon grains (R4).
*/
for (j = 0; j < numLay; ++j) {
for (i = 0; i < numImp; ++i) {
float rdata;
if (fscanf(fpSuprem, "%e%e", &rdata, &rdata) != 2) {
(void) fprintf(cp_err, "Unable to read integrated dopant "
"and interior concentration of layer %d and "
"impurity %d from file \"%s\".\n",
j + 1, i + 1, inFile);
xrc = -1;
goto EXITPOINT;
}
}
}
}
DEBUG fprintf(stderr,"set 4:\n" );
DEBUG fprintf(stderr,"set 4:\n" );
/*
* The fifth set of lines contains, for each node in the structure,
* the distance to the next deepest node (R4), the distance from the
* surface (R4), and, for each impurity type, the impurity's
* chemical concentration (R4) and the impurity's active concentration (R4).
*/
for ( i=1; i <= numGrid; i++ ) {
fscanf( fpSuprem, "%e %e", &rdata, &x[i] );
/*
* The fifth set of lines contains, for each node in the structure,
* the distance to the next deepest node (R4), the distance from the
* surface (R4), and, for each impurity type, the impurity's
* chemical concentration (R4) and the impurity's active concentration (R4).
*/
for (i = 1; i <= numGrid; ++i) {
float rdata;
if (fscanf(fpSuprem, "%e %e", &rdata, &x[i]) != 2) {
(void) fprintf(cp_err, "Unable to read grid %d "
"from file \"%s\".\n",
i + 1, inFile);
xrc = -1;
goto EXITPOINT;
}
for ( j=0; j < numImp; j++ ) {
/* chemical concentration - not required */
fscanf( fpSuprem, "%e", &con[i] );
/* store active concentration */
fscanf( fpSuprem, "%e", &con[i] );
for (j = 0; j < numImp; j++) {
float junk;
/* chemical concentration - not required */
if (fscanf(fpSuprem, "%e", &junk) != 1) {
(void) fprintf(cp_err, "Unable to chemical concentration "
"%d of layer %d "
"from file \"%s\".\n",
j + 1, i + 1, inFile);
xrc = -1;
goto EXITPOINT;
}
/* orient sign properly */
if (impTyp[j] == *impId) {
/*...Boron...*/
if (impTyp[j] == 1) {
conc[i] = - con[i];
} else {
/*...All Other Impurities: P, As, Sb ...*/
conc[i] = con[i];
}
}
/* store active concentration */
if (fscanf(fpSuprem, "%e", &con[i]) != 1) {
(void) fprintf(cp_err, "Unable to active concentration "
"%d of layer %d "
"from file \"%s\".\n",
j + 1, i + 1, inFile);
xrc = -1;
goto EXITPOINT;
}
/* orient sign properly */
if (impTyp[j] == *impId) {
/*...Boron...*/
if (impTyp[j] == 1) {
conc[i] = - con[i];
}
else {
/*...All Other Impurities: P, As, Sb ...*/
conc[i] = con[i];
}
}
}
} /* end of loop over num grid */
DEBUG fprintf( stderr, "set 5: %e %e\n", x[1], conc[1] );
/*
* The last line in the file contains some random stuff that might be
* useful to some people, the temperature in degrees Kelvin of the last
* diffusion step (R4), the phosphorus implant dose (R4), the arsenic
* implant flag (L4). However, we can just ignore that stuff.
*/
if (fclose(fpSuprem) != 0) {
(void) fprintf(cp_err, "Unable to close file \"%s\": %s.\n",
inFile, strerror(errno));
xrc = -1;
goto EXITPOINT;
}
}
DEBUG fprintf( stderr, "set 5: %e %e\n", x[1], conc[1] );
fpSuprem = (FILE *) NULL;
/*
* The last line in the file contains some random stuff that might be
* useful to some people, the temperature in degrees Kelvin of the last
* diffusion step (R4), the phosphorus implant dose (R4), the arsenic
* implant flag (L4). However, we can just ignore that stuff.
*/
fclose( fpSuprem );
/* shift silicon layer to beginning of array */
for (j = numLay; --j >= 0; ) {
if (matTyp[j] == 1) {
break;
}
}
if (j < 0) {
(void) fprintf(cp_err, "internal error in %s!\n", __FUNCTION__);
xrc = -1;
goto EXITPOINT;
}
siIndex = j;
offset = topNod[siIndex] - 1;
numGrid -= offset;
xStart = x[1 + offset];
for (i = 1; i <= numGrid; i++) {
x[i] = x[i + offset] - xStart;
conc[i] = conc[i + offset];
}
/* Store number of valid nodes using pointer */
*numNod = numGrid;
EXITPOINT:
if (fpSuprem != (FILE *) NULL) {
if (fclose(fpSuprem) != 0) {
(void) fprintf(cp_err, "Unable to close \"%s\" at exit: %s\n",
inFile, strerror(errno));
xrc = -1;
}
}
return xrc;
} /* end of function SUPascRead */
/* shift silicon layer to beginning of array */
for ( j=numLay; --j >= 0; )
if (matTyp[ j ] == 1)
break;
if(j < 0) {
fprintf(stderr, "internal error in %s, bye !\n", __FUNCTION__);
controlled_exit(1);
}
siIndex = j;
offset = topNod[ siIndex ] - 1;
numGrid -= offset;
xStart = x[1 + offset];
for ( i=1; i <= numGrid; i++ ) {
x[i] = x[i + offset] - xStart;
conc[i] = conc[i + offset];
}
/* Store number of valid nodes using pointer */
*numNod = numGrid;
return;
}

View File

@ -153,7 +153,7 @@ extern BOOLEAN TWOdeltaConverged(TWOdevice *);
extern BOOLEAN TWOdeviceConverged(TWOdevice *);
extern void TWOresetJacobian(TWOdevice *);
extern void TWOstoreNeutralGuess(TWOdevice *);
extern void TWOequilSolve(TWOdevice *);
extern int TWOequilSolve(TWOdevice *);
extern void TWObiasSolve(TWOdevice *, int, BOOLEAN, TWOtranInfo *);
extern void TWOstoreEquilibGuess(TWOdevice *);
extern void TWOstoreInitialGuess(TWOdevice *);

View File

@ -98,6 +98,7 @@ TWOdopingValue(DOPprofile *pProfile, DOPtable *pTable, double x,
} else {
value = pProfile->PEAK_CONC * exp( -argP );
}
break;
case EXP:
argP = ABS(argP);
if ( argP > 80.0 ) {
@ -143,6 +144,7 @@ TWOdopingValue(DOPprofile *pProfile, DOPtable *pTable, double x,
} else {
value *= exp( -argL );
}
break;
case EXP:
argL = ABS(argL);
if ( argL > 80.0 ) {

View File

@ -4,21 +4,20 @@ Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
**********/
#include "../../maths/misc/norm.h"
#include "ngspice/bool.h"
#include "ngspice/cidersupt.h"
#include "ngspice/cpextern.h"
#include "ngspice/ifsim.h"
#include "ngspice/macros.h"
#include "ngspice/ngspice.h"
#include "ngspice/numglobs.h"
#include "ngspice/numenum.h"
#include "ngspice/numglobs.h"
#include "ngspice/spmatrix.h"
#include "ngspice/twodev.h"
#include "ngspice/twomesh.h"
#include "ngspice/spmatrix.h"
#include "ngspice/bool.h"
#include "ngspice/macros.h"
#include "twoddefs.h"
#include "twodext.h"
#include "ngspice/cidersupt.h"
#include "../../maths/misc/norm.h"
#include "ngspice/ifsim.h"
extern IFfrontEnd *SPfrontEnd;
@ -96,19 +95,24 @@ TWOdcSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
error = spFactor(pDevice->matrix);
factorTime += SPfrontEnd->IFseconds() - startTime;
if (newSolver) {
if (pDevice->iterationNumber == 1) {
orderTime = factorTime;
} else if (pDevice->iterationNumber == 2) {
orderTime -= factorTime - orderTime;
factorTime -= orderTime;
if (pDevice->poissonOnly) {
pDevice->pStats->orderTime[STAT_SETUP] += orderTime;
} else {
pDevice->pStats->orderTime[STAT_DC] += orderTime;
}
newSolver = FALSE;
}
}
if (pDevice->iterationNumber == 1) {
orderTime = factorTime;
}
else if (pDevice->iterationNumber == 2) {
orderTime -= factorTime - orderTime;
factorTime -= orderTime;
if (pDevice->poissonOnly) {
pDevice->pStats->orderTime[STAT_SETUP] += orderTime;
}
else {
pDevice->pStats->orderTime[STAT_DC] += orderTime;
}
/* After first two iterations, no special handling for a
* new solver */
newSolver = FALSE;
} /* end of case of iteratin 2 */
} /* end of special processing for a new solver */
if (foundError(error)) {
if (error == spSINGULAR) {
int badRow, badCol;
@ -430,58 +434,69 @@ TWOstoreNeutralGuess(TWOdevice *pDevice)
/* computing the equilibrium solution; solution of Poisson's eqn */
/* the solution is used as an initial starting point for bias conditions */
void
TWOequilSolve(TWOdevice *pDevice)
int TWOequilSolve(TWOdevice *pDevice)
{
BOOLEAN newSolver = FALSE;
int error;
int nIndex, eIndex;
TWOelem *pElem;
TWOnode *pNode;
double startTime, setupTime, miscTime;
BOOLEAN newSolver = FALSE;
int error;
int nIndex, eIndex;
TWOelem *pElem;
TWOnode *pNode;
double startTime, setupTime, miscTime;
setupTime = miscTime = 0.0;
setupTime = miscTime = 0.0;
/* SETUP */
startTime = SPfrontEnd->IFseconds();
switch (pDevice->solverType) {
case SLV_SMSIG:
case SLV_BIAS:
/* free up memory allocated for the bias solution */
FREE(pDevice->dcSolution);
FREE(pDevice->dcDeltaSolution);
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
FREE(pDevice->rhsImag);
spDestroy(pDevice->matrix);
case SLV_NONE:
pDevice->poissonOnly = TRUE;
pDevice->numEqns = pDevice->dimEquil - 1;
XCALLOC(pDevice->dcSolution, double, pDevice->dimEquil);
XCALLOC(pDevice->dcDeltaSolution, double, pDevice->dimEquil);
XCALLOC(pDevice->copiedSolution, double, pDevice->dimEquil);
XCALLOC(pDevice->rhs, double, pDevice->dimEquil);
pDevice->matrix = spCreate(pDevice->numEqns, 0, &error);
if (error == spNO_MEMORY) {
printf("TWOequilSolve: Out of Memory\n");
exit(-1);
}
newSolver = TRUE;
spSetReal(pDevice->matrix);
TWOQjacBuild(pDevice);
pDevice->numOrigEquil = spElementCount(pDevice->matrix);
pDevice->numFillEquil = 0;
case SLV_EQUIL:
pDevice->solverType = SLV_EQUIL;
break;
default:
fprintf(stderr, "Panic: Unknown solver type in equil solution.\n");
exit(-1);
break;
}
TWOstoreNeutralGuess(pDevice);
setupTime += SPfrontEnd->IFseconds() - startTime;
/* SETUP */
startTime = SPfrontEnd->IFseconds();
/* Set up pDevice to compute the equilibrium solution. If the solver
* is for bias, the arrays must be freed and allocated to the correct
* sizes for an equilibrium solution; if it is a new solver, they are
* only allocated; and if already an equilibrium solve, nothing
* needs to be done */
/* FALLTHROUGH added to suppress GCC warning due to
* -Wimplicit-fallthrough flag */
switch (pDevice->solverType) {
case SLV_SMSIG:
case SLV_BIAS:
/* Free memory allocated for the bias solution */
FREE(pDevice->dcSolution);
FREE(pDevice->dcDeltaSolution);
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
FREE(pDevice->rhsImag);
spDestroy(pDevice->matrix);
/* FALLTHROUGH */
case SLV_NONE: {
/* Allocate memory needed for an equilibrium solution */
const int n_dim = pDevice->dimEquil;
const int n_eqn = n_dim - 1;
pDevice->poissonOnly = TRUE;
pDevice->numEqns = n_eqn;
XCALLOC(pDevice->dcSolution, double, n_dim);
XCALLOC(pDevice->dcDeltaSolution, double, n_dim);
XCALLOC(pDevice->copiedSolution, double, n_dim);
XCALLOC(pDevice->rhs, double, n_dim);
pDevice->matrix = spCreate(n_eqn, 0, &error);
if (error == spNO_MEMORY) {
(void) fprintf(cp_err, "TWOequilSolve: Out of Memory\n");
return E_NOMEM;
}
newSolver = TRUE;
spSetReal(pDevice->matrix); /* set to a real matrix */
TWOQjacBuild(pDevice);
pDevice->numOrigEquil = spElementCount(pDevice->matrix);
pDevice->numFillEquil = 0;
pDevice->solverType = SLV_EQUIL;
break;
}
case SLV_EQUIL: /* Nothing to do if already equilibrium solver */
break;
default: /* Invalid data */
fprintf(stderr, "Panic: Unknown solver type in equil solution.\n");
return E_PANIC;
} /* end of switch over solve type */
TWOstoreNeutralGuess(pDevice);
setupTime += SPfrontEnd->IFseconds() - startTime;
/* SOLVE */
TWOdcSolve(pDevice, MaxIterations, newSolver, FALSE, NULL);
@ -510,6 +525,8 @@ TWOequilSolve(TWOdevice *pDevice)
miscTime += SPfrontEnd->IFseconds() - startTime;
pDevice->pStats->setupTime[STAT_SETUP] += setupTime;
pDevice->pStats->miscTime[STAT_SETUP] += miscTime;
return 0;
}
/* compute the solution under an applied bias */
@ -530,15 +547,20 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
/* SETUP */
startTime = SPfrontEnd->IFseconds();
switch (pDevice->solverType) {
case SLV_EQUIL:
/* free up the vectors allocated in the equilibrium solution */
FREE(pDevice->dcSolution);
FREE(pDevice->dcDeltaSolution);
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
spDestroy(pDevice->matrix);
/* Set up for solving for bias */
/* FALLTHROUGH added to suppress GCC warning due to
* -Wimplicit-fallthrough flag */
switch (pDevice->solverType) {
case SLV_EQUIL:
/* free up the vectors allocated in the equilibrium solution */
FREE(pDevice->dcSolution);
FREE(pDevice->dcDeltaSolution);
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
spDestroy(pDevice->matrix);
/* FALLTHROUGH */
case SLV_NONE:
/* Set up for bias */
pDevice->poissonOnly = FALSE;
pDevice->numEqns = pDevice->dimBias - 1;
XCALLOC(pDevice->dcSolution, double, pDevice->dimBias);
@ -562,11 +584,13 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
pDevice->numOrigBias = spElementCount(pDevice->matrix);
pDevice->numFillBias = 0;
TWOstoreInitialGuess(pDevice);
/* FALLTHROUGH */
case SLV_SMSIG:
spSetReal(pDevice->matrix);
case SLV_BIAS:
pDevice->solverType = SLV_BIAS;
break;
case SLV_BIAS:
break;
default:
fprintf(stderr, "Panic: Unknown solver type in bias solution.\n");
exit(-1);