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