31 m_hasUserMobility(false),
32 m_hasUserSaturationVelocity(false),
33 m_hasOpticalData(false),
34 opticalDataFile(
"OpticalData_Si.txt") {
54 std::string& label,
double& f) {
68 std::cerr <<
m_className <<
"::SetTrapCrossSection:\n";
69 std::cerr <<
" Capture cross-section [cm2] must positive.\n";
75 std::cerr <<
m_className <<
"::SetTrapCrossSection:\n";
76 std::cerr <<
" Capture cross-section [cm2] must be positive.n";
89 std::cerr <<
" Trap density [cm-3] must be greater than zero.\n";
102 std::cerr <<
m_className <<
"::SetTrappingTime:\n";
103 std::cerr <<
" Trapping time [ns-1] must be positive.\n";
109 std::cerr <<
m_className <<
"::SetTrappingTime:\n";
110 std::cerr <<
" Trapping time [ns-1] must be positive.\n";
120 const double ez,
const double bx,
121 const double by,
const double bz,
double& vx,
122 double& vy,
double& vz) {
130 double mu = eMobility;
132 const double b =
sqrt(bx * bx + by * by + bz * bz);
139 const double muH = eHallFactor * mu;
140 const double eb = bx * ex + by * ey + bz * ez;
141 const double nom = 1. +
pow(muH * b, 2);
143 vx = mu * (ex + muH * (ey * bz - ez * by) + muH * muH * bx * eb) / nom;
144 vy = mu * (ey + muH * (ez * bx - ex * bz) + muH * muH * by * eb) / nom;
145 vz = mu * (ez + muH * (ex * by - ey * bx) + muH * muH * bz * eb) / nom;
151 const double ez,
const double bx,
152 const double by,
const double bz,
164 const double ez,
const double bx,
165 const double by,
const double bz,
174 switch (trappingModel) {
176 eta = eTrapCs * eTrapDensity;
181 eta = eTrapTime *
sqrt(vx * vx + vy * vy + vz * vz);
182 if (eta > 0.) eta = 1. / eta;
185 std::cerr <<
m_className <<
"::ElectronAttachment:\n";
186 std::cerr <<
" Unknown model activated. Program bug!\n";
195 const double bx,
const double by,
const double bz,
196 double& vx,
double& vy,
double& vz) {
204 double mu = hMobility;
205 const double b =
sqrt(bx * bx + by * by + bz * bz);
212 const double muH = hHallFactor * mu;
213 const double eb = bx * ex + by * ey + bz * ez;
214 const double nom = 1. +
pow(muH * b, 2);
216 vx = mu * (ex + muH * (ey * bz - ez * by) + muH * muH * bx * eb) / nom;
217 vy = mu * (ey + muH * (ez * bx - ex * bz) + muH * muH * by * eb) / nom;
218 vz = mu * (ez + muH * (ex * by - ey * bx) + muH * muH * bz * eb) / nom;
224 const double bx,
const double by,
const double bz,
236 const double ez,
const double bx,
237 const double by,
const double bz,
double& eta) {
244 switch (trappingModel) {
246 eta = hTrapCs * hTrapDensity;
251 eta = hTrapTime *
sqrt(vx * vx + vy * vy + vz * vz);
252 if (eta > 0.) eta = 1. / eta;
256 std::cerr <<
" Unknown model activated. Program bug!\n";
265 if (mue <= 0. || muh <= 0.) {
266 std::cerr <<
m_className <<
"::SetLowFieldMobility:\n";
267 std::cerr <<
" Mobility must be greater than zero.\n";
273 m_hasUserMobility =
true;
279 if (vsate <= 0. || vsath <= 0.) {
280 std::cout <<
m_className <<
"::SetSaturationVelocity:\n";
281 std::cout <<
" Restoring default values.\n";
282 m_hasUserSaturationVelocity =
false;
286 m_hasUserSaturationVelocity =
true;
292 const unsigned int& i) {
295 std::cerr <<
m_className <<
"::GetOpticalDataRange:\n";
296 std::cerr <<
" Medium has only one component.\n";
300 if (!m_hasOpticalData) {
301 if (!LoadOpticalData(opticalDataFile)) {
302 std::cerr <<
m_className <<
"::GetOpticalDataRange:\n";
303 std::cerr <<
" Optical data table could not be loaded.\n";
306 m_hasOpticalData =
true;
309 emin = opticalDataTable[0].energy;
310 emax = opticalDataTable.back().energy;
312 std::cout <<
m_className <<
"::GetOpticalDataRange:\n";
313 std::cout <<
" " << emin <<
" < E [eV] < " << emax <<
"\n";
319 double& eps2,
const unsigned int& i) {
322 std::cerr <<
m_className <<
"::GetDielectricFunction:\n";
323 std::cerr <<
" Medium has only one component.\n";
328 if (!m_hasOpticalData) {
329 if (!LoadOpticalData(opticalDataFile)) {
330 std::cerr <<
m_className <<
"::GetDielectricFunction:\n";
331 std::cerr <<
" Optical data table could not be loaded.\n";
334 m_hasOpticalData =
true;
338 const double emin = opticalDataTable[0].energy;
339 const double emax = opticalDataTable.back().energy;
340 if (e < emin || e > emax) {
341 std::cerr <<
m_className <<
"::GetDielectricFunction:\n";
342 std::cerr <<
" Requested energy (" << e <<
" eV) "
343 <<
" is outside the range of the optical data table.\n";
344 std::cerr <<
" " << emin <<
" < E [eV] < " << emax <<
"\n";
351 int iUp = opticalDataTable.size() - 1;
353 while (iUp - iLow > 1) {
354 iM = (iUp + iLow) >> 1;
355 if (e >= opticalDataTable[iM].energy) {
365 const double logX0 = log(opticalDataTable[iLow].energy);
366 const double logX1 = log(opticalDataTable[iUp].energy);
367 const double logX = log(e);
368 if (opticalDataTable[iLow].eps1 <= 0. || opticalDataTable[iUp].eps1 <= 0.) {
369 eps1 = opticalDataTable[iLow].eps1 +
370 (e - opticalDataTable[iLow].energy) *
371 (opticalDataTable[iUp].eps1 - opticalDataTable[iLow].eps1) /
372 (opticalDataTable[iUp].energy - opticalDataTable[iLow].energy);
374 const double logY0 = log(opticalDataTable[iLow].eps1);
375 const double logY1 = log(opticalDataTable[iUp].eps1);
376 eps1 = logY0 + (logX - logX0) * (logY1 - logY0) / (logX1 - logX0);
382 const double logY0 = log(opticalDataTable[iLow].eps2);
383 const double logY1 = log(opticalDataTable[iUp].eps2);
384 eps2 = logY0 + (log(e) - logX0) * (logY1 - logY0) / (logX1 - logX0);
389bool MediumCdTe::LoadOpticalData(
const std::string filename) {
392 char* pPath = getenv(
"GARFIELD_HOME");
394 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
395 std::cerr <<
" Environment variable GARFIELD_HOME is not set.\n";
398 std::string filepath = pPath;
399 filepath = filepath +
"/Data/" + filename;
402 std::ifstream infile;
403 infile.open(filepath.c_str(), std::ios::in);
406 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
407 std::cerr <<
" Error opening file " << filename <<
".\n";
412 opticalDataTable.clear();
414 double lastEnergy = -1.;
415 double energy, eps1, eps2, loss;
419 std::istringstream dataStream;
421 while (!infile.eof()) {
424 std::getline(infile, line);
426 line.erase(line.begin(),
427 std::find_if(line.begin(), line.end(),
428 not1(std::ptr_fun<int, int>(isspace))));
430 if (line[0] ==
'#' || line[0] ==
'*' || (line[0] ==
'/' && line[1] ==
'/'))
433 dataStream.str(line);
434 dataStream >> energy >> eps1 >> eps2 >> loss;
435 if (dataStream.eof())
break;
438 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
439 std::cerr <<
" Error reading file " << filename <<
" (line " << i
449 if (energy <= lastEnergy) {
450 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
451 std::cerr <<
" Table is not in monotonically "
452 <<
"increasing order (line " << i <<
").\n";
453 std::cerr <<
" " << lastEnergy <<
" " << energy <<
" " << eps1
454 <<
" " << eps2 <<
"\n";
459 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
460 std::cerr <<
" Negative value of the loss function "
461 <<
"(line " << i <<
").\n";
465 if (energy <= 0.)
continue;
467 data.energy = energy;
470 opticalDataTable.push_back(data);
474 const int nEntries = opticalDataTable.size();
476 std::cerr <<
m_className <<
"::LoadOpticalData:\n";
477 std::cerr <<
" Import of data from file " << filepath <<
"failed.\n";
478 std::cerr <<
" No valid data found.\n";
483 std::cout <<
m_className <<
"::LoadOpticalData:\n";
484 std::cout <<
" Read " << nEntries <<
" values from file " << filepath
DoubleAc pow(const DoubleAc &f, double p)
DoubleAc sqrt(const DoubleAc &f)
DoubleAc exp(const DoubleAc &f)
void SetTrapDensity(const double n)
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)
bool GetDielectricFunction(const double &e, double &eps1, double &eps2, const unsigned int &i=0)
bool ElectronAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
void GetComponent(const unsigned int &i, std::string &label, double &f)
bool ElectronTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
void SetSaturationVelocity(const double vsate, const double vsath)
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)
bool GetOpticalDataRange(double &emin, double &emax, const unsigned int &i=0)
void SetTrapCrossSection(const double ecs, const double hcs)
bool HoleTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
bool HoleAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
void SetLowFieldMobility(const double mue, const double muh)
void SetTrappingTime(const double etau, const double htau)
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)
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)