18 m_nElectronEndpoints(0),
22 m_plotExcitations(true),
23 m_plotIonisations(true),
24 m_plotAttachments(true),
25 m_histElectronEnergy(NULL),
26 m_histHoleEnergy(NULL),
27 m_hasElectronEnergyHistogram(false),
28 m_hasHoleEnergyHistogram(false),
30 m_hasDistanceHistogram(false),
31 m_distanceOption(
'r'),
32 m_histSecondary(NULL),
33 m_hasSecondaryHistogram(false),
35 m_useInducedCharge(false),
36 m_useDriftLines(false),
38 m_useBandStructureDefault(true),
39 m_useNullCollisionSteps(false),
58 m_hasTimeWindow(false),
61 m_hasUserHandleStep(false),
62 m_hasUserHandleAttachment(false),
63 m_hasUserHandleInelastic(false),
64 m_hasUserHandleIonisation(false),
66 m_userHandleAttachment(0),
67 m_userHandleInelastic(0),
68 m_userHandleIonisation(0),
71 m_className =
"AvalancheMicroscopic";
73 m_stack.reserve(1000);
74 m_endpointsElectrons.reserve(1000);
75 m_endpointsHoles.reserve(1000);
76 m_photons.reserve(100);
83 std::cerr << m_className <<
"::SetSensor:\n";
84 std::cerr <<
" Sensor pointer is a null pointer.\n";
93 std::cerr << m_className <<
"::EnablePlotting:\n";
94 std::cerr <<
" Viewer pointer is a null pointer.\n";
100 if (!m_useDriftLines) {
101 std::cout << m_className <<
"::EnablePlotting:\n";
102 std::cout <<
" Enabling storage of drift line.\n";
110 m_usePlotting =
false;
116 std::cerr << m_className <<
"::EnableElectronEnergyHistogramming:\n";
117 std::cerr <<
" Histogram pointer is a null pointer.\n";
121 m_histElectronEnergy = histo;
122 m_hasElectronEnergyHistogram =
true;
127 m_hasElectronEnergyHistogram =
false;
133 std::cerr << m_className <<
"::EnableHoleEnergyHistogramming:\n";
134 std::cerr <<
" Histogram pointer is a null pointer.\n";
138 m_histHoleEnergy = histo;
139 m_hasHoleEnergyHistogram =
true;
144 m_hasHoleEnergyHistogram =
false;
150 std::cerr << m_className <<
"::SetDistanceHistogram:\n";
151 std::cerr <<
" Histogram pointer is a null pointer.\n";
155 m_histDistance = histo;
156 m_hasDistanceHistogram =
true;
158 if (opt ==
'x' || opt ==
'y' || opt ==
'z' || opt ==
'r') {
159 m_distanceOption = opt;
161 std::cerr << m_className <<
"::SetDistanceHistogram:";
162 std::cerr <<
" Unknown option " << opt <<
".\n";
163 std::cerr <<
" Valid options are x, y, z, r.\n";
164 std::cerr <<
" Using default value (r).\n";
165 m_distanceOption =
'r';
168 if (m_distanceHistogramType.empty()) {
169 std::cout << m_className <<
"::SetDistanceHistogram:\n";
170 std::cout <<
" Don't forget to call EnableDistanceHistogramming.\n";
178 const unsigned int nDistanceHistogramTypes = m_distanceHistogramType.size();
179 if (nDistanceHistogramTypes > 0) {
180 for (
int i = nDistanceHistogramTypes; i--;) {
181 if (m_distanceHistogramType[i] == type) {
182 std::cout << m_className <<
"::EnableDistanceHistogramming:\n";
183 std::cout <<
" Collision type " << type
184 <<
" is already histogrammed.\n";
190 m_distanceHistogramType.push_back(type);
191 std::cout << m_className <<
"::EnableDistanceHistogramming:\n";
192 std::cout <<
" Histogramming of collision type " << type <<
" enabled.\n";
193 if (!m_hasDistanceHistogram) {
194 std::cout <<
" Don't forget to set the histogram.\n";
200 if (m_distanceHistogramType.empty()) {
201 std::cerr << m_className <<
"::DisableDistanceHistogramming:\n";
202 std::cerr <<
" Collision type " << type <<
" is not histogrammed.\n";
205 const unsigned int nDistanceHistogramTypes = m_distanceHistogramType.size();
206 for (
int i = nDistanceHistogramTypes; i--;) {
207 if (m_distanceHistogramType[i] == type) {
208 m_distanceHistogramType.erase(m_distanceHistogramType.begin() + i);
209 std::cout <<
" Histogramming of collision type " << type
215 std::cerr << m_className <<
"::DisableDistanceHistogramming:\n";
216 std::cerr <<
" Collision type " << type <<
" is not histogrammed.\n";
221 m_hasDistanceHistogram =
false;
222 m_distanceHistogramType.clear();
228 std::cerr << m_className <<
"::EnableSecondaryEnergyHistogramming:\n";
229 std::cerr <<
" Histogram pointer is a null pointer.\n";
233 m_histSecondary = histo;
234 m_hasSecondaryHistogram =
true;
239 m_hasSecondaryHistogram =
false;
245 std::cerr << m_className <<
"::SetCollisionSteps:\n";
246 std::cerr <<
" Number of collisions to be skipped set to"
247 <<
" default value (100).\n";
257 if (
fabs(t1 - t0) < Small) {
258 std::cerr << m_className <<
"::SetTimeWindow:\n";
259 std::cerr <<
" Time interval must be greater than zero.\n";
263 m_tMin = std::min(t0, t1);
264 m_tMax = std::max(t0, t1);
265 m_hasTimeWindow =
true;
271 double& y0,
double& z0,
272 double& t0,
double& e0,
273 double& x1,
double& y1,
274 double& z1,
double& t1,
275 double& e1,
int& status)
const {
277 if (i >= m_nElectronEndpoints) {
278 std::cerr << m_className <<
"::GetElectronEndpoint:\n";
279 std::cerr <<
" Endpoint index " << i <<
" out of range.\n";
280 x0 = y0 = z0 = t0 = e0 = 0.;
281 x1 = y1 = z1 = t1 = e1 = 0.;
286 x0 = m_endpointsElectrons[i].x0;
287 y0 = m_endpointsElectrons[i].y0;
288 z0 = m_endpointsElectrons[i].z0;
289 t0 = m_endpointsElectrons[i].t0;
290 e0 = m_endpointsElectrons[i].e0;
291 x1 = m_endpointsElectrons[i].x;
292 y1 = m_endpointsElectrons[i].y;
293 z1 = m_endpointsElectrons[i].z;
294 t1 = m_endpointsElectrons[i].t;
295 e1 = m_endpointsElectrons[i].energy;
296 status = m_endpointsElectrons[i].status;
300 const unsigned int i,
double& x0,
double& y0,
double& z0,
double& t0,
double& e0,
301 double& x1,
double& y1,
double& z1,
double& t1,
double& e1,
double& dx1,
302 double& dy1,
double& dz1,
int& status)
const {
304 if (i >= m_nElectronEndpoints) {
305 std::cerr << m_className <<
"::GetElectronEndpoint:\n";
306 std::cerr <<
" Endpoint index " << i <<
" out of range.\n";
307 x0 = y0 = z0 = t0 = e0 = 0.;
308 x1 = y1 = z1 = t1 = e1 = 0.;
309 dx1 = dy1 = dz1 = 0.;
314 x0 = m_endpointsElectrons[i].x0;
315 y0 = m_endpointsElectrons[i].y0;
316 z0 = m_endpointsElectrons[i].z0;
317 t0 = m_endpointsElectrons[i].t0;
318 e0 = m_endpointsElectrons[i].e0;
319 x1 = m_endpointsElectrons[i].x;
320 y1 = m_endpointsElectrons[i].y;
321 z1 = m_endpointsElectrons[i].z;
322 t1 = m_endpointsElectrons[i].t;
323 e1 = m_endpointsElectrons[i].energy;
324 dx1 = m_endpointsElectrons[i].kx;
325 dy1 = m_endpointsElectrons[i].ky;
326 dz1 = m_endpointsElectrons[i].kz;
327 status = m_endpointsElectrons[i].status;
331 double& z0,
double& t0,
double& e0,
332 double& x1,
double& y1,
double& z1,
333 double& t1,
double& e1,
336 if (i >= m_nHoleEndpoints) {
337 std::cerr << m_className <<
"::GetHoleEndpoint:\n";
338 std::cerr <<
" Endpoint index " << i <<
" out of range.\n";
339 x0 = y0 = z0 = t0 = e0 = 0.;
340 x1 = y1 = z1 = t1 = e1 = 0.;
345 x0 = m_endpointsHoles[i].x0;
346 y0 = m_endpointsHoles[i].y0;
347 z0 = m_endpointsHoles[i].z0;
348 t0 = m_endpointsHoles[i].t0;
349 e0 = m_endpointsHoles[i].e0;
350 x1 = m_endpointsHoles[i].x;
351 y1 = m_endpointsHoles[i].y;
352 z1 = m_endpointsHoles[i].z;
353 t1 = m_endpointsHoles[i].t;
354 e1 = m_endpointsHoles[i].energy;
355 status = m_endpointsHoles[i].status;
361 if (i >= m_nElectronEndpoints) {
362 std::cerr << m_className <<
"::GetNumberOfElectronDriftLinePoints:\n";
363 std::cerr <<
" Endpoint index (" << i <<
") out of range.\n";
367 if (!m_useDriftLines)
return 2;
369 return m_endpointsElectrons[i].driftLine.size() + 2;
374 if (i >= m_nHoleEndpoints) {
375 std::cerr << m_className <<
"::GetNumberOfHoleDriftLinePoints:\n";
376 std::cerr <<
" Endpoint index (" << i <<
") out of range.\n";
380 if (!m_useDriftLines)
return 2;
382 return m_endpointsHoles[i].driftLine.size() + 2;
386 double& z,
double& t,
388 const unsigned int iel)
const {
390 if (iel >= m_nElectronEndpoints) {
391 std::cerr << m_className <<
"::GetElectronDriftLinePoint:\n";
392 std::cerr <<
" Endpoint index (" << iel <<
") out of range.\n";
397 x = m_endpointsElectrons[iel].x0;
398 y = m_endpointsElectrons[iel].y0;
399 z = m_endpointsElectrons[iel].z0;
400 t = m_endpointsElectrons[iel].t0;
404 const int np = m_endpointsElectrons[iel].driftLine.size();
406 x = m_endpointsElectrons[iel].x;
407 y = m_endpointsElectrons[iel].y;
408 z = m_endpointsElectrons[iel].z;
409 t = m_endpointsElectrons[iel].t;
413 x = m_endpointsElectrons[iel].driftLine[ip - 1].x;
414 y = m_endpointsElectrons[iel].driftLine[ip - 1].y;
415 z = m_endpointsElectrons[iel].driftLine[ip - 1].z;
416 t = m_endpointsElectrons[iel].driftLine[ip - 1].t;
420 double& z,
double& t,
422 const unsigned int ih)
const {
424 if (ih >= m_nHoleEndpoints) {
425 std::cerr << m_className <<
"::GetHoleDriftLinePoint:\n";
426 std::cerr <<
" Endpoint index (" << ih <<
") out of range.\n";
431 x = m_endpointsHoles[ih].x0;
432 y = m_endpointsHoles[ih].y0;
433 z = m_endpointsHoles[ih].z0;
434 t = m_endpointsHoles[ih].t0;
438 const int np = m_endpointsHoles[ih].driftLine.size();
440 x = m_endpointsHoles[ih].x;
441 y = m_endpointsHoles[ih].y;
442 z = m_endpointsHoles[ih].z;
443 t = m_endpointsHoles[ih].t;
447 x = m_endpointsHoles[ih].driftLine[ip - 1].x;
448 y = m_endpointsHoles[ih].driftLine[ip - 1].y;
449 z = m_endpointsHoles[ih].driftLine[ip - 1].z;
450 t = m_endpointsHoles[ih].driftLine[ip - 1].t;
454 double& y0,
double& z0,
double& t0,
455 double& x1,
double& y1,
double& z1,
456 double& t1,
int& status)
const {
458 if (i >= m_nPhotons) {
459 std::cerr << m_className <<
"::GetPhoton:\n";
460 std::cerr <<
" Photon " << i <<
" does not exist.\n";
464 x0 = m_photons[i].x0;
465 x1 = m_photons[i].x1;
466 y0 = m_photons[i].y0;
467 y1 = m_photons[i].y1;
468 z0 = m_photons[i].z0;
469 z1 = m_photons[i].z1;
470 t0 = m_photons[i].t0;
471 t1 = m_photons[i].t1;
472 status = m_photons[i].status;
473 e = m_photons[i].energy;
477 void (*f)(
double x,
double y,
double z,
double t,
double e,
double dx,
478 double dy,
double dz,
bool hole)) {
481 std::cerr << m_className <<
"::SetUserHandleStep:\n";
482 std::cerr <<
" Function pointer is a null pointer.\n";
485 m_userHandleStep = f;
486 m_hasUserHandleStep =
true;
491 m_userHandleStep = 0;
492 m_hasUserHandleStep =
false;
496 double x,
double y,
double z,
double t,
int type,
int level,
Medium* m)) {
498 m_userHandleAttachment = f;
499 m_hasUserHandleAttachment =
true;
504 m_userHandleAttachment = 0;
505 m_hasUserHandleAttachment =
false;
509 double x,
double y,
double z,
double t,
int type,
int level,
Medium* m)) {
511 m_userHandleInelastic = f;
512 m_hasUserHandleInelastic =
true;
517 m_userHandleInelastic = 0;
518 m_hasUserHandleInelastic =
false;
522 double x,
double y,
double z,
double t,
int type,
int level,
Medium* m)) {
524 m_userHandleIonisation = f;
525 m_hasUserHandleIonisation =
true;
530 m_userHandleIonisation = 0;
531 m_hasUserHandleIonisation =
false;
535 const double z0,
const double t0,
536 const double e0,
const double dx0,
537 const double dy0,
const double dz0) {
540 m_endpointsElectrons.clear();
541 m_endpointsHoles.clear();
545 m_nPhotons = m_nElectrons = m_nHoles = m_nIons = 0;
546 m_nElectronEndpoints = m_nHoleEndpoints = 0;
548 return TransportElectron(x0, y0, z0, t0, e0, dx0, dy0, dz0,
false,
false);
552 const double z0,
const double t0,
553 const double e0,
const double dx0,
558 m_endpointsElectrons.clear();
559 m_endpointsHoles.clear();
563 m_nPhotons = m_nElectrons = m_nHoles = m_nIons = 0;
564 m_nElectronEndpoints = m_nHoleEndpoints = 0;
566 return TransportElectron(x0, y0, z0, t0, e0, dx0, dy0, dz0,
true,
false);
569bool AvalancheMicroscopic::TransportElectron(
const double x0,
const double y0,
570 const double z0,
const double t0,
571 const double e0,
const double dx0,
572 const double dy0,
const double dz0,
573 const bool aval,
bool hole) {
577 std::cerr << m_className <<
"::TransportElectron:\n";
578 std::cerr <<
" Sensor is not defined.\n";
583 Medium* medium = NULL;
584 if (!m_sensor->
GetMedium(x0, y0, z0, medium)) {
585 std::cerr << m_className <<
"::TransportElectron:\n";
586 std::cerr <<
" No medium at initial position.\n";
590 std::cerr << m_className <<
"::TransportElectron:\n";
591 std::cerr <<
" No medium at initial position.\n";
597 std::cerr << m_className <<
"::TransportElectron:\n";
598 std::cerr <<
" Medium at initial position does not provide "
599 <<
" microscopic tracking data.\n";
604 bool m_useBandStructure = m_useBandStructureDefault;
606 m_useBandStructure =
true;
608 m_useBandStructure =
false;
611 std::cout << m_className <<
"::TransportElectron:\n";
612 std::cout <<
" Starting to drift in medium " <<
medium->
GetName()
620 const double c1 = SpeedOfLight *
sqrt(2. / ElectronMass);
621 const double c2 = c1 * c1 / 4.;
624 std::vector<double> stackPhotonsTime;
625 std::vector<double> stackPhotonsEnergy;
628 double ex = 0., ey = 0., ez = 0., emag = 0.;
629 double bx = 0., by = 0., bz = 0.,
bmag = 0.;
632 double cwt = 1., swt = 0.;
638 double x = x0, y = y0, z = z0, t = t0;
639 double kx = dx0, ky = dy0, kz = dz0;
640 double vx = dx0, vy = dy0, vz = dz0;
648 double newKx = 0., newKy = 0., newKz = 0.;
649 double newVx = 0., newVy = 0., newVz = 0.;
650 double newEnergy = 0.;
657 int nion = 0, ndxc = 0;
662 double a1 = 0., a2 = 0., a3 = 0., a4 = 0.;
667 electron newElectron;
668 newElectron.status = 0;
670 newElectron.hole =
true;
672 newElectron.hole =
false;
682 newElectron.kx = dx0;
683 newElectron.ky = dy0;
684 newElectron.kz = dz0;
685 newElectron.e0 = std::max(e0, Small);
686 newElectron.energy = newElectron.e0;
687 newElectron.band = band;
689 newElectron.xLast = x0;
690 newElectron.yLast = y0;
691 newElectron.zLast = z0;
692 newElectron.driftLine.clear();
693 m_stack.push_back(newElectron);
700 if (m_useBandStructure) {
707 m_stack[0].band = band;
712 const double k =
sqrt(dx0 * dx0 + dy0 * dy0 + dz0 * dz0);
713 if (
fabs(k) < Small) {
717 const double stheta =
sqrt(1. - ctheta * ctheta);
718 m_stack[0].kx =
cos(phi) * stheta;
719 m_stack[0].ky =
sin(phi) * stheta;
720 m_stack[0].kz = ctheta;
732 std::cerr << m_className <<
"::TransportElectron:\n";
733 std::cerr <<
" Got null-collision rate <= 0.\n";
741 const int nSize = m_stack.size();
742 if (nSize <= 0)
break;
744 for (
int iE = nSize; iE--;) {
750 energy = m_stack[iE].energy;
751 band = m_stack[iE].band;
755 hole = m_stack[iE].hole;
763 m_sensor->
ElectricField(x, y, z, ex, ey, ez, medium, status);
772 std::cout << m_className <<
"::TransportElectron:\n";
774 std::cout <<
" Drifting hole " << iE <<
".\n";
776 std::cout <<
" Drifting electron " << iE <<
".\n";
778 std::cout <<
" Field [V/cm] at (" << x <<
", " << y <<
", " << z
779 <<
"): " << ex <<
", " << ey <<
", " << ez <<
"\n";
780 std::cout <<
" Status: " << status <<
"\n";
790 m_stack[iE].energy = energy;
791 m_stack[iE].band = band;
795 m_stack[iE].status = StatusLeftDriftMedium;
797 m_endpointsHoles.push_back(m_stack[iE]);
799 m_endpointsElectrons.push_back(m_stack[iE]);
801 m_stack.erase(m_stack.begin() + iE);
803 std::cout << m_className <<
"::TransportElectron:\n";
805 std::cout <<
" Hole left the drift medium.\n";
807 std::cout <<
" Electron left the drift medium.\n";
809 std::cout <<
" At " << x <<
", " << y <<
"," << z <<
"\n";
818 bx *= Tesla2Internal;
819 by *= Tesla2Internal;
820 bz *= Tesla2Internal;
822 bx *= -Tesla2Internal;
823 by *= -Tesla2Internal;
824 bz *= -Tesla2Internal;
827 bmag =
sqrt(bx * bx + by * by + bz * bz);
828 emag =
sqrt(ex * ex + ey * ey + ez * ez);
829 if (bmag > Small && emag > Small)
838 bool isNullCollision =
false;
841 if (energy < m_deltaCut) {
846 m_stack[iE].energy = energy;
847 m_stack[iE].band = band;
851 m_stack[iE].status = StatusBelowTransportCut;
853 m_endpointsHoles.push_back(m_stack[iE]);
855 m_endpointsElectrons.push_back(m_stack[iE]);
857 m_stack.erase(m_stack.begin() + iE);
859 std::cout << m_className <<
"::TransportElectron:\n";
860 std::cout <<
" Kinetic energy (" << energy <<
")"
861 <<
" below transport cut.\n";
868 if (hole && m_hasHoleEnergyHistogram) {
869 m_histHoleEnergy->Fill(energy);
870 }
else if (!hole && m_hasElectronEnergyHistogram) {
871 m_histElectronEnergy->Fill(energy);
875 if (m_hasTimeWindow && (t < m_tMin || t > m_tMax)) {
880 m_stack[iE].energy = energy;
881 m_stack[iE].band = band;
885 m_stack[iE].status = StatusOutsideTimeWindow;
887 m_endpointsHoles.push_back(m_stack[iE]);
889 m_endpointsElectrons.push_back(m_stack[iE]);
891 m_stack.erase(m_stack.begin() + iE);
893 std::cout << m_className <<
"::TransportElectron:\n";
895 std::cout <<
" Hole left the time window.\n";
897 std::cout <<
" Electron left the time window.\n";
899 std::cout <<
" Time: " << t <<
"\n";
913 m_stack[iE].energy = energy;
914 m_stack[iE].band = band;
918 m_stack[iE].status = StatusLeftDriftMedium;
920 m_endpointsHoles.push_back(m_stack[iE]);
922 m_endpointsElectrons.push_back(m_stack[iE]);
924 m_stack.erase(m_stack.begin() + iE);
927 std::cout << m_className <<
"::TransportElectron:\n";
928 std::cout <<
" Medium at " << x <<
", " << y <<
", " << z
929 <<
" does not have microscopic data.\n";
935 m_useBandStructure =
true;
937 m_useBandStructure =
false;
942 std::cerr << m_className <<
"::TransportElectron:\n";
943 std::cerr <<
" Got null-collision rate <= 0.\n";
948 if (m_useBfield && bOk) {
950 wb = OmegaCyclotronOverB *
bmag;
952 ComputeRotationMatrix(bx, by, bz, bmag, ex, ey, ez);
953 RotateGlobal2Local(kx, ky, kz);
955 RotateGlobal2Local(ex, ey, ez);
957 const double v = c1 *
sqrt(energy);
965 }
else if (m_useBandStructure) {
970 const double v = c1 *
sqrt(energy);
975 a1 = vx * ex + vy * ey + vz * ez;
976 a2 = c2 * (ex * ex + ey * ey + ez * ez);
979 if (m_hasUserHandleStep) {
980 m_userHandleStep(x, y, z, t, energy, kx, ky, kz, hole);
988 dt += -log(r) / fLim;
990 if (m_useBfield && bOk) {
993 newEnergy = std::max(energy + (a1 + a2 * dt) * dt +
994 a4 * (a3 * (1. - cwt) + vz * swt),
996 }
else if (m_useBandStructure) {
997 newEnergy = std::max(
999 kx + ex * dt * SpeedOfLight, ky + ey * dt * SpeedOfLight,
1000 kz + ez * dt * SpeedOfLight, newVx, newVy, newVz, band),
1003 newEnergy = std::max(energy + (a1 + a2 * dt) * dt, Small);
1008 std::cerr << m_className <<
"::TransportElectron:\n";
1009 std::cerr <<
" Got collision rate <= 0.\n";
1010 std::cerr <<
" At " << newEnergy <<
" eV (band " << band
1016 dt += log(r) / fLim;
1018 std::cerr << m_className <<
"::TransportElectron:\n";
1019 std::cerr <<
" Increasing null-collision rate by 5%.\n";
1020 if (m_useBandStructure) std::cerr <<
" Band " << band <<
"\n";
1026 if (m_useNullCollisionSteps) {
1027 isNullCollision =
true;
1038 if (m_useBfield && bOk) {
1040 newVx = vx + 2. * c2 * ex * dt;
1041 newVy = vz * swt - a3 * cwt + ez /
bmag;
1042 newVz = vz * cwt + a3 * swt;
1044 const double v =
sqrt(newVx * newVx + newVy * newVy + newVz * newVz);
1048 RotateLocal2Global(newKx, newKy, newKz);
1051 ky = (vz * (1. - cwt) - a3 * swt) / (
wb * dt) + ez / bmag;
1052 kz = (vz * swt + a3 * (1. - cwt)) / (
wb * dt);
1056 RotateLocal2Global(vx, vy, vz);
1057 }
else if (m_useBandStructure) {
1059 newKx = kx + ex * dt * SpeedOfLight;
1060 newKy = ky + ey * dt * SpeedOfLight;
1061 newKz = kz + ez * dt * SpeedOfLight;
1063 vx = 0.5 * (vx + newVx);
1064 vy = 0.5 * (vy + newVy);
1065 vz = 0.5 * (vz + newVz);
1068 a1 =
sqrt(energy / newEnergy);
1069 a2 = 0.5 * c1 * dt /
sqrt(newEnergy);
1070 newKx = kx * a1 + ex * a2;
1071 newKy = ky * a1 + ey * a2;
1072 newKz = kz * a1 + ez * a2;
1075 a1 = c1 *
sqrt(energy);
1077 vx = kx * a1 + ex * a2;
1078 vy = ky * a1 + ey * a2;
1079 vz = kz * a1 + ez * a2;
1083 m_sensor->
ElectricField(x + vx * dt, y + vy * dt, z + vz * dt, ex, ey, ez,
1099 m_stack[iE].energy = energy;
1100 double dx = vx * dt, dy = vy * dt, dz = vz * dt;
1101 double d =
sqrt(dx * dx + dy * dy + dz * dz);
1108 double xM = x, yM = y, zM = z;
1109 while (d > BoundaryDistance) {
1116 m_sensor->
ElectricField(xM, yM, zM, ex, ey, ez, medium, status);
1131 +1, m_stack[iE].t, t - m_stack[iE].t, 0.5 * (x + m_stack[iE].x),
1132 0.5 * (y + m_stack[iE].y), 0.5 * (z + m_stack[iE].z), vx, vy, vz);
1135 -1, m_stack[iE].t, t - m_stack[iE].t, 0.5 * (x + m_stack[iE].x),
1136 0.5 * (y + m_stack[iE].y), 0.5 * (z + m_stack[iE].z), vx, vy, vz);
1143 m_stack[iE].kx = newKx;
1144 m_stack[iE].ky = newKy;
1145 m_stack[iE].kz = newKz;
1146 m_stack[iE].status = StatusLeftDriftMedium;
1148 m_endpointsHoles.push_back(m_stack[iE]);
1150 m_endpointsElectrons.push_back(m_stack[iE]);
1152 m_stack.erase(m_stack.begin() + iE);
1155 std::cout << m_className <<
"::TransportElectron:\n";
1157 std::cout <<
" Hole left the drift medium.\n";
1159 std::cout <<
" Electron left the drift medium.\n";
1161 std::cout <<
" At " << x <<
", " << y <<
"," << z <<
"\n";
1167 if (!m_sensor->
IsInArea(x + vx * dt, y + vy * dt, z + vz * dt)) {
1174 m_stack[iE].energy = energy;
1175 double dx = vx * dt, dy = vy * dt, dz = vz * dt;
1176 double d =
sqrt(dx * dx + dy * dy + dz * dz);
1183 double xM = x, yM = y, zM = z;
1184 while (d > BoundaryDistance) {
1191 if (m_sensor->
IsInArea(xM, yM, zM)) {
1207 +1, m_stack[iE].t, t - m_stack[iE].t, 0.5 * (x + m_stack[iE].x),
1208 0.5 * (y + m_stack[iE].y), 0.5 * (z + m_stack[iE].z), vx, vy, vz);
1211 -1, m_stack[iE].t, t - m_stack[iE].t, 0.5 * (x + m_stack[iE].x),
1212 0.5 * (y + m_stack[iE].y), 0.5 * (z + m_stack[iE].z), vx, vy, vz);
1219 m_stack[iE].kx = newKx;
1220 m_stack[iE].ky = newKy;
1221 m_stack[iE].kz = newKz;
1222 m_stack[iE].status = StatusLeftDriftArea;
1224 m_endpointsHoles.push_back(m_stack[iE]);
1226 m_endpointsElectrons.push_back(m_stack[iE]);
1228 m_stack.erase(m_stack.begin() + iE);
1231 std::cout << m_className <<
"::TransportElectron:\n";
1233 std::cout <<
" Hole left the drift area.\n";
1235 std::cout <<
" Electron left the drift area.\n";
1237 std::cout <<
" At " << x <<
", " << y <<
", " << z <<
"\n";
1243 double xCross = x, yCross = y, zCross = z;
1244 if (m_sensor->
IsWireCrossed(x, y, z, x + vx * dt, y + vy * dt,
1245 z + vz * dt, xCross, yCross, zCross)) {
1248 dt =
sqrt(
pow(xCross - x, 2) +
pow(yCross - y, 2) +
1249 pow(zCross - z, 2)) /
1250 sqrt(vx * vx + vy * vy + vz * vz);
1252 m_sensor->
AddSignal(+1, t, dt, 0.5 * (x + xCross),
1253 0.5 * (y + yCross), 0.5 * (z + zCross), vx, vy,
1256 m_sensor->
AddSignal(-1, t, dt, 0.5 * (x + xCross),
1257 0.5 * (y + yCross), 0.5 * (z + zCross), vx, vy,
1261 m_stack[iE].x = xCross;
1262 m_stack[iE].y = yCross;
1263 m_stack[iE].z = zCross;
1264 m_stack[iE].t = t + dt;
1265 m_stack[iE].kx = newKx;
1266 m_stack[iE].ky = newKy;
1267 m_stack[iE].kz = newKz;
1268 m_stack[iE].status = StatusLeftDriftMedium;
1270 m_endpointsHoles.push_back(m_stack[iE]);
1272 m_endpointsElectrons.push_back(m_stack[iE]);
1274 m_stack.erase(m_stack.begin() + iE);
1277 std::cout << m_className <<
"::TransportElectron:\n";
1278 std::cout <<
" Electron/hole hit a wire.\n";
1279 std::cout <<
" At " << x <<
", " << y <<
"," << z <<
"\n";
1287 m_sensor->
AddSignal(+1, t, dt, x + 0.5 * vx * dt, y + 0.5 * vy * dt,
1288 z + 0.5 * vz * dt, vx, vy, vz);
1290 m_sensor->
AddSignal(-1, t, dt, x + 0.5 * vx * dt, y + 0.5 * vy * dt,
1291 z + 0.5 * vy * dt, vx, vy, vz);
1305 bx *= Tesla2Internal;
1306 by *= Tesla2Internal;
1307 bz *= Tesla2Internal;
1309 bx *= -Tesla2Internal;
1310 by *= -Tesla2Internal;
1311 bz *= -Tesla2Internal;
1314 bmag =
sqrt(bx * bx + by * by + bz * bz);
1315 emag =
sqrt(ex * ex + ey * ey + ez * ez);
1316 if (bmag > Small && emag > Small)
1322 if (isNullCollision) {
1332 newKy, newKz, nion, ndxc, band);
1336 if (m_hasDistanceHistogram && m_histDistance &&
1337 !m_distanceHistogramType.empty()) {
1338 const int nDistanceHistogramTypes = m_distanceHistogramType.size();
1339 for (
int iType = nDistanceHistogramTypes; iType--;) {
1340 if (m_distanceHistogramType[iType] != cstype)
continue;
1342 std::cout << m_className <<
"::TransportElectron:\n";
1343 std::cout <<
" Collision type: " << cstype <<
"\n";
1344 std::cout <<
" Fill distance histogram.\n";
1347 switch (m_distanceOption) {
1349 m_histDistance->Fill(m_stack[iE].xLast - x);
1352 m_histDistance->Fill(m_stack[iE].yLast - y);
1355 m_histDistance->Fill(m_stack[iE].zLast - z);
1358 const double r2 =
pow(m_stack[iE].xLast - x, 2) +
1359 pow(m_stack[iE].yLast - y, 2) +
1360 pow(m_stack[iE].zLast - z, 2);
1361 m_histDistance->Fill(
sqrt(r2));
1364 m_stack[iE].xLast = x;
1365 m_stack[iE].yLast = y;
1366 m_stack[iE].zLast = z;
1373 case ElectronCollisionTypeElastic:
1376 case ElectronCollisionTypeIonisation:
1377 if (m_usePlotting && m_plotIonisations) {
1380 if (m_hasUserHandleIonisation) {
1381 m_userHandleIonisation(x, y, z, t, cstype, level, medium);
1383 for (
int j = nion; j--;) {
1387 if (itype == IonProdTypeElectron) {
1388 esec = std::max(esec, Small);
1389 if (m_hasSecondaryHistogram) m_histSecondary->Fill(esec);
1391 newElectron = m_stack[iE];
1392 newElectron.hole =
false;
1401 newElectron.energy = esec;
1402 newElectron.e0 = newElectron.energy;
1403 if (m_useBandStructure) {
1404 newElectron.band = -1;
1406 newElectron.ky, newElectron.kz,
1412 const double stheta =
sqrt(1. - ctheta * ctheta);
1413 newElectron.kx =
cos(phi) * stheta;
1414 newElectron.ky =
sin(phi) * stheta;
1415 newElectron.kz = ctheta;
1417 newElectron.status = 0;
1418 newElectron.driftLine.clear();
1419 if (aval && (m_sizeCut <= 0 || (
int)m_stack.size() < m_sizeCut)) {
1420 m_stack.push_back(newElectron);
1424 }
else if (itype == IonProdTypeHole) {
1425 esec = std::max(esec, Small);
1427 newElectron = m_stack[iE];
1428 newElectron.hole =
true;
1437 newElectron.energy = esec;
1438 newElectron.e0 = newElectron.energy;
1439 if (m_useBandStructure) {
1440 newElectron.band = -1;
1442 newElectron.ky, newElectron.kz,
1448 const double stheta =
sqrt(1. - ctheta * ctheta);
1449 newElectron.kx =
cos(phi) * stheta;
1450 newElectron.ky =
sin(phi) * stheta;
1451 newElectron.kz = ctheta;
1453 newElectron.status = 0;
1454 newElectron.driftLine.clear();
1455 if (aval && (m_sizeCut <= 0 || (
int)m_stack.size() < m_sizeCut)) {
1456 m_stack.push_back(newElectron);
1460 }
else if (itype == IonProdTypeIon) {
1465 std::cout << m_className <<
"::TransportElectron:\n";
1466 std::cout <<
" Ionisation.\n";
1467 std::cout <<
" At " << x <<
"," << y <<
"," << z <<
"\n";
1471 case ElectronCollisionTypeAttachment:
1472 if (m_usePlotting && m_plotAttachments) {
1475 if (m_hasUserHandleAttachment) {
1476 m_userHandleAttachment(x, y, z, t, cstype, level, medium);
1482 m_stack[iE].energy = energy;
1483 m_stack[iE].status = StatusAttached;
1485 m_endpointsHoles.push_back(m_stack[iE]);
1488 m_endpointsElectrons.push_back(m_stack[iE]);
1491 m_stack.erase(m_stack.begin() + iE);
1495 case ElectronCollisionTypeInelastic:
1496 if (m_hasUserHandleInelastic) {
1497 m_userHandleInelastic(x, y, z, t, cstype, level, medium);
1501 case ElectronCollisionTypeExcitation:
1502 if (m_usePlotting && m_plotExcitations) {
1505 if (m_hasUserHandleInelastic) {
1506 m_userHandleInelastic(x, y, z, t, cstype, level, medium);
1511 double tDxc = 0., sDxc = 0., eDxc = 0.;
1513 stackPhotonsTime.clear();
1514 stackPhotonsEnergy.clear();
1515 for (
int j = ndxc; j--;) {
1518 std::cerr << m_className <<
"::TransportElectron:\n";
1519 std::cerr <<
" Cannot retrieve deexcitation product " << j
1520 <<
"/" << ndxc <<
".\n";
1524 if (typeDxc == DxcProdTypeElectron) {
1525 if (!aval || (m_sizeCut > 0 && (
int)m_stack.size() >= m_sizeCut))
1528 newElectron = m_stack[iE];
1529 double xDxc = x, yDxc = y, zDxc = z;
1534 double sthetaDxc =
sqrt(1. - cthetaDxc * cthetaDxc);
1535 xDxc += sDxc *
cos(phiDxc) * sthetaDxc;
1536 yDxc += sDxc *
sin(phiDxc) * sthetaDxc;
1537 zDxc += sDxc * cthetaDxc;
1540 Medium* dxcMedium = 0;
1541 double fx = 0., fy = 0., fz = 0.;
1542 m_sensor->
ElectricField(xDxc, yDxc, zDxc, fx, fy, fz, dxcMedium,
1545 if (status != 0)
continue;
1547 if (!m_sensor->
IsInArea(xDxc, yDxc, zDxc))
continue;
1549 double xCross, yCross, zCross;
1550 if (m_sensor->
IsWireCrossed(x, y, z, xDxc, yDxc, zDxc, xCross,
1554 newElectron.x0 = xDxc;
1555 newElectron.x = xDxc;
1556 newElectron.y0 = yDxc;
1557 newElectron.y = yDxc;
1558 newElectron.z0 = zDxc;
1559 newElectron.z = zDxc;
1560 newElectron.t0 = t + tDxc;
1561 newElectron.t = t + tDxc;
1562 newElectron.energy = std::max(eDxc, Small);
1563 newElectron.e0 = newElectron.energy;
1567 const double stheta =
sqrt(1. - ctheta * ctheta);
1568 newElectron.kx =
cos(phi) * stheta;
1569 newElectron.ky =
sin(phi) * stheta;
1570 newElectron.kz = ctheta;
1571 newElectron.status = 0;
1572 newElectron.driftLine.clear();
1574 m_stack.push_back(newElectron);
1578 }
else if (typeDxc == DxcProdTypePhoton && m_usePhotons &&
1579 eDxc > m_gammaCut) {
1581 stackPhotonsTime.push_back(t + tDxc);
1582 stackPhotonsEnergy.push_back(eDxc);
1587 const int nSizePhotons = stackPhotonsTime.size();
1588 for (
int j = nSizePhotons; j--;) {
1590 TransportPhoton(x, y, z, stackPhotonsTime[j],
1591 stackPhotonsEnergy[j]);
1597 case ElectronCollisionTypeSuperelastic:
1600 case ElectronCollisionTypeAcousticPhonon:
1603 case ElectronCollisionTypeOpticalPhonon:
1606 case ElectronCollisionTypeIntervalleyG:
1607 case ElectronCollisionTypeIntervalleyF:
1608 case ElectronCollisionTypeInterbandXL:
1609 case ElectronCollisionTypeInterbandXG:
1610 case ElectronCollisionTypeInterbandLG:
1613 case ElectronCollisionTypeImpurity:
1616 std::cerr << m_className <<
"::TransportElectron:\n";
1617 std::cerr <<
" Unknown collision type.\n";
1623 if (!ok || nCollTemp > m_nCollSkip ||
1624 cstype == ElectronCollisionTypeIonisation ||
1625 (m_plotExcitations && cstype == ElectronCollisionTypeExcitation) ||
1626 (m_plotAttachments && cstype == ElectronCollisionTypeAttachment)) {
1636 if (!m_useBandStructure) {
1638 const double k =
sqrt(kx * kx + ky * ky + kz * kz);
1644 m_stack[iE].energy = energy;
1649 m_stack[iE].kx = kx;
1650 m_stack[iE].ky = ky;
1651 m_stack[iE].kz = kz;
1653 if (m_useDriftLines) {
1659 m_stack[iE].driftLine.push_back(newPoint);
1663 m_nElectronEndpoints = m_endpointsElectrons.size();
1664 m_nHoleEndpoints = m_endpointsHoles.size();
1667 if (m_useInducedCharge) {
1668 for (
int i = m_nElectronEndpoints; i--;) {
1670 -1, m_endpointsElectrons[i].x0, m_endpointsElectrons[i].y0,
1671 m_endpointsElectrons[i].z0, m_endpointsElectrons[i].x,
1672 m_endpointsElectrons[i].y, m_endpointsElectrons[i].z);
1674 for (
int i = m_nHoleEndpoints; i--;) {
1675 m_sensor->
AddInducedCharge(+1, m_endpointsHoles[i].x0, m_endpointsHoles[i].y0,
1676 m_endpointsHoles[i].z0, m_endpointsHoles[i].x,
1677 m_endpointsHoles[i].y, m_endpointsHoles[i].z);
1682 if (m_usePlotting) {
1684 for (
int i = m_nElectronEndpoints; i--;) {
1687 if (np <= 0)
continue;
1689 m_endpointsElectrons[i].y0,
1690 m_endpointsElectrons[i].z0);
1691 for (
int jP = np; jP--;) {
1697 for (
int i = m_nHoleEndpoints; i--;) {
1700 if (np <= 0)
continue;
1702 m_endpointsHoles[i].y0, m_endpointsHoles[i].z0);
1703 for (
int jP = np; jP--;) {
1709 for (
int i = m_nPhotons; i--;) {
1710 m_viewer->
NewPhotonTrack(m_photons[i].x0, m_photons[i].y0, m_photons[i].z0,
1711 m_photons[i].x1, m_photons[i].y1, m_photons[i].z1);
1717void AvalancheMicroscopic::TransportPhoton(
const double x0,
const double y0,
1718 const double z0,
const double t0,
1723 std::cerr << m_className <<
"::TransportPhoton:\n";
1724 std::cerr <<
" Sensor is not defined.\n";
1730 if (!m_sensor->
GetMedium(x0, y0, z0, medium)) {
1731 std::cerr << m_className <<
"::TransportPhoton:\n";
1732 std::cerr <<
" No medium at initial position.\n";
1738 std::cerr << m_className <<
"::TransportPhoton:\n";
1739 std::cerr <<
" Medium at initial position does not provide "
1740 <<
" microscopic tracking data.\n";
1745 std::cout << m_className <<
"::TransportPhoton:\n";
1746 std::cout <<
" Starting photon transport in medium " <<
medium->
GetName()
1754 double x = x0, y = y0, z = z0;
1758 double stheta =
sqrt(1. - ctheta * ctheta);
1760 double dx =
cos(phi) * stheta;
1761 double dy =
sin(phi) * stheta;
1776 if (f <= 0.)
return;
1795 double delta =
sqrt(dx * dx + dy * dy + dz * dz);
1802 double xM = x, yM = y, zM = z;
1803 while (delta > BoundaryDistance) {
1806 xM = x + delta * dx;
1807 yM = y + delta * dy;
1808 zM = z + delta * dz;
1824 newPhoton.energy = e0;
1825 newPhoton.status = StatusLeftDriftMedium;
1826 m_photons.push_back(newPhoton);
1834 if (type == PhotonCollisionTypeIonisation) {
1838 stheta =
sqrt(1. - ctheta * ctheta);
1840 electron newElectron;
1841 newElectron.hole =
false;
1850 newElectron.energy = std::max(esec, Small);
1851 newElectron.e0 = newElectron.energy;
1852 newElectron.kx =
cos(phi) * stheta;
1853 newElectron.ky =
sin(phi) * stheta;
1854 newElectron.kz = ctheta;
1855 newElectron.status = 0;
1856 newElectron.driftLine.clear();
1857 if (m_sizeCut <= 0 || (
int)m_stack.size() < m_sizeCut)
1858 m_stack.push_back(newElectron);
1862 }
else if (type == PhotonCollisionTypeExcitation) {
1866 std::vector<double> stackPhotonsTime;
1867 stackPhotonsTime.clear();
1868 std::vector<double> stackPhotonsEnergy;
1869 stackPhotonsEnergy.clear();
1870 for (
int j = nsec; j--;) {
1873 if (typeDxc == DxcProdTypeElectron) {
1877 stheta =
sqrt(1. - ctheta * ctheta);
1879 electron newElectron;
1880 newElectron.hole =
false;
1887 newElectron.t0 = t + tDxc;
1888 newElectron.t = t + tDxc;
1889 newElectron.energy = std::max(esec, Small);
1890 newElectron.e0 = newElectron.energy;
1891 newElectron.kx =
cos(phi) * stheta;
1892 newElectron.ky =
sin(phi) * stheta;
1893 newElectron.kz = ctheta;
1894 newElectron.status = 0;
1895 newElectron.driftLine.clear();
1896 m_stack.push_back(newElectron);
1900 }
else if (typeDxc == DxcProdTypePhoton && m_usePhotons &&
1901 esec > m_gammaCut) {
1903 stackPhotonsTime.push_back(t + tDxc);
1904 stackPhotonsEnergy.push_back(esec);
1908 const int nSizePhotons = stackPhotonsTime.size();
1909 for (
int k = nSizePhotons; k--;) {
1910 TransportPhoton(x, y, z, stackPhotonsTime[k], stackPhotonsEnergy[k]);
1921 newPhoton.energy = e0;
1922 newPhoton.status = -2;
1923 m_photons.push_back(newPhoton);
1927void AvalancheMicroscopic::ComputeRotationMatrix(
1928 const double bx,
const double by,
const double bz,
const double bmag,
1929 const double ex,
const double ey,
const double ez) {
1936 const double bt = by * by + bz * bz;
1939 m_rb11 = m_rb22 = m_rb33 = 1.;
1940 m_rb12 = m_rb13 = m_rb21 = m_rb23 = m_rb31 = m_rb32 = 0.;
1947 m_rb22 = (m_rb11 * by * by + bz * bz) / bt;
1948 m_rb33 = (m_rb11 * bz * bz + by * by) / bt;
1949 m_rb23 = m_rb32 = (m_rb11 - 1.) * by * bz / bt;
1952 const double fy = m_rb21 * ex + m_rb22 * ey + m_rb23 * ez;
1953 const double fz = m_rb31 * ex + m_rb32 * ey + m_rb33 * ez;
1954 const double ft =
sqrt(fy * fy + fz * fz);
1957 m_rx22 = m_rx33 = 1.;
1958 m_rx23 = m_rx32 = 0.;
1960 m_rx22 = m_rx33 = fz / ft;
1966void AvalancheMicroscopic::RotateGlobal2Local(
double& dx,
double& dy,
1969 const double dx1 = m_rb11 * dx + m_rb12 * dy + m_rb13 * dz;
1970 const double dy1 = m_rb21 * dx + m_rb22 * dy + m_rb23 * dz;
1971 const double dz1 = m_rb31 * dx + m_rb32 * dy + m_rb33 * dz;
1974 dy = m_rx22 * dy1 + m_rx23 * dz1;
1975 dz = m_rx32 * dy1 + m_rx33 * dz1;
1978void AvalancheMicroscopic::RotateLocal2Global(
double& dx,
double& dy,
1981 const double dx1 = dx;
1982 const double dy1 = m_rx22 * dy + m_rx32 * dz;
1983 const double dz1 = m_rx23 * dy + m_rx33 * dz;
1985 dx = m_rb11 * dx1 + m_rb21 * dy1 + m_rb31 * dz1;
1986 dy = m_rb12 * dx1 + m_rb22 * dy1 + m_rb32 * dz1;
1987 dz = m_rb13 * dx1 + m_rb23 * dy1 + m_rb33 * dz1;
DoubleAc cos(const DoubleAc &f)
DoubleAc pow(const DoubleAc &f, double p)
DoubleAc sqrt(const DoubleAc &f)
DoubleAc sin(const DoubleAc &f)
DoubleAc fabs(const DoubleAc &f)
void SetCollisionSteps(const int n)
void EnableDistanceHistogramming(const int type)
void SetDistanceHistogram(TH1 *histo, const char opt='r')
void SetUserHandleStep(void(*f)(double x, double y, double z, double t, double e, double dx, double dy, double dz, bool hole))
void EnableHoleEnergyHistogramming(TH1 *histo)
void EnablePlotting(ViewDrift *view)
void SetUserHandleIonisation(void(*f)(double x, double y, double z, double t, int type, int level, Medium *m))
void UnsetUserHandleAttachment()
void DisableHoleEnergyHistogramming()
bool DriftElectron(const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0=0., const double dy0=0., const double dz0=0.)
void DisableSecondaryEnergyHistogramming()
unsigned int GetNumberOfElectronDriftLinePoints(const unsigned int i=0) const
void SetUserHandleAttachment(void(*f)(double x, double y, double z, double t, int type, int level, Medium *m))
void SetSensor(Sensor *sensor)
void GetHoleDriftLinePoint(double &x, double &y, double &z, double &t, const int ip, const unsigned int iel=0) const
void GetElectronEndpoint(const unsigned int i, double &x0, double &y0, double &z0, double &t0, double &e0, double &x1, double &y1, double &z1, double &t1, double &e1, int &status) const
void GetHoleEndpoint(const unsigned int i, double &x0, double &y0, double &z0, double &t0, double &e0, double &x1, double &y1, double &z1, double &t1, double &e1, int &status) const
void GetElectronDriftLinePoint(double &x, double &y, double &z, double &t, const int ip, const unsigned int iel=0) const
void UnsetUserHandleStep()
void EnableElectronEnergyHistogramming(TH1 *histo)
void UnsetUserHandleIonisation()
void DisableDistanceHistogramming()
void GetPhoton(const unsigned int i, double &e, double &x0, double &y0, double &z0, double &t0, double &x1, double &y1, double &z1, double &t1, int &status) const
void EnableSecondaryEnergyHistogramming(TH1 *histo)
bool AvalancheElectron(const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0=0., const double dy0=0., const double dz0=0.)
void DisableElectronEnergyHistogramming()
unsigned int GetNumberOfHoleDriftLinePoints(const unsigned int i=0) const
void SetUserHandleInelastic(void(*f)(double x, double y, double z, double t, int type, int level, Medium *m))
void UnsetUserHandleInelastic()
void SetTimeWindow(const double t0, const double t1)
virtual bool GetPhotonCollision(const double e, int &type, int &level, double &e1, double &ctheta, int &nsec, double &esec)
virtual void GetElectronMomentum(const double e, double &px, double &py, double &pz, int &band)
bool IsMicroscopic() const
virtual bool GetIonisationProduct(const int i, int &type, double &energy)
virtual bool GetElectronCollision(const double e, int &type, int &level, double &e1, double &dx, double &dy, double &dz, int &nion, int &ndxc, int &band)
virtual double GetElectronNullCollisionRate(const int band=0)
virtual double GetElectronCollisionRate(const double e, const int band=0)
virtual bool IsSemiconductor() const
virtual bool GetDeexcitationProduct(const int i, double &t, double &s, int &type, double &energy)
virtual double GetElectronEnergy(const double px, const double py, const double pz, double &vx, double &vy, double &vz, const int band=0)
virtual double GetPhotonCollisionRate(const double &e)
std::string GetName() const
void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
void AddSignal(const double &q, const double &t, const double &dt, const double &x, const double &y, const double &z, const double &vx, const double &vy, const double &vz)
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&medium, int &status)
bool IsInArea(const double x, const double y, const double z)
bool GetMedium(const double x, const double y, const double z, Medium *&medium)
bool IsWireCrossed(const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, double &xc, double &yc, double &zc)
void AddInducedCharge(const double q, const double x0, const double y0, const double z0, const double x1, const double y1, const double z1)
void NewElectronDriftLine(const unsigned int np, int &id, const double x0, const double y0, const double z0)
void AddExcitationMarker(const double x, const double y, const double z)
void AddIonisationMarker(const double x, const double y, const double z)
void SetDriftLinePoint(const unsigned int iL, const unsigned int iP, const double x, const double y, const double z)
void AddAttachmentMarker(const double x, const double y, const double z)
void NewPhotonTrack(const double x0, const double y0, const double z0, const double x1, const double y1, const double z1)
void NewHoleDriftLine(const unsigned int np, int &id, const double x0, const double y0, const double z0)