1 /**********
2 Copyright 1991 Regents of the University of California. All rights reserved.
3 Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
4 **********/
5
6 #include "ngspice/ngspice.h"
7 #include "ngspice/numglobs.h"
8 #include "ngspice/numenum.h"
9 #include "ngspice/twomesh.h"
10 #include "ngspice/twodev.h"
11 #include "twoddefs.h"
12 #include "twodext.h"
13
14 /* Forward declarations */
15 static void setDirichlet(TWOcontact *, double);
16
17
NUMD2setBCs(TWOdevice * pDevice,double vd)18 void NUMD2setBCs(TWOdevice *pDevice, double vd)
19 {
20 TWOcontact *pContact = pDevice->pLastContact;
21
22 setDirichlet( pContact, - vd );
23 }
24
NBJT2setBCs(TWOdevice * pDevice,double vce,double vbe)25 void NBJT2setBCs(TWOdevice *pDevice, double vce, double vbe)
26 {
27 TWOcontact *pCollContact = pDevice->pFirstContact;
28 TWOcontact *pBaseContact = pDevice->pFirstContact->next;
29
30 setDirichlet( pCollContact, vce );
31 setDirichlet( pBaseContact, vbe );
32 }
33
NUMOSsetBCs(TWOdevice * pDevice,double vdb,double vsb,double vgb)34 void NUMOSsetBCs(TWOdevice *pDevice, double vdb, double vsb, double vgb)
35 {
36 TWOcontact *pDContact = pDevice->pFirstContact;
37 TWOcontact *pGContact = pDevice->pFirstContact->next;
38 TWOcontact *pSContact = pDevice->pFirstContact->next->next;
39
40 setDirichlet( pDContact, vdb );
41 setDirichlet( pSContact, vsb );
42 setDirichlet( pGContact, vgb );
43 }
44
45 static void
setDirichlet(TWOcontact * pContact,double voltage)46 setDirichlet(TWOcontact *pContact, double voltage)
47 {
48 int index, numContactNodes, i;
49 TWOelem *pElem = NULL;
50 TWOnode *pNode;
51 double psi, ni, pi, nie;
52 double conc, sign, absConc;
53
54 voltage /= VNorm;
55
56 numContactNodes = pContact->numNodes;
57 for ( index = 0; index < numContactNodes; index++ ) {
58 pNode = pContact->pNodes[ index ];
59
60 /* Find this node's owner element. */
61 for ( i = 0; i <= 3; i++ ) {
62 pElem = pNode->pElems[ i ];
63 if ( pElem != NULL && pElem->evalNodes[ (i+2)%4 ] ) {
64 break; /* got it */
65 }
66 }
67
68 if (pElem->elemType == INSULATOR) {
69 pNode->psi = RefPsi - pNode->eaff;
70 pNode->nConc = 0.0;
71 pNode->pConc = 0.0;
72 }
73 else if (pElem->elemType == SEMICON) {
74 nie = pNode->nie;
75 conc = pNode->netConc / nie;
76 sign = SGN( conc );
77 absConc = ABS( conc );
78 if ( conc != 0.0 ) {
79 psi = sign * log( 0.5 * absConc + sqrt( 1.0 + 0.25*absConc*absConc ));
80 ni = nie * exp( psi );
81 pi = nie * exp( - psi );
82 }
83 else {
84 psi = 0.0;
85 ni = nie;
86 pi = nie;
87 }
88 pNode->psi = pElem->matlInfo->refPsi + psi;
89 pNode->nConc = ni;
90 pNode->pConc = pi;
91 }
92 pNode->psi += voltage;
93 }
94 }
95