Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_MaterialSupport.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2014 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_MaterialSupport.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 07/19/03
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.33 $
40 //
41 // Revision Date : $Date: 2014/04/24 21:57:47 $
42 //
43 // Current Owner : $Author: erkeite $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 
49 // ---------- Standard Includes ----------
50 #ifdef HAVE_CMATH
51 #include <cmath>
52 #else
53 #include <math.h>
54 #endif
55 
56 #ifdef Xyce_DEBUG_DEVICE
57 #include <iostream>
58 #endif
59 
60 // ---------- Xyce Includes ----------
61 #include <N_DEV_MaterialSupport.h>
62 
63 namespace Xyce {
64 namespace Device {
65 
66 // ----------------------------------------------------------------------------
67 // Function : MaterialSupport::getEffectiveMassN
68 // Purpose : returns effective mass for electrons.
69 // Special Notes : Relative to free space mass.
70 //
71 // These are from Appendix 3 of Streetman.
72 //
73 // Scope : public
74 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
75 // Creation Date : 7/19/03
76 // ----------------------------------------------------------------------------
77 double MaterialSupport::getEffectiveMassN (const std::string & material)
78 {
79  ExtendedString mater = material;
80  mater.toLower();
81 
82  double mass=0.0;
83 
84  if (mater == "si")
85  {
86  double ml = 0.98; // longitudinal mass
87  double mt = 0.19; // transverse mass
88  mass = pow((ml*mt*mt),1.0/3.0);
89  }
90  else if (mater == "ge" )
91  {
92  double ml = 1.64; // longitudinal mass
93  double mt = 0.082; // transverse mass
94  mass = pow((1.64*0.082*0.082),1.0/3.0);
95  }
96  else if (mater == "gaas")
97  {
98  //mass = 0.067;
99  mass = 6.69935094e-2;
100  }
101  else if (mater=="inalas" || mater=="alinas")
102  {
103  mass = 0.074;
104  //dnco= 0.020;
105  }
106  else if (mater=="ingaas" || mater=="gainas")
107  {
108  mass = 0.041;
109  // dnco= 0.0083;
110  }
111  else if (mater == "ingap")
112  {
113  mass = 0.0179;
114  // dnco = 0.02391;
115  }
116  else if (mater == "inp")
117  {
118  mass = 0.079;
119  // dnco= 0.01734;
120  }
121  else
122  {
123  Report::UserFatal0() << material << " material not recognized.";
124  }
125 
126  return mass;
127 }
128 
129 // ----------------------------------------------------------------------------
130 // Function : MaterialSupport::getEffectiveMassP
131 // Purpose : returns effective mass for holes.
132 // Special Notes : Relative to free space mass.
133 //
134 // These are from Appendix 3 of Streetman.
135 //
136 // Scope : public
137 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
138 // Creation Date : 7/19/03
139 // ----------------------------------------------------------------------------
140 double MaterialSupport::getEffectiveMassP (const std::string & material)
141 {
142  ExtendedString mater = material;
143  mater.toLower();
144  double mass=0.0;
145 
146  if (mater == "si")
147  {
148  double mlh = 0.16; // light hole mass
149  double mhh = 0.49; // heavy hole mass
150  mass = pow((pow(mlh,1.5) + pow(mhh,1.5)),2.0/3.0);
151  }
152  else if (mater == "ge" )
153  {
154  double mlh = 0.04; // light hole mass
155  double mhh = 0.28; // heavy hole mass
156  mass = pow((pow(mlh, 1.5) + pow(mhh, 1.5)),2.0/3.0);
157  }
158  else if (mater == "gaas")
159  {
160 #if 1
161  // Note: Wampler's value of dnva = 0.4318
162  // Their SAND report uses a DOS effective mass as: mh*=0.571
163  // Note that the electron effective mass for GaAs seems to be uncontroversial m=0.067
164  // In order to match XPD, and pass historical regression tests, etc, using this number.
165  //mass=0.571;
166  mass=5.71287987e-1;
167 #endif
168 #if 0
169  // These are the original values in this file:
170  // Streetman, Appendix III:
171  // This gives dnva = 0.373684
172  double mlh = 0.074; // light hole mass
173  double mhh = 0.5; // heavy hole mass
174  mass = pow((pow(mlh,1.5) + pow(mhh, 1.5)), 2.0/3.0);
175 #endif
176 #if 0
177  // Websites: http://ecee.colorado.edu/~bart/book/book/chapter2/pdf/ch2_3_7.pdf
178  // http://ecee.colorado.edu/~bart/book/effmass.htm#dosmass
179  // http://www.semiconductors.co.uk/propiiiv5653.htm
180  //
181  // These have been referenced as coming from "Singh, 1993":
182  // Singh J, 1993, "Physics of Semiconductors and Their Heterostructures" (McGraw-Hill)
183  //
184  // This gives dnva = 0.32535
185  double mlh = 0.082; // light hole mass
186  double mhh = 0.45; // heavy hole mass
187  mass = pow((pow(mlh,1.5) + pow(mhh, 1.5)), 2.0/3.0);
188 #endif
189 #if 0
190  // William Liu HBT book:
191  // this gives dnva = 0.51385
192  double mlh = 0.087; // light hole mass
193  double mhh = 0.62; // heavy hole mass
194  mass = pow((pow(mlh,1.5) + pow(mhh, 1.5)), 2.0/3.0);
195 #endif
196  }
197  else if (mater=="inalas" || mater=="alinas")
198  {
199  double mlh = 0.08; // light hole mass
200  double mhh = 0.6; // heavy hole mass
201  mass = pow((pow(mlh,1.5) + pow(mhh, 1.5)), 2.0/3.0);
202  }
203  else if (mater=="ingaas" || mater=="gainas")
204  {
205  double mlh = 0.05; // light hole mass
206  double mhh = 0.54; // heavy hole mass
207  mass = pow((pow(mlh,1.5) + pow(mhh, 1.5)), 2.0/3.0);
208  }
209  else if (mater=="ingap")
210  {
211  // dnva = 0.5423;
212  //mass = 0.665;
213  mass = 6.65007285e-1;
214  }
215  else if (mater == "inp")
216  {
217  double mlh = 0.074; // light hole mass
218  double mhh = 0.5; // heavy hole mass
219  mass = pow((pow(mlh,1.5) + pow(mhh, 1.5)), 2.0/3.0);
220  }
221  else
222  {
223  Report::UserFatal0() << material << " material not recognized.";
224  }
225 
226  return mass;
227 }
228 
229 // ----------------------------------------------------------------------------
230 // Function : MaterialSupport::get_DOS_EffectiveMassN
231 // Purpose : returns effective mass for electrons for density of states
232 // Special Notes : See http://ecee.colorado.edu/~bart/book/effmass.htm#dosmass.
233 //
234 // m_e_dos = Mc^(2/3) * (m_l*m_t*m_t)^(1/3)
235 //
236 // Scope : public
237 // Creator : Eric R. Keiter, SNL
238 // Creation Date :
239 // ----------------------------------------------------------------------------
240 double MaterialSupport::get_DOS_EffectiveMassN (const std::string & material)
241 {
242  ExtendedString mater = material;
243  mater.toLower();
244  double mass;
245 
246  if (mater == "si")
247  {
248  double ml = 0.98; // longitudinal mass
249  double mt = 0.19; // transverse mass
250  double Mc = 6.0; // degeneracy factor (number of equivalent band minimums)
251  mass = pow(Mc,2.0/3.0)*pow((ml*mt*mt),1.0/3.0);
252  // Note, this should evaluate to 1.08.
253  }
254  else if (mater == "ge")
255  {
256  double ml = 1.64; // longitudinal mass
257  double mt = 0.082; // transverse mass
258  double Mc = 4.0; // degeneracy factor
259  mass = pow(Mc,2.0/3.0)*pow((ml*mt*mt),1.0/3.0);
260  // this mass should be around 0.56
261  }
262  else if (mater == "gaas")
263  {
264  mass = 0.067; // GaAs is isotropic
265  }
266  else if (mater=="inalas" || mater=="alinas")
267  {
268  //dnco= 0.020; = mass^(1.5)
269  mass = 0.074;
270  }
271  else if (mater=="ingaas" || mater=="gainas")
272  {
273  // dnco= 0.0083; = mass^(1.5)
274  mass = 0.041;
275  }
276  else if (mater=="ingap")
277  {
278  // dnco = 0.02391;
279  //mass = 0.0179;
280  mass = 8.29952143e-2;
281  }
282  else if (mater == "inp")
283  {
284  mass = 0.079;
285  }
286  else
287  {
288  Report::UserFatal0() << material << " material not recognized.";
289  }
290 
291  return mass;
292 }
293 
294 // ----------------------------------------------------------------------------
295 // Function : MaterialSupport::get_DOS_EffectiveMassP
296 // Purpose : returns effective mass for holes for density of states
297 // Special Notes :
298 //
299 // Scope : public
300 // Creator : Eric R. Keiter, SNL
301 // Creation Date :
302 // ----------------------------------------------------------------------------
303 double MaterialSupport::get_DOS_EffectiveMassP (const std::string & material)
304 {
305  // Unlike for electrons, Mc is not applied to holes, so this is simply
306  // the same as the non-DOS version.
307  return getEffectiveMassP (material);
308 }
309 
310 // ----------------------------------------------------------------------------
311 // Function : MaterialSupport::getNc
312 // Purpose : density of states, conduction band
313 // Special Notes :
314 //
315 // Nc = 2*(2*pi*me*kT/h^2)^(3/2)
316 // = 2*(2*pi*me_DOS*m0*kT/h^2)^(3/2)
317 //
318 // Scope : public
319 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
320 // Creation Date : 4/10/2014
321 // ----------------------------------------------------------------------------
322 double MaterialSupport::getNc (const std::string & material, double temp)
323 {
324  double h_planck(CONSTplanck); // Planck's constant (in J-s)
325  double e_mass (CONSTemass); // e- mass in kg.
326  double kb (1.3806488e-23); // boltzmann's constant (J/K)
327  double meDOS = get_DOS_EffectiveMassN(material);
328  double dnbnd0 = 2.0*M_PI*meDOS*e_mass*kb*temp/(h_planck*h_planck);
329  double Nc = 2.0*pow(dnbnd0,1.5)/1.0e6;
330  return Nc;
331 }
332 
333 // ----------------------------------------------------------------------------
334 // Function : MaterialSupport::getNv
335 // Purpose : Density of states, valance band.
336 // Special Notes :
337 //
338 // Nv = 2*(2*pi*mh*kT/h^2)^(3/2)
339 // = 2*(2*pi*mh_DOS*m0*kT/h^2)^(3/2)
340 //
341 // Scope : public
342 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
343 // Creation Date : 4/10/2014
344 // ----------------------------------------------------------------------------
345 double MaterialSupport::getNv (const std::string & material, double temp)
346 {
347  double h_planck(CONSTplanck); // Planck's constant (in J-s)
348  double e_mass (CONSTemass); // e- mass in kg.
349  double kb (1.3806488e-23); // boltzmann's constant (J/K)
350  double mhDOS = get_DOS_EffectiveMassP(material);
351  double dnbnd0 = 2.0*M_PI*mhDOS*e_mass*kb*temp/(h_planck*h_planck);
352  double Nv = 2.0*pow(dnbnd0,1.5)/1.0e6;
353  return Nv;
354 }
355 
356 // ----------------------------------------------------------------------------
357 // Function : MaterialSupport::getNi
358 // Purpose : returns intrinsic electron concentration.
359 // Special Notes :
360 // Scope : public
361 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
362 // Creation Date : 10/24/12
363 // ----------------------------------------------------------------------------
364 double MaterialSupport::getNi (const std::string & material, double temp)
365 {
366  ExtendedString mater = material;
367  mater.toLower();
368  double ni=0.0;
369  double kbq = 8.6173324e-5; // boltzmann's constant (eV/K)
370  double bg = bandgap(mater,temp);
371  double Nc = getNc(mater,temp);
372  double Nv = getNv(mater,temp);
373  ni = sqrt (Nc * Nv) * exp(-bg/(2.0 * kbq * temp));
374  return ni;
375 }
376 
377 // ----------------------------------------------------------------------------
378 // Function : MaterialSupport::getNi_old
379 // Purpose : returns intrinsic electron concentration.
380 // Special Notes :
381 // Scope : public
382 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
383 // Creation Date : 7/19/03
384 // ----------------------------------------------------------------------------
385 double MaterialSupport::getNi_old (const std::string & material, double temp)
386 {
387  ExtendedString mater = material;
388  mater.toLower();
389  double ni=0.0;
390 
391  if (mater == "si")
392  {
393  ni = 4.9e15
394  * pow(getEffectiveMassN(mater)*getEffectiveMassP(mater),0.75)
395  * pow(6.0,0.5) * pow(temp, 1.5) * exp(-bandgap(mater,temp)/
396  (2.0 * 8.6174e-5 * temp));
397  // ni = 1.25e10;
398  }
399  else if (mater == "gaas")
400  {
401  ni = 4.9e15
402  * pow(getEffectiveMassN(mater)*getEffectiveMassP(mater),0.75)
403  * pow(temp, 1.5) * exp(-bandgap(mater,temp)/
404  (2.0 * 8.6174e-5 * temp));
405  //ni = 2.0e6;
406  }
407  else if (mater == "ge")
408  {
409  ni = 4.9e15
410  * pow(getEffectiveMassN(mater)*getEffectiveMassP(mater),0.75)
411  * 2.0 * pow(temp, 1.5) * exp(-bandgap(mater,temp)/
412  (2.0 * 8.6174e-5 * temp));
413  // ni = 2.5e13;
414  }
415  // for the next several, as they are all III-V materials, I copied the
416  // gaas functions. I *think* this is correct, as I *think* that Mc is
417  // going to be 1.0 for all of these.
418  else if (mater=="inalas" || mater=="alinas") // indium aluminum arsenide
419  {
420  ni = 4.9e15
421  * pow(getEffectiveMassN(mater)*getEffectiveMassP(mater),0.75)
422  * pow(temp, 1.5) * exp(-bandgap(mater,temp)/
423  (2.0 * 8.6174e-5 * temp));
424  }
425  else if (mater=="ingaas" || mater=="gainas") // indium galium arsenide
426  {
427  ni = 4.9e15
428  * pow(getEffectiveMassN(mater)*getEffectiveMassP(mater),0.75)
429  * pow(temp, 1.5) * exp(-bandgap(mater,temp)/
430  (2.0 * 8.6174e-5 * temp));
431  }
432  else if (mater == "inp")
433  {
434  ni = 4.9e15
435  * pow(getEffectiveMassN(mater)*getEffectiveMassP(mater),0.75)
436  * pow(temp, 1.5) * exp(-bandgap(mater,temp)/
437  (2.0 * 8.6174e-5 * temp));
438  }
439  else
440  {
441  std::string msg = "MaterialSupport::getNi: ";
442  msg += material;
443  msg += " material not recognized.\n";
444  N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
445  }
446 
447  return ni;
448 }
449 
450 // ----------------------------------------------------------------------------
451 // Function : MaterialSupport::getRelPerm
452 // Purpose : returns relative permitivity
453 // Special Notes :
454 // Scope : public
455 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
456 // Creation Date : 7/19/03
457 // ----------------------------------------------------------------------------
458 double MaterialSupport::getRelPerm (const std::string & material)
459 {
460  ExtendedString mater = material;
461  mater.toLower();
462 
463  double perm;
464  if (mater == "si")
465  {
466  perm = 11.8;
467  }
468  else if (mater == "sio2")
469  {
470  perm = 3.9;
471  }
472  else if (mater == "ge" )
473  {
474  perm = 16.0;
475  }
476  else if (mater == "gaas")
477  {
478  perm = 13.2;
479  }
480  else if (mater=="inalas" || mater=="alinas") // indium aluminum arsenide
481  {
482  perm = 12.5;
483  }
484  else if (mater=="ingaas" || mater=="gainas") // indium galium arsenide
485  {
486  perm = 14.0;
487  }
488  else if (mater == "inp")
489  {
490  perm = 12.6;
491  }
492  else
493  {
494  Report::UserFatal0() << material << " material not recognized.";
495  }
496 
497  return perm;
498 }
499 
500 // ----------------------------------------------------------------------------
501 // Function : MaterialSupport::calcRsrh
502 // Purpose : Calculates schockley-read-hall recombination.
503 //
504 // Special Notes : For this function, it shouldn't matter if the variables
505 // are scaled or not.
506 //
507 // The material dependence here comes indirectly, from the
508 // lifetimes, the carrier densities, and Ni, the intrinsic
509 // concentration.
510 //
511 // Scope : public
512 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
513 // Creation Date : 6/27/03
514 // ----------------------------------------------------------------------------
516  (const std::string & material, double ni, double n, double p, double tn, double tp)
517 {
518  double Ni = ni;
519  double pn = Ni*Ni;
520 
521  double A = (n*p-pn);
522  double B = (tp*(n+Ni)+tn*(p+Ni));
523 
524  double arg = CONSTMAX_EXP_ARG;
525  if (B >= exp(arg)) B = exp(arg);
526 
527  return (A/B);
528 }
529 
530 // ----------------------------------------------------------------------------
531 // Function : MaterialSupport::pdRsrhN
532 // Purpose : Calculates partial derivatives for schockley-read-hall
533 // recombination, with respect to electron density.
534 //
535 // Special Notes : For this function, it shouldn't matter if the variables
536 // are scaled or not.
537 //
538 // The material dependence here comes indirectly, from the
539 // lifetimes, the carrier densities, and Ni, the intrinsic
540 // concentration.
541 //
542 // Scope : public
543 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
544 // Creation Date : 7/19/03
545 // ----------------------------------------------------------------------------
547  (const std::string & material, double ni, double n, double p, double tn, double tp)
548 {
549  double Ni = ni;
550  double pdRsrhN;
551  double A1, B1, C1;
552  double dAdn;
553  double dBdn;
554 
555  double pn = Ni*Ni;
556 
557  double arg = CONSTMAX_EXP_ARG;
558 
559  A1 = (n*p-pn);
560  if (A1 >= exp(arg)) A1 = exp(arg);
561 
562  dAdn = (p);
563 
564  C1 = (tp*(n+Ni)+tn*(p+Ni));
565  if (C1 >= exp(arg)) C1 = exp(arg);
566 
567  B1 = 1.0/C1;
568  dBdn = -1.0/(C1*C1) * tp;
569 
570  pdRsrhN = dAdn * B1 + dBdn * A1;
571 
572  return pdRsrhN;
573 }
574 
575 // ----------------------------------------------------------------------------
576 // Function : MaterialSupport::pdRsrhP
577 // Purpose : Calculates partial derivatives for schockley-read-hall
578 // recombination, with respect to hole density.
579 //
580 // Special Notes : For this function, it shouldn't matter if the variables
581 // are scaled or not.
582 //
583 // The material dependence here comes indirectly, from the
584 // lifetimes, the carrier densities, and Ni, the intrinsic
585 // concentration.
586 //
587 // Scope : public
588 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
589 // Creation Date : 7/19/03
590 // ----------------------------------------------------------------------------
592  (const std::string & material, double ni, double n, double p, double tn, double tp)
593 {
594  double Ni = ni;
595  double pdRsrhP;
596  double A1, B1, C1;
597  double dAdp;
598  double dBdp;
599 
600  double pn = Ni*Ni;
601 
602  double arg = CONSTMAX_EXP_ARG;
603 
604  A1 = (n*p-pn);
605  if (A1 >= exp(arg)) A1 = exp(arg);
606 
607  dAdp = (n);
608 
609  C1 = (tp*(n+Ni)+tn*(p+Ni));
610  if (C1 >= exp(arg)) C1 = exp(arg);
611 
612  B1 = 1.0/C1;
613  dBdp = -1.0/(C1*C1) * tn;
614 
615  pdRsrhP = dAdp * B1 + dBdp * A1;
616 
617  return pdRsrhP;
618 }
619 
620 
621 // ----------------------------------------------------------------------------
622 // Function : MaterialSupport::calcRaug
623 // Purpose : Calculates Auger recombination.
624 //
625 // Special Notes : For this function, it shouldn't matter if the variables
626 // are scaled or not.
627 //
628 // I believe (but am not sure) that the constants Cn and Cp
629 // are material dependent. That is part of why the
630 // material name is passed in as an argument. The values
631 // here are for Si.
632 //
633 // Scope : public
634 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
635 // Creation Date : 6/27/03
636 // ----------------------------------------------------------------------------
638  (const std::string & material, double ni, double n, double p)
639 {
640  double Ni = ni;
641  double Cn = 2.8e-31;
642  double Cp = 1.2e-31;
643  double pn = Ni*Ni;
644 
645  double A = (n*p-pn);
646  double C = (Cn*n+Cp*p);
647 
648  double arg = CONSTMAX_EXP_ARG;
649  if (C >= exp(arg)) C = exp(arg);
650 
651  return (A*C);
652 }
653 
654 // ----------------------------------------------------------------------------
655 // Function : MaterialSupport::pdRaugN
656 // Purpose : Calculates partial derivative w.r.t. electron density
657 // for Auger recombination.
658 //
659 // Special Notes : For this function, it shouldn't matter if the variables
660 // are scaled or not.
661 //
662 // I believe (but am not sure) that the constants Cn and Cp
663 // are material dependent. That is part of why the
664 // material name is passed in as an argument. The values
665 // here are for Si.
666 //
667 // Scope : public
668 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
669 // Creation Date : 7/19/03
670 // ----------------------------------------------------------------------------
672  (const std::string & material, double ni, double n, double p)
673 {
674  double Ni = ni;
675  double pdRaugN;
676  double A1, B1;
677  double dAdn;
678  double dBdn;
679 
680  double Cn = 2.8e-31;
681  double Cp = 1.2e-31;
682  double pn = Ni*Ni;
683  double arg = CONSTMAX_EXP_ARG;
684 
685  A1 = (n*p-pn);
686  if (A1 >= exp(arg)) A1 = exp(arg);
687 
688  dAdn = (p);
689 
690  B1 = (Cn*n+Cp*p);
691  if (B1 >= exp(arg)) B1 = exp(arg);
692 
693  dBdn = Cn;
694 
695  pdRaugN = dAdn*B1 + A1*dBdn;
696 
697  return pdRaugN;
698 }
699 
700 // ----------------------------------------------------------------------------
701 // Function : MaterialSupport::pdRaugP
702 // Purpose : Calculates partial derivative w.r.t. hole density
703 // for Auger recombination.
704 //
705 // Special Notes : For this function, it shouldn't matter if the variables
706 // are scaled or not.
707 //
708 // I believe (but am not sure) that the constants Cn and Cp
709 // are material dependent. That is part of why the
710 // material name is passed in as an argument. The values
711 // here are for Si.
712 //
713 // Scope : public
714 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
715 // Creation Date : 7/19/03
716 // ----------------------------------------------------------------------------
718  (const std::string & material, double ni, double n, double p)
719 {
720  double Ni = ni;
721  double pdRaugP;
722  double A1, B1;
723  double dAdp;
724  double dBdp;
725 
726  double Cn = 2.8e-31;
727  double Cp = 1.2e-31;
728  double pn = Ni*Ni;
729  double arg = CONSTMAX_EXP_ARG;
730 
731  A1 = (n*p-pn);
732  if (A1 >= exp(arg)) A1 = exp(arg);
733 
734  dAdp = (n);
735 
736  B1 = (Cn*n+Cp*p);
737  if (B1 >= exp(arg)) B1 = exp(arg);
738 
739  dBdp = Cp;
740 
741  pdRaugP = dAdp*B1 + A1*dBdp;
742 
743  return pdRaugP;
744 }
745 
746 //----------------------------------------------------------------------------
747 // Function : MaterialSupport::workfunc
748 // Purpose : This function returns the workfunction
749 // of various metals
750 //
751 // Special Notes :
752 //
753 // Scope : public
754 // Creator : Deborah Fixel, SNL, Parallel Computational Sciences
755 // Creation Date : 7/15/03
756 //----------------------------------------------------------------------------
757 double MaterialSupport::workfunc(std::string & metal)
758 {
759  double wkfunc=0.0;
760 
761  ExtendedString metalName = metal;
762  metalName.toLower ();
763 
764  if (metalName=="al")
765  {
766  wkfunc = 4.10; //aluminum
767  }
768  else if (metalName=="ppoly")
769  {
770  wkfunc = 5.25; // p+-polysilicon
771  }
772  else if (metalName=="npoly")
773  {
774  wkfunc = 4.17; // n+-polysilicon
775  }
776  else if (metalName=="mo")
777  {
778  wkfunc = 4.53; // molybdenum
779  }
780  else if (metalName=="w")
781  {
782  wkfunc = 4.63; // tungsten
783  }
784  else if (metalName=="modi")
785  {
786  wkfunc = 4.80; // molybdenum disilicide
787  }
788  else if (metalName=="wdi")
789  {
790  wkfunc = 4.80; // tungsten disilicide
791  }
792  else if (metalName=="cu")
793  {
794  wkfunc = 4.25; // copper
795  }
796  else if (metalName=="pt")
797  {
798  wkfunc = 5.30; // platinum
799  }
800  else if (metalName=="au")
801  {
802  wkfunc = 4.80; // gold
803  }
804  else if (metalName=="neutral")
805  {
806  wkfunc = 0.0;
807  }
808  else
809  {
810  Report::UserFatal0() << metalName << " material not recognized.";
811  }
812 
813  return wkfunc;
814 }
815 //----------------------------------------------------------------------------
816 // Function : MaterialSupport::affin
817 // Purpose : This function returns the electron affinity
818 // of various semiconductor materials
819 //
820 // Special Notes :
821 //
822 // Scope : public
823 // Creator : Deborah Fixel, SNL, Parallel Computational Sciences
824 // Creation Date : 7/15/03
825 //---------------------------------------------------------------------------
826 double MaterialSupport::affin(const std::string & material)
827 {
828 
829  double afty=0.0;
830 
831  ExtendedString materialName = material;
832  materialName.toLower();
833 
834  if (materialName=="si")
835  {
836  afty = 4.17; // silicon
837  }
838  else if (materialName=="ge")
839  {
840  afty = 4.00; // germanium
841  }
842  else if (materialName=="gaas")
843  {
844  afty = 4.07; // gallium arsenide
845  }
846  else if (materialName=="sio2")
847  {
848  afty = 0.97; // silicon dioxide
849  }
850  else if (materialName=="nitride")
851  {
852  afty = 0.97; // silicon nitride
853  }
854  else if (materialName=="sapphire")
855  {
856  afty = 0.97; // sapphire (also known as aluminum oxide)
857  }
858  else
859  {
860  Report::UserError0() << materialName << " material not recognized.";
861  }
862 
863  return afty;
864 }
865 
866 //----------------------------------------------------------------------------
867 // Function : MaterialSupport::bandgap
868 // Purpose : This function returns the electronic bandgap
869 // of various semiconductor materials.
870 //
871 // Special Notes : Reference for temperature-dependent semiconductor
872 // materials is "The Standard Thermodynamic Function
873 // of the Formation of Electrons and Holes in Ge, Si,
874 // GaAs, and GaP," by C. D. Thurmond, J. Electrochem. Soc.,
875 // vol. 122, p. 1133, 1975.
876 //
877 // Scope : public
878 // Creator : Deborah Fixel, SNL, Parallel Computational Sciences
879 // Creation Date : 7/18/03
880 //---------------------------------------------------------------------------
881 double MaterialSupport::bandgap(const std::string & material, double temp)
882 {
883  double gap = 0.0;
884  ExtendedString materialName = material;
885  materialName.toLower();
886 
887  if (materialName=="si") // silicon
888  {
889  gap = 1.17 - 4.73e-4*pow(temp,2.0)/(temp + 636.0);
890  }
891  else if (materialName=="ge") // germanium
892  {
893  gap = 0.7437 - 4.774e-4*pow(temp,2.0)/(temp + 235);
894  }
895  else if (materialName=="gaas") // gallium arsenide
896  {
897  gap = 1.519 - 5.405e-4*pow(temp,2.0)/(temp + 204);
898  }
899  else if (materialName=="ingap")
900  {
901  gap = 1.86098;
902  }
903  else if (materialName=="sio2") // silicon dioxide
904  {
905  gap = 9.00;
906  }
907  else if (materialName=="nitride") // silicon nitride
908  {
909  gap = 4.7;
910  }
911  else if (materialName=="sapphire") // sapphire
912  {
913  gap = 4.7;
914  }
915  else if (materialName=="inalas" || materialName=="alinas") // indium aluminum arsenide
916  {
917  gap = 1.46;
918  }
919  else if (materialName=="ingaas" || materialName=="gainas") // indium galium arsenide
920  {
921  gap = 0.75;
922  }
923  else if (materialName=="inp") // indium phosphide
924  {
925  gap = 1.07;
926  }
927  else
928  {
929  Report::UserError0() << materialName << " material not recognized.";
930  }
931 
932  return gap;
933 }
934 
935 
936 //----------------------------------------------------------------------------
937 // Function : MaterialSupport::Ebgn
938 // Purpose : Band-gap narrowing
939 // Special Notes :
940 // Scope : public
941 // Creator : Eric R. Keiter, SNL
942 // Creation Date : 4/18/2014
943 //---------------------------------------------------------------------------
945  const std::string & material,
946  const std::string & bgnModel,
947  double dope)
948 {
949  double Ebgn=0.0;
950  double n0_bgn=0.0;
951  double v0_bgn=0.0;
952  double con_bgn=0.0;
953 
954  ExtendedString bgnModelName = bgnModel;
955  bgnModelName.toLower();
956 
957  if (bgnModelName=="slotboom") // parameters taken from Medici manual
958  {
959  ExtendedString materialName = material;
960  materialName.toLower();
961 
962  if (materialName=="si") // silicon
963  {
964  // Old Slotboom model:
965  n0_bgn = 1.0e17; // Nref
966  v0_bgn = 9.0e-3; // Eref
967  con_bgn = 0.5;
968 #if 0
969  // New Slotboom model:
970  double n0_bgn = 1.3e17; // Nref
971  double v0_bgn = 6.92e-3; // Eref
972  double con_bgn = 0.5;
973 #endif
974  }
975  else if (materialName=="ge") // germanium
976  {
977  n0_bgn = 1.0e17;
978  v0_bgn = 9.0e-3;
979  con_bgn = 0.5;
980  }
981  else if (materialName=="gaas") // gallium arsenide
982  {
983  n0_bgn = 1.0e17;
984  v0_bgn = 0.0;
985  con_bgn = 0.0;
986  }
987  else if (materialName=="ingap")
988  {
989  n0_bgn = 1.0e17;
990  v0_bgn = 0.0;
991  con_bgn = 0.0;
992  }
993  else if (materialName=="sio2") // silicon dioxide
994  {
995  n0_bgn = 1.0e17; // Nref
996  v0_bgn = 9.0e-3; // Eref
997  con_bgn = 0.5;
998  }
999 #if 0
1000  else if (materialName=="nitride") // silicon nitride
1001  {
1002  n0_bgn = 1.0;
1003  v0_bgn = 0.0;
1004  con_bgn = 0.0;
1005  }
1006  else if (materialName=="sapphire") // sapphire
1007  {
1008  n0_bgn = 1.0;
1009  v0_bgn = 0.0;
1010  con_bgn = 0.0;
1011  }
1012  else if (materialName=="inalas" || materialName=="alinas") // indium aluminum arsenide
1013  {
1014  n0_bgn = 1.0e17;
1015  v0_bgn = 0.0;
1016  con_bgn = 0.0;
1017  }
1018  else if (materialName=="ingaas" || materialName=="gainas") // indium galium arsenide
1019  {
1020  Ebgn = 0.12;
1021  }
1022  else if (materialName=="inp") // indium phosphide
1023  {
1024  Ebgn = 9.4e-2;
1025  }
1026 #endif
1027  else
1028  {
1029  Report::UserError0() << materialName << " material not recognized.";
1030  }
1031 
1032  double tmp1 = log(dope/n0_bgn);
1033  Ebgn = (v0_bgn) * (tmp1 + sqrt(tmp1*tmp1 + con_bgn));
1034  }
1035  else if ("bennet-wilson") // default model for Sentaurus.
1036  {
1037  ExtendedString materialName = material;
1038  materialName.toLower();
1039 
1040  if (materialName=="si")
1041  {
1042  double Eref = 6.84e-3;
1043  double Nref = 3.162e+18;
1044  if (dope >= Nref) // Bennet-Wilson model
1045  {
1046  Ebgn = Eref*pow(log(dope/Nref),2.0);
1047  }
1048  }
1049  else
1050  {
1051  // bennet-wilson not implemented for this material
1052  Ebgn=0.0;
1053  }
1054  }
1055  else if (bgnModelName=="jain") // consistent with Wampler's XPD code.
1056  {
1057  Ebgn = jainEbgn( material, dope) ;
1058  }
1059  else // assume this is the default
1060  {
1061  Ebgn = jainEbgn( material, dope) ;
1062  }
1063 
1064  return Ebgn;
1065 }
1066 
1067 
1068 //----------------------------------------------------------------------------
1069 // Function : MaterialSupport::jainEbgn
1070 //
1071 // Purpose : Band-gap narrowing, using the Jain model.
1072 //
1073 // This corresponds to the BGN2 model in Davinci/Medici
1074 //
1075 // Special Notes : Ntype vs. Ptype is determined by the sign of "dope".
1076 //
1077 // Scope : public
1078 // Creator : Eric R. Keiter, SNL
1079 // Creation Date : 4/18/2014
1080 //---------------------------------------------------------------------------
1082  const std::string & material,
1083  double dope)
1084 {
1085  double Ebgn=0.0;
1086 
1087  double deltaEcn=0.0;
1088  double deltaEvn=0.0;
1089  double deltaEcp=0.0;
1090  double deltaEvp=0.0;
1091 
1092  double anc_bgn = 0.0;
1093  double bnc_bgn = 0.0;
1094  double cnc_bgn = 0.0;
1095  double anv_bgn = 0.0;
1096  double bnv_bgn = 0.0;
1097  double cnv_bgn = 0.0;
1098  double apc_bgn = 0.0;
1099  double bpc_bgn = 0.0;
1100  double cpc_bgn = 0.0;
1101  double apv_bgn = 0.0;
1102  double bpv_bgn = 0.0;
1103  double cpv_bgn = 0.0;
1104 
1105  ExtendedString materialName = material;
1106  materialName.toLower();
1107 
1108  if (materialName=="si") // silicon
1109  {
1110  anc_bgn = -14.84e-3;
1111  bnc_bgn = 0.0;
1112  cnc_bgn = 0.78e-3;
1113 
1114  anv_bgn = 0.0;
1115  bnv_bgn = 15.08e-3;
1116  cnv_bgn = 0.74e-3;
1117 
1118  apc_bgn = 0.0;
1119  bpc_bgn = -16.27e-3;
1120  cpc_bgn = -0.18e-3;
1121 
1122  apv_bgn = 18.46e-3;
1123  bpv_bgn = 0.0;
1124  cpv_bgn = -2.63e-3;
1125  }
1126  else if (materialName=="ge") // germanium
1127  {
1128  anc_bgn = -8.67e-3;
1129  bnc_bgn = 0.0;
1130  cnc_bgn = -2.02e-3;
1131  anv_bgn = 0.0;
1132  bnv_bgn = 8.14e-3;
1133  cnv_bgn = 2.29e-3;
1134  apc_bgn = -8.21e-3;
1135  bpc_bgn = 0.0;
1136  cpc_bgn = -2.19e-3;
1137  apv_bgn = 0.0;
1138  bpv_bgn = 9.18e-3;
1139  cpv_bgn = 3.58e-3;
1140  }
1141  else if (materialName=="gaas") // gallium arsenide
1142  {
1143  anc_bgn = -16.30e-3;
1144  bnc_bgn = 0.0;
1145  cnc_bgn = -18.13e-3;
1146  anv_bgn = 0.0;
1147  bnv_bgn = 7.47e-3;
1148  cnv_bgn = 72.52e-3;
1149  apc_bgn = -9.71e-3;
1150  bpc_bgn = 0.0;
1151  cpc_bgn = -0.47e-3;
1152  apv_bgn = 0.0;
1153  bpv_bgn = 12.19e-3;
1154  cpv_bgn = 3.41e-3;
1155  }
1156  else if (materialName=="ingap")
1157  {
1158  anc_bgn = -16.3e-3;
1159  bnc_bgn = 0.0;
1160  cnc_bgn = -18.13e-3;
1161  anv_bgn = 0.0;
1162  bnv_bgn = 7.47e-3;
1163  cnv_bgn = 72.52e-3;
1164  apc_bgn = -9.71e-3;
1165  bpc_bgn = 0.0;
1166  cpc_bgn = -0.47e-3;
1167  apv_bgn = 0.0;
1168  bpv_bgn = 12.19e-3;
1169  cpv_bgn = 3.41e-3;
1170  }
1171  else if (materialName=="sio2") // silicon dioxide (use same as Si)
1172  {
1173  anc_bgn = -14.84e-3;
1174  bnc_bgn = 0.0;
1175  cnc_bgn = 0.78e-3;
1176 
1177  anv_bgn = 0.0;
1178  bnv_bgn = 15.08e-3;
1179  cnv_bgn = 0.74e-3;
1180 
1181  apc_bgn = 0.0;
1182  bpc_bgn = -16.27e-3;
1183  cpc_bgn = -0.18e-3;
1184 
1185  apv_bgn = 18.46e-3;
1186  bpv_bgn = 0.0;
1187  cpv_bgn = -2.63e-3;
1188  }
1189 #if 0
1190  else if (materialName=="nitride") // silicon nitride
1191  {
1192  // zero
1193  }
1194  else if (materialName=="sapphire") // sapphire
1195  {
1196  // zero
1197  }
1198 #endif
1199  else if (materialName=="inalas" || materialName=="alinas") // indium aluminum arsenide
1200  {
1201  anc_bgn = -16.3e-3;
1202  bnc_bgn = 0.0;
1203  cnc_bgn = -18.13e-3;
1204  anv_bgn = 0.0;
1205  bnv_bgn = 7.47e-3;
1206  cnv_bgn = 72.52e-3;
1207  apc_bgn = -9.71e-3;
1208  bpc_bgn = 0.0;
1209  cpc_bgn = -0.47e-3;
1210  apv_bgn = 0.0;
1211  bpv_bgn = 12.19e-3;
1212  cpv_bgn = 3.41e-3;
1213  }
1214  else if (materialName=="ingaas" || materialName=="gainas") // indium galium arsenide
1215  {
1216  anc_bgn = -16.3e-3;
1217  bnc_bgn = 0.0;
1218  cnc_bgn = -18.13e-3;
1219  anv_bgn = 0.0;
1220  bnv_bgn = 7.47e-3;
1221  cnv_bgn = 72.52e-3;
1222  apc_bgn = -9.71e-3;
1223  bpc_bgn = 0.0;
1224  cpc_bgn = -0.47e-3;
1225  apv_bgn = 0.0;
1226  bpv_bgn = 12.19e-3;
1227  cpv_bgn = 3.41e-3;
1228  }
1229  else if (materialName=="inp") // indium phosphide
1230  {
1231  anc_bgn = -16.3e-3;
1232  bnc_bgn = 0.0;
1233  cnc_bgn = -18.13e-3;
1234  anv_bgn = 0.0;
1235  bnv_bgn = 7.47e-3;
1236  cnv_bgn = 72.52e-3;
1237  apc_bgn = -9.71e-3;
1238  bpc_bgn = 0.0;
1239  cpc_bgn = -0.47e-3;
1240  apv_bgn = 0.0;
1241  bpv_bgn = 12.19e-3;
1242  cpv_bgn = 3.41e-3;
1243  }
1244  else
1245  {
1246  Report::UserError0() << materialName << " material not recognized.";
1247  }
1248 
1249  double dopeScaled=fabs(dope)/1.0e+18;
1250 
1251  if (dope > 0.0) // n-type
1252  {
1253  deltaEcn=
1254  +anc_bgn*pow(dopeScaled,(1.0/3.0))
1255  +bnc_bgn*pow(dopeScaled,(0.25))
1256  +cnc_bgn*pow(dopeScaled,(0.5));
1257 
1258  deltaEvn=
1259  +anv_bgn*pow(dopeScaled,(1.0/3.0))
1260  +bnv_bgn*pow(dopeScaled,(0.25))
1261  +cnv_bgn*pow(dopeScaled,(0.5));
1262 
1263  Ebgn = deltaEcn-deltaEvn;
1264  }
1265  else // p-type
1266  {
1267  deltaEcp=
1268  +apc_bgn*pow(dopeScaled,(1.0/3.0))
1269  +bpc_bgn*pow(dopeScaled,(0.25))
1270  +cpc_bgn*pow(dopeScaled,(0.5));
1271 
1272  deltaEvp=
1273  +apv_bgn*pow(dopeScaled,(1.0/3.0))
1274  +bpv_bgn*pow(dopeScaled,(0.25))
1275  +cpv_bgn*pow(dopeScaled,(0.5));
1276 
1277  Ebgn = deltaEcp-deltaEvp;
1278  }
1279 
1280 
1281  return Ebgn;
1282 }
1283 
1284 // ----------------------------------------------------------------------------
1285 // Function : MaterialSupport::calcLt
1286 // Purpose : This function calculates carrier lifetimes.
1287 //
1288 // Special Notes : holeFlag parameter indicates electrons or holes:
1289 // holeFlag = true -> holes
1290 // holeFlag = false -> electrons
1291 //
1292 // This function assumes that conc is an absolute value.
1293 //
1294 // This function comes from this paper:
1295 //
1296 // "Analysis of High-Efficiency Silicon Solar Cells",
1297 // IEEE Transactions on Electron Devices, by Harry T.
1298 // Weaver and R. D. Nasby, vol. ED-28, no. 5, May 1981.
1299 //
1300 // This is a function that probably should have some material dependence,
1301 // but at the moment it doesn't. I think all the values in this function
1302 // are for Si.
1303 //
1304 // Scope : public
1305 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1306 // Creation Date : 6/20/03
1307 // ----------------------------------------------------------------------------
1308 double MaterialSupport::calcLt (bool holeFlag, double conc)
1309 {
1310  double lt = 0.0;
1311  double LT0, Nref;
1312 
1313  conc = fabs(conc);
1314 
1315  if (holeFlag)
1316  {
1317  LT0 = 3.52e-5;
1318  Nref = 7.1e15;
1319  lt = LT0 / (1.0 + conc / Nref);
1320  }
1321  else
1322  {
1323  LT0 = 3.95e-4;
1324  Nref = 7.1e15;
1325  lt = LT0 / (1.0 + conc / Nref);
1326  }
1327  return lt;
1328 }
1329 
1330 } // namespace Device
1331 } // namespace Xyce