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