Garfield++ 4.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
HeedPhoton.cpp
Go to the documentation of this file.
1#include <algorithm>
10
11// 2003, I. Smirnov
12
13namespace Heed {
14
15using CLHEP::cm;
16using CLHEP::cm3;
17using CLHEP::gram;
18using CLHEP::mole;
19using CLHEP::c_light;
20using CLHEP::electron_mass_c2;
21using CLHEP::Avogadro;
22
23HeedPhoton::HeedPhoton(manip_absvol* primvol, const point& pt, const vec& vel,
24 vfloat ftime, long fparent_particle_number,
25 double fenergy, HeedFieldMap* fieldmap,
26 const bool fs_print_listing)
27 : gparticle(primvol, pt, vel, ftime),
28 m_particle_number(last_particle_number++),
29 m_parent_particle_number(fparent_particle_number),
30 m_energy(fenergy),
31#ifdef SFER_PHOTOEL
32 s_sfer_photoel(0),
33#endif
34 m_print_listing(fs_print_listing),
35 m_fieldMap(fieldmap) {
36 mfunname("HeedPhoton::HeedPhoton(...)");
37 double length_vel = vel.length();
38 check_econd11(fabs(length_vel - c_light) / (length_vel + c_light), > 1.0e-10,
39 mcerr);
40}
41
42void HeedPhoton::physics(std::vector<gparticle*>& /*secondaries*/) {
43 mfunname("void HeedPhoton::physics()");
44 if (m_print_listing) mcout << "HeedPhoton::physics() starts\n";
45 // Stop here if the photon has already been absorbed.
46 if (m_photon_absorbed) return;
47 if (m_nextpos.prange <= 0.0) return;
48 // Get least address of volume
49 const absvol* av = m_currpos.volume();
50 HeedMatterDef* hmd = nullptr;
51 auto etcs = dynamic_cast<const EnTransfCS*>(av);
52 if (etcs) {
53 hmd = etcs->hmd;
54 } else {
55 auto hdecs = dynamic_cast<const HeedDeltaElectronCS*>(av);
56 if (hdecs) hmd = hdecs->hmd;
57 }
58 // Stop here if we couldn't retrieve the material definition.
59 if (!hmd) return;
60 // Sum up the cross-sections.
61 std::vector<double> cs;
62 std::vector<long> nat;
63 std::vector<long> nsh;
64 double s = 0.0;
65 const long qa = hmd->matter->qatom();
66 for (long na = 0; na < qa; na++) {
67 const long qs = hmd->apacs[na]->get_qshell();
68 const double awq = hmd->matter->weight_quan(na);
69 for (long ns = 0; ns < qs; ns++) {
70 cs.push_back(hmd->apacs[na]->get_ICS(ns, m_energy) * awq);
71 // threshold is taken into account in apacs[na]->get_ACS(ns,..)
72 nat.push_back(na);
73 nsh.push_back(ns);
74 s += cs.back();
75 }
76 }
77 if (m_print_listing) Iprintn(mcout, s);
78 // Multiply with the density and calculate the path length.
79 // s = s * hmd->eldens / hmd->matter->Z_mean() * C1_MEV_CM;
80 s = s * 1.0e-18 * Avogadro / (hmd->matter->A_mean() / (gram / mole)) *
81 hmd->matter->density() / (gram / cm3);
82 if (m_print_listing) Iprintn(mcout, s);
83 const double path_length = 1.0 / s; // cm
84 if (m_print_listing) Iprint2n(mcout, m_energy, path_length);
85 // Draw a random step length.
86 const double xleng = -path_length * log(1.0 - SRANLUX());
87 if (m_print_listing) Iprint2n(mcout, xleng, m_nextpos.prange / cm);
88 if (xleng * cm < m_nextpos.prange) {
89 m_photon_absorbed = true;
90#ifdef SFER_PHOTOEL
91 // Assume that virtual photons are already
92 // absorbed and s_sfer_photoel is 0 for them
93 s_sfer_photoel = 1;
94#endif
95 // Sample the shell.
96 chispre(cs);
97 const double r = chisran(SRANLUX(), cs);
98 const long n = std::min(std::max(long(r), 0L), long(cs.size() - 1));
99 if (m_print_listing) Iprintn(mcout, n);
100 m_na_absorbing = nat[n];
101 m_ns_absorbing = nsh[n];
102 m_nextpos.prange = xleng * cm;
106 }
107}
108
109void HeedPhoton::physics_after_new_speed(std::vector<gparticle*>& secondaries) {
110 mfunname("void HeedPhoton::physics_after_new_speed()");
111 if (m_print_listing) mcout << "HeedPhoton::physics_after_new_speed starts\n";
112 // Stop if the photon has not been absorbed.
113 if (!m_photon_absorbed) return;
114 // Stop if the delta electrons have already been generated.
115 if (m_delta_generated) return;
116 // Get local volume.
117 const absvol* av = m_currpos.volume();
118 HeedMatterDef* hmd = nullptr;
119 auto etcs = dynamic_cast<const EnTransfCS*>(av);
120 if (etcs) {
121 hmd = etcs->hmd;
122 } else {
123 auto hdecs = dynamic_cast<const HeedDeltaElectronCS*>(av);
124 if (hdecs) hmd = hdecs->hmd;
125 }
126 // Stop here if we couldn't retrieve the material definition.
127 if (!hmd) return;
128 // Generate delta-electrons.
129 std::vector<double> el_energy;
130 std::vector<double> ph_energy;
132 ->get_escape_particles(m_ns_absorbing, m_energy, el_energy, ph_energy);
133 if (m_print_listing) {
134 mcout << "The condition:\n";
136 mcout << "The decay products:\n";
137 for (unsigned int k = 0; k < el_energy.size(); ++k)
138 mcout << el_energy[k] << "\n";
139 for (unsigned int k = 0; k < ph_energy.size(); ++k)
140 mcout << ph_energy[k] << "\n";
141 }
142 const long qel = el_energy.size();
143 for (long nel = 0; nel < qel; nel++) {
144 vec vel = m_currpos.dir;
145 if (nel == 0) {
146 // The first in the list should be the photoelectron.
147#ifdef SFER_PHOTOEL
148 if (s_sfer_photoel == 1) {
149 vel.random_sfer_vec();
150 } else {
151 vel = m_currpos.dir;
152 }
153#else
154 vel = m_currpos.dir; // direction is OK
155#endif
156 } else {
157 vel.random_sfer_vec();
158 }
159 const double gam_1 = el_energy[nel] / electron_mass_c2;
160 const double inv = 1.0 / (gam_1 + 1.0);
161 const double beta = sqrt(1.0 - inv * inv);
162 const double mod_v = beta * c_light;
163 vel = vel * mod_v;
164 if (m_print_listing) {
165 mcout << "Initializing delta electron\n";
166 Iprint4n(mcout, el_energy[nel], gam_1, beta, mod_v);
167 }
170 m_currpos.time, m_particle_number, m_fieldMap);
171 secondaries.push_back(hd);
172 }
173 const long qph = ph_energy.size();
174 for (long nph = 0; nph < qph; nph++) {
175 vec vel;
176 vel.random_sfer_vec();
177 vel *= c_light;
178 if (m_print_listing) {
179 mcout << "Initializing photon\n";
180 Iprint2n(mcout, el_energy[nph], vel);
181 }
184 ph_energy[nph], m_fieldMap);
185 secondaries.push_back(hp);
186 }
187 m_delta_generated = true;
188 m_alive = false;
189 if (m_print_listing) mcout << "HeedPhoton::physics_after_new_speed exited\n";
190}
191
192void HeedPhoton::print(std::ostream& file, int l) const {
193 if (l < 0) return;
194 Ifile << "HeedPhoton (l=" << l << "): particle_number=" << m_particle_number
195 << " energy=" << m_energy << "MeV\n";
196 if (l == 1) return;
197 indn.n += 2;
198 Ifile << "s_photon_absorbed=" << m_photon_absorbed
199 << " na_absorbing=" << m_na_absorbing
200 << " ns_absorbing=" << m_ns_absorbing
201 << " s_delta_generated=" << m_delta_generated
202#ifdef SFER_PHOTOEL
203 << " s_sfer_photoel=" << s_sfer_photoel
204#endif
205 << " parent_particle_number=" << m_parent_particle_number
206 << " s_print_listing=" << m_print_listing << '\n';
207 gparticle::print(file, l - 1);
208 indn.n -= 2;
209}
210}
#define check_econd11(a, signb, stream)
Definition: FunNameStack.h:155
#define mfunname(string)
Definition: FunNameStack.h:45
const std::vector< double > & weight_quan() const
Definition: AtomDef.h:136
long qatom() const
Definition: AtomDef.h:133
double A_mean() const
Definition: AtomDef.h:141
Retrieve electric and magnetic field from Sensor.
Definition: HeedFieldMap.h:15
std::vector< const AtomPhotoAbsCS * > apacs
Definition: HeedMatterDef.h:29
MatterDef * matter
Definition: HeedMatterDef.h:28
long m_na_absorbing
Index of absorbing atom.
Definition: HeedPhoton.h:42
long m_ns_absorbing
Index of absorbing shell.
Definition: HeedPhoton.h:44
void physics_after_new_speed(std::vector< gparticle * > &secondaries) override
Apply any other processes (turn the trajectory, kill the particle, ...).
Definition: HeedPhoton.cpp:109
bool m_photon_absorbed
Definition: HeedPhoton.h:40
void physics(std::vector< gparticle * > &secondaries) override
Apply any other processes (turn the trajectory, kill the particle, ...).
Definition: HeedPhoton.cpp:42
long m_parent_particle_number
Definition: HeedPhoton.h:33
long m_particle_number
Definition: HeedPhoton.h:32
HeedPhoton()=default
Default constructor.
double m_energy
Photon energy [MeV].
Definition: HeedPhoton.h:36
void print(std::ostream &file, int l) const override
Print-out.
Definition: HeedPhoton.cpp:192
bool m_delta_generated
Flag that delta-electrons are already generated (or cannot be created).
Definition: HeedPhoton.h:51
double density() const
Definition: MatterDef.h:51
virtual void print(std::ostream &file, int l) const
Print-out.
Definition: gparticle.cpp:192
stvpoint m_nextpos
Next point.
Definition: gparticle.h:266
stvpoint m_currpos
Current point.
Definition: gparticle.h:264
bool m_alive
Status flag whether the particle is active.
Definition: gparticle.h:247
void up_absref(absref *f)
Definition: volume.cpp:27
std::vector< manip_absvol * > eid
List of volumes.
Definition: volume.h:37
Abstract base classs for volume "manipulators".
Definition: volume.h:128
Point.
Definition: vec.h:368
vfloat time
Definition: gparticle.h:47
absvol * volume()
Definition: gparticle.h:137
vec dir
Unit vector, in the first system in the tree.
Definition: gparticle.h:25
vfloat prange
Range from previous point.
Definition: gparticle.h:46
point pt
Coordinates in the first system in the tree.
Definition: gparticle.h:23
manip_absvol_treeid tid
Definition: gparticle.h:32
point ptloc
Coordinates in the local system (last system in the tree).
Definition: gparticle.h:27
Definition: vec.h:179
vfloat length() const
Definition: vec.h:196
void random_sfer_vec()
Definition: vec.cpp:244
Definition: BGMesh.cpp:6
long last_particle_number
Definition: HeedParticle.h:9
double chisran(double flat_random_number, const std::vector< double > &f)
Definition: chisran.cpp:32
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615
indentation indn
Definition: prstream.cpp:15
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314
double chispre(std::vector< double > &f, int s_allow_zero_f)
Definition: chisran.cpp:8
double vfloat
Definition: vfloat.h:16
#define mcout
Definition: prstream.h:126
#define Ifile
Definition: prstream.h:195
#define mcerr
Definition: prstream.h:128
#define Iprintn(file, name)
Definition: prstream.h:204
#define Iprint2n(file, name1, name2)
Definition: prstream.h:219
#define Iprint4n(file, name1, name2, name3, name4)
Definition: prstream.h:243