PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/ciderlib/twod/twomobfn.c

https://github.com/cogenda/ngspice-gss
C | 412 lines | 368 code | 20 blank | 24 comment | 38 complexity | a0a42f64b40813b9508d68cdc6818549 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. /**********
  2. Copyright 1991 Regents of the University of California. All rights reserved.
  3. Author: 1990 David A. Gates, U. C. Berkeley CAD Group
  4. $Id: twomobfn.c,v 1.2 2005/05/21 12:37:24 sjborley Exp $
  5. **********/
  6. #include "ngspice.h"
  7. #include "numglobs.h"
  8. #include "numconst.h"
  9. #include "numenum.h"
  10. #include "twomesh.h"
  11. #include "material.h"
  12. #include "twoddefs.h"
  13. #include "twodext.h"
  14. /*
  15. * These functions calculate the variable-dependence
  16. * of the surface mobilities
  17. */
  18. void
  19. MOBsurfElec(TWOmaterial *info, TWOelem *pElem, double ex, double ey,
  20. double es, double wx, double wy, double totalConc)
  21. {
  22. double thetaA = info->thetaA[ELEC];
  23. double thetaB = info->thetaB[ELEC];
  24. double eL, eN, eD, e0, mun;
  25. double temp1, temp2, temp3, temp4, temp5;
  26. double temp6, temp7, temp8, temp9;
  27. double sgnN, sgnL;
  28. double dMunDEs; /* Surface Field Derivative */
  29. double dMunDEn; /* (Local) Normal Field Derivative */
  30. double dMunDEl; /* Tangent Field Derivative */
  31. double muHC, muSR, muLV;
  32. double dMuSRDEn;
  33. double d2MuSRDEn2;
  34. double dMuHCDEl;
  35. double dMuHCDMuSR;
  36. double d2MuHCDMuSR2;
  37. double d2MuHCDElDMuSR;
  38. double dEnDEx; /* Normal Derivative x Component */
  39. double dEnDEy; /* Normal Derivative y Component */
  40. double dEnDWx; /* Normal Derivative x Component */
  41. double dEnDWy; /* Normal Derivative y Component */
  42. double dElDEx; /* Lateral Derivative x Component */
  43. double dElDEy; /* Lateral Derivative y Component */
  44. double dElDWx; /* Lateral Derivative x Component */
  45. double dElDWy; /* Lateral Derivative y Component */
  46. if ( pElem->surface ) { /* replace one field component with surface field */
  47. if ( pElem->direction == 0 ) {
  48. ey = es;
  49. } else {
  50. ex = es;
  51. }
  52. }
  53. e0 = 1.0 / ENorm;
  54. if ( pElem->direction == 0 ) {
  55. eN = ABS( SALPHA_N*ey + SBETA_N*es );
  56. sgnN = SGN( SALPHA_N*ey + SBETA_N*es );
  57. eD = SALPHA_N*( es - ey );
  58. dEnDEx = 0.0;
  59. dEnDEy = 1.0;
  60. dEnDWx = 0.0;
  61. dEnDWy = 0.0;
  62. eL = ABS( ex );
  63. sgnL = SGN( ex );
  64. dElDEx = 1.0;
  65. dElDEy = 0.0;
  66. dElDWx = 0.0;
  67. dElDWy = 0.0;
  68. } else { /* pElem->direction == Y */
  69. eN = ABS( SALPHA_N*ex + SBETA_N*es );
  70. sgnN = SGN( SALPHA_N*ex + SBETA_N*es );
  71. eD = SALPHA_N*( es - ex );
  72. dEnDEx = 1.0;
  73. dEnDEy = 0.0;
  74. dEnDWx = 0.0;
  75. dEnDWy = 0.0;
  76. eL = ABS( ey );
  77. sgnL = SGN( ey );
  78. dElDEx = 0.0;
  79. dElDEy = 1.0;
  80. dElDWx = 0.0;
  81. dElDWy = 0.0;
  82. }
  83. /*
  84. fprintf(stderr,"En = %e, Ep = %e, Ey = %e, Es= %e\n",eN,eL,ey,es);
  85. */
  86. muLV = pElem->mun0;
  87. if ( TransDepMobility ) {
  88. /* Compute various partial derivatives of muSR */
  89. temp1 = 1.0 / ( 1.0 + thetaA*eN + thetaB*eN*eN );
  90. temp2 = (thetaA + 2.0*thetaB*eN);
  91. muSR = muLV * temp1;
  92. dMuSRDEn = - muSR * temp1 * temp2;
  93. d2MuSRDEn2 = - 2.0 * (dMuSRDEn * temp1 * temp2 + muSR * temp1 * thetaB);
  94. if ( FieldDepMobility ) {
  95. /* Compute various partial derivatives of muHC */
  96. switch ( info->fieldModel ) {
  97. case CT:
  98. case AR:
  99. case UF:
  100. temp1 = 1.0 / info->vSat[ELEC];
  101. temp2 = muSR * temp1;
  102. temp3 = eL * temp1;
  103. temp4 = eL * temp2;
  104. temp5 = 1.0 / ( 1.0 + temp4 * temp4 );
  105. temp6 = sqrt( temp5 );
  106. muHC = muSR * temp6;
  107. dMuHCDMuSR = temp5 * temp6;
  108. temp7 = temp4 * dMuHCDMuSR;
  109. temp8 = - 3.0 * temp7 * temp5;
  110. dMuHCDEl = - muSR * temp7 * temp2;
  111. d2MuHCDMuSR2 = temp8 * temp3;
  112. d2MuHCDElDMuSR = temp8 * temp2;
  113. break;
  114. case SG:
  115. default:
  116. temp1 = 1.0 / info->vSat[ELEC];
  117. temp2 = muSR * eL * temp1; /* Vdrift / Vsat */
  118. temp3 = 1.0 / info->vWarm[ELEC];
  119. temp4 = muSR * eL * temp3; /* Vdrift / Vwarm */
  120. temp5 = temp4 / (temp4 + SG_FIT_N);
  121. temp6 = 1.0 / (1.0 + temp5*temp4 + temp2*temp2);
  122. temp7 = sqrt(temp6);
  123. muHC = muSR * temp7;
  124. temp7 *= temp6;
  125. temp8 = (2.0 - temp5)*temp5*temp3 + 2.0*temp2*temp1;
  126. dMuHCDEl = - 0.5*muSR*temp7*temp8 * muSR;
  127. temp9 = temp5*temp5;
  128. dMuHCDMuSR = (1.0 + 0.5*temp9*temp4) * temp7;
  129. temp9 = (1.5 - temp5)*temp9*temp3 * temp7;
  130. temp9 -= 1.5 * dMuHCDMuSR * temp6 * temp8;
  131. d2MuHCDMuSR2 = temp9 * eL;
  132. d2MuHCDElDMuSR = temp9 * muSR;
  133. break;
  134. }
  135. /* Now compute total derivatives */
  136. temp1 = dMuHCDMuSR * dMuSRDEn * sgnN;
  137. temp2 = d2MuHCDMuSR2 * dMuSRDEn * dMuSRDEn + dMuHCDMuSR * d2MuSRDEn2;
  138. temp3 = temp1 - temp2 * eD;
  139. mun = muHC - temp1 * eD;
  140. dMunDEn = (temp3 + temp1) * SALPHA_N;
  141. dMunDEs = temp3 * SBETA_N - temp1 * SALPHA_N;
  142. dMunDEl = (dMuHCDEl - d2MuHCDElDMuSR * dMuSRDEn * sgnN * eD) * sgnL;
  143. } else {
  144. /* Now compute total derivatives */
  145. temp1 = dMuSRDEn * sgnN;
  146. temp3 = temp1 - d2MuSRDEn2 * eD;
  147. mun = muSR - temp1 * eD;
  148. dMunDEn = (temp3 + temp1) * SALPHA_N;
  149. dMunDEs = temp3 * SBETA_N - temp1 * SALPHA_N;
  150. dMunDEl = 0.0;
  151. }
  152. } else {
  153. if ( FieldDepMobility ) {
  154. /* Compute various partial derivatives of muHC */
  155. switch ( info->fieldModel ) {
  156. case CT:
  157. case AR:
  158. case UF:
  159. temp1 = muLV / info->vSat[ELEC];
  160. temp2 = eL * temp1;
  161. temp3 = 1.0 / ( 1.0 + temp2 * temp2 );
  162. temp4 = sqrt( temp3 );
  163. muHC = muLV * temp4;
  164. dMuHCDEl = - muHC*temp2*temp3 * temp1;
  165. break;
  166. case SG:
  167. default:
  168. temp1 = 1.0 / info->vSat[ELEC];
  169. temp2 = muLV * eL * temp1; /* Vdrift / Vsat */
  170. temp3 = 1.0 / info->vWarm[ELEC];
  171. temp4 = muLV * eL * temp3; /* Vdrift / Vwarm */
  172. temp5 = temp4 / (temp4 + SG_FIT_N);
  173. temp6 = 1.0 / (1.0 + temp5*temp4 + temp2*temp2);
  174. temp7 = sqrt(temp6);
  175. muHC = muLV * temp7;
  176. temp8 = (2.0 - temp5)*temp5*temp3 + 2.0*temp2*temp1;
  177. dMuHCDEl = - 0.5*muHC*temp6*temp8 * muLV;
  178. break;
  179. }
  180. /* Now compute total derivatives */
  181. mun = muHC;
  182. dMunDEn = 0.0;
  183. dMunDEs = 0.0;
  184. dMunDEl = dMuHCDEl * sgnL;
  185. } else {
  186. mun = muLV;
  187. dMunDEn = 0.0;
  188. dMunDEs = 0.0;
  189. dMunDEl = 0.0;
  190. }
  191. }
  192. pElem->mun = mun;
  193. pElem->dMunDEs = dMunDEs;
  194. pElem->dMunDEx = dMunDEn * dEnDEx + dMunDEl * dElDEx;
  195. pElem->dMunDEy = dMunDEn * dEnDEy + dMunDEl * dElDEy;
  196. pElem->dMunDWx = dMunDEn * dEnDWx + dMunDEl * dElDWx;
  197. pElem->dMunDWy = dMunDEn * dEnDWy + dMunDEl * dElDWy;
  198. if ( pElem->surface ) { /* replace one field component with surface field */
  199. if ( pElem->direction == 0 ) {
  200. pElem->dMunDEs += pElem->dMunDEy;
  201. pElem->dMunDEy = 0.0;
  202. } else {
  203. pElem->dMunDEs += pElem->dMunDEx;
  204. pElem->dMunDEx = 0.0;
  205. }
  206. }
  207. return;
  208. }
  209. void
  210. MOBsurfHole(TWOmaterial *info, TWOelem *pElem, double ex, double ey,
  211. double es, double wx, double wy, double totalConc)
  212. {
  213. double thetaA = info->thetaA[HOLE];
  214. double thetaB = info->thetaB[HOLE];
  215. double eL, eN, eD, mup;
  216. double temp1, temp2, temp3, temp4, temp5;
  217. double temp6, temp7, temp8, temp9;
  218. double sgnN, sgnL;
  219. double dMupDEs; /* Surface Field Derivative */
  220. double dMupDEn; /* (Local) Normal Field Derivative */
  221. double dMupDEl; /* Tangent Field Derivative */
  222. double muHC, muSR, muLV;
  223. double dMuSRDEn;
  224. double d2MuSRDEn2;
  225. double dMuHCDEl;
  226. double dMuHCDMuSR;
  227. double d2MuHCDMuSR2;
  228. double d2MuHCDElDMuSR;
  229. double dEnDEx; /* Normal Derivative x Component */
  230. double dEnDEy; /* Normal Derivative y Component */
  231. double dEnDWx; /* Normal Derivative x Component */
  232. double dEnDWy; /* Normal Derivative y Component */
  233. double dElDEx; /* Lateral Derivative x Component */
  234. double dElDEy; /* Lateral Derivative y Component */
  235. double dElDWx; /* Lateral Derivative x Component */
  236. double dElDWy; /* Lateral Derivative y Component */
  237. if ( pElem->surface ) { /* replace one field component with surface field */
  238. if ( pElem->direction == 0 ) {
  239. ey = es;
  240. } else {
  241. ex = es;
  242. }
  243. }
  244. if ( pElem->direction == 0 ) {
  245. eN = ABS( SALPHA_P*ey + SBETA_P*es );
  246. sgnN = SGN( SALPHA_P*ey + SBETA_P*es );
  247. eD = SALPHA_P*( es - ey );
  248. dEnDEx = 0.0;
  249. dEnDEy = 1.0;
  250. dEnDWx = 0.0;
  251. dEnDWy = 0.0;
  252. eL = ABS( ex );
  253. sgnL = SGN( ex );
  254. dElDEx = 1.0;
  255. dElDEy = 0.0;
  256. dElDWx = 0.0;
  257. dElDWy = 0.0;
  258. } else { /* pElem->direction == Y */
  259. eN = ABS( SALPHA_P*ex + SBETA_P*es );
  260. sgnN = SGN( SALPHA_P*ex + SBETA_P*es );
  261. eD = SALPHA_P*( es - ex );
  262. dEnDEx = 1.0;
  263. dEnDEy = 0.0;
  264. dEnDWx = 0.0;
  265. dEnDWy = 0.0;
  266. eL = ABS( ey );
  267. sgnL = SGN( ey );
  268. dElDEx = 0.0;
  269. dElDEy = 1.0;
  270. dElDWx = 0.0;
  271. dElDWy = 0.0;
  272. }
  273. muLV = pElem->mup0;
  274. if ( TransDepMobility ) {
  275. /* Compute various partial derivatives of muSR */
  276. temp1 = 1.0 / ( 1.0 + thetaA*eN + thetaB*eN*eN );
  277. temp2 = thetaA + 2.0*thetaB*eN;
  278. muSR = muLV * temp1;
  279. dMuSRDEn = - muSR * temp1 * temp2;
  280. d2MuSRDEn2 = - 2.0 * (dMuSRDEn * temp1 * temp2 + muSR * temp1 * thetaB);
  281. if ( FieldDepMobility ) {
  282. /* Compute various partial derivatives of muHC */
  283. switch ( info->fieldModel ) {
  284. case CT:
  285. case AR:
  286. case UF:
  287. temp1 = 1.0 / info->vSat[HOLE];
  288. temp2 = muSR * temp1;
  289. temp3 = eL * temp1;
  290. temp4 = eL * temp2;
  291. temp5 = 1.0 / ( 1.0 + temp4 );
  292. muHC = muSR * temp5;
  293. dMuHCDMuSR = temp5 * temp5;
  294. dMuHCDEl = - muSR * dMuHCDMuSR * temp2;
  295. temp6 = - 2.0 * dMuHCDMuSR * temp5;
  296. d2MuHCDMuSR2 = temp6 * temp3;
  297. d2MuHCDElDMuSR = temp6 * temp2;
  298. break;
  299. case SG:
  300. default:
  301. temp1 = 1.0 / info->vSat[HOLE];
  302. temp2 = muSR * eL * temp1; /* Vdrift / Vsat */
  303. temp3 = 1.0 / info->vWarm[HOLE];
  304. temp4 = muSR * eL * temp3; /* Vdrift / Vwarm */
  305. temp5 = temp4 / (temp4 + SG_FIT_P);
  306. temp6 = 1.0 / (1.0 + temp5*temp4 + temp2*temp2);
  307. temp7 = sqrt(temp6);
  308. muHC = muSR * temp7;
  309. temp7 *= temp6;
  310. temp8 = (2.0 - temp5)*temp5*temp3 + 2.0*temp2*temp1;
  311. dMuHCDEl = - 0.5*muSR*temp7*temp8 * muSR;
  312. temp9 = temp5*temp5;
  313. dMuHCDMuSR = (1.0 + 0.5*temp9*temp4) * temp7;
  314. temp9 = (1.5 - temp5)*temp9*temp3 * temp7;
  315. temp9 -= 1.5 * dMuHCDMuSR * temp6 * temp8;
  316. d2MuHCDMuSR2 = temp9 * eL;
  317. d2MuHCDElDMuSR = temp9 * muSR;
  318. break;
  319. }
  320. /* Now compute total derivatives */
  321. temp1 = dMuHCDMuSR * dMuSRDEn * sgnN;
  322. temp2 = d2MuHCDMuSR2 * dMuSRDEn * dMuSRDEn + dMuHCDMuSR * d2MuSRDEn2;
  323. temp3 = temp1 - temp2 * eD;
  324. mup = muHC - temp1 * eD;
  325. dMupDEn = (temp3 + temp1) * SALPHA_P;
  326. dMupDEs = temp3 * SBETA_P - temp1 * SALPHA_P;
  327. dMupDEl = (dMuHCDEl - d2MuHCDElDMuSR * dMuSRDEn * sgnN * eD ) * sgnL;
  328. } else {
  329. /* Now compute total derivatives */
  330. temp1 = dMuSRDEn * sgnN;
  331. temp3 = temp1 - d2MuSRDEn2 * eD;
  332. mup = muSR - temp1 * eD;
  333. dMupDEn = (temp3 + temp1) * SALPHA_P;
  334. dMupDEs = temp3 * SBETA_P - temp1 * SALPHA_P;
  335. dMupDEl = 0.0;
  336. }
  337. } else {
  338. if ( FieldDepMobility ) {
  339. /* Compute various partial derivatives of muHC */
  340. switch ( info->fieldModel ) {
  341. case CT:
  342. case AR:
  343. case UF:
  344. temp1 = muLV / info->vSat[HOLE];
  345. temp2 = eL * temp1;
  346. temp3 = 1.0 / ( 1.0 + temp2 );
  347. muHC = muLV * temp3;
  348. dMuHCDEl = - muHC * temp3 * temp1;
  349. break;
  350. case SG:
  351. default:
  352. temp1 = 1.0 / info->vSat[HOLE];
  353. temp2 = muLV * eL * temp1; /* Vdrift / Vsat */
  354. temp3 = 1.0 / info->vWarm[HOLE];
  355. temp4 = muLV * eL * temp3; /* Vdrift / Vwarm */
  356. temp5 = temp4 / (temp4 + SG_FIT_P);
  357. temp6 = 1.0 / (1.0 + temp5*temp4 + temp2*temp2);
  358. temp7 = sqrt(temp6);
  359. muHC = muLV * temp7;
  360. temp8 = (2.0 - temp5)*temp5*temp3 + 2.0*temp2*temp1;
  361. dMuHCDEl = - 0.5*muHC*temp6*temp8 * muLV;
  362. break;
  363. }
  364. /* Now compute total derivatives */
  365. mup = muHC;
  366. dMupDEn = 0.0;
  367. dMupDEs = 0.0;
  368. dMupDEl = dMuHCDEl * sgnL;
  369. } else {
  370. mup = muLV;
  371. dMupDEn = 0.0;
  372. dMupDEs = 0.0;
  373. dMupDEl = 0.0;
  374. }
  375. }
  376. pElem->mup = mup;
  377. pElem->dMupDEs = dMupDEs;
  378. pElem->dMupDEx = dMupDEn * dEnDEx + dMupDEl * dElDEx;
  379. pElem->dMupDEy = dMupDEn * dEnDEy + dMupDEl * dElDEy;
  380. pElem->dMupDWx = dMupDEn * dEnDWx + dMupDEl * dElDWx;
  381. pElem->dMupDWy = dMupDEn * dEnDWy + dMupDEl * dElDWy;
  382. if ( pElem->surface ) { /* replace one field component with surface field */
  383. if ( pElem->direction == 0 ) {
  384. pElem->dMupDEs += pElem->dMupDEy;
  385. pElem->dMupDEy = 0.0;
  386. } else {
  387. pElem->dMupDEs += pElem->dMupDEx;
  388. pElem->dMupDEx = 0.0;
  389. }
  390. }
  391. return;
  392. }