1 /**********
2 Copyright 1991 Regents of the University of California.  All rights reserved.
3 Author:	1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
4 Author:	1990 David A. Gates, U. C. Berkeley CAD Group
5 **********/
6 
7 #include "ngspice/ngspice.h"
8 #include "ngspice/numglobs.h"
9 #include "ngspice/numenum.h"
10 #include "ngspice/twomesh.h"
11 #include "twoddefs.h"
12 #include "twodext.h"
13 
14 
15 double
TWOavalanche(TWOelem * pElem,TWOnode * pNode)16 TWOavalanche(TWOelem *pElem, TWOnode *pNode)
17 {
18 
19     TWOelem *pElemTL, *pElemTR, *pElemBL, *pElemBR;
20     TWOedge *pEdgeT, *pEdgeB, *pEdgeL, *pEdgeR;
21     int materT = 0 , materB = 0, materL = 0 , materR = 0;
22     double dxL = 0.0, dxR = 0.0, dyT = 0.0, dyB = 0.0;
23     double ef1, ef2, coeff1, coeff2;
24     double enx, eny, epx, epy, jnx, jny, jpx, jpy;
25     double current, eField;
26     double generation = 0.0;
27     double eiip2 = 4.0e5 / ENorm;
28     double aiip2 = 6.71e5 * LNorm;
29     double biip2 = 1.693e6 / ENorm;
30     TWOmaterial *info = pElem->matlInfo;
31 
32     /* Find all four neighboring elements */
33     pElemTL = pNode->pTLElem;
34     pElemTR = pNode->pTRElem;
35     pElemBL = pNode->pBLElem;
36     pElemBR = pNode->pBRElem;
37 
38     /* Null edge pointers */
39     pEdgeT = pEdgeB = pEdgeL = pEdgeR = NULL;
40 
41     /* Find edges next to node */
42     if ( pElemTL != NULL ) {
43       if (pElemTL->evalEdges[1]) {
44 	pEdgeT = pElemTL->pRightEdge;
45 	materT = pElemTL->elemType;
46 	dyT = pElemTL->dy;
47       }
48       if (pElemTL->evalEdges[2]) {
49 	pEdgeL = pElemTL->pBotEdge;
50 	materL = pElemTL->elemType;
51 	dxL = pElemTL->dx;
52       }
53     }
54     if ( pElemTR != NULL ) {
55       if (pElemTR->evalEdges[3]) {
56 	pEdgeT = pElemTR->pLeftEdge;
57 	materT = pElemTR->elemType;
58 	dyT = pElemTR->dy;
59       }
60       if (pElemTR->evalEdges[2]) {
61 	pEdgeR = pElemTR->pBotEdge;
62 	materR = pElemTR->elemType;
63 	dxR = pElemTR->dx;
64       }
65     }
66     if ( pElemBR != NULL ) {
67       if (pElemBR->evalEdges[3]) {
68 	pEdgeB = pElemBR->pLeftEdge;
69 	materB = pElemBR->elemType;
70 	dyB = pElemBR->dy;
71       }
72       if (pElemBR->evalEdges[0]) {
73 	pEdgeR = pElemBR->pTopEdge;
74 	materR = pElemBR->elemType;
75 	dxR = pElemBR->dx;
76       }
77     }
78     if ( pElemBL != NULL ) {
79       if (pElemBL->evalEdges[1]) {
80 	pEdgeB = pElemBL->pRightEdge;
81 	materB = pElemBL->elemType;
82 	dyB = pElemBL->dy;
83       }
84       if (pElemBL->evalEdges[0]) {
85 	pEdgeL = pElemBL->pTopEdge;
86 	materL = pElemBL->elemType;
87 	dxL = pElemBL->dx;
88       }
89     }
90 
91     /* compute horizontal vector components */
92     /* No more than one of Left Edge or Right Edge is absent */
93     /* If one is absent the other is guaranteed to be from silicon */
94     if (pEdgeL == NULL) {
95       if ( pNode->nodeType == CONTACT ) {
96 	enx = -(pEdgeR->dPsi + pEdgeR->dCBand) / dxR;
97 	epx = -(pEdgeR->dPsi - pEdgeR->dVBand) / dxR;
98 	jnx = pEdgeR->jn;
99 	jpx = pEdgeR->jp;
100       } else {
101 	enx = 0.0;
102 	epx = 0.0;
103 	jnx = 0.0;
104 	jpx = 0.0;
105       }
106     } else if (pEdgeR == NULL) {
107       if ( pNode->nodeType == CONTACT ) {
108 	enx = -(pEdgeL->dPsi + pEdgeL->dCBand) / dxL;
109 	epx = -(pEdgeL->dPsi - pEdgeL->dVBand) / dxL;
110 	jnx = pEdgeL->jn;
111 	jpx = pEdgeL->jp;
112       } else {
113 	enx = 0.0;
114 	epx = 0.0;
115 	jnx = 0.0;
116 	jpx = 0.0;
117       }
118     } else { /* Both edges are present */
119       coeff1 = dxL / (dxL + dxR);
120       coeff2 = dxR / (dxL + dxR);
121       ef1 = -(pEdgeL->dPsi + pEdgeL->dCBand) / dxL;
122       ef2 = -(pEdgeR->dPsi + pEdgeR->dCBand) / dxR;
123       enx = coeff2 * ef1 + coeff1 * ef2;
124       ef1 = -(pEdgeL->dPsi - pEdgeL->dVBand) / dxL;
125       ef2 = -(pEdgeR->dPsi - pEdgeR->dVBand) / dxR;
126       epx = coeff2 * ef1 + coeff1 * ef2;
127       if ( (materL == INSULATOR) || (materR == INSULATOR) ) {
128 	jnx = 0.0;
129 	jpx = 0.0;
130       } else {
131         jnx = coeff2 * pEdgeL->jn + coeff1 * pEdgeR->jn;
132         jpx = coeff2 * pEdgeL->jp + coeff1 * pEdgeR->jp;
133       }
134     }
135 
136     /* compute vertical vector components */
137     /* No more than one of Top Edge or Bottom Edge is absent */
138     /* If one is absent the other is guaranteed to be from silicon */
139     if (pEdgeT == NULL) {
140       if ( pNode->nodeType == CONTACT ) {
141 	eny = -(pEdgeB->dPsi + pEdgeB->dCBand) / dyB;
142 	epy = -(pEdgeB->dPsi - pEdgeB->dVBand) / dyB;
143 	jny = pEdgeB->jn;
144 	jpy = pEdgeB->jp;
145       } else {
146 	eny = 0.0;
147 	epy = 0.0;
148 	jny = 0.0;
149 	jpy = 0.0;
150       }
151     } else if (pEdgeB == NULL) {
152       if ( pNode->nodeType == CONTACT ) {
153 	eny = -(pEdgeT->dPsi + pEdgeT->dCBand) / dyT;
154 	epy = -(pEdgeT->dPsi - pEdgeT->dVBand) / dyT;
155 	jny = pEdgeT->jn;
156 	jpy = pEdgeT->jp;
157       } else {
158 	eny = 0.0;
159 	epy = 0.0;
160 	jny = 0.0;
161 	jpy = 0.0;
162       }
163     } else { /* Both edges are present */
164       coeff1 = dyT / (dyT + dyB);
165       coeff2 = dyB / (dyT + dyB);
166       ef1 = -(pEdgeT->dPsi + pEdgeT->dCBand) / dyT;
167       ef2 = -(pEdgeB->dPsi + pEdgeB->dCBand) / dyB;
168       eny = coeff2 * ef1 + coeff1 * ef2;
169       ef1 = -(pEdgeT->dPsi - pEdgeT->dVBand) / dyT;
170       ef2 = -(pEdgeB->dPsi - pEdgeB->dVBand) / dyB;
171       epy = coeff2 * ef1 + coeff1 * ef2;
172       if ( (materT == INSULATOR) || (materB == INSULATOR) ) {
173 	jny = 0.0;
174 	jpy = 0.0;
175       } else {
176         jny = coeff2 * pEdgeT->jn + coeff1 * pEdgeB->jn;
177         jpy = coeff2 * pEdgeT->jp + coeff1 * pEdgeB->jp;
178       }
179     }
180 
181 /*
182     fprintf(stderr,"%% en = (%9.2e,%9.2e), jn = (%9.2e,%9.2e)\n",
183       enx,eny,jnx,jny);
184     fprintf(stderr,"%% ep = (%9.2e,%9.2e), jp = (%9.2e,%9.2e)\n",
185       epx,epy,jpx,jpy);
186 */
187 
188     /* now calculate the avalanche generation rate */
189     current = hypot(jnx, jny);
190     if ( current != 0.0 ) {
191 	eField = (enx * jnx + eny * jny) / current;
192 	if ( (eField > 0) && ( info->bii[ELEC] / eField <= 80.0) ) {
193 	    generation += current * info->aii[ELEC]
194 		    * exp( - info->bii[ELEC] / eField );
195 	}
196     }
197     current = hypot(jpx, jpy);
198     if ( current != 0.0 ) {
199 	eField = (epx * jpx + epy * jpy) / current;
200 	if ( eField > eiip2 ) {
201 	    generation += current * aiip2 * exp( - biip2 / eField );
202 	} else if ( (eField > 0) && ( info->bii[HOLE] / eField <= 80.0) ) {
203 	    generation += current * info->aii[HOLE]
204 		    * exp( - info->bii[HOLE] / eField );
205 	}
206     }
207     return( generation );
208 }
209