-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathemcParticleType.hpp
229 lines (195 loc) · 8.37 KB
/
emcParticleType.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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#ifndef EMC_PARTICLE_TYPE_HPP
#define EMC_PARTICLE_TYPE_HPP
#include <cmath>
#include <memory>
#include <random>
#include <string>
#include <SurfaceScatterMechanisms/emcSurfaceScatterMechanism.hpp>
#include <ValleyTypes/emcAbstractValley.hpp>
#include <emcBoundaryPos.hpp>
#include <emcGrainScatterMechanism.hpp>
#include <emcGrid.hpp>
#include <emcMessage.hpp>
#include <emcParticle.hpp>
#include <emcScatterHandler.hpp>
#include <emcUtil.hpp>
/// abstract class that holds characteristics and behaviour
/// of specific particleType
/// @param valleys vector of valleys that describe the dispersion relation of a
/// particle (only needed if particle is moving)
/// @param scatterHandler vector of scatterHandler ( each handler handles
/// scattering events of one valley) (only needed if particle is moving)
template <class T, class DeviceType> struct emcParticleType {
static const SizeType Dim = DeviceType::Dimension;
typedef typename DeviceType::ValueVec ValueVec;
typedef typename DeviceType::SizeVec SizeVec;
typedef emcAbstractValley<T> AbstractValley;
typedef emcScatterMechanism<T> AbstractScatterMechanism;
typedef emcSurfaceScatterMechanism<T, DeviceType>
AbstractSurfaceScatterMechanism;
std::vector<std::unique_ptr<AbstractValley>> valleys;
emcScatterHandler<T, DeviceType> scatterHandler;
mutable std::uniform_real_distribution<T> uniDistLog{1e-6, 1.};
emcParticleType(SizeType inHandlerNrEnergyLevels = 1000,
T inHandlerMaxEnergy = 4.)
: valleys(), scatterHandler(emcScatterHandler<T, DeviceType>(
inHandlerNrEnergyLevels, inHandlerMaxEnergy)) {}
virtual ~emcParticleType() = default;
/// returns name of particle type, e.g. "electrons"
virtual std::string getName() const = 0;
/// returns mass of particle type
virtual T getMass() const {
addError("getMass", "isMoved");
return 0;
}
/// returns charge of particle type
virtual T getCharge() const = 0;
/// tells if particle is moved during the simulation
virtual bool isMoved() const = 0;
/// tells if particles at contact should be injected during simulation
virtual bool isInjected() const = 0;
/// calculates the initial nr of particles near each coordinate.
virtual T getInitialNrParticles(const SizeVec &coord,
const DeviceType &device,
const emcGrid<T, Dim> &potential) = 0;
/// generates a particle with initial random characteristics.
/// is only called if isMoved() returns true
virtual emcParticle<T> generateInitialParticle(const SizeVec &coord,
const DeviceType &device,
emcRNG &rng) {
addError("generateIntialParticle", "isMoved");
return emcParticle<T>();
}
/// calculates the number of particles that should be near an ohmic contact.
/// is only called if isInjected() returns true
virtual T getExpectedNrParticlesAtContact(const SizeVec &coord,
const DeviceType &device) {
addError("getExpectedNrParticlesAtContact", "isInjected");
return 0;
}
/// generates an injected particle with random characteristics.
/// is only called if isInjected() returns true
virtual emcParticle<T> generateInjectedParticle(const SizeVec &coord,
const DeviceType &device,
emcRNG &rng) {
addError("generateInjectedParticle", "isInjected");
return emcParticle<T>();
}
/// scatters the particle (used during free-flight-scatter-function)
/// is only called if isMoved() returns true
void scatterParticle(emcParticle<T> &particle, emcRNG &rng) const {
scatterHandler.scatterParticle(particle, rng);
}
/// scatters the particle at boundary
/// is only called if isMoved() returns true
void scatterParticleAtBoundary(emcBoundaryPos boundary,
emcParticle<T> &particle,
const DeviceType &device,
std::array<T, Dim> &pos, emcRNG &rng) const {
scatterHandler.scatterParticleAtBoundary(boundary, particle, device, pos,
rng);
}
/// scatters the particle at grain
/// is only called if isMoved() returns true
void scatterParticleAtGrain(emcParticle<T> &particle, emcRNG &rng) const {
scatterHandler.scatterParticleAtGrain(particle, rng);
}
SizeType getNrValleys() const { return valleys.size(); }
auto getValley(SizeType idxValley) const {
checkIdxValley(idxValley);
return valleys[idxValley].get();
}
/// add a valley to particleType
template <class DerivedValley>
typename std::enable_if<
std::is_base_of<AbstractValley, DerivedValley>::value>::type
addValley(std::unique_ptr<DerivedValley> &&newValleyType) {
newValleyType->check();
// TODO check if particle mass is right
valleys.push_back(std::move(newValleyType));
}
void setGrainScatterMechanism(
std::unique_ptr<emcGrainScatterMechanism<T>> &&newMechanism) {
scatterHandler.setGrainScatterMechanism(
std::forward<std::unique_ptr<emcGrainScatterMechanism<T>> &&>(
newMechanism));
}
template <class DerivedScatterMechanism>
typename std::enable_if<std::is_base_of<AbstractScatterMechanism,
DerivedScatterMechanism>::value>::type
addScatterMechanism(const std::vector<int> ®ions,
std::unique_ptr<DerivedScatterMechanism> &&newMechanism) {
auto idxValley = newMechanism->getIdxValley();
checkIdxValley(idxValley);
newMechanism->setPtrValley(valleys);
newMechanism->check();
scatterHandler.addScatterMechanism(
std::forward<std::unique_ptr<DerivedScatterMechanism> &&>(newMechanism),
regions);
}
template <class DerivedSurfaceScatterMechanism>
typename std::enable_if<
std::is_base_of<AbstractSurfaceScatterMechanism,
DerivedSurfaceScatterMechanism>::value>::type
setSurfaceScatterMechanism(
emcBoundaryPos boundaryPosition,
std::unique_ptr<DerivedSurfaceScatterMechanism> &&newMechanism) {
scatterHandler.setSurfaceScatterMechanism(
std::forward<std::unique_ptr<DerivedSurfaceScatterMechanism> &&>(
newMechanism),
boundaryPosition);
}
void initScatterTables() { scatterHandler.initScatterTables(); }
T getGrainTau() const { return scatterHandler.getGrainTau(); }
T getTau(SizeType idxValley, SizeType idxRegion) const {
return scatterHandler.getTau(idxRegion, idxValley);
}
/**
* @brief Helper function that returns new random remaining free-flight time
* (tau) for a given particle
* @param idxValley index of the current valley of the particle
* @param idxRegion index of the current region of the partice
* @param rng random number generator
*/
T getNewTau(SizeType idxValley, SizeType idxRegion, emcRNG &rng) const {
return -std::log(uniDistLog(rng)) * getTau(idxValley, idxRegion);
}
/**
* @brief Helper function that returns new random remaining free-flight time
* (tau) until the next grain scattering event for a given particle
* @param idxValley index of the current valley of the particle
* @param idxRegion index of the current region of the partice
* @param rng random number generator
*/
T getNewGrainTau(emcRNG &rng) const {
return -std::log(uniDistLog(rng)) * getGrainTau();
}
void check() const {
if (isMoved()) {
if (valleys.empty()) {
emcMessage::getInstance()
.addError("Moving Particle Type " + getName() +
" has to at least have one added valley.")
.print();
}
}
}
private:
void checkIdxValley(SizeType idxValley) const {
if (idxValley >= valleys.size()) {
emcMessage::getInstance()
.addError("Used index for Valley for" + getName() + "is invalid.")
.print();
}
}
void addError(std::string nameFunc, std::string dependentFunc) const {
emcMessage::getInstance()
.addError("Function " + nameFunc + "() is not implemented for " +
getName() + ". Either set the return value of " +
dependentFunc +
"() to false or implement required Function for given "
"ParticleType.")
.print();
}
};
#endif // EMC_PARTICLE_TYPE_HPP