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