-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathelectronVWD.hpp
93 lines (77 loc) · 3.49 KB
/
electronVWD.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#ifndef ELECTRON_VWD_HPP
#define ELECTRON_VWD_HPP
#include <math.h>
#include <ParticleType/emcParticleType.hpp>
#include <emcConstants.hpp>
#include <emcParticleDrift.hpp>
#include <emcParticleInitialization.hpp>
#include <emcUtil.hpp>
/**
* @brief Electrons that behave as implemented in ViennaWD.
*/
template <class T, class DeviceType>
struct electronVWD : public emcParticleType<T, DeviceType> {
typedef typename DeviceType::ValueVec ValueVec;
typedef typename DeviceType::SizeVec SizeVec;
static const SizeType Dim = DeviceType::Dimension;
std::uniform_real_distribution<T> dist{0, 1};
electronVWD(SizeType inHandlerNrEnergyLevels = 1000,
T inHandlerMaxEnergy = 4.)
: emcParticleType<T, DeviceType>(inHandlerNrEnergyLevels,
inHandlerMaxEnergy){};
std::string getName() const { return "Electrons"; }
T getMass() const { return constants::me; }
T getCharge() const { return -constants::q; }
bool isMoved() const { return true; }
bool isInjected() const { return true; }
//! Diff to emcElectron: nr of initial particles always based on potential.
//! Diff to emcElectron: round number of expected electrons.
T getInitialNrParticles(const SizeVec &coord, const DeviceType &device,
const emcGrid<T, Dim> &potential) {
T eDensity = std::exp(potential[coord]) * device.getMaterial().getNi();
for (SizeType idxDim = 0; idxDim < Dim; idxDim++) {
if (coord[idxDim] == 0 || coord[idxDim] == potential.getSize(idxDim) - 1)
eDensity *= 0.5;
}
return std::round(eDensity * device.getCellVolume());
}
//! Diff to emcElectron: round number of expected electrons.
T getExpectedNrParticlesAtContact(const SizeVec &coord,
const DeviceType &device) {
T doping = device.getDopingProfile().getDoping(coord);
T expectedNrPart = device.getCellVolume() * doping;
const auto &extent = device.getGridExtent();
for (SizeType idxDim = 0; idxDim < Dim; idxDim++) {
if (coord[idxDim] == 0 || coord[idxDim] == extent[idxDim] - 1)
expectedNrPart *= 0.5;
}
return std::round(expectedNrPart);
}
emcParticle<T> generateInitialParticle(const SizeVec &coord,
const DeviceType &device,
emcRNG &rng) {
emcParticle<T> part;
part.region = device.getDopingProfile().getDopingRegionIdx(coord);
part.valley = std::floor(this->getNrValleys() * dist(rng));
auto valley = this->getValley(part.valley);
part.subValley = std::floor(valley->getDegeneracyFactor() * dist(rng));
initParticleKSpaceMaxwellian(part, coord, device, valley, rng);
part.tau = this->getNewTau(part.valley, part.valley, rng);
part.grainTau = this->getNewGrainTau(rng);
return part;
}
emcParticle<T> generateInjectedParticle(const SizeVec &coord,
const DeviceType &device,
emcRNG &rng) {
emcParticle<T> part;
part.region = device.getDopingProfile().getDopingRegionIdx(coord);
part.valley = std::floor(this->getNrValleys() * dist(rng));
auto valley = this->getValley(part.valley);
part.subValley = std::floor(valley->getDegeneracyFactor() * dist(rng));
initParticleKSpaceMaxwellian(part, coord, device, valley, rng);
part.tau = this->getNewTau(part.valley, part.valley, rng);
part.grainTau = this->getNewGrainTau(rng);
return part;
}
};
#endif // ELECTRON_VWD_HPP