-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathemcNonParabolicAnisotropSingleLayerValley.hpp
174 lines (154 loc) · 7.07 KB
/
emcNonParabolicAnisotropSingleLayerValley.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#ifndef EMC_NONPARABOLIC_ANISOTROP_SINGLELAYER_VALLEY_HPP
#define EMC_NONPARABOLIC_ANISOTROP_SINGLELAYER_VALLEY_HPP
#include <math.h>
#include <ValleyTypes/emcAbstractValley.hpp>
#include <emcConstants.hpp>
#include <emcUtil.hpp>
/*! \brief Non-Parabolic Anisotropical Valley for Single Layer (assumes
* 2D-extension in x and y-direction!)
*
* @param alpha non-parabolicity (in 1 / eV)
* @param degFactor number of subvalleys in that valley
* @param effMassLong longitudinal effective mass
* @param effMassTrans transversal effective mass
* @param effMassCond conductive effective mass
* @param effMassDOS density of states effective mass
* @param vogtFactor factor for herring-vogt transformation, (1,1,0) for isotrop
* 2d valley
* @param bottomEnergy energy of the bottom of the valley (in eV)
* @param rotationAngle angles which describe the orientation of the subvalleys
* w.r.t. the x-axis (and the long. effective mass) in radians between 0 and 2 *
* pi
*/
template <class T>
class emcNonParabolicAnisotropSingleLayerValley : public emcAbstractValley<T> {
private:
T alpha;
SizeType degFactor;
T effMassLong, effMassTrans;
T effMassCond, effMassDOS;
T bottomEnergy;
std::array<T, 3> vogtFactor;
std::vector<T> rotationAngle;
std::vector<T> sinAngle, cosAngle;
public:
emcNonParabolicAnisotropSingleLayerValley() = delete;
/*! \brief Constructor.
*
* @param relEffMassLongitudinal longitudinal rel. effective mass
* @param relEffMassTransversal transversal rel. effective mass
* @param inParticleMass mass of particles
* @param inDegFactor nr of equivalent subvalleys
* @param inAlpha non-parabolicity factor (in 1 / eV)
* @param inBottomEnergy energy of the bottom of the valley (in eV)
*/
emcNonParabolicAnisotropSingleLayerValley(T relEffMassLongitudinal,
T relEffMassTransversal,
T inParticleMass,
SizeType inDegFactor, T inAlpha,
T inBottomEnergy = 0.)
: emcNonParabolicAnisotropSingleLayerValley(
relEffMassLongitudinal, relEffMassTransversal, inParticleMass,
inDegFactor, inAlpha, std::vector<T>(degFactor, 0.),
inBottomEnergy) {}
/*! \brief Constructor.
*
* @param relEffMassLongitudinal longitudinal rel. effective mass
* @param relEffMassTransversal transversal rel. effective mass
* @param inParticleMass mass of particles
* @param inDegFactor nr of equivalent subvalleys
* @param inAlpha non-parabolicity factor (in 1 / eV)
* @param inRotationAngles angles which describe the orientation of each
* subvalley w.r.t. the x-axis (and the long. effective mass) in radians
* between 0 and 2 * pi
* @param inBottomEnergy energy of the bottom of the valley (in eV)
*/
emcNonParabolicAnisotropSingleLayerValley(T relEffMassLongitudinal,
T relEffMassTransversal,
T inParticleMass,
SizeType inDegFactor, T inAlpha,
std::vector<T> inRotationAngles,
T inBottomEnergy = 0.)
: degFactor(inDegFactor),
effMassLong(relEffMassLongitudinal * inParticleMass),
effMassTrans(relEffMassTransversal * inParticleMass),
effMassCond(2. / (1. / effMassLong + 1. / effMassTrans)),
effMassDOS(std::sqrt(effMassLong * effMassTrans)),
vogtFactor({std::sqrt(effMassDOS / effMassLong),
std::sqrt(effMassDOS / effMassTrans), 0}),
alpha(inAlpha), bottomEnergy(inBottomEnergy),
rotationAngle(inRotationAngles), sinAngle(rotationAngle.size(), 0.),
cosAngle(rotationAngle.size(), 0.) {
if (rotationAngle.size() != degFactor) {
emcMessage::getInstance()
.addError("Wrong size of rotationAngle vector!")
.print();
}
for (SizeType idxSubValley = 0; idxSubValley < degFactor; idxSubValley++)
setSubValleyEllipseCoordSystem(idxSubValley, rotationAngle[idxSubValley]);
}
void setSubValleyEllipseCoordSystem(SizeType idxSubValley,
T newRotationAngle) {
if (newRotationAngle < 0 || newRotationAngle > 2 * constants::pi) {
emcMessage::getInstance()
.addError("Rotation angle has to between 0 and 2 * PI.")
.print();
}
rotationAngle[idxSubValley] = newRotationAngle;
sinAngle[idxSubValley] = std::sin(newRotationAngle);
cosAngle[idxSubValley] = std::cos(newRotationAngle);
}
T getBottomEnergy() const { return bottomEnergy; }
T getEffMassDOS(T energy = 0) const {
return effMassDOS * std::pow(1 + 2 * alpha * energy, 3.);
}
T getEffMassCond(T energy = 0) const {
return effMassCond * (1 + 2 * energy * alpha);
}
T getNonParabolicity() const { return alpha; }
SizeType getDegeneracyFactor() const { return degFactor; }
T getNormWaveVec(T energy) const {
return std::sqrt(2 * effMassDOS * constants::q * getGamma(energy)) /
constants::hbar;
}
/// returns energy (in eV): E (1 + alpha E) = (k_x^2 + k_y^2) * h^2 / (2 * m)
T getEnergy(const std::array<T, 3> &k) const {
T gamma = constants::hbar * constants::hbar * (k[0] * k[0] + k[1] * k[1]) /
(effMassDOS * constants::q);
return gamma / (1 + std::sqrt(1 + 2 * alpha * gamma));
}
const std::array<T, 3> &getVogtTransformationFactor() const {
return vogtFactor;
}
std::array<T, 3> getVelocity(const std::array<T, 3> &k, T energy,
SizeType idxSubValley) const {
std::array<T, 3> vel = transformToEllipseCoord(idxSubValley, k);
auto nonParaFactor = std::sqrt(1 + 4 * alpha * getGamma(energy));
std::transform(vel.begin(), vel.end() - 1, vogtFactor.begin(), vel.begin(),
[this, &nonParaFactor](const T &waveVec, const T &vogt) {
return constants::hbar * vogt * waveVec /
(effMassDOS * nonParaFactor);
});
return transformToDeviceCoord(idxSubValley, vel);
}
T getGamma(T energy) const { return energy * (1 + alpha * energy); }
// return rotated coordinate system (use predefined roationAngle)
std::array<T, 3> transformToEllipseCoord(SizeType idxSubValley,
const std::array<T, 3> &vec) const {
auto res = vec;
res[0] = vec[0] * cosAngle[idxSubValley] - vec[1] * sinAngle[idxSubValley];
res[1] = vec[0] * sinAngle[idxSubValley] + vec[1] * cosAngle[idxSubValley];
res[2] = 0;
return res;
}
// rotate coordinate system back (-rotationAngle)
std::array<T, 3> transformToDeviceCoord(SizeType idxSubValley,
const std::array<T, 3> &vec) const {
auto res = vec;
res[0] = vec[0] * cosAngle[idxSubValley] + vec[1] * sinAngle[idxSubValley];
res[1] = -vec[0] * sinAngle[idxSubValley] + vec[1] * cosAngle[idxSubValley];
res[2] = 0;
return res;
}
};
#endif // EMC_NONPARABOLIC_ANISOTROP_SINGLELAYER_VALLEY_HPP