152 lines
4.0 KiB
C
152 lines
4.0 KiB
C
/**********
|
|
Copyright 1991 Regents of the University of California. All rights reserved.
|
|
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
|
|
Modified: 2001 Paolo Nenzi
|
|
**********/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/cktdefs.h"
|
|
#include "ngspice/numconst.h"
|
|
#include "ngspice/numenum.h"
|
|
#include "ngspice/mobdefs.h"
|
|
#include "ngspice/material.h"
|
|
#include "ngspice/sperror.h"
|
|
#include "ngspice/suffix.h"
|
|
#include "ngspice/cidersupt.h"
|
|
|
|
extern int MOBcheck( MOBcard *, MaterialInfo * );
|
|
extern int MOBsetup( MOBcard *, MaterialInfo * );
|
|
|
|
/*
|
|
* Name: MOBcheck
|
|
* Purpose: checks a list of MOBcards for input errors
|
|
* Formals: cardList: the list to check
|
|
* Returns: OK/E_PRIVATE
|
|
* Users: numerical device setup routines
|
|
* Calls: error message handler
|
|
*/
|
|
int
|
|
MOBcheck(MOBcard *cardList, MaterialInfo *matlList)
|
|
{
|
|
MOBcard *card;
|
|
MATLmaterial *matl;
|
|
int cardNum = 0;
|
|
int error = OK;
|
|
|
|
for ( card = cardList; card != NULL; card = card->MOBnextCard ) {
|
|
cardNum++;
|
|
if (!card->MOBmaterialGiven) {
|
|
SPfrontEnd->IFerrorf( ERR_WARNING, "mobility card %d is missing a material index", cardNum );
|
|
error = E_PRIVATE;
|
|
} else {
|
|
/* Make sure the material exists */
|
|
for ( matl = matlList; matl != NULL; matl = matl->next ) {
|
|
if ( card->MOBmaterial == matl->id ) {
|
|
break;
|
|
}
|
|
}
|
|
if (matl == NULL) {
|
|
SPfrontEnd->IFerrorf( ERR_WARNING, "mobility card %d specifies a non-existent material", cardNum );
|
|
error = E_PRIVATE;
|
|
}
|
|
}
|
|
if (!card->MOBcarrierGiven) {
|
|
card->MOBcarrier = ELEC;
|
|
}
|
|
if (!card->MOBcarrTypeGiven) {
|
|
card->MOBcarrType = MAJOR;
|
|
}
|
|
if (!card->MOBinitGiven) {
|
|
card->MOBinit = FALSE;
|
|
}
|
|
|
|
/* Return now if anything has failed */
|
|
if (error) return(error);
|
|
|
|
}
|
|
return(OK);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Name: MOBsetup
|
|
* Purpose: setup the mobility model parameters
|
|
* Formals: cardList: list of cards to setup
|
|
* Returns: OK/E_PRIVATE
|
|
* Users: numerical devices
|
|
* Calls: MOBcheck
|
|
*/
|
|
int
|
|
MOBsetup(MOBcard *cardList, MaterialInfo *materialList)
|
|
{
|
|
MOBcard *card;
|
|
MATLmaterial *matl;
|
|
int error;
|
|
|
|
/* Check the card list */
|
|
if ((error = MOBcheck( cardList, materialList )) != 0) return( error );
|
|
|
|
for ( card = cardList; card != NULL; card = card->MOBnextCard ) {
|
|
|
|
/* Find the right material */
|
|
for ( matl = materialList; matl != NULL; matl = matl->next ) {
|
|
if ( card->MOBmaterial == matl->id ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Default models depend on previous value */
|
|
if (!card->MOBconcModelGiven) {
|
|
card->MOBconcModel = matl->concModel;
|
|
}
|
|
if (!card->MOBfieldModelGiven) {
|
|
card->MOBfieldModel = matl->fieldModel;
|
|
}
|
|
|
|
/* Load in default values if desired */
|
|
if ( card->MOBinitGiven ) {
|
|
MOBdefaults( matl, card->MOBcarrier, card->MOBcarrType,
|
|
card->MOBconcModel, card->MOBfieldModel );
|
|
}
|
|
|
|
/* Override defaults */
|
|
if ( card->MOBconcModelGiven ) {
|
|
matl->concModel = card->MOBconcModel;
|
|
}
|
|
if ( card->MOBfieldModelGiven ) {
|
|
matl->fieldModel = card->MOBfieldModel;
|
|
}
|
|
if ( card->MOBmuMaxGiven ) {
|
|
matl->muMax[card->MOBcarrier][card->MOBcarrType] = card->MOBmuMax;
|
|
}
|
|
if ( card->MOBmuMinGiven ) {
|
|
matl->muMin[card->MOBcarrier][card->MOBcarrType] = card->MOBmuMin;
|
|
}
|
|
if ( card->MOBntRefGiven ) {
|
|
matl->ntRef[card->MOBcarrier][card->MOBcarrType] = card->MOBntRef;
|
|
}
|
|
if ( card->MOBntExpGiven ) {
|
|
matl->ntExp[card->MOBcarrier][card->MOBcarrType] = card->MOBntExp;
|
|
}
|
|
if ( card->MOBvSatGiven ) {
|
|
matl->vSat[card->MOBcarrier] = card->MOBvSat;
|
|
}
|
|
if ( card->MOBvWarmGiven ) {
|
|
matl->vWarm[card->MOBcarrier] = card->MOBvWarm;
|
|
}
|
|
if ( card->MOBmusGiven ) {
|
|
matl->mus[card->MOBcarrier] = card->MOBmus;
|
|
}
|
|
if ( card->MOBecAGiven ) {
|
|
matl->thetaA[card->MOBcarrier] = 1.0 / MAX( card->MOBecA, 1e-20 );
|
|
}
|
|
if ( card->MOBecBGiven ) {
|
|
matl->thetaB[card->MOBcarrier] = 1.0 / MAX( ABS(card->MOBecB), 1e-20 );
|
|
matl->thetaB[card->MOBcarrier] *= matl->thetaB[card->MOBcarrier];
|
|
matl->thetaB[card->MOBcarrier] *= SGN( card->MOBecB );
|
|
}
|
|
}
|
|
return( OK );
|
|
}
|