19 m_dopingConcentration(0.),
26 eLatticeMobility(1.35e-6),
27 hLatticeMobility(0.45e-6),
32 eBetaCanaliInv(1. / 1.109),
33 hBetaCanaliInv(1. / 1.213),
55 m_hasUserMobility(false),
56 m_hasUserSaturationVelocity(false),
57 latticeMobilityModel(LatticeMobilityModelSentaurus),
58 dopingMobilityModel(DopingMobilityModelMasetti),
59 saturationVelocityModel(SaturationVelocityModelCanali),
60 highFieldMobilityModel(HighFieldMobilityModelCanali),
61 impactIonisationModel(ImpactIonisationModelVanOverstraeten),
63 useNonParabolicity(true),
67 eStepXL(eFinalXL / nEnergyStepsXL),
69 eStepG(eFinalG / nEnergyStepsG),
71 eStepV(eFinalV / nEnergyStepsV),
82 m_hasOpticalData(false),
83 opticalDataFile(
"OpticalData_Si.txt") {
101 cfTotElectronsX.clear();
102 cfElectronsX.clear();
103 energyLossElectronsX.clear();
104 scatTypeElectronsX.clear();
106 cfTotElectronsL.clear();
107 cfElectronsL.clear();
108 energyLossElectronsL.clear();
109 scatTypeElectronsL.clear();
111 cfTotElectronsG.clear();
112 cfElectronsG.clear();
113 energyLossElectronsG.clear();
114 scatTypeElectronsG.clear();
116 ieMinL = int(eMinL / eStepXL) + 1;
117 ieMinG = int(eMinG / eStepG) + 1;
121 energyLossHoles.clear();
122 scatTypeHoles.clear();
125 InitialiseDensityOfStates();
128 nCollElectronAcoustic = nCollElectronOptical = 0;
129 nCollElectronIntervalley = 0;
130 nCollElectronImpurity = 0;
131 nCollElectronIonisation = 0;
132 nCollElectronDetailed.clear();
133 nCollElectronBand.clear();
135 nIonisationProducts = 0;
141 if (toupper(type) ==
'N') {
144 m_dopingConcentration = c;
147 std::cerr <<
" Doping concentration must be greater than zero.\n";
148 std::cerr <<
" Using default value for n-type silicon "
149 <<
"(10^12 cm-3) instead.\n";
150 m_dopingConcentration = 1.e12;
152 }
else if (toupper(type) ==
'P') {
155 m_dopingConcentration = c;
158 std::cerr <<
" Doping concentration must be greater than zero.\n";
159 std::cerr <<
" Using default value for p-type silicon "
160 <<
"(10^18 cm-3) instead.\n";
161 m_dopingConcentration = 1.e18;
163 }
else if (toupper(type) ==
'I') {
165 m_dopingConcentration = 0.;
168 std::cerr <<
" Unknown dopant type (" << type <<
").\n";
169 std::cerr <<
" Available types are n, p and i (intrinsic).\n";
179 c = m_dopingConcentration;
185 std::cerr <<
m_className <<
"::SetTrapCrossSection:\n";
186 std::cerr <<
" Capture cross-section [cm2] must positive.\n";
192 std::cerr <<
m_className <<
"::SetTrapCrossSection:\n";
193 std::cerr <<
" Capture cross-section [cm2] must be positive.n";
206 std::cerr <<
" Trap density [cm-3] must be greater than zero.\n";
219 std::cerr <<
m_className <<
"::SetTrappingTime:\n";
220 std::cerr <<
" Trapping time [ns-1] must be positive.\n";
226 std::cerr <<
m_className <<
"::SetTrappingTime:\n";
227 std::cerr <<
" Trapping time [ns-1] must be positive.\n";
237 const double ez,
const double bx,
238 const double by,
const double bz,
239 double& vx,
double& vy,
double& vz) {
243 if (!UpdateTransportParameters()) {
244 std::cerr <<
m_className <<
"::ElectronVelocity:\n";
245 std::cerr <<
" Error calculating the transport parameters.\n";
256 const double e =
sqrt(ex * ex + ey * ey + ez * ez);
260 switch (highFieldMobilityModel) {
261 case HighFieldMobilityModelMinimos:
262 ElectronMobilityMinimos(e, mu);
264 case HighFieldMobilityModelCanali:
265 ElectronMobilityCanali(e, mu);
267 case HighFieldMobilityModelReggiani:
268 ElectronMobilityReggiani(e, mu);
276 const double b =
sqrt(bx * bx + by * by + bz * bz);
283 const double muH = eHallFactor * mu;
284 const double eb = bx * ex + by * ey + bz * ez;
285 const double nom = 1. +
pow(muH * b, 2);
287 vx = mu * (ex + muH * (ey * bz - ez * by) + muH * muH * bx * eb) / nom;
288 vy = mu * (ey + muH * (ez * bx - ex * bz) + muH * muH * by * eb) / nom;
289 vz = mu * (ez + muH * (ex * by - ey * bx) + muH * muH * bz * eb) / nom;
295 const double ez,
const double bx,
296 const double by,
const double bz,
301 if (!UpdateTransportParameters()) {
302 std::cerr <<
m_className <<
"::ElectronTownsend:\n";
303 std::cerr <<
" Error calculating the transport parameters.\n";
314 const double e =
sqrt(ex * ex + ey * ey + ez * ez);
316 switch (impactIonisationModel) {
317 case ImpactIonisationModelVanOverstraeten:
318 return ElectronImpactIonisationVanOverstraetenDeMan(e, alpha);
320 case ImpactIonisationModelGrant:
321 return ElectronImpactIonisationGrant(e, alpha);
324 std::cerr <<
m_className <<
"::ElectronTownsend:\n";
325 std::cerr <<
" Unknown model activated. Program bug!\n";
332 const double ez,
const double bx,
333 const double by,
const double bz,
338 if (!UpdateTransportParameters()) {
339 std::cerr <<
m_className <<
"::ElectronAttachment:\n";
340 std::cerr <<
" Error calculating the transport parameters.\n";
351 switch (trappingModel) {
353 eta = eTrapCs * eTrapDensity;
358 eta = eTrapTime *
sqrt(vx * vx + vy * vy + vz * vz);
359 if (eta > 0.) eta = 1. / eta;
362 std::cerr <<
m_className <<
"::ElectronAttachment:\n";
363 std::cerr <<
" Unknown model activated. Program bug!\n";
372 const double ez,
const double bx,
373 const double by,
const double bz,
double& vx,
374 double& vy,
double& vz) {
378 if (!UpdateTransportParameters()) {
380 std::cerr <<
" Error calculating the transport parameters.\n";
391 const double e =
sqrt(ex * ex + ey * ey + ez * ez);
395 switch (highFieldMobilityModel) {
396 case HighFieldMobilityModelMinimos:
397 HoleMobilityMinimos(e, mu);
399 case HighFieldMobilityModelCanali:
400 HoleMobilityCanali(e, mu);
402 case HighFieldMobilityModelReggiani:
403 HoleMobilityReggiani(e, mu);
409 const double b =
sqrt(bx * bx + by * by + bz * bz);
416 const double muH = hHallFactor * mu;
417 const double eb = bx * ex + by * ey + bz * ez;
418 const double nom = 1. +
pow(muH * b, 2);
420 vx = mu * (ex + muH * (ey * bz - ez * by) + muH * muH * bx * eb) / nom;
421 vy = mu * (ey + muH * (ez * bx - ex * bz) + muH * muH * by * eb) / nom;
422 vz = mu * (ez + muH * (ex * by - ey * bx) + muH * muH * bz * eb) / nom;
428 const double ez,
const double bx,
429 const double by,
const double bz,
434 if (!UpdateTransportParameters()) {
436 std::cerr <<
" Error calculating the transport parameters.\n";
447 const double e =
sqrt(ex * ex + ey * ey + ez * ez);
449 switch (impactIonisationModel) {
450 case ImpactIonisationModelVanOverstraeten:
451 return HoleImpactIonisationVanOverstraetenDeMan(e, alpha);
453 case ImpactIonisationModelGrant:
454 return HoleImpactIonisationGrant(e, alpha);
458 std::cerr <<
" Unknown model activated. Program bug!\n";
465 const double ez,
const double bx,
466 const double by,
const double bz,
471 if (!UpdateTransportParameters()) {
473 std::cerr <<
" Error calculating the transport parameters.\n";
484 switch (trappingModel) {
486 eta = hTrapCs * hTrapDensity;
491 eta = hTrapTime *
sqrt(vx * vx + vy * vy + vz * vz);
492 if (eta > 0.) eta = 1. / eta;
496 std::cerr <<
" Unknown model activated. Program bug!\n";
506 if (mue <= 0. || muh <= 0.) {
507 std::cerr <<
m_className <<
"::SetLowFieldMobility:\n";
508 std::cerr <<
" Mobility must be greater than zero.\n";
514 m_hasUserMobility =
true;
520 latticeMobilityModel = LatticeMobilityModelMinimos;
521 m_hasUserMobility =
false;
527 latticeMobilityModel = LatticeMobilityModelSentaurus;
528 m_hasUserMobility =
false;
534 latticeMobilityModel = LatticeMobilityModelReggiani;
535 m_hasUserMobility =
false;
541 dopingMobilityModel = DopingMobilityModelMinimos;
542 m_hasUserMobility =
false;
548 dopingMobilityModel = DopingMobilityModelMasetti;
549 m_hasUserMobility =
false;
554 const double vsath) {
556 if (vsate <= 0. || vsath <= 0.) {
557 std::cout <<
m_className <<
"::SetSaturationVelocity:\n";
558 std::cout <<
" Restoring default values.\n";
559 m_hasUserSaturationVelocity =
false;
563 m_hasUserSaturationVelocity =
true;
571 saturationVelocityModel = SaturationVelocityModelMinimos;
572 m_hasUserSaturationVelocity =
false;
578 saturationVelocityModel = SaturationVelocityModelCanali;
579 m_hasUserSaturationVelocity =
false;
585 saturationVelocityModel = SaturationVelocityModelReggiani;
586 m_hasUserSaturationVelocity =
false;
592 highFieldMobilityModel = HighFieldMobilityModelMinimos;
598 highFieldMobilityModel = HighFieldMobilityModelCanali;
604 highFieldMobilityModel = HighFieldMobilityModelReggiani;
610 highFieldMobilityModel = HighFieldMobilityModelConstant;
615 impactIonisationModel = ImpactIonisationModelVanOverstraeten;
621 impactIonisationModel = ImpactIonisationModelGrant;
627 if (e <= eMinG + Small) {
628 std::cerr <<
m_className <<
"::SetMaxElectronEnergy:\n";
629 std::cerr <<
" Provided upper electron energy limit (" << e
630 <<
" eV) is too small.\n";
636 eStepG = eFinalG / nEnergyStepsG;
644 const double pz,
double& vx,
double& vy,
645 double& vz,
const int band) {
648 double mx = ElectronMass, my = ElectronMass, mz = ElectronMass;
651 if (band >= 0 && band < nValleysX) {
677 std::cerr <<
m_className <<
"::GetElectronEnergy:\n";
678 std::cerr <<
" Unexpected band index " << band <<
"!\n";
683 const double mc = 3. / (1. / mLongX + 2. / mTransX);
688 }
else if (band < nValleysX + nValleysL) {
692 const double mc = 3. / (1. / mLongL + 2. / mTransL);
696 }
else if (band == nValleysX + nValleysL) {
700 if (useNonParabolicity) {
703 if (band < nValleysX) {
706 }
else if (band < nValleysX + nValleysL) {
711 const double p2 = 0.5 * (px * px / mx + py * py / my + pz * pz / mz);
713 const double e = 0.5 * (
sqrt(1. + 4 * alpha * p2) - 1.) / alpha;
714 const double a = SpeedOfLight / (1. + 2 * alpha * e);
722 const double e = 0.5 * (px * px / mx + py * py / my + pz * pz / mz);
723 vx = SpeedOfLight * px / mx;
724 vy = SpeedOfLight * py / my;
725 vz = SpeedOfLight * pz / mz;
730 double& pz,
int& band) {
732 int nBands = nValleysX;
733 if (e > eMinL) nBands += nValleysL;
734 if (e > eMinG) ++nBands;
737 if (band < 0 || band > nValleysX + nValleysL ||
738 (e < eMinL || band >= nValleysX) ||
739 (e < eMinG || band == nValleysX + nValleysL)) {
742 if (band >= nValleysX) band = nValleysX - 1;
748 const double dosSum = nValleysX * dosX + nValleysL * dosL + dosG;
749 if (dosSum < Small) {
750 band = nValleysX + nValleysL;
755 if (band >= nValleysX) band = nValleysX - 1;
756 }
else if (r < dosX + dosL) {
758 if (band >= nValleysX + nValleysL) band = nValleysL - 1;
760 band = nValleysX + nValleysL;
765 std::cout <<
m_className <<
"::GetElectronMomentum:\n";
766 std::cout <<
" Randomised band index: " << band <<
"\n";
769 if (band < nValleysX) {
771 double pstar =
sqrt(2. * ElectronMass * e);
772 if (useNonParabolicity) {
773 const double alpha = alphaX;
774 pstar *=
sqrt(1. + alpha * e);
778 const double stheta =
sqrt(1. - ctheta * ctheta);
782 const double pl = pstar *
sqrt(mLongX);
783 const double pt = pstar *
sqrt(mTransX);
789 py = pt *
cos(phi) * stheta;
790 pz = pt *
sin(phi) * stheta;
795 px = pt *
sin(phi) * stheta;
797 pz = pt *
cos(phi) * stheta;
802 px = pt *
cos(phi) * stheta;
803 py = pt *
sin(phi) * stheta;
808 std::cerr <<
m_className <<
"::GetElectronMomentum:\n";
809 std::cerr <<
" Unexpected band index (" << band <<
").\n";
810 px = pstar * stheta *
cos(phi);
811 py = pstar * stheta *
sin(phi);
816 pstar *=
sqrt(3. / (1. / mLongX + 2. / mTransX));
817 px = pstar *
cos(phi) * stheta;
818 py = pstar *
sin(phi) * stheta;
821 }
else if (band < nValleysX + nValleysL) {
823 double pstar =
sqrt(2. * ElectronMass * (e - eMinL));
824 if (useNonParabolicity) {
825 const double alpha = alphaL;
826 pstar *=
sqrt(1. + alpha * (e - eMinL));
828 pstar *=
sqrt(3. / (1. / mLongL + 2. / mTransL));
831 const double stheta =
sqrt(1. - ctheta * ctheta);
834 px = pstar *
cos(phi) * stheta;
835 py = pstar *
sin(phi) * stheta;
837 }
else if (band == nValleysX + nValleysL) {
839 double pstar =
sqrt(2. * ElectronMass * e);
842 const double stheta =
sqrt(1. - ctheta * ctheta);
845 px = pstar *
cos(phi) * stheta;
846 py = pstar *
sin(phi) * stheta;
854 if (!UpdateTransportParameters()) {
855 std::cerr <<
m_className <<
"::GetElectronNullCollisionRate:\n";
856 std::cerr <<
" Error calculating the collision rates table.\n";
862 if (band >= 0 && band < nValleysX) {
863 return cfNullElectronsX;
864 }
else if (band >= nValleysX && band < nValleysX + nValleysL) {
865 return cfNullElectronsL;
866 }
else if (band == nValleysX + nValleysL) {
867 return cfNullElectronsG;
869 std::cerr <<
m_className <<
"::GetElectronNullCollisionRate:\n";
870 std::cerr <<
" Band index (" << band <<
") out of range.\n";
877 std::cerr <<
m_className <<
"::GetElectronCollisionRate:\n";
878 std::cerr <<
" Electron energy must be positive.\n";
883 std::cerr <<
m_className <<
"::GetElectronCollisionRate:\n";
884 std::cerr <<
" Collision rate at " << e <<
" eV (band " << band
885 <<
") is not included"
886 <<
" in the current table.\n";
887 std::cerr <<
" Increasing energy range to " << 1.05 * e <<
" eV.\n";
892 if (!UpdateTransportParameters()) {
893 std::cerr <<
m_className <<
"::GetElectronCollisionRate:\n";
894 std::cerr <<
" Error calculating the collision rates table.\n";
900 if (band >= 0 && band < nValleysX) {
901 int iE = int(e / eStepXL);
902 if (iE >= nEnergyStepsXL)
903 iE = nEnergyStepsXL - 1;
906 return cfTotElectronsX[iE];
907 }
else if (band >= nValleysX && band < nValleysX + nValleysL) {
908 int iE = int(e / eStepXL);
909 if (iE >= nEnergyStepsXL)
910 iE = nEnergyStepsXL - 1;
911 else if (iE < ieMinL)
913 return cfTotElectronsL[iE];
914 }
else if (band == nValleysX + nValleysL) {
915 int iE = int(e / eStepG);
916 if (iE >= nEnergyStepsG)
917 iE = nEnergyStepsG - 1;
918 else if (iE < ieMinG)
920 return cfTotElectronsG[iE];
923 std::cerr <<
m_className <<
"::GetElectronCollisionRate:\n";
924 std::cerr <<
" Band index (" << band <<
") out of range.\n";
929 double& e1,
double& px,
double& py,
930 double& pz,
int& nion,
int& ndxc,
934 std::cerr <<
m_className <<
"::GetElectronCollision:\n";
935 std::cerr <<
" Requested electron energy (" << e;
936 std::cerr <<
" eV) exceeds current energy range (" << eFinalG;
937 std::cerr <<
" eV).\n";
938 std::cerr <<
" Increasing energy range to " << 1.05 * e <<
" eV.\n";
940 }
else if (e <= 0.) {
941 std::cerr <<
m_className <<
"::GetElectronCollision:\n";
942 std::cerr <<
" Electron energy must be greater than zero.\n";
947 if (!UpdateTransportParameters()) {
948 std::cerr <<
m_className <<
"::GetElectronCollision:\n";
949 std::cerr <<
" Error calculating the collision rates table.\n";
958 if (band >= 0 && band < nValleysX) {
961 int iE = int(e / eStepXL);
962 if (iE >= nEnergyStepsXL) iE = nEnergyStepsXL - 1;
967 int iUp = nLevelsX - 1;
968 if (r <= cfElectronsX[iE][iLow]) {
970 }
else if (r >= cfElectronsX[iE][nLevelsX - 1]) {
974 while (iUp - iLow > 1) {
975 iMid = (iLow + iUp) >> 1;
976 if (r < cfElectronsX[iE][iMid]) {
986 type = scatTypeElectronsX[level];
988 ++nCollElectronDetailed[level];
989 ++nCollElectronBand[band];
990 if (type == ElectronCollisionTypeAcousticPhonon) {
991 ++nCollElectronAcoustic;
992 }
else if (type == ElectronCollisionTypeIntervalleyG) {
994 ++nCollElectronIntervalley;
1018 }
else if (type == ElectronCollisionTypeIntervalleyF) {
1020 ++nCollElectronIntervalley;
1030 if (band > 1) band += 2;
1037 }
else if (type == ElectronCollisionTypeInterbandXL) {
1039 ++nCollElectronIntervalley;
1041 band = nValleysX + int(
RndmUniform() * nValleysL);
1042 if (band >= nValleysX + nValleysL) band = nValleysX + nValleysL - 1;
1043 }
else if (type == ElectronCollisionTypeInterbandXG) {
1044 ++nCollElectronIntervalley;
1045 band = nValleysX + nValleysL;
1046 }
else if (type == ElectronCollisionTypeImpurity) {
1047 ++nCollElectronImpurity;
1048 }
else if (type == ElectronCollisionTypeIonisation) {
1049 ++nCollElectronIonisation;
1051 std::cerr <<
m_className <<
"::GetElectronCollision:\n";
1052 std::cerr <<
" Unexpected collision type (" << type <<
").\n";
1056 loss = energyLossElectronsX[level];
1058 }
else if (band >= nValleysX && band < nValleysX + nValleysL) {
1061 int iE = int(e / eStepXL);
1062 if (iE >= nEnergyStepsXL) iE = nEnergyStepsXL - 1;
1063 if (iE < ieMinL) iE = ieMinL;
1067 int iUp = nLevelsL - 1;
1068 if (r <= cfElectronsL[iE][iLow]) {
1070 }
else if (r >= cfElectronsL[iE][nLevelsL - 1]) {
1074 while (iUp - iLow > 1) {
1075 iMid = (iLow + iUp) >> 1;
1076 if (r < cfElectronsL[iE][iMid]) {
1086 type = scatTypeElectronsL[level];
1088 ++nCollElectronDetailed[nLevelsX + level];
1089 ++nCollElectronBand[band];
1090 if (type == ElectronCollisionTypeAcousticPhonon) {
1091 ++nCollElectronAcoustic;
1092 }
else if (type == ElectronCollisionTypeOpticalPhonon) {
1093 ++nCollElectronOptical;
1094 }
else if (type == ElectronCollisionTypeIntervalleyG ||
1095 type == ElectronCollisionTypeIntervalleyF) {
1097 ++nCollElectronIntervalley;
1099 band = nValleysX + int(
RndmUniform() * nValleysL);
1100 if (band >= nValleysX + nValleysL) band = nValleysX + nValleysL;
1101 }
else if (type == ElectronCollisionTypeInterbandXL) {
1103 ++nCollElectronIntervalley;
1106 if (band >= nValleysX) band = nValleysX - 1;
1107 }
else if (type == ElectronCollisionTypeInterbandLG) {
1109 ++nCollElectronIntervalley;
1110 band = nValleysX + nValleysL;
1111 }
else if (type == ElectronCollisionTypeImpurity) {
1112 ++nCollElectronImpurity;
1113 }
else if (type == ElectronCollisionTypeIonisation) {
1114 ++nCollElectronIonisation;
1116 std::cerr <<
m_className <<
"::GetElectronCollision:\n";
1117 std::cerr <<
" Unexpected collision type (" << type <<
").\n";
1121 loss = energyLossElectronsL[level];
1122 }
else if (band == nValleysX + nValleysL) {
1125 int iE = int(e / eStepG);
1126 if (iE >= nEnergyStepsG) iE = nEnergyStepsG - 1;
1127 if (iE < ieMinG) iE = ieMinG;
1131 int iUp = nLevelsG - 1;
1132 if (r <= cfElectronsG[iE][iLow]) {
1134 }
else if (r >= cfElectronsG[iE][nLevelsG - 1]) {
1138 while (iUp - iLow > 1) {
1139 iMid = (iLow + iUp) >> 1;
1140 if (r < cfElectronsG[iE][iMid]) {
1150 type = scatTypeElectronsG[level];
1152 ++nCollElectronDetailed[nLevelsX + nLevelsL + level];
1153 ++nCollElectronBand[band];
1154 if (type == ElectronCollisionTypeAcousticPhonon) {
1155 ++nCollElectronAcoustic;
1156 }
else if (type == ElectronCollisionTypeOpticalPhonon) {
1157 ++nCollElectronOptical;
1158 }
else if (type == ElectronCollisionTypeIntervalleyG ||
1159 type == ElectronCollisionTypeIntervalleyF) {
1161 ++nCollElectronIntervalley;
1162 }
else if (type == ElectronCollisionTypeInterbandXG) {
1164 ++nCollElectronIntervalley;
1167 if (band >= nValleysX) band = nValleysX - 1;
1168 }
else if (type == ElectronCollisionTypeInterbandLG) {
1170 ++nCollElectronIntervalley;
1172 band = nValleysX + int(
RndmUniform() * nValleysL);
1173 if (band >= nValleysX + nValleysL) band = nValleysX + nValleysL - 1;
1174 }
else if (type == ElectronCollisionTypeIonisation) {
1175 ++nCollElectronIonisation;
1177 std::cerr <<
m_className <<
"::GetElectronCollision:\n";
1178 std::cerr <<
" Unexpected collision type (" << type <<
").\n";
1182 loss = energyLossElectronsG[level];
1184 std::cerr <<
m_className <<
"::GetElectronCollision:\n";
1185 std::cerr <<
" Band index (" << band <<
") out of range.\n";
1192 if (type == ElectronCollisionTypeIonisation) {
1193 double ee = 0., eh = 0.;
1195 loss = ee + eh + m_bandGap;
1196 ionProducts.clear();
1199 newIonProd.type = IonProdTypeElectron;
1200 newIonProd.energy = ee;
1201 ionProducts.push_back(newIonProd);
1203 newIonProd.type = IonProdTypeHole;
1204 newIonProd.energy = eh;
1205 ionProducts.push_back(newIonProd);
1206 nion = nIonisationProducts = 2;
1209 if (e < loss) loss = e - 0.00001;
1212 if (e1 < Small) e1 = Small;
1215 if (band >= 0 && band < nValleysX) {
1217 double pstar =
sqrt(2. * ElectronMass * e1);
1218 if (useNonParabolicity) {
1219 const double alpha = alphaX;
1220 pstar *=
sqrt(1. + alpha * e1);
1224 const double stheta =
sqrt(1. - ctheta * ctheta);
1227 if (useAnisotropy) {
1228 const double pl = pstar *
sqrt(mLongX);
1229 const double pt = pstar *
sqrt(mTransX);
1235 py = pt *
cos(phi) * stheta;
1236 pz = pt *
sin(phi) * stheta;
1241 px = pt *
sin(phi) * stheta;
1243 pz = pt *
cos(phi) * stheta;
1248 px = pt *
cos(phi) * stheta;
1249 py = pt *
sin(phi) * stheta;
1257 pstar *=
sqrt(3. / (1. / mLongX + 2. / mTransX));
1258 px = pstar *
cos(phi) * stheta;
1259 py = pstar *
sin(phi) * stheta;
1260 pz = pstar * ctheta;
1264 }
else if (band >= nValleysX && band < nValleysX + nValleysL) {
1266 double pstar =
sqrt(2. * ElectronMass * (e1 - eMinL));
1267 if (useNonParabolicity) {
1268 const double alpha = alphaL;
1269 pstar *=
sqrt(1. + alpha * (e1 - eMinL));
1273 const double stheta =
sqrt(1. - ctheta * ctheta);
1276 pstar *=
sqrt(3. / (1. / mLongL + 2. / mTransL));
1277 px = pstar *
cos(phi) * stheta;
1278 py = pstar *
sin(phi) * stheta;
1279 pz = pstar * ctheta;
1283 double pstar =
sqrt(2. * ElectronMass * e1);
1286 const double stheta =
sqrt(1. - ctheta * ctheta);
1289 px = pstar *
cos(phi) * stheta;
1290 py = pstar *
sin(phi) * stheta;
1291 pz = pstar * ctheta;
1295 std::cerr <<
m_className <<
"::GetElectronCollision:\n";
1296 std::cerr <<
" Band index (" << band <<
") out of range.\n";
1305 if (i < 0 || i >= nIonisationProducts) {
1306 std::cerr <<
m_className <<
"::GetIonisationProduct:\n";
1307 std::cerr <<
" Index (" << i <<
") out of range.\n";
1311 type = ionProducts[i].type;
1312 energy = ionProducts[i].energy;
1318 nCollElectronAcoustic = nCollElectronOptical = 0;
1319 nCollElectronIntervalley = 0;
1320 nCollElectronImpurity = 0;
1321 nCollElectronIonisation = 0;
1322 const int nLevels = nLevelsX + nLevelsL + nLevelsG;
1323 nCollElectronDetailed.resize(nLevels);
1324 for (
int j = nLevels; j--;) nCollElectronDetailed[j] = 0;
1325 const int nBands = nValleysX + nValleysL + 1;
1326 nCollElectronBand.resize(nBands);
1327 for (
int j = nBands; j--;) nCollElectronBand[j] = 0;
1332 return nCollElectronAcoustic + nCollElectronOptical +
1333 nCollElectronIntervalley + nCollElectronImpurity +
1334 nCollElectronIonisation;
1339 const int nLevels = nLevelsX + nLevelsL + nLevelsG;
1345 const int nLevels = nLevelsX + nLevelsL + nLevelsG;
1346 if (level < 0 || level >= nLevels) {
1347 std::cerr <<
m_className <<
"::GetNumberOfElectronCollisions:\n";
1348 std::cerr <<
" Requested scattering rate term (" << level
1349 <<
") does not exist.\n";
1352 return nCollElectronDetailed[level];
1357 const int nBands = nValleysX + nValleysL + 1;
1363 const int nBands = nValleysX + nValleysL + 1;
1364 if (band < 0 || band >= nBands) {
1365 std::cerr <<
m_className <<
"::GetElectronBandPopulation:\n";
1366 std::cerr <<
" Band index (" << band <<
") out of range.\n";
1369 return nCollElectronBand[band];
1373 const unsigned int& i) {
1376 std::cerr <<
m_className <<
"::GetOpticalDataRange:\n";
1377 std::cerr <<
" Medium has only one component.\n";
1381 if (!m_hasOpticalData) {
1382 if (!LoadOpticalData(opticalDataFile)) {
1383 std::cerr <<
m_className <<
"::GetOpticalDataRange:\n";
1384 std::cerr <<
" Optical data table could not be loaded.\n";
1387 m_hasOpticalData =
true;
1390 emin = opticalDataTable[0].energy;
1391 emax = opticalDataTable.back().energy;
1393 std::cout <<
m_className <<
"::GetOpticalDataRange:\n";
1394 std::cout <<
" " << emin <<
" < E [eV] < " << emax <<
"\n";
1400 double& eps2,
const unsigned int& i) {
1403 std::cerr <<
m_className <<
"::GetDielectricFunction:\n";
1404 std::cerr <<
" Medium has only one component.\n";
1409 if (!m_hasOpticalData) {
1410 if (!LoadOpticalData(opticalDataFile)) {
1411 std::cerr <<
m_className <<
"::GetDielectricFunction:\n";
1412 std::cerr <<
" Optical data table could not be loaded.\n";
1415 m_hasOpticalData =
true;
1419 const double emin = opticalDataTable[0].energy;
1420 const double emax = opticalDataTable.back().energy;
1421 if (e < emin || e > emax) {
1422 std::cerr <<
m_className <<
"::GetDielectricFunction:\n";
1423 std::cerr <<
" Requested energy (" << e <<
" eV) "
1424 <<
" is outside the range of the optical data table.\n";
1425 std::cerr <<
" " << emin <<
" < E [eV] < " << emax <<
"\n";
1432 int iUp = opticalDataTable.size() - 1;
1434 while (iUp - iLow > 1) {
1435 iM = (iUp + iLow) >> 1;
1436 if (e >= opticalDataTable[iM].energy) {
1446 const double logX0 = log(opticalDataTable[iLow].energy);
1447 const double logX1 = log(opticalDataTable[iUp].energy);
1448 const double logX = log(e);
1449 if (opticalDataTable[iLow].eps1 <= 0. || opticalDataTable[iUp].eps1 <= 0.) {
1450 eps1 = opticalDataTable[iLow].eps1 +
1451 (e - opticalDataTable[iLow].energy) *
1452 (opticalDataTable[iUp].eps1 - opticalDataTable[iLow].eps1) /
1453 (opticalDataTable[iUp].energy - opticalDataTable[iLow].energy);
1455 const double logY0 = log(opticalDataTable[iLow].eps1);
1456 const double logY1 = log(opticalDataTable[iUp].eps1);
1457 eps1 = logY0 + (logX - logX0) * (logY1 - logY0) / (logX1 - logX0);
1463 const double logY0 = log(opticalDataTable[iLow].eps2);
1464 const double logY1 = log(opticalDataTable[iUp].eps2);
1465 eps2 = logY0 + (log(e) - logX0) * (logY1 - logY0) / (logX1 - logX0);
1475 std::cerr <<
" Nothing changed.\n";
1479 if (!UpdateTransportParameters()) {
1481 std::cerr <<
" Error preparing transport parameters/"
1482 <<
"calculating collision rates.\n";
1488bool MediumSilicon::UpdateTransportParameters() {
1491 switch (impactIonisationModel) {
1492 case ImpactIonisationModelVanOverstraeten:
1493 UpdateImpactIonisationVanOverstraetenDeMan();
1495 case ImpactIonisationModelGrant:
1496 UpdateImpactIonisationGrant();
1499 std::cerr <<
m_className <<
"::UpdateTransportParameters:\n";
1500 std::cerr <<
" Unknown impact ionisation model. Bug!\n";
1504 if (!m_hasUserMobility) {
1506 switch (latticeMobilityModel) {
1507 case LatticeMobilityModelMinimos:
1508 UpdateLatticeMobilityMinimos();
1510 case LatticeMobilityModelSentaurus:
1511 UpdateLatticeMobilitySentaurus();
1513 case LatticeMobilityModelReggiani:
1514 UpdateLatticeMobilityReggiani();
1517 std::cerr <<
m_className <<
"::UpdateTransportParameters:\n";
1518 std::cerr <<
" Unknown lattice mobility model.\n";
1519 std::cerr <<
" Program bug!\n";
1524 switch (dopingMobilityModel) {
1525 case DopingMobilityModelMinimos:
1526 UpdateDopingMobilityMinimos();
1528 case DopingMobilityModelMasetti:
1529 UpdateDopingMobilityMasetti();
1532 std::cerr <<
m_className <<
"::UpdateTransportParameters:\n";
1533 std::cerr <<
" Unknown doping mobility model.\n";
1534 std::cerr <<
" Program bug!\n";
1540 if (!m_hasUserSaturationVelocity) {
1541 switch (saturationVelocityModel) {
1542 case SaturationVelocityModelMinimos:
1543 UpdateSaturationVelocityMinimos();
1545 case SaturationVelocityModelCanali:
1546 UpdateSaturationVelocityCanali();
1548 case SaturationVelocityModelReggiani:
1549 UpdateSaturationVelocityReggiani();
1555 switch (highFieldMobilityModel) {
1556 case HighFieldMobilityModelCanali:
1557 UpdateHighFieldMobilityCanali();
1562 std::cout <<
m_className <<
"::UpdateTransportParameters:\n";
1563 std::cout <<
" Low-field mobility [cm2 V-1 ns-1]\n";
1564 std::cout <<
" Electrons: " << eMobility <<
"\n";
1565 std::cout <<
" Holes: " << hMobility <<
"\n";
1566 if (highFieldMobilityModel > 2) {
1567 std::cout <<
" Mobility is not field-dependent.\n";
1569 std::cout <<
" Saturation velocity [cm / ns]\n";
1570 std::cout <<
" Electrons: " << eSatVel <<
"\n";
1571 std::cout <<
" Holes: " << hSatVel <<
"\n";
1575 if (!ElectronScatteringRates())
return false;
1576 if (!HoleScatteringRates())
return false;
1584void MediumSilicon::UpdateLatticeMobilityMinimos() {
1592 const double eMu0 = 1.43e-6;
1593 const double hMu0 = 0.46e-6;
1597 eLatticeMobility = eMu0 *
pow(t, -2.);
1598 hLatticeMobility = hMu0 *
pow(t, -2.18);
1601void MediumSilicon::UpdateLatticeMobilitySentaurus() {
1609 const double eMu0 = 1.417e-6;
1610 const double hMu0 = 0.4705e-6;
1614 eLatticeMobility = eMu0 *
pow(t, -2.5);
1615 hLatticeMobility = hMu0 *
pow(t, -2.2);
1618void MediumSilicon::UpdateLatticeMobilityReggiani() {
1625 const double eMu0 = 1.320e-6;
1626 const double hMu0 = 0.460e-6;
1630 eLatticeMobility = eMu0 *
pow(t, -2.);
1631 hLatticeMobility = hMu0 *
pow(t, -2.2);
1634void MediumSilicon::UpdateDopingMobilityMinimos() {
1643 double eMuMin = 0.080e-6;
1644 double hMuMin = 0.045e-6;
1656 eMobility = eMuMin + (eLatticeMobility - eMuMin) /
1657 (1. +
pow(m_dopingConcentration / eRefC, alpha));
1658 hMobility = hMuMin + (hLatticeMobility - hMuMin) /
1659 (1. +
pow(m_dopingConcentration / hRefC, alpha));
1662void MediumSilicon::UpdateDopingMobilityMasetti() {
1670 if (m_dopingConcentration < 1.e13) {
1671 eMobility = eLatticeMobility;
1672 hMobility = hLatticeMobility;
1677 const double eMuMin1 = 0.0522e-6;
1678 const double eMuMin2 = 0.0522e-6;
1679 const double eMu1 = 0.0434e-6;
1680 const double hMuMin1 = 0.0449e-6;
1681 const double hMuMin2 = 0.;
1682 const double hMu1 = 0.029e-6;
1683 const double eCr = 9.68e16;
1684 const double eCs = 3.42e20;
1685 const double hCr = 2.23e17;
1686 const double hCs = 6.10e20;
1687 const double hPc = 9.23e16;
1688 const double eAlpha = 0.68;
1689 const double eBeta = 2.;
1690 const double hAlpha = 0.719;
1691 const double hBeta = 2.;
1693 eMobility = eMuMin1 + (eLatticeMobility - eMuMin2) /
1694 (1. +
pow(m_dopingConcentration / eCr, eAlpha)) -
1695 eMu1 / (1. +
pow(eCs / m_dopingConcentration, eBeta));
1697 hMobility = hMuMin1 *
exp(-hPc / m_dopingConcentration) +
1698 (hLatticeMobility - hMuMin2) /
1699 (1. +
pow(m_dopingConcentration / hCr, hAlpha)) -
1700 hMu1 / (1. +
pow(hCs / m_dopingConcentration, hBeta));
1703void MediumSilicon::UpdateSaturationVelocityMinimos() {
1711 eSatVel = 1.e-2 / (1. + 0.74 * (
m_temperature / 300. - 1.));
1712 hSatVel = 0.704e-2 / (1. + 0.37 * (
m_temperature / 300. - 1.));
1715void MediumSilicon::UpdateSaturationVelocityCanali() {
1726void MediumSilicon::UpdateSaturationVelocityReggiani() {
1736void MediumSilicon::UpdateHighFieldMobilityCanali() {
1746 eBetaCanaliInv = 1. / eBetaCanali;
1747 hBetaCanaliInv = 1. / hBetaCanali;
1750void MediumSilicon::UpdateImpactIonisationVanOverstraetenDeMan() {
1761 const double hbarOmega = 0.063;
1763 const double gamma = tanh(hbarOmega / (2. * BoltzmannConstant * 300.)) /
1767 eImpactA0 = gamma * 3.318e5;
1768 eImpactB0 = gamma * 1.135e6;
1769 eImpactA1 = gamma * 7.03e5;
1770 eImpactB1 = gamma * 1.231e6;
1772 hImpactA0 = gamma * 1.582e6;
1773 hImpactB0 = gamma * 2.036e6;
1774 hImpactA1 = gamma * 6.71e5;
1775 hImpactB1 = gamma * 1.693e6;
1778void MediumSilicon::UpdateImpactIonisationGrant() {
1787 double hbarOmega = 0.063;
1789 double gamma = tanh(hbarOmega / (2. * BoltzmannConstant * 300.)) /
1792 eImpactA0 = 2.60e6 * gamma;
1793 eImpactB0 = 1.43e6 * gamma;
1794 eImpactA1 = 6.20e5 * gamma;
1795 eImpactB1 = 1.08e6 * gamma;
1796 eImpactA2 = 5.05e5 * gamma;
1797 eImpactB2 = 9.90e5 * gamma;
1799 hImpactA0 = 2.00e6 * gamma;
1800 hImpactB0 = 1.97e6 * gamma;
1801 hImpactA1 = 5.60e5 * gamma;
1802 hImpactB1 = 1.32e6 * gamma;
1805bool MediumSilicon::ElectronMobilityMinimos(
const double e,
double& mu)
const {
1813 mu = 2. * eMobility /
1814 (1. +
sqrt(1. +
pow(2. * eMobility * e / eSatVel, 2.)));
1819bool MediumSilicon::ElectronMobilityCanali(
const double e,
double& mu)
const {
1828 pow(1. +
pow(eMobility * e / eSatVel, eBetaCanali), eBetaCanaliInv);
1833bool MediumSilicon::ElectronMobilityReggiani(
const double e,
double& mu)
const {
1842 mu = eMobility /
pow(1 +
pow(eMobility * e / eSatVel, 1.5), 1. / 1.5);
1847bool MediumSilicon::ElectronImpactIonisationVanOverstraetenDeMan(
1848 const double e,
double& alpha)
const {
1858 }
else if (e < 1.2786e5) {
1859 alpha = eImpactA0 *
exp(-eImpactB0 / e);
1861 alpha = eImpactA1 *
exp(-eImpactB1 / e);
1866bool MediumSilicon::ElectronImpactIonisationGrant(
const double e,
1867 double& alpha)
const {
1874 }
else if (e < 2.4e5) {
1875 alpha = eImpactA0 *
exp(-eImpactB0 / e);
1876 }
else if (e < 5.3e5) {
1877 alpha = eImpactA1 *
exp(-eImpactB1 / e);
1879 alpha = eImpactA2 *
exp(-eImpactB2 / e);
1884bool MediumSilicon::HoleMobilityMinimos(
const double e,
double& mu)
const {
1892 mu = hMobility / (1. + hMobility * e / eSatVel);
1897bool MediumSilicon::HoleMobilityCanali(
const double e,
double& mu)
const {
1906 pow(1. +
pow(hMobility * e / hSatVel, hBetaCanali), hBetaCanaliInv);
1911bool MediumSilicon::HoleMobilityReggiani(
const double e,
double& mu)
const {
1920 mu = hMobility /
pow(1. +
pow(hMobility * e / hSatVel, 2.), 0.5);
1925bool MediumSilicon::HoleImpactIonisationVanOverstraetenDeMan(
1926 const double e,
double& alpha)
const {
1935 alpha = hImpactA1 *
exp(-hImpactB1 / e);
1940bool MediumSilicon::HoleImpactIonisationGrant(
const double e,
1941 double& alpha)
const {
1948 }
else if (e < 5.3e5) {
1949 alpha = hImpactA0 *
exp(-hImpactB0 / e);
1951 alpha = hImpactA1 *
exp(-hImpactB1 / e);
1956bool MediumSilicon::LoadOpticalData(
const std::string filename) {
1959 char* pPath = getenv(
"GARFIELD_HOME");
1961 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
1962 std::cerr <<
" Environment variable GARFIELD_HOME is not set.\n";
1965 std::string filepath = pPath;
1966 filepath = filepath +
"/Data/" + filename;
1969 std::ifstream infile;
1970 infile.open(filepath.c_str(), std::ios::in);
1973 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
1974 std::cerr <<
" Error opening file " << filename <<
".\n";
1979 opticalDataTable.clear();
1981 double lastEnergy = -1.;
1982 double energy, eps1, eps2, loss;
1986 std::istringstream dataStream;
1988 while (!infile.eof()) {
1991 std::getline(infile, line);
1993 line.erase(line.begin(),
1994 std::find_if(line.begin(), line.end(),
1995 not1(std::ptr_fun<int, int>(isspace))));
1997 if (line[0] ==
'#' || line[0] ==
'*' || (line[0] ==
'/' && line[1] ==
'/'))
2000 dataStream.str(line);
2001 dataStream >> energy >> eps1 >> eps2 >> loss;
2002 if (dataStream.eof())
break;
2004 if (infile.fail()) {
2005 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
2006 std::cerr <<
" Error reading file " << filename <<
" (line " << i
2016 if (energy <= lastEnergy) {
2017 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
2018 std::cerr <<
" Table is not in monotonically "
2019 <<
"increasing order (line " << i <<
").\n";
2020 std::cerr <<
" " << lastEnergy <<
" " << energy <<
" " << eps1
2021 <<
" " << eps2 <<
"\n";
2026 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
2027 std::cerr <<
" Negative value of the loss function "
2028 <<
"(line " << i <<
").\n";
2032 if (energy <= 0.)
continue;
2034 data.energy = energy;
2037 opticalDataTable.push_back(data);
2038 lastEnergy = energy;
2041 const int nEntries = opticalDataTable.size();
2042 if (nEntries <= 0) {
2043 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
2044 std::cerr <<
" Import of data from file " << filepath <<
"failed.\n";
2045 std::cerr <<
" No valid data found.\n";
2050 std::cout <<
m_className <<
"::LoadOpticalData:\n";
2051 std::cout <<
" Read " << nEntries <<
" values from file " << filepath
2057bool MediumSilicon::ElectronScatteringRates() {
2060 cfTotElectronsX.resize(nEnergyStepsXL);
2061 cfTotElectronsL.resize(nEnergyStepsXL);
2062 cfTotElectronsG.resize(nEnergyStepsG);
2063 cfElectronsX.resize(nEnergyStepsXL);
2064 cfElectronsL.resize(nEnergyStepsXL);
2065 cfElectronsG.resize(nEnergyStepsG);
2066 for (
int i = nEnergyStepsXL; i--;) {
2067 cfTotElectronsX[i] = 0.;
2068 cfTotElectronsL[i] = 0.;
2069 cfElectronsX[i].clear();
2070 cfElectronsL[i].clear();
2072 for (
int i = nEnergyStepsG; i--;) {
2073 cfTotElectronsG[i] = 0.;
2074 cfElectronsG[i].clear();
2076 energyLossElectronsX.clear();
2077 energyLossElectronsL.clear();
2078 energyLossElectronsG.clear();
2079 scatTypeElectronsX.clear();
2080 scatTypeElectronsL.clear();
2081 scatTypeElectronsG.clear();
2082 cfNullElectronsX = 0.;
2083 cfNullElectronsL = 0.;
2084 cfNullElectronsG = 0.;
2090 ElectronAcousticScatteringRates();
2091 ElectronOpticalScatteringRates();
2092 ElectronImpurityScatteringRates();
2093 ElectronIntervalleyScatteringRatesXX();
2094 ElectronIntervalleyScatteringRatesXL();
2095 ElectronIntervalleyScatteringRatesLL();
2096 ElectronIntervalleyScatteringRatesXGLG();
2097 ElectronIonisationRatesXL();
2098 ElectronIonisationRatesG();
2101 std::cout <<
m_className <<
"::ElectronScatteringRates:\n";
2102 std::cout <<
" " << nLevelsX <<
" X-valley scattering terms\n";
2103 std::cout <<
" " << nLevelsL <<
" L-valley scattering terms\n";
2104 std::cout <<
" " << nLevelsG <<
" higher band scattering terms\n";
2107 std::ofstream outfileX;
2108 std::ofstream outfileL;
2110 outfileX.open(
"ratesX.txt", std::ios::out);
2111 outfileL.open(
"ratesL.txt", std::ios::out);
2114 ieMinL = int(eMinL / eStepXL) + 1;
2115 for (
int i = 0; i < nEnergyStepsXL; ++i) {
2117 for (
int j = nLevelsX; j--;) cfTotElectronsX[i] += cfElectronsX[i][j];
2118 for (
int j = nLevelsL; j--;) cfTotElectronsL[i] += cfElectronsL[i][j];
2121 outfileX << i* eStepXL <<
" " << cfTotElectronsX[i] <<
" ";
2122 for (
int j = 0; j < nLevelsX; ++j) {
2123 outfileX << cfElectronsX[i][j] <<
" ";
2126 outfileL << i* eStepXL <<
" " << cfTotElectronsL[i] <<
" ";
2127 for (
int j = 0; j < nLevelsL; ++j) {
2128 outfileL << cfElectronsL[i][j] <<
" ";
2133 if (cfTotElectronsX[i] > cfNullElectronsX) {
2134 cfNullElectronsX = cfTotElectronsX[i];
2136 if (cfTotElectronsL[i] > cfNullElectronsL) {
2137 cfNullElectronsL = cfTotElectronsL[i];
2141 if (cfTotElectronsX[i] <= 0.) {
2142 std::cerr <<
m_className <<
"::ElectronScatteringRates:\n";
2143 std::cerr <<
" X-valley scattering rate at " << i* eStepXL
2148 for (
int j = 0; j < nLevelsX; ++j) {
2149 cfElectronsX[i][j] /= cfTotElectronsX[i];
2150 if (j > 0) cfElectronsX[i][j] += cfElectronsX[i][j - 1];
2154 if (cfTotElectronsL[i] <= 0.) {
2155 if (i < ieMinL)
continue;
2156 std::cerr <<
m_className <<
"::ElectronScatteringRates:\n";
2157 std::cerr <<
" L-valley scattering rate at " << i* eStepXL
2162 for (
int j = 0; j < nLevelsL; ++j) {
2163 cfElectronsL[i][j] /= cfTotElectronsL[i];
2164 if (j > 0) cfElectronsL[i][j] += cfElectronsL[i][j - 1];
2173 std::ofstream outfileG;
2175 outfileG.open(
"ratesG.txt", std::ios::out);
2177 ieMinG = int(eMinG / eStepG) + 1;
2178 for (
int i = 0; i < nEnergyStepsG; ++i) {
2180 for (
int j = nLevelsG; j--;) cfTotElectronsG[i] += cfElectronsG[i][j];
2183 outfileG << i* eStepG <<
" " << cfTotElectronsG[i] <<
" ";
2184 for (
int j = 0; j < nLevelsG; ++j) {
2185 outfileG << cfElectronsG[i][j] <<
" ";
2190 if (cfTotElectronsG[i] > cfNullElectronsG) {
2191 cfNullElectronsG = cfTotElectronsG[i];
2195 if (cfTotElectronsG[i] <= 0.) {
2196 if (i < ieMinG)
continue;
2197 std::cerr <<
m_className <<
"::ElectronScatteringRates:\n";
2198 std::cerr <<
" Higher band scattering rate at " << i* eStepG
2202 for (
int j = 0; j < nLevelsG; ++j) {
2203 cfElectronsG[i][j] /= cfTotElectronsG[i];
2204 if (j > 0) cfElectronsG[i][j] += cfElectronsG[i][j - 1];
2215bool MediumSilicon::ElectronAcousticScatteringRates() {
2222 const double rho =
m_density *
m_a * AtomicMassUnitElectronVolt;
2228 const double defpot = 9.;
2230 const double u = 9.04e-4;
2232 const double cIntra = TwoPi * SpeedOfLight * SpeedOfLight * kbt * defpot *
2233 defpot / (Hbar * u * u * rho);
2237 for (
int i = 0; i < nEnergyStepsXL; ++i) {
2241 cfElectronsX[i].push_back(cIntra * dosX);
2242 cfElectronsL[i].push_back(cIntra * dosL);
2247 for (
int i = 0; i < nEnergyStepsG; ++i) {
2250 cfElectronsG[i].push_back(cIntra * dosG);
2255 energyLossElectronsX.push_back(0.);
2256 energyLossElectronsL.push_back(0.);
2257 energyLossElectronsG.push_back(0.);
2258 scatTypeElectronsX.push_back(ElectronCollisionTypeAcousticPhonon);
2259 scatTypeElectronsL.push_back(ElectronCollisionTypeAcousticPhonon);
2260 scatTypeElectronsG.push_back(ElectronCollisionTypeAcousticPhonon);
2268bool MediumSilicon::ElectronOpticalScatteringRates() {
2280 const double rho =
m_density *
m_a * AtomicMassUnitElectronVolt;
2285 const double dtk = 2.2e8;
2287 const double eph = 63.0e-3;
2289 const double nocc = 1. / (
exp(eph / kbt) - 1);
2291 const double c0 = HbarC * SpeedOfLight * Pi / rho;
2292 double c = c0 * dtk * dtk / eph;
2319 for (
int i = 0; i < nEnergyStepsG; ++i) {
2323 cfElectronsG[i].push_back(c * nocc * dos);
2325 cfElectronsG[i].push_back(0.);
2328 if (en > eMinG + eph) {
2330 cfElectronsG[i].push_back(c * (nocc + 1) * dos);
2332 cfElectronsG[i].push_back(0.);
2339 energyLossElectronsG.push_back(-eph);
2342 energyLossElectronsG.push_back(eph);
2345 scatTypeElectronsG.push_back(ElectronCollisionTypeOpticalPhonon);
2346 scatTypeElectronsG.push_back(ElectronCollisionTypeOpticalPhonon);
2354bool MediumSilicon::ElectronIntervalleyScatteringRatesXX() {
2361 const double rho =
m_density *
m_a * AtomicMassUnitElectronVolt;
2365 const int nPhonons = 6;
2371 const double dtk[nPhonons] = {0.5e8, 0.8e8, 1.1e9, 0.3e8, 2.0e8, 2.0e8};
2373 const double eph[nPhonons] = {12.06e-3, 18.53e-3, 62.04e-3,
2374 18.86e-3, 47.39e-3, 59.03e-3};
2376 double nocc[nPhonons];
2378 const double c0 = HbarC * SpeedOfLight * Pi / rho;
2381 for (
int j = 0; j < nPhonons; ++j) {
2382 nocc[j] = 1. / (
exp(eph[j] / kbt) - 1);
2383 c[j] = c0 * dtk[j] * dtk[j] / eph[j];
2384 if (j > 2) c[j] *= 4;
2389 for (
int i = 0; i < nEnergyStepsXL; ++i) {
2390 for (
int j = 0; j < nPhonons; ++j) {
2393 cfElectronsX[i].push_back(c[j] * nocc[j] * dos);
2397 cfElectronsX[i].push_back(c[j] * (nocc[j] + 1) * dos);
2399 cfElectronsX[i].push_back(0.);
2405 for (
int j = 0; j < nPhonons; ++j) {
2407 energyLossElectronsX.push_back(-eph[j]);
2409 energyLossElectronsX.push_back(eph[j]);
2411 scatTypeElectronsX.push_back(ElectronCollisionTypeIntervalleyG);
2412 scatTypeElectronsX.push_back(ElectronCollisionTypeIntervalleyG);
2414 scatTypeElectronsX.push_back(ElectronCollisionTypeIntervalleyF);
2415 scatTypeElectronsX.push_back(ElectronCollisionTypeIntervalleyF);
2419 nLevelsX += 2 * nPhonons;
2424bool MediumSilicon::ElectronIntervalleyScatteringRatesXL() {
2432 const double rho =
m_density *
m_a * AtomicMassUnitElectronVolt;
2436 const int nPhonons = 4;
2439 const double dtk[nPhonons] = {2.e8, 2.e8, 2.e8, 2.e8};
2441 const double eph[nPhonons] = {58.e-3, 55.e-3, 41.e-3, 17.e-3};
2447 double nocc[nPhonons] = {0.};
2449 const double c0 = HbarC * SpeedOfLight * Pi / rho;
2452 for (
int j = 0; j < nPhonons; ++j) {
2453 nocc[j] = 1. / (
exp(eph[j] / kbt) - 1);
2454 c[j] = c0 * dtk[j] * dtk[j] / eph[j];
2459 for (
int i = 0; i < nEnergyStepsXL; ++i) {
2460 for (
int j = 0; j < nPhonons; ++j) {
2463 if (en + eph[j] > eMinL) {
2465 cfElectronsX[i].push_back(zL * c[j] * nocc[j] * dos);
2467 cfElectronsX[i].push_back(0.);
2470 if (en - eph[j] > eMinL) {
2472 cfElectronsX[i].push_back(zL * c[j] * (nocc[j] + 1) * dos);
2474 cfElectronsX[i].push_back(0.);
2480 cfElectronsL[i].push_back(zX * c[j] * nocc[j] * dos);
2483 cfElectronsL[i].push_back(zX * c[j] * (nocc[j] + 1) * dos);
2485 cfElectronsL[i].push_back(0.);
2486 cfElectronsL[i].push_back(0.);
2492 for (
int j = 0; j < nPhonons; ++j) {
2494 energyLossElectronsX.push_back(-eph[j]);
2495 energyLossElectronsL.push_back(-eph[j]);
2497 energyLossElectronsX.push_back(eph[j]);
2498 energyLossElectronsL.push_back(eph[j]);
2499 scatTypeElectronsX.push_back(ElectronCollisionTypeInterbandXL);
2500 scatTypeElectronsX.push_back(ElectronCollisionTypeInterbandXL);
2501 scatTypeElectronsL.push_back(ElectronCollisionTypeInterbandXL);
2502 scatTypeElectronsL.push_back(ElectronCollisionTypeInterbandXL);
2505 nLevelsX += 2 * nPhonons;
2506 nLevelsL += 2 * nPhonons;
2511bool MediumSilicon::ElectronIntervalleyScatteringRatesLL() {
2521 const double rho =
m_density *
m_a * AtomicMassUnitElectronVolt;
2525 const int nPhonons = 1;
2527 const double dtk[nPhonons] = {2.63e8};
2529 const double eph[nPhonons] = {38.87e-3};
2531 double nocc[nPhonons];
2533 const double c0 = HbarC * SpeedOfLight * Pi / rho;
2536 for (
int j = 0; j < nPhonons; ++j) {
2537 nocc[j] = 1. / (
exp(eph[j] / kbt) - 1);
2538 c[j] = c0 * dtk[j] * dtk[j] / eph[j];
2544 for (
int i = 0; i < nEnergyStepsXL; ++i) {
2545 for (
int j = 0; j < nPhonons; ++j) {
2548 cfElectronsL[i].push_back(c[j] * nocc[j] * dos);
2550 if (en > eMinL + eph[j]) {
2552 cfElectronsL[i].push_back(c[j] * (nocc[j] + 1) * dos);
2554 cfElectronsL[i].push_back(0.);
2560 for (
int j = 0; j < nPhonons; ++j) {
2562 energyLossElectronsL.push_back(-eph[j]);
2564 energyLossElectronsL.push_back(eph[j]);
2565 scatTypeElectronsL.push_back(ElectronCollisionTypeIntervalleyF);
2566 scatTypeElectronsL.push_back(ElectronCollisionTypeIntervalleyF);
2569 nLevelsL += 2 * nPhonons;
2574bool MediumSilicon::ElectronIntervalleyScatteringRatesXGLG() {
2582 const double rho =
m_density *
m_a * AtomicMassUnitElectronVolt;
2586 const int nPhonons = 1;
2590 const double dtk[nPhonons] = {2.43e8};
2592 const double eph[nPhonons] = {37.65e-3};
2599 double nocc[nPhonons] = {0.};
2601 const double c0 = HbarC * SpeedOfLight * Pi / rho;
2604 for (
int j = 0; j < nPhonons; ++j) {
2605 nocc[j] = 1. / (
exp(eph[j] / kbt) - 1);
2606 c[j] = c0 * dtk[j] * dtk[j] / eph[j];
2612 for (
int i = 0; i < nEnergyStepsXL; ++i) {
2613 for (
int j = 0; j < nPhonons; ++j) {
2615 if (en + eph[j] > eMinG) {
2617 nValleysX + nValleysL);
2618 cfElectronsX[i].push_back(zG * c[j] * nocc[j] * dos);
2619 cfElectronsL[i].push_back(zG * c[j] * nocc[j] * dos);
2621 cfElectronsX[i].push_back(0.);
2622 cfElectronsL[i].push_back(0.);
2625 if (en - eph[j] > eMinG) {
2627 nValleysX + nValleysL);
2628 cfElectronsX[i].push_back(zG * c[j] * (nocc[j] + 1) * dos);
2629 cfElectronsL[i].push_back(zG * c[j] * (nocc[j] + 1) * dos);
2631 cfElectronsX[i].push_back(0.);
2632 cfElectronsL[i].push_back(0.);
2640 double dosX = 0., dosL = 0.;
2641 for (
int i = 0; i < nEnergyStepsG; ++i) {
2642 for (
int j = 0; j < nPhonons; ++j) {
2646 cfElectronsG[i].push_back(zX * c[j] * nocc[j] * dosX);
2648 cfElectronsG[i].push_back(zL * c[j] * nocc[j] * dosL);
2650 cfElectronsG[i].push_back(0.);
2656 cfElectronsG[i].push_back(zX * c[j] * (nocc[j] + 1) * dosX);
2658 cfElectronsG[i].push_back(0.);
2660 if (en - eph[j] > eMinL) {
2661 cfElectronsG[i].push_back(zL * c[j] * (nocc[j] + 1) * dosL);
2663 cfElectronsG[i].push_back(0.);
2669 for (
int j = 0; j < nPhonons; ++j) {
2671 energyLossElectronsX.push_back(-eph[j]);
2672 energyLossElectronsL.push_back(-eph[j]);
2674 energyLossElectronsX.push_back(eph[j]);
2675 energyLossElectronsL.push_back(eph[j]);
2677 energyLossElectronsG.push_back(-eph[j]);
2678 energyLossElectronsG.push_back(-eph[j]);
2680 energyLossElectronsG.push_back(eph[j]);
2681 energyLossElectronsG.push_back(eph[j]);
2683 scatTypeElectronsX.push_back(ElectronCollisionTypeInterbandXG);
2684 scatTypeElectronsX.push_back(ElectronCollisionTypeInterbandXG);
2685 scatTypeElectronsL.push_back(ElectronCollisionTypeInterbandLG);
2686 scatTypeElectronsL.push_back(ElectronCollisionTypeInterbandLG);
2688 scatTypeElectronsG.push_back(ElectronCollisionTypeInterbandXG);
2689 scatTypeElectronsG.push_back(ElectronCollisionTypeInterbandLG);
2690 scatTypeElectronsG.push_back(ElectronCollisionTypeInterbandXG);
2691 scatTypeElectronsG.push_back(ElectronCollisionTypeInterbandLG);
2694 nLevelsX += 2 * nPhonons;
2695 nLevelsL += 2 * nPhonons;
2696 nLevelsG += 4 * nPhonons;
2701bool MediumSilicon::ElectronIonisationRatesXL() {
2709 const double p[3] = {6.25e1, 3.e3, 6.8e5};
2711 const double eth[3] = {1.2, 1.8, 3.45};
2714 for (
int i = 0; i < nEnergyStepsXL; ++i) {
2717 fIon += p[0] * (en - eth[0]) * (en - eth[0]);
2720 fIon += p[1] * (en - eth[1]) * (en - eth[1]);
2723 fIon += p[2] * (en - eth[2]) * (en - eth[2]);
2725 cfElectronsX[i].push_back(fIon);
2726 cfElectronsL[i].push_back(fIon);
2730 energyLossElectronsX.push_back(eth[0]);
2731 energyLossElectronsL.push_back(eth[0]);
2732 scatTypeElectronsX.push_back(ElectronCollisionTypeIonisation);
2733 scatTypeElectronsL.push_back(ElectronCollisionTypeIonisation);
2740bool MediumSilicon::ElectronIonisationRatesG() {
2749 const double p[3] = {6.25e1, 3.e3, 6.8e5};
2751 const double eth[3] = {1.2, 1.8, 3.45};
2754 for (
int i = 0; i < nEnergyStepsG; ++i) {
2757 fIon += p[0] * (en - eth[0]) * (en - eth[0]);
2760 fIon += p[1] * (en - eth[1]) * (en - eth[1]);
2763 fIon += p[2] * (en - eth[2]) * (en - eth[2]);
2766 cfElectronsG[i].push_back(fIon);
2768 cfElectronsG[i].push_back(0.);
2773 energyLossElectronsG.push_back(eth[0]);
2774 scatTypeElectronsG.push_back(ElectronCollisionTypeIonisation);
2780bool MediumSilicon::ElectronImpurityScatteringRates() {
2787 const double mdX = ElectronMass *
pow(mLongX * mTransX * mTransX, 1. / 3.);
2788 const double mdL = ElectronMass *
pow(mLongL * mTransL * mTransL, 1. / 3.);
2793 const double impurityConcentration = m_dopingConcentration;
2794 if (impurityConcentration < Small)
return true;
2797 const double ls =
sqrt(eps * kbt / (4 * Pi * FineStructureConstant * HbarC *
2798 impurityConcentration));
2799 const double ebX = 0.5 * HbarC * HbarC / (mdX * ls * ls);
2800 const double ebL = 0.5 * HbarC * HbarC / (mdL * ls * ls);
2807 const double cX = impurityConcentration * Pi *
2808 pow(FineStructureConstant * HbarC, 2) * SpeedOfLight /
2809 (
sqrt(2 * mdX) * eps * eps);
2810 const double cL = impurityConcentration * Pi *
2811 pow(FineStructureConstant * HbarC, 2) * SpeedOfLight /
2812 (
sqrt(2 * mdL) * eps * eps);
2815 for (
int i = 0; i < nEnergyStepsXL; ++i) {
2816 const double gammaX = en * (1. + alphaX * en);
2817 const double gammaL = (en - eMinL) * (1. + alphaL * (en - eMinL));
2821 cfElectronsX[i].push_back(0.);
2823 const double b = 4 * gammaX / ebX;
2825 .push_back((cX /
pow(gammaX, 1.5)) * (log(1. + b) - b / (1. + b)));
2827 if (en <= eMinL || gammaL <= 0.) {
2828 cfElectronsL[i].push_back(0.);
2830 const double b = 4 * gammaL / ebL;
2832 .push_back((cL /
pow(gammaL, 1.5)) * (log(1. + b) - b / (1. + b)));
2837 energyLossElectronsX.push_back(0.);
2838 energyLossElectronsL.push_back(0.);
2839 scatTypeElectronsX.push_back(ElectronCollisionTypeImpurity);
2840 scatTypeElectronsL.push_back(ElectronCollisionTypeImpurity);
2847bool MediumSilicon::HoleScatteringRates() {
2850 cfTotHoles.resize(nEnergyStepsV);
2851 cfHoles.resize(nEnergyStepsV);
2852 for (
int i = nEnergyStepsV; i--;) {
2856 energyLossHoles.clear();
2857 scatTypeHoles.clear();
2862 HoleAcousticScatteringRates();
2863 HoleOpticalScatteringRates();
2865 HoleIonisationRates();
2867 std::ofstream outfile;
2869 outfile.open(
"ratesV.txt", std::ios::out);
2872 for (
int i = 0; i < nEnergyStepsV; ++i) {
2874 for (
int j = nLevelsV; j--;) cfTotHoles[i] += cfHoles[i][j];
2877 outfile << i* eStepV <<
" " << cfTotHoles[i] <<
" ";
2878 for (
int j = 0; j < nLevelsV; ++j) {
2879 outfile << cfHoles[i][j] <<
" ";
2884 if (cfTotHoles[i] > cfNullHoles) {
2885 cfNullHoles = cfTotHoles[i];
2889 if (cfTotHoles[i] <= 0.) {
2890 std::cerr <<
m_className <<
"::HoleScatteringRates:\n";
2891 std::cerr <<
" Scattering rate at " << i* eStepV <<
" eV <= 0.\n";
2895 for (
int j = 0; j < nLevelsV; ++j) {
2896 cfHoles[i][j] /= cfTotHoles[i];
2897 if (j > 0) cfHoles[i][j] += cfHoles[i][j - 1];
2908bool MediumSilicon::HoleAcousticScatteringRates() {
2917 const double rho =
m_density *
m_a * AtomicMassUnitElectronVolt;
2924 const double defpot = 4.6;
2926 const double u = 9.04e-4;
2928 const double cIntra = TwoPi * SpeedOfLight * SpeedOfLight * kbt * defpot *
2929 defpot / (Hbar * u * u * rho);
2933 for (
int i = 0; i < nEnergyStepsV; ++i) {
2935 cfHoles[i].push_back(cIntra * dos);
2940 energyLossHoles.push_back(0.);
2941 scatTypeHoles.push_back(ElectronCollisionTypeAcousticPhonon);
2947bool MediumSilicon::HoleOpticalScatteringRates() {
2956 const double rho =
m_density *
m_a * AtomicMassUnitElectronVolt;
2962 const double dtk = 6.6e8;
2964 const double eph = 63.0e-3;
2966 const double nocc = 1. / (
exp(eph / kbt) - 1);
2968 const double c0 = HbarC * SpeedOfLight * Pi / rho;
2969 double c = c0 * dtk * dtk / eph;
2973 for (
int i = 0; i < nEnergyStepsV; ++i) {
2976 cfHoles[i].push_back(c * nocc * dos);
2980 cfHoles[i].push_back(c * (nocc + 1) * dos);
2982 cfHoles[i].push_back(0.);
2988 energyLossHoles.push_back(-eph);
2990 energyLossHoles.push_back(eph);
2991 scatTypeHoles.push_back(ElectronCollisionTypeOpticalPhonon);
2992 scatTypeHoles.push_back(ElectronCollisionTypeOpticalPhonon);
2999bool MediumSilicon::HoleIonisationRates() {
3005 const double p[2] = {2., 1.e3};
3007 const double eth[2] = {1.1, 1.45};
3009 const double b[2] = {6., 4.};
3012 for (
int i = 0; i < nEnergyStepsV; ++i) {
3015 fIon += p[0] *
pow(en - eth[0], b[0]);
3018 fIon += p[1] *
pow(en - eth[1], b[1]);
3020 cfHoles[i].push_back(fIon);
3024 energyLossHoles.push_back(eth[0]);
3025 scatTypeHoles.push_back(ElectronCollisionTypeIonisation);
3034 int iE = int(e / eStepDos);
3035 if (iE >= nFbDosEntriesConduction || iE < 0) {
3037 }
else if (iE == nFbDosEntriesConduction - 1) {
3038 return fbDosConduction[nFbDosEntriesConduction - 1];
3042 fbDosConduction[iE] +
3043 (fbDosConduction[iE + 1] - fbDosConduction[iE]) * (e / eStepDos - iE);
3046 }
else if (band < nValleysX) {
3048 if (e <= 0.)
return 0.;
3050 const double md3 =
pow(ElectronMass, 3) * mLongX * mTransX * mTransX;
3052 if (useFullBandDos) {
3055 }
else if (e < eMinG) {
3061 return dosX / nValleysX;
3069 if (dosX <= 0.)
return 0.;
3070 return dosX / nValleysX;
3072 }
else if (useNonParabolicity) {
3073 const double alpha = alphaX;
3074 return sqrt(md3 * e * (1. + alpha * e) / 2.) * (1. + 2 * alpha * e) /
3075 (Pi2 *
pow(HbarC, 3.));
3077 return sqrt(md3 * e / 2.) / (Pi2 *
pow(HbarC, 3.));
3079 }
else if (band < nValleysX + nValleysL) {
3081 if (e <= eMinL)
return 0.;
3084 const double md3 =
pow(ElectronMass, 3) * mLongL * mTransL * mTransL;
3086 const double alpha = alphaL;
3088 if (useFullBandDos) {
3090 const double ej = eMinL + 0.5;
3092 return sqrt(md3 * (e - eMinL) * (1. + alpha * (e - eMinL))) *
3093 (1. + 2 * alpha * (e - eMinL)) / (Sqrt2 * Pi2 *
pow(HbarC, 3.));
3096 double fL =
sqrt(md3 * (ej - eMinL) * (1. + alpha * (ej - eMinL))) *
3097 (1. + 2 * alpha * (ej - eMinL)) /
3098 (Sqrt2 * Pi2 *
pow(HbarC, 3.));
3105 if (dosXL <= 0.)
return 0.;
3106 return fL * dosXL / 8.;
3108 }
else if (useNonParabolicity) {
3109 return sqrt(md3 * (e - eMinL) * (1. + alpha * (e - eMinL))) *
3110 (1. + 2 * alpha * (e - eMinL)) / (Sqrt2 * Pi2 *
pow(HbarC, 3.));
3112 return sqrt(md3 * (e - eMinL) / 2.) / (Pi2 *
pow(HbarC, 3.));
3114 }
else if (band == nValleysX + nValleysL) {
3116 const double ej = 2.7;
3118 std::cerr <<
m_className <<
"::GetConductionBandDensityOfStates:\n";
3119 std::cerr <<
" Cannot determine higher band density-of-states.\n";
3120 std::cerr <<
" Program bug. Check offset energy!\n";
3125 }
else if (e < ej) {
3129 return dj * (e - eMinG) / (ej - eMinG);
3135 std::cerr <<
m_className <<
"::GetConductionBandDensityOfStates:\n";
3136 std::cerr <<
" Band index (" << band <<
") out of range.\n";
3137 return ElectronMass *
sqrt(ElectronMass * e / 2.) / (Pi2 *
pow(HbarC, 3.));
3146 int iE = int(e / eStepDos);
3147 if (iE >= nFbDosEntriesValence || iE < 0) {
3149 }
else if (iE == nFbDosEntriesValence - 1) {
3150 return fbDosValence[nFbDosEntriesValence - 1];
3155 (fbDosValence[iE + 1] - fbDosValence[iE]) * (e / eStepDos - iE);
3159 std::cerr <<
m_className <<
"::GetConductionBandDensityOfStates:\n";
3160 std::cerr <<
" Band index (" << band <<
") out of range.\n";
3167 const double widthValenceBand = eStepDos * nFbDosEntriesValence;
3168 const double widthConductionBand = eStepDos * nFbDosEntriesConduction;
3174 int ih = std::min(
int(eh / eStepDos), nFbDosEntriesValence - 1);
3175 while (
RndmUniform() > fbDosValence[ih] / fbDosMaxV) {
3177 ih = std::min(
int(eh / eStepDos), nFbDosEntriesValence - 1);
3181 int ie = std::min(
int(ee / eStepDos), nFbDosEntriesConduction - 1);
3182 while (
RndmUniform() > fbDosConduction[ie] / fbDosMaxC) {
3184 ie = std::min(
int(ee / eStepDos), nFbDosEntriesConduction - 1);
3187 const double ep = e0 - m_bandGap - eh - ee;
3188 if (ep < Small)
continue;
3189 if (ep > 5.)
return;
3191 int ip = std::min(
int(ep / eStepDos), nFbDosEntriesConduction - 1);
3192 if (
RndmUniform() > fbDosConduction[ip] / fbDosMaxC)
continue;
3197void MediumSilicon::InitialiseDensityOfStates() {
3201 const int nFbDosEntriesV = 83;
3202 const double fbDosV[nFbDosEntriesV] = {
3203 0., 1.28083, 2.08928, 2.70763, 3.28095, 3.89162, 4.50547, 5.15043,
3204 5.89314, 6.72667, 7.67768, 8.82725, 10.6468, 12.7003, 13.7457, 14.0263,
3205 14.2731, 14.5527, 14.8808, 15.1487, 15.4486, 15.7675, 16.0519, 16.4259,
3206 16.7538, 17.0589, 17.3639, 17.6664, 18.0376, 18.4174, 18.2334, 16.7552,
3207 15.1757, 14.2853, 13.6516, 13.2525, 12.9036, 12.7203, 12.6104, 12.6881,
3208 13.2862, 14.0222, 14.9366, 13.5084, 9.77808, 6.15266, 3.47839, 2.60183,
3209 2.76747, 3.13985, 3.22524, 3.29119, 3.40868, 3.6118, 3.8464, 4.05776,
3210 4.3046, 4.56219, 4.81553, 5.09909, 5.37616, 5.67297, 6.04611, 6.47252,
3211 6.9256, 7.51254, 8.17923, 8.92351, 10.0309, 11.726, 16.2853, 18.2457,
3212 12.8879, 7.86019, 6.02275, 5.21777, 4.79054, 3.976, 3.11855, 2.46854,
3213 1.65381, 0.830278, 0.217735};
3216 const int nFbDosEntriesC = 101;
3217 const double fbDosC[nFbDosEntriesC] = {
3218 0., 1.5114, 2.71026, 3.67114, 4.40173, 5.05025, 5.6849, 6.28358,
3219 6.84628, 7.43859, 8.00204, 8.80658, 9.84885, 10.9579, 12.0302, 13.2051,
3220 14.6948, 16.9879, 18.4492, 18.1933, 17.6747, 16.8135, 15.736, 14.4965,
3221 13.1193, 12.1817, 12.6109, 15.3148, 19.4936, 23.0093, 24.4106, 22.2834,
3222 19.521, 18.9894, 18.8015, 17.9363, 17.0252, 15.9871, 14.8486, 14.3797,
3223 14.2426, 14.3571, 14.7271, 14.681, 14.3827, 14.2789, 14.144, 14.1684,
3224 14.1418, 13.9237, 13.7558, 13.5691, 13.4567, 13.2693, 12.844, 12.4006,
3225 12.045, 11.7729, 11.3607, 11.14, 11.0586, 10.5475, 9.73786, 9.34423,
3226 9.4694, 9.58071, 9.6967, 9.84854, 10.0204, 9.82705, 9.09102, 8.30665,
3227 7.67306, 7.18925, 6.79675, 6.40713, 6.21687, 6.33267, 6.5223, 6.17877,
3228 5.48659, 4.92208, 4.44239, 4.02941, 3.5692, 3.05953, 2.6428, 2.36979,
3229 2.16273, 2.00627, 1.85206, 1.71265, 1.59497, 1.46681, 1.34913, 1.23951,
3230 1.13439, 1.03789, 0.924155, 0.834962, 0.751017};
3232 nFbDosEntriesValence = nFbDosEntriesV;
3233 nFbDosEntriesConduction = nFbDosEntriesC;
3234 fbDosValence.resize(nFbDosEntriesValence);
3235 fbDosConduction.resize(nFbDosEntriesConduction);
3236 fbDosMaxV = fbDosV[nFbDosEntriesV - 1];
3237 fbDosMaxC = fbDosC[nFbDosEntriesC - 1];
3238 for (
int i = nFbDosEntriesV; i--;) {
3239 fbDosValence[i] = fbDosV[i];
3240 if (fbDosV[i] > fbDosMaxV) fbDosMaxV = fbDosV[i];
3242 for (
int i = nFbDosEntriesC; i--;) {
3243 fbDosConduction[i] = fbDosC[i];
3244 if (fbDosC[i] > fbDosMaxC) fbDosMaxC = fbDosC[i];
DoubleAc cos(const DoubleAc &f)
DoubleAc pow(const DoubleAc &f, double p)
DoubleAc sqrt(const DoubleAc &f)
DoubleAc sin(const DoubleAc &f)
DoubleAc exp(const DoubleAc &f)
bool ElectronVelocity(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
void SetTrappingTime(const double &etau, const double &htau)
bool HoleVelocity(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
void SetLatticeMobilityModelReggiani()
void GetDoping(char &type, double &c) const
void SetHighFieldMobilityModelReggiani()
bool HoleAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
void SetSaturationVelocityModelReggiani()
double GetValenceBandDensityOfStates(const double e, const int band=-1)
void SetDopingMobilityModelMasetti()
double GetElectronNullCollisionRate(const int band)
bool GetDielectricFunction(const double &e, double &eps1, double &eps2, const unsigned int &i=0)
void SetHighFieldMobilityModelMinimos()
void SetSaturationVelocity(const double vsate, const double vsath)
bool ElectronAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
void ComputeSecondaries(const double e0, double &ee, double &eh)
void ResetCollisionCounters()
int GetNumberOfElectronBands()
bool HoleTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
double GetElectronEnergy(const double px, const double py, const double pz, double &vx, double &vy, double &vz, const int band=0)
void SetDoping(const char &type, const double &c)
void SetTrapDensity(const double &n)
double GetConductionBandDensityOfStates(const double e, const int band=0)
bool SetMaxElectronEnergy(const double e)
void SetHighFieldMobilityModelConstant()
bool GetIonisationProduct(const int i, int &type, double &energy)
void SetLatticeMobilityModelSentaurus()
void SetSaturationVelocityModelCanali()
void SetHighFieldMobilityModelCanali()
void SetImpactIonisationModelVanOverstraetenDeMan()
bool GetOpticalDataRange(double &emin, double &emax, const unsigned int &i=0)
void SetTrapCrossSection(const double &ecs, const double &hcs)
void SetSaturationVelocityModelMinimos()
void SetLowFieldMobility(const double mue, const double muh)
double GetElectronCollisionRate(const double e, const int band)
bool ElectronTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
void SetLatticeMobilityModelMinimos()
void GetElectronMomentum(const double e, double &px, double &py, double &pz, int &band)
int GetNumberOfElectronCollisions() const
int GetElectronBandPopulation(const int band)
void SetImpactIonisationModelGrant()
bool GetElectronCollision(const double e, int &type, int &level, double &e1, double &dx, double &dy, double &dz, int &nion, int &ndxc, int &band)
void SetDopingMobilityModelMinimos()
virtual void SetAtomicWeight(const double &a)
virtual void SetMassDensity(const double &rho)
virtual bool HoleTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
bool m_hasElectronTownsend
virtual bool HoleVelocity(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
double GetDielectricConstant() const
virtual void SetAtomicNumber(const double &z)
virtual bool ElectronVelocity(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
virtual void EnableDrift()
void SetTemperature(const double &t)
void SetDielectricConstant(const double &eps)
virtual bool ElectronTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
virtual bool ElectronAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
virtual void EnablePrimaryIonisation()
bool m_hasElectronVelocityE
bool m_hasElectronAttachment
virtual bool HoleAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)