31void ClearBank(std::vector<Heed::gparticle*>& bank) {
32 for (
auto particle : bank)
33 if (particle)
delete particle;
51 m_conductionElectrons.reserve(1000);
52 m_conductionIons.reserve(1000);
60 const double t0,
const double dx0,
const double dy0,
62 m_hasActiveTrack =
false;
67 std::cerr <<
m_className <<
"::NewTrack: Sensor is not defined.\n";
72 if (!UpdateBoundingBox(update))
return false;
78 <<
" No medium at initial position.\n";
82 <<
" Medium at initial position is not ionisable.\n";
87 if (medium->
GetName() != m_mediumName ||
97 m_mediumName = medium->
GetName();
103 m_deltaElectrons.clear();
104 m_conductionElectrons.clear();
105 m_conductionIons.clear();
108 double dx = dx0, dy = dy0, dz = dz0;
109 const double d = sqrt(dx * dx + dy * dy + dz * dz);
113 <<
" Direction vector has zero norm.\n"
114 <<
" Initial direction is randomized.\n";
125 velocity = velocity * Heed::CLHEP::c_light *
GetBeta();
128 std::cout <<
m_className <<
"::NewTrack:\n Track starts at (" << x0
129 <<
", " << y0 <<
", " << z0 <<
") at time " << t0 <<
"\n"
130 <<
" Direction: (" << dx <<
", " << dy <<
", " << dz <<
")\n";
135 Heed::point p0((x0 - m_cX) * 10., (y0 - m_cY) * 10., (z0 - m_cZ) * 10.);
181 m_radStraight * Heed::CLHEP::cm,
182 m_stepAngleStraight * Heed::CLHEP::rad,
183 m_stepAngleCurved * Heed::CLHEP::rad);
185 if (m_useOneStepFly) {
186 particle.
fly(m_particleBank,
true);
188 particle.
fly(m_particleBank);
191 m_bankIterator = m_particleBank.begin();
192 m_hasActiveTrack =
true;
203 std::cerr <<
m_className <<
"::GetClusterDensity:\n"
204 <<
" Ionisation cross-section is not available.\n";
208 return m_transferCs->quanC;
214 std::cerr <<
m_className <<
"::GetStoppingPower:\n"
215 <<
" Ionisation cross-section is not available.\n";
219 return m_transferCs->meanC1 * 1.e6;
223 double& tcls,
int& n,
double& e,
double& extra) {
225 return GetCluster(xcls, ycls, zcls, tcls, n, ni, e, extra);
229 double& tcls,
int& ne,
int& ni,
double& e,
232 xcls = ycls = zcls = tcls = 0.;
237 m_deltaElectrons.clear();
238 m_conductionElectrons.clear();
239 m_conductionIons.clear();
244 <<
" Track has not been initialized. Call NewTrack first.\n";
248 if (m_particleBank.empty())
return false;
249 std::vector<Heed::gparticle*>::const_iterator end = m_particleBank.end();
250 if (m_bankIterator == end)
return false;
254 for (; m_bankIterator != end; ++m_bankIterator) {
257 if (!virtualPhoton) {
259 <<
" Particle is not a virtual photon. Program bug!\n";
266 xcls = virtualPhoton->
position().
x * 0.1 + m_cX;
267 ycls = virtualPhoton->
position().
y * 0.1 + m_cY;
268 zcls = virtualPhoton->
position().
z * 0.1 + m_cZ;
269 tcls = virtualPhoton->
time();
271 if (!IsInside(xcls, ycls, zcls))
continue;
273 m_conductionIons.emplace_back(
280 if (!virtualPhoton)
return false;
284 std::vector<Heed::gparticle*> secondaries;
286 virtualPhoton->
fly(secondaries);
290 while (!secondaries.empty()) {
291 std::vector<Heed::gparticle*> newSecondaries;
293 for (
auto secondary : secondaries) {
298 const double x = delta->position().x * 0.1 + m_cX;
299 const double y = delta->position().y * 0.1 + m_cY;
300 const double z = delta->position().z * 0.1 + m_cZ;
301 if (!IsInside(x, y, z))
continue;
302 if (m_doDeltaTransport) {
304 delta->fly(newSecondaries);
306 m_conductionElectrons.insert(m_conductionElectrons.end(),
307 delta->conduction_electrons.begin(),
308 delta->conduction_electrons.end());
309 m_conductionIons.insert(m_conductionIons.end(),
310 delta->conduction_ions.begin(),
311 delta->conduction_ions.end());
314 deltaElectron newDeltaElectron;
315 newDeltaElectron.x = delta->position().x * 0.1 + m_cX;
316 newDeltaElectron.y = delta->position().y * 0.1 + m_cY;
317 newDeltaElectron.z = delta->position().z * 0.1 + m_cZ;
318 newDeltaElectron.t = delta->time();
319 newDeltaElectron.e = delta->kinetic_energy() * 1.e6;
320 newDeltaElectron.dx = delta->direction().x;
321 newDeltaElectron.dy = delta->direction().y;
322 newDeltaElectron.dz = delta->direction().z;
323 m_deltaElectrons.push_back(std::move(newDeltaElectron));
331 <<
" Particle is neither an electron nor a photon.\n";
334 extra += photon->m_energy * 1.e6;
335 const double x = photon->position().x * 0.1 + m_cX;
336 const double y = photon->position().y * 0.1 + m_cY;
337 const double z = photon->position().z * 0.1 + m_cZ;
338 if (!IsInside(x, y, z))
continue;
340 if (m_usePhotonReabsorption) photon->fly(newSecondaries);
342 for (
auto secondary : secondaries)
343 if (secondary)
delete secondary;
345 secondaries.swap(newSecondaries);
348 ne = m_doDeltaTransport ? m_conductionElectrons.size()
349 : m_deltaElectrons.size();
350 ni = m_conductionIons.size();
355 double& z,
double& t,
double& e,
double& dx,
356 double& dy,
double& dz) {
360 <<
" Track has not been initialized. Call NewTrack first.\n";
364 if (m_doDeltaTransport) {
366 if (i >= m_conductionElectrons.size()) {
367 std::cerr <<
m_className <<
"::GetElectron: Index out of range.\n";
371 x = m_conductionElectrons[i].x * 0.1 + m_cX;
372 y = m_conductionElectrons[i].y * 0.1 + m_cY;
373 z = m_conductionElectrons[i].z * 0.1 + m_cZ;
374 t = m_conductionElectrons[i].time;
380 if (i >= m_deltaElectrons.size()) {
382 <<
" Delta electron number out of range.\n";
386 x = m_deltaElectrons[i].x;
387 y = m_deltaElectrons[i].y;
388 z = m_deltaElectrons[i].z;
389 t = m_deltaElectrons[i].t;
390 e = m_deltaElectrons[i].e;
391 dx = m_deltaElectrons[i].dx;
392 dy = m_deltaElectrons[i].dy;
393 dz = m_deltaElectrons[i].dz;
401 if (i >= m_conductionIons.size()) {
402 std::cerr <<
m_className <<
"::GetIon: Index out of range.\n";
406 x = m_conductionIons[i].x * 0.1 + m_cX;
407 y = m_conductionIons[i].y * 0.1 + m_cY;
408 z = m_conductionIons[i].z * 0.1 + m_cZ;
409 t = m_conductionIons[i].time;
414 const double z0,
const double t0,
415 const double e0,
const double dx0,
416 const double dy0,
const double dz0,
423 const double z0,
const double t0,
424 const double e0,
const double dx0,
425 const double dy0,
const double dz0,
431 if (!m_doDeltaTransport) {
432 std::cerr <<
m_className <<
"::TransportDeltaElectron:\n"
433 <<
" Delta electron transport has been switched off.\n";
439 std::cerr <<
m_className <<
"::TransportDeltaElectron:\n"
440 <<
" Sensor is not defined.\n";
446 if (!UpdateBoundingBox(update))
return;
451 std::cerr <<
m_className <<
"::TransportDeltaElectron:\n"
452 <<
" No medium at initial position.\n";
455 std::cerr <<
"TrackHeed:TransportDeltaElectron:\n"
456 <<
" Medium at initial position is not ionisable.\n";
462 if (medium->
GetName() != m_mediumName ||
467 m_hasActiveTrack =
false;
474 m_mediumName = medium->
GetName();
478 m_deltaElectrons.clear();
479 m_conductionElectrons.clear();
480 m_conductionIons.clear();
484 Heed::point p0((x0 - m_cX) * 10., (y0 - m_cY) * 10., (z0 - m_cZ) * 10.);
495 double dx = dx0, dy = dy0, dz = dz0;
496 const double d = sqrt(dx * dx + dy * dy + dz * dz);
509 const double gamma = 1. + e0 / ElectronMass;
510 const double beta = sqrt(1. - 1. / (gamma * gamma));
511 double speed = Heed::CLHEP::c_light * beta;
512 velocity = velocity * speed;
515 std::vector<Heed::gparticle*> secondaries;
518 delta.
fly(secondaries);
519 ClearBank(secondaries);
523 nel = m_conductionElectrons.size();
524 ni = m_conductionIons.size();
528 const double z0,
const double t0,
529 const double e0,
const double dx0,
530 const double dy0,
const double dz0,
int& nel) {
536 const double z0,
const double t0,
537 const double e0,
const double dx0,
538 const double dy0,
const double dz0,
int& nel,
546 <<
" Photon energy must be positive.\n";
552 std::cerr <<
m_className <<
"::TransportPhoton: Sensor is not defined.\n";
558 if (!UpdateBoundingBox(update))
return;
564 <<
" No medium at initial position.\n";
567 std::cerr <<
"TrackHeed:TransportPhoton:\n"
568 <<
" Medium at initial position is not ionisable.\n";
574 if (medium->
GetName() != m_mediumName ||
585 m_mediumName = medium->
GetName();
591 m_hasActiveTrack =
false;
593 m_deltaElectrons.clear();
594 m_conductionElectrons.clear();
595 m_conductionIons.clear();
598 double dx = dx0, dy = dy0, dz = dz0;
599 const double d = sqrt(dx * dx + dy * dy + dz * dz);
610 velocity = velocity * Heed::CLHEP::c_light;
614 Heed::point p0((x0 - m_cX) * 10., (y0 - m_cY) * 10., (z0 - m_cZ) * 10.);
619 std::vector<Heed::gparticle*> secondaries;
620 photon.
fly(secondaries);
622 while (!secondaries.empty()) {
623 std::vector<Heed::gparticle*> newSecondaries;
625 std::vector<Heed::gparticle*>::iterator it;
626 for (it = secondaries.begin(); it != secondaries.end(); ++it) {
630 if (m_doDeltaTransport) {
632 delta->
fly(newSecondaries);
634 m_conductionElectrons.insert(m_conductionElectrons.end(),
635 delta->conduction_electrons.begin(),
636 delta->conduction_electrons.end());
637 m_conductionIons.insert(m_conductionIons.end(),
638 delta->conduction_ions.begin(),
639 delta->conduction_ions.end());
642 deltaElectron newDeltaElectron;
643 newDeltaElectron.x = delta->position().x * 0.1 + m_cX;
644 newDeltaElectron.y = delta->position().y * 0.1 + m_cY;
645 newDeltaElectron.z = delta->position().z * 0.1 + m_cZ;
646 newDeltaElectron.t = delta->time();
647 newDeltaElectron.e = delta->kinetic_energy() * 1.e6;
648 newDeltaElectron.dx = delta->direction().x;
649 newDeltaElectron.dy = delta->direction().y;
650 newDeltaElectron.dz = delta->direction().z;
651 m_deltaElectrons.push_back(std::move(newDeltaElectron));
657 if (!fluorescencePhoton) {
659 <<
" Unknown secondary particle.\n";
660 ClearBank(secondaries);
661 ClearBank(newSecondaries);
664 fluorescencePhoton->fly(newSecondaries);
666 secondaries.swap(newSecondaries);
667 ClearBank(newSecondaries);
669 ClearBank(secondaries);
671 nel = m_doDeltaTransport ? m_conductionElectrons.size()
672 : m_deltaElectrons.size();
673 ni = m_conductionIons.size();
683 if (fabs(e1 - e0) < Small) {
685 <<
" Invalid energy range:\n"
686 <<
" " << e0 <<
" < E [eV] < " << e1 <<
"\n";
692 <<
" Number of intervals must be > 0.\n";
696 m_emin = std::min(e0, e1);
697 m_emax = std::max(e0, e1);
700 m_nEnergyIntervals = nsteps;
704 if (fabs(z) < Small) {
706 <<
" Particle cannot have zero charge.\n";
711 <<
" Particle mass must be greater than zero.\n";
722 std::string databasePath;
723 char* dbPath = std::getenv(
"HEED_DATABASE");
724 if (dbPath == NULL) {
726 dbPath = std::getenv(
"GARFIELD_HOME");
727 if (dbPath == NULL) {
729 <<
" Cannot retrieve database path "
730 <<
"(environment variables HEED_DATABASE and GARFIELD_HOME "
731 <<
"are not defined).\n Cannot proceed.\n";
734 databasePath = std::string(dbPath) +
"/Heed/heed++/database";
736 databasePath = dbPath;
738 if (databasePath[databasePath.size() - 1] !=
'/') {
739 databasePath.append(
"/");
744 std::cerr <<
m_className <<
"::Initialise: Null pointer.\n";
749 m_energyMesh.reset(
new Heed::EnergyMesh(m_emin, m_emax, m_nEnergyIntervals));
751 if (medium->
IsGas()) {
752 if (!SetupGas(medium))
return false;
754 if (!SetupMaterial(medium))
return false;
763 if (!SetupDelta(databasePath))
return false;
766 const double nc = m_transferCs->quanC;
767 const double dedx = m_transferCs->meanC * 1.e3;
768 const double dedx1 = m_transferCs->meanC1 * 1.e3;
769 const double w = m_matter->W * 1.e6;
770 const double f = m_matter->F;
771 const double minI = m_matter->min_ioniz_pot * 1.e6;
773 std::cout <<
" Cluster density: " << nc <<
" cm-1\n";
774 std::cout <<
" Stopping power (restricted): " << dedx <<
" keV/cm\n";
775 std::cout <<
" Stopping power (incl. tail): " << dedx1 <<
" keV/cm\n";
776 std::cout <<
" W value: " << w <<
" eV\n";
777 std::cout <<
" Fano factor: " << f <<
"\n";
778 std::cout <<
" Min. ionization potential: " << minI <<
" eV\n";
783 m_chamber.reset(
new HeedChamber(primSys, m_lX, m_lY, m_lZ,
784 *m_transferCs.get(), *m_deltaCs.get()));
789bool TrackHeed::SetupGas(
Medium* medium) {
792 pressure = (pressure / AtmosphericPressure) * Heed::CLHEP::atmosphere;
796 if (nComponents < 1) {
798 std::cerr <<
" Gas " << medium->
GetName() <<
" has zero constituents.\n";
802 std::vector<Heed::MolecPhotoAbsCS*> molPacs(nComponents,
nullptr);
803 std::vector<std::string> notations;
804 std::vector<double> fractions;
806 for (
int i = 0; i < nComponents; ++i) {
811 if (gasname ==
"He-3") gasname =
"He";
812 if (gasname ==
"CD4") gasname =
"CH4";
813 if (gasname ==
"iC4H10" || gasname ==
"nC4H10") gasname =
"C4H10";
814 if (gasname ==
"neoC5H12" || gasname ==
"nC5H12") gasname =
"C5H12";
815 if (gasname ==
"H2O") gasname =
"Water";
816 if (gasname ==
"D2") gasname =
"H2";
817 if (gasname ==
"cC3H6") gasname =
"C3H6";
819 if (gasname ==
"CF4")
821 else if (gasname ==
"Ar")
823 else if (gasname ==
"He")
825 else if (gasname ==
"Ne")
827 else if (gasname ==
"Kr")
829 else if (gasname ==
"Xe")
831 else if (gasname ==
"CH4")
833 else if (gasname ==
"C2H6")
835 else if (gasname ==
"C3H8")
837 else if (gasname ==
"C4H10")
839 else if (gasname ==
"CO2")
841 else if (gasname ==
"C5H12")
843 else if (gasname ==
"Water")
845 else if (gasname ==
"O2")
847 else if (gasname ==
"N2" || gasname ==
"N2 (Phelps)")
849 else if (gasname ==
"NO")
851 else if (gasname ==
"N2O")
853 else if (gasname ==
"C2H4")
855 else if (gasname ==
"C2H2")
857 else if (gasname ==
"H2")
859 else if (gasname ==
"CO")
861 else if (gasname ==
"Methylal")
863 else if (gasname ==
"DME")
865 else if (gasname ==
"C2F6")
867 else if (gasname ==
"SF6")
869 else if (gasname ==
"NH3")
871 else if (gasname ==
"C3H6")
873 else if (gasname ==
"CH3OH")
875 else if (gasname ==
"C2H5OH")
877 else if (gasname ==
"C3H7OH")
879 else if (gasname ==
"Cs")
881 else if (gasname ==
"F2")
883 else if (gasname ==
"CS2")
885 else if (gasname ==
"COS")
887 else if (gasname ==
"CD4")
889 else if (gasname ==
"BF3")
891 else if (gasname ==
"C2HF5")
893 else if (gasname ==
"C2H2F4")
895 else if (gasname ==
"CHF3")
897 else if (gasname ==
"CF3Br")
899 else if (gasname ==
"C3F8")
901 else if (gasname ==
"O3")
903 else if (gasname ==
"Hg")
905 else if (gasname ==
"H2S")
907 else if (gasname ==
"GeH4")
909 else if (gasname ==
"SiH4")
912 std::cerr <<
m_className <<
"::SetupGas:\n Photoabsorption "
913 <<
"cross-section for " << gasname <<
" not available.\n";
916 notations.push_back(gasname);
917 fractions.push_back(frac);
919 if (m_usePacsOutput) {
920 std::ofstream pacsfile;
921 pacsfile.open(
"heed_pacs.txt", std::ios::out);
922 const int nValues = m_energyMesh->get_q();
924 for (
int i = 0; i < nValues; ++i) {
925 double e = m_energyMesh->get_e(i);
926 pacsfile << 1.e6 * e <<
" ";
927 for (
int j = 0; j < nComponents; ++j) {
928 pacsfile << molPacs[j]->get_ACS(e) <<
" " << molPacs[j]->get_ICS(e)
937 const std::string gasname = FindUnusedMaterialName(medium->
GetName());
938 m_gas.reset(
new Heed::GasDef(gasname, gasname, nComponents, notations,
939 fractions, pressure, temperature, -1.));
941 const double w = std::max(medium->
GetW() * 1.e-6, 0.);
951bool TrackHeed::SetupMaterial(Medium* medium) {
953 double temperature = medium->GetTemperature();
954 const double density =
955 medium->GetMassDensity() * Heed::CLHEP::gram / Heed::CLHEP::cm3;
957 const int nComponents = medium->GetNumberOfComponents();
958 std::vector<Heed::AtomPhotoAbsCS*> atPacs(nComponents,
nullptr);
960 std::vector<std::string> notations;
961 std::vector<double> fractions;
962 for (
int i = 0; i < nComponents; ++i) {
963 std::string materialName;
965 medium->GetComponent(i, materialName, frac);
966 if (materialName ==
"C") {
967 if (medium->GetName() ==
"Diamond") {
969 }
else if (materialName ==
"Diamond") {
972 }
else if (materialName ==
"Si") {
975 }
else if (materialName ==
"Ga") {
977 }
else if (materialName ==
"Ge") {
979 }
else if (materialName ==
"As") {
981 }
else if (materialName ==
"Cd") {
983 }
else if (materialName ==
"Te") {
987 std::cerr <<
" Photoabsorption cross-section data for " << materialName
988 <<
" are not implemented.\n";
991 notations.push_back(materialName);
992 fractions.push_back(frac);
994 if (m_usePacsOutput) {
995 std::ofstream pacsfile;
996 pacsfile.open(
"heed_pacs.txt", std::ios::out);
997 const int nValues = m_energyMesh->get_q();
999 for (
int i = 0; i < nValues; ++i) {
1000 double e = m_energyMesh->get_e(i);
1001 pacsfile << 1.e6 * e <<
" ";
1002 for (
int j = 0; j < nComponents; ++j) {
1003 pacsfile << atPacs[j]->get_ACS(e) <<
" " << atPacs[j]->get_ICS(e)
1011 const std::string materialName = FindUnusedMaterialName(medium->GetName());
1012 m_material.reset(
new Heed::MatterDef(materialName, materialName, nComponents,
1013 notations, fractions, density,
1016 double w = medium->GetW() * 1.e-6;
1018 double f = medium->GetFanoFactor();
1027bool TrackHeed::SetupDelta(
const std::string& databasePath) {
1029 std::string filename = databasePath +
"cbdel.dat";
1032 filename = databasePath +
"elastic_disp.dat";
1037 const double w = m_matter->W * 1.e6;
1038 const double f = m_matter->F;
1039 filename = databasePath +
"delta_path.dat";
1043 m_matter.get(), m_elScat.get(), m_lowSigma.get(), m_pairProd.get()));
1052 if (!m_matter)
return 0.;
1054 const double e = 1.e-6 * en;
1056 const auto n = m_matter->apacs.size();
1057 for (
size_t i = 0; i < n; ++i) {
1058 const double w = m_matter->matter->weight_quan(i);
1059 cs += m_matter->apacs[i]->get_ACS(e) * w;
1065std::string TrackHeed::FindUnusedMaterialName(
const std::string& namein) {
1066 std::string nameout = namein;
1067 unsigned int counter = 0;
1069 nameout = namein +
"_" + std::to_string(counter);
1075void TrackHeed::ClearParticleBank() {
1077 ClearBank(m_particleBank);
1078 m_bankIterator = m_particleBank.end();
1081bool TrackHeed::IsInside(
const double x,
const double y,
const double z) {
1085 Medium* medium =
nullptr;
1088 if (medium->GetName() != m_mediumName ||
1089 fabs(medium->GetMassDensity() - m_mediumDensity) > 1.e-9 ||
1090 !medium->IsIonisable()) {
1096bool TrackHeed::UpdateBoundingBox(
bool& update) {
1098 double xmin = 0., ymin = 0., zmin = 0.;
1099 double xmax = 0., ymax = 0., zmax = 0.;
1101 std::cerr <<
m_className <<
"::UpdateBoundingBox: Drift area is not set.\n";
1106 const double lx =
fabs(xmax - xmin);
1107 const double ly =
fabs(ymax - ymin);
1108 const double lz =
fabs(zmax - zmin);
1110 std::cout <<
m_className <<
"::UpdateBoundingBox:\n"
1111 <<
" Bounding box dimensions:\n"
1112 <<
" x: " << lx <<
" cm\n"
1113 <<
" y: " << ly <<
" cm\n"
1114 <<
" z: " << lz <<
" cm\n";
1116 if (
fabs(lx - m_lX) > Small ||
fabs(ly - m_lY) > Small ||
1117 fabs(lz - m_lZ) > Small) {
1123 m_hasActiveTrack =
false;
1126 m_cX = (std::isinf(xmin) || std::isinf(xmax)) ? 0. : 0.5 * (xmin + xmax);
1127 m_cY = (std::isinf(ymin) || std::isinf(ymax)) ? 0. : 0.5 * (ymin + ymax);
1128 m_cZ = (std::isinf(zmin) || std::isinf(zmax)) ? 0. : 0.5 * (zmin + zmax);
1130 std::cout <<
m_className <<
"::UpdateBoundingBox:\n"
1131 <<
" Center of bounding box:\n"
1132 <<
" x: " << m_cX <<
" cm\n"
1133 <<
" y: " << m_cY <<
" cm\n"
1134 <<
" z: " << m_cZ <<
" cm\n";
1138 m_fieldMap->SetCentre(m_cX, m_cY, m_cZ);
Abstract base class for media.
virtual void GetComponent(const unsigned int i, std::string &label, double &f)
Get the name and fraction of a given component.
virtual double GetMassDensity() const
Get the mass density [g/cm3].
double GetFanoFactor()
Get the Fano factor.
double GetW()
Get the W value.
double GetPressure() const
unsigned int GetNumberOfComponents() const
Get number of components of the medium.
const std::string & GetName() const
Get the medium name/identifier.
virtual bool IsGas() const
Is this medium a gas?
bool IsIonisable() const
Is charge deposition by charged particles/photon enabled in this medium?
double GetTemperature() const
Get the temperature [K].
bool IsInArea(const double x, const double y, const double z)
Check if a point is inside the user area.
bool GetMedium(const double x, const double y, const double z, Medium *&medium)
Get the medium at (x, y, z).
bool GetArea(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Return the current user area.
void EnableMagneticField()
Take the magnetic field into account in the stepping algorithm.
void SetEnergyMesh(const double e0, const double e1, const int nsteps)
bool GetCluster(double &xcls, double &ycls, double &zcls, double &tcls, int &n, double &e, double &extra) override
void EnableElectricField()
Take the electric field into account in the stepping algorithm.
void DisableMagneticField()
Do not take the magnetic field into account in the stepping algorithm.
double GetPhotoAbsorptionCrossSection(const double e) const
Return the photoabsorption cross-section at a given energy.
void TransportDeltaElectron(const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &ne, int &ni)
double GetFanoFactor() const
Return the Fano factor of the medium (of the last simulated track).
bool Initialise(Medium *medium)
Compute the differential cross-section for a given medium.
bool NewTrack(const double x0, const double y0, const double z0, const double t0, const double dx0, const double dy0, const double dz0) override
bool GetElectron(const unsigned int i, double &x, double &y, double &z, double &t, double &e, double &dx, double &dy, double &dz)
void TransportPhoton(const double x0, const double y0, const double z0, const double t0, const double e0, const double dx0, const double dy0, const double dz0, int &ne, int &ni)
bool GetIon(const unsigned int i, double &x, double &y, double &z, double &t) const
virtual ~TrackHeed()
Destructor.
double GetW() const
Return the W value of the medium (of the last simulated track).
void SetParticleUser(const double m, const double z)
double GetClusterDensity() override
void DisableElectricField()
Do not take the electric field into account in the stepping algorithm.
double GetStoppingPower() override
Get the stopping power (mean energy loss [eV] per cm).
Abstract base class for track generation.
double GetBeta() const
Return the speed ( ) of the projectile.
double GetGamma() const
Return the Lorentz factor of the projectile.
std::string m_particleName
void PlotCluster(const double x0, const double y0, const double z0)
void PlotNewTrack(const double x0, const double y0, const double z0)
std::vector< HeedCondElectron > conduction_electrons
std::vector< HeedCondElectron > conduction_ions
Retrieve electric and magnetic field from Sensor.
double m_energy
Photon energy [MeV].
static MatterDef * get_MatterDef(const std::string &fnotation)
vfloat time() const
Get the current time of the particle.
const vec & position() const
Get the current position of the particle.
virtual void fly(std::vector< gparticle * > &secondaries)
Transport the particle.
void set_step_limits(const vfloat fmax_range, const vfloat frad_for_straight, const vfloat fmax_straight_arange, const vfloat fmax_circ_arange)
Set limits/parameters for trajectory steps.
double kinetic_energy() const
Get the current kinetic energy.
void set_mass(const double m)
void set_charge(const double z)
void RndmDirection(double &dx, double &dy, double &dz, const double length=1.)
Draw a random (isotropic) direction vector.
ExAtomPhotoAbsCS Gallium_for_GaAs_PACS(31, shelllist_dir_name+"shelllist_solid.dat", pacs_table_dir_name+"Ga.dat", "Ga_for_GaAs")
ExAtomPhotoAbsCS Tellurium_for_CdTe_PACS(52, shelllist_dir_name+"shelllist_solid.dat", pacs_table_dir_name+"Te.dat", "Te_for_CdTe")
MolecPhotoAbsCS C2H2_MPACS
MolecPhotoAbsCS Methylal_MPACS
particle_def pi_minus_meson_def("pi_minus_meson", "pi-", 139.56755 *MeV/c_squared, -eplus, 0, 0, 0.0, spin_def(1.0, -1.0))
MolecPhotoAbsCS CH3OH_MPACS
particle_def pi_plus_meson_def("pi_plus_meson", "pi+", 139.56755 *MeV/c_squared, eplus, 0, 0, 0.0, spin_def(1.0, 1.0))
MolecPhotoAbsCS CF4_MPACS
ExAtomPhotoAbsCS Silicon_crystal_PACS(14, shelllist_dir_name+"shelllist_solid.dat", pacs_table_dir_name+"Si.dat", "Si_crystal")
particle_def muon_minus_def("muon_minus", "mu-", 105.658367 *MeV/c_squared, electron_charge, 1, 0, 0.5, spin_def(0.0, 0.0))
MolecPhotoAbsCS CS2_MPACS
MolecPhotoAbsCS NH3_MPACS
MolecPhotoAbsCS CF3Br_MPACS
long last_particle_number
particle_def alpha_particle_def("alpha_particle", "alpha", 3727.417 *MeV/c_squared, 2 *eplus, 0, 4, 0.0, spin_def(0.0, 0.0))
particle_def anti_proton_def("", "p-", proton_def)
MolecPhotoAbsCS C2H6_MPACS
particle_def deuteron_def("deuteron", "dtr", 1875.613 *MeV/c_squared, eplus, 0, 2, 0.0, spin_def(0.0, 0.0))
MolecPhotoAbsCS SiH4_MPACS
particle_def proton_def("proton", "p+", proton_mass_c2/c_squared, eplus, 0, 1, 0.5, spin_def(0.5, 0.5))
MolecPhotoAbsCS SF6_MPACS
MolecPhotoAbsCS C2H2F4_MPACS
MolecPhotoAbsCS H2O_MPACS
MolecPhotoAbsCS C2H4_MPACS
MolecPhotoAbsCS C2F6_MPACS
MolecPhotoAbsCS CO2_MPACS
MolecPhotoAbsCS COS_MPACS
particle_def K_minus_meson_def("K_minus_meson_def", "K-", K_plus_meson_def)
MolecPhotoAbsCS N2O_MPACS
ExAtomPhotoAbsCS Arsenic_for_GaAs_PACS(33, shelllist_dir_name+"shelllist_solid.dat", pacs_table_dir_name+"As.dat", "As_for_GaAs")
particle_def K_plus_meson_def("K_plus_meson_def", "K+", 493.677 *MeV/c_squared, 1, 0, 0, 0.0, spin_def(0.5, -0.5))
MolecPhotoAbsCS C2HF5_MPACS
particle_def user_particle_def("user_particle", "X", 139.56755 *MeV/c_squared, eplus, 0, 0, 0.0, spin_def(0.0, 0.0))
ExAtomPhotoAbsCS Germanium_PACS(32, shelllist_dir_name+"shelllist.dat", pacs_table_dir_name+"Ge.dat")
ExAtomPhotoAbsCS Cadmium_for_CdTe_PACS(48, shelllist_dir_name+"shelllist_solid.dat", pacs_table_dir_name+"Cd.dat", "Cd_for_CdTe")
DoubleAc fabs(const DoubleAc &f)
MolecPhotoAbsCS BF3_MPACS
MolecPhotoAbsCS H2S_MPACS
particle_def muon_plus_def("muon_plus", "mu+", muon_minus_def)
particle_def positron_def("positron", "e+", electron_def)
MolecPhotoAbsCS DME_MPACS
particle_def electron_def("electron", "e-", electron_mass_c2/c_squared, electron_charge, 1, 0, 0.5, spin_def(0.0, 0.0))
MolecPhotoAbsCS C3H7OH_MPACS
MolecPhotoAbsCS C3F8_MPACS
MolecPhotoAbsCS C3H6_MPACS
MolecPhotoAbsCS C4H10_MPACS
ExAtomPhotoAbsCS Carbon_PACS(6, shelllist_dir_name+"shelllist.dat", pacs_table_dir_name+"C.dat")
MolecPhotoAbsCS C3H8_MPACS
constexpr double standard_factor_Fano
MolecPhotoAbsCS C5H12_MPACS
MolecPhotoAbsCS C2H5OH_MPACS
MolecPhotoAbsCS CHF3_MPACS
MolecPhotoAbsCS CH4_MPACS
ExAtomPhotoAbsCS Diamond_PACS(6, shelllist_dir_name+"shelllist_solid.dat", pacs_table_dir_name+"C.dat", "Diamond")
MolecPhotoAbsCS GeH4_MPACS