dopset.c

来自「ngspice又一个电子CAD仿真软件代码.功能更全」· C语言 代码 · 共 396 行

C
396
字号
/**********Copyright 1991 Regents of the University of California.  All rights reserved.Author:	1991 David A. Gates, U. C. Berkeley CAD GroupModifed: 2001 Paolo Nenzi$Id: dopset.c,v 1.2 2005/05/21 12:37:23 sjborley Exp $**********/#include "ngspice.h"#include "cktdefs.h"#include "numenum.h"#include "dopdefs.h"#include "meshext.h"#include "profile.h"#include "gendev.h"#include "sperror.h"#include "suffix.h"#include "cidersupt.h"extern int DOPnewCard(void**,void*);extern int DOPparam(int,IFvalue*,void*);/* * Name:	DOPcheck * Purpose:	checks a list of DOPcards for input errors * Formals:	cardList: the list to check * Returns:	OK/E_PRIVATE * Users:	 numerical device setup routines * Calls:	error message handler */intDOPcheck(DOPcard *cardList, MESHcoord *xMeshList, MESHcoord *yMeshList){  DOPcard *card;  int cardNum = 0;  int error = OK;  char ebuf[512];		/* error message buffer */  for ( card = cardList; card != NIL(DOPcard); card = card->DOPnextCard ) {    cardNum++;    if (!card->DOPdomainsGiven) {      card->DOPnumDomains = 0;      card->DOPdomains = NIL(int);    }    if (!card->DOPprofileTypeGiven) {      sprintf( ebuf,	  "doping card %d does not specify profile type",	  cardNum );      SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );      error = E_PRIVATE;    } else switch (card->DOPprofileType) {      case DOP_UNIF:	if (!card->DOPconcGiven) {	  sprintf( ebuf,	      "doping card %d needs conc of uniform distribution",	      cardNum );	  SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );	  error = E_PRIVATE;	}	break;      case DOP_LINEAR:	if (!card->DOPconcGiven) {	  sprintf( ebuf,	      "doping card %d needs peak conc of linear distribution",	      cardNum );	  SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );	  error = E_PRIVATE;	}	break;      case DOP_GAUSS:	if (!card->DOPconcGiven) {	  sprintf( ebuf,	      "doping card %d needs peak conc of gaussian distribution",	      cardNum );	  SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );	  error = E_PRIVATE;	}	break;      case DOP_ERFC:	if (!card->DOPconcGiven) {	  sprintf( ebuf,	      "doping card %d needs peak conc of error-function distribution",	      cardNum );	  SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );	  error = E_PRIVATE;	}	break;      case DOP_EXP:	if (!card->DOPconcGiven) {	  sprintf( ebuf,	      "doping card %d needs peak conc of exponential distribution",	      cardNum );	  SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );	  error = E_PRIVATE;	}	break;      case DOP_SUPREM3:      case DOP_SUPASCII:	if (!card->DOPinFileGiven) {	  sprintf( ebuf,	      "doping card %d needs input-file name of suprem3 data",	      cardNum );	  SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );	  error = E_PRIVATE;	}	break;      case DOP_ASCII:	if (!card->DOPinFileGiven) {	  sprintf( ebuf,	      "doping card %d needs input-file name of ascii data",	      cardNum );	  SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );	  error = E_PRIVATE;	}	break;      default:	sprintf( ebuf,	    "doping card %d has unrecognized profile type",	    cardNum );	SPfrontEnd->IFerror( ERR_FATAL, ebuf, NIL(IFuid) );	error = E_NOTFOUND;	break;    }    if (!card->DOProtateLatGiven) {      card->DOProtateLat = FALSE;    }    if (!card->DOPlatProfileTypeGiven || card->DOProtateLat) {      card->DOPlatProfileType = card->DOPprofileType;    }    if (!card->DOPratioLatGiven) {      card->DOPratioLat = 1.0;    }    if (!card->DOPcharLenGiven) {      card->DOPcharLen = 1.0e-4; 	/* 1um in centimeters */    }    if (!card->DOPlocationGiven) {      card->DOPlocation = 0.0;    }    if (!card->DOPimpurityTypeGiven) {      card->DOPimpurityType = IMP_N_TYPE;    } else switch (card->DOPimpurityType) {      case DOP_BORON:	card->DOPimpurityType = IMP_BORON;	break;      case DOP_PHOSP:	card->DOPimpurityType = IMP_PHOSPHORUS;	break;      case DOP_ARSEN:	card->DOPimpurityType = IMP_ARSENIC;	break;      case DOP_ANTIM:	card->DOPimpurityType = IMP_ANTIMONY;	break;      case DOP_N_TYPE:	card->DOPimpurityType = IMP_N_TYPE;	break;      case DOP_P_TYPE:	card->DOPimpurityType = IMP_P_TYPE;	break;      default:	break;    }    if (!card->DOPaxisTypeGiven) {      if ( xMeshList && yMeshList ) { /* both lists are non-empty */	card->DOPaxisType = DOP_Y_AXIS;      } else if ( xMeshList ) { /* x-mesh list is non-empty */	card->DOPaxisType = DOP_X_AXIS;      } else if ( yMeshList ) { /* y-mesh list is non-empty */	card->DOPaxisType = DOP_Y_AXIS;      }    }/* Return now if anything has failed */    if (error) return(error);  }  return(OK);}/* * Name:	DOPsetup * Purpose:	convert a list of DOPcard's to DOPprofile's * Formals:	cardList: list of cards to setup *		profileList: returns the list of DOPprofile's *		xMeshList: list of coordinates in the x mesh *		yMeshList: list of coordinates in the y mesh * Returns:	OK/E_PRIVATE * Users:	 numerical devices * Calls:	DOPcheck */intDOPsetup(DOPcard *cardList, DOPprofile **profileList, DOPtable **tableList,         MESHcoord *xMeshList, MESHcoord *yMeshList){  DOPcard *card;  DOPprofile *newProfile = NULL, *endProfile;  int impurityId = 0;  double xMin, xMax, yMin, yMax;  double sign;  int error, xProfUnif, yProfUnif;/* Initialize list of profiles */  *profileList = endProfile = NIL(DOPprofile);/* Check the card list */  if ((error = DOPcheck( cardList, xMeshList, yMeshList ))) return( error );/* Find the limits on locations */  MESHlBounds( xMeshList, &xMin, &xMax );  MESHlBounds( yMeshList, &yMin, &yMax );  for ( card = cardList; card != NIL(DOPcard); card = card->DOPnextCard ) {    if (*profileList == NIL(DOPprofile)) {      RALLOC( newProfile, DOPprofile, 1 );      *profileList = newProfile;    }    else {      RALLOC( newProfile->next, DOPprofile, 1 );      newProfile = newProfile->next;    }    newProfile->next = NIL(DOPprofile);    newProfile->numDomains = card->DOPnumDomains;    if ( newProfile->numDomains > 0 ) {      int i;      RALLOC( newProfile->domains, int, newProfile->numDomains );      for ( i=0; i < newProfile->numDomains; i++ ) {	newProfile->domains[i] = card->DOPdomains[i];      }    }    else {      newProfile->domains = NIL(int);    }    if ( card->DOPimpurityType == IMP_P_TYPE ) {      sign = -1.0;    }    else {      sign = 1.0;    }    switch( card->DOPprofileType ) {      case DOP_UNIF:	newProfile->type = UNIF;	newProfile->CONC = sign * card->DOPconc;	break;      case DOP_LINEAR:	newProfile->type = LIN;	newProfile->CONC = sign * card->DOPconc;	break;      case DOP_GAUSS:	newProfile->type = GAUSS;	newProfile->CONC = sign * card->DOPconc;	break;      case DOP_ERFC:	newProfile->type = ERRFC;	newProfile->CONC = sign * card->DOPconc;	break;      case DOP_EXP:	newProfile->type = EXP;	newProfile->CONC = sign * card->DOPconc;	break;      case DOP_SUPREM3:	newProfile->type = LOOKUP;	readSupremData( card->DOPinFile, 0, card->DOPimpurityType, tableList );	newProfile->IMPID = ++impurityId;	break;      case DOP_SUPASCII:	newProfile->type = LOOKUP;	readSupremData( card->DOPinFile, 1, card->DOPimpurityType, tableList );	newProfile->IMPID = ++impurityId;	break;      case DOP_ASCII:	newProfile->type = LOOKUP;	readAsciiData( card->DOPinFile, card->DOPimpurityType, tableList );	newProfile->IMPID = ++impurityId;	break;      default:	break;    }    switch( card->DOPlatProfileType ) {      case DOP_UNIF:	newProfile->latType = UNIF;	break;      case DOP_LINEAR:	newProfile->latType = LIN;	break;      case DOP_GAUSS:	newProfile->latType = GAUSS;	break;      case DOP_ERFC:	newProfile->latType = ERRFC;	break;      case DOP_EXP:	newProfile->latType = EXP;	break;      case DOP_SUPREM3:      case DOP_SUPASCII:	newProfile->latType = LOOKUP;	break;      case DOP_ASCII:	newProfile->latType = LOOKUP;	break;      default:	break;    }    newProfile->rotate = card->DOProtateLat;    newProfile->LOCATION = card->DOPlocation;    newProfile->CHAR_LENGTH = card->DOPcharLen;    newProfile->LAT_RATIO = card->DOPratioLat;    xProfUnif = yProfUnif = FALSE;    if (card->DOPaxisType == DOP_X_AXIS) {      newProfile->DIRECTION = X;      if (newProfile->type == UNIF) xProfUnif = TRUE;      if (newProfile->latType == UNIF) yProfUnif = TRUE;    }     else {      newProfile->DIRECTION = Y;      if (newProfile->type == UNIF) yProfUnif = TRUE;      if (newProfile->latType == UNIF) xProfUnif = TRUE;    }/* Fill in x coordinates.  Use defaults if necessary */    if (card->DOPxLowGiven && card->DOPxHighGiven) {      newProfile->X_LOW = card->DOPxLow;      newProfile->X_HIGH = card->DOPxHigh;    }    else if (card->DOPxLowGiven) {      newProfile->X_LOW = card->DOPxLow;      if (xProfUnif) {	newProfile->X_HIGH = xMax;      }      else {	newProfile->X_HIGH = newProfile->X_LOW;      }    }    else if (card->DOPxHighGiven) {      newProfile->X_HIGH = card->DOPxHigh;      if (xProfUnif) {	newProfile->X_LOW = xMin;      }      else {	newProfile->X_LOW = newProfile->X_HIGH;      }    }    else {      if (xProfUnif) {	newProfile->X_LOW = xMin;	newProfile->X_HIGH = xMax;      }      else {	newProfile->X_LOW = 0.5 * (xMin + xMax);	newProfile->X_HIGH = 0.5 * (xMin + xMax);      }    }/* Fill in y coordinates.  Use defaults if necessary */    if (card->DOPyLowGiven && card->DOPyHighGiven) {      newProfile->Y_LOW = card->DOPyLow;      newProfile->Y_HIGH = card->DOPyHigh;    }    else if (card->DOPyLowGiven) {      newProfile->Y_LOW = card->DOPyLow;      if (yProfUnif) {	newProfile->Y_HIGH = yMax;      }      else {	newProfile->Y_HIGH = newProfile->Y_LOW;      }    }    else if (card->DOPyHighGiven) {      newProfile->Y_HIGH = card->DOPyHigh;      if (xProfUnif) {	newProfile->Y_LOW = yMin;      }      else {	newProfile->Y_LOW = newProfile->Y_HIGH;      }    }    else {      if (yProfUnif) {	newProfile->Y_LOW = yMin;	newProfile->Y_HIGH = yMax;      }      else {	newProfile->Y_LOW = 0.5 * (yMin + yMax);	newProfile->Y_HIGH = 0.5 * (yMin + yMax);      }    }  }  return( OK );}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?