Garfield++ v2r0
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 time, long fparent_particle_number,
25 double fenergy, HeedFieldMap* fieldmap,
26 const bool fs_print_listing)
27 : gparticle(primvol, pt, vel, time),
28 particle_number(last_particle_number++),
29 parent_particle_number(fparent_particle_number),
30 energy(fenergy),
31 s_photon_absorbed(false),
32#ifdef SFER_PHOTOEL
33 s_sfer_photoel(0),
34#endif
35 s_delta_generated(false),
36 s_print_listing(fs_print_listing),
37 m_fieldMap(fieldmap) {
38 mfunname("HeedPhoton::HeedPhoton(...)");
39 double length_vel = vel.length();
40 check_econd11(fabs(length_vel - c_light) / (length_vel + c_light), > 1.0e-10,
41 mcerr);
42}
43
44void HeedPhoton::physics(std::vector<gparticle*>& /*secondaries*/) {
45 mfunname("void HeedPhoton::physics()");
46 if (s_print_listing) mcout << "HeedPhoton::physics() starts\n";
47 // Stop here if the photon has already been absorbed.
48 if (s_photon_absorbed) return;
49 if (nextpos.prange <= 0.0) return;
50 // Get least address of volume
51 const absvol* av = currpos.tid.G_lavol();
52 HeedMatterDef* hmd = NULL;
53 const EnTransfCS* etcs = dynamic_cast<const EnTransfCS*>(av);
54 if (etcs) {
55 hmd = etcs->hmd.getver();
56 } else {
57 const HeedDeltaElectronCS* hdecs =
58 dynamic_cast<const HeedDeltaElectronCS*>(av);
59 if (hdecs) hmd = hdecs->hmd.get();
60 }
61 // Stop here if we couldn't retrieve the material definition.
62 if (!hmd) return;
63 // Sum up the cross-sections.
64 std::vector<double> cs;
65 std::vector<long> nat;
66 std::vector<long> nsh;
67 double s = 0.0;
68 const long qa = hmd->matter->qatom();
69 for (long na = 0; na < qa; na++) {
70 const long qs = hmd->apacs[na]->get_qshell();
71 const double awq = hmd->matter->weight_quan(na);
72 for (long ns = 0; ns < qs; ns++) {
73 cs.push_back(hmd->apacs[na]->get_ICS(ns, energy) * awq);
74 // threshold is taken into account in apacs[na]->get_ACS(ns,..)
75 nat.push_back(na);
76 nsh.push_back(ns);
77 s += cs.back();
78 }
79 }
80 if (s_print_listing) Iprintn(mcout, s);
81 // Multiply with the density and calculate the path length.
82 // s = s * hmd->eldens / hmd->matter->Z_mean() * C1_MEV_CM;
83 s = s * 1.0e-18 * Avogadro / (hmd->matter->A_mean() / (gram / mole)) *
84 hmd->matter->density() / (gram / cm3);
85 if (s_print_listing) Iprintn(mcout, s);
86 const double path_length = 1.0 / s; // cm
87 if (s_print_listing) Iprint2n(mcout, energy, path_length);
88 // Draw a random step length.
89 const double xleng = -path_length * log(1.0 - SRANLUX());
90 if (s_print_listing) Iprint2n(mcout, xleng, nextpos.prange / cm);
91 if (xleng * cm < nextpos.prange) {
92 s_photon_absorbed = true;
93#ifdef SFER_PHOTOEL
94 // Assume that virtual photons are already
95 // absorbed and s_sfer_photoel is 0 for them
96 s_sfer_photoel = 1;
97#endif
98 // Sample the shell.
99 chispre(cs);
100 const double r = chisran(SRANLUX(), cs);
101 const long n = std::min(std::max(long(r), 0L), long(cs.size() - 1));
102 if (s_print_listing) Iprintn(mcout, n);
103 na_absorbing = nat[n];
104 ns_absorbing = nsh[n];
105 nextpos.prange = xleng * cm;
109 }
110}
111
112void HeedPhoton::physics_after_new_speed(std::vector<gparticle*>& secondaries) {
113 mfunname("void HeedPhoton::physics_after_new_speed()");
114 if (s_print_listing) mcout << "HeedPhoton::physics_after_new_speed starts\n";
115 // Stop if the photon has not been absorbed.
116 if (!s_photon_absorbed) return;
117 // Stop if the delta electrons have already been generated.
118 if (s_delta_generated) return;
119 // Get least address of volume
120 const absvol* av = currpos.tid.G_lavol();
121 HeedMatterDef* hmd = NULL;
122 const EnTransfCS* etcs = dynamic_cast<const EnTransfCS*>(av);
123 if (etcs) {
124 hmd = etcs->hmd.getver();
125 } else {
126 const HeedDeltaElectronCS* hdecs =
127 dynamic_cast<const HeedDeltaElectronCS*>(av);
128 if (hdecs) hmd = hdecs->hmd.get();
129 }
130 // Stop here if we couldn't retrieve the material definition.
131 if (!hmd) return;
132 // Generate delta-electrons.
133 std::vector<double> el_energy;
134 std::vector<double> ph_energy;
135 hmd->apacs[na_absorbing]
136 ->get_escape_particles(ns_absorbing, energy, el_energy, ph_energy);
137 if (s_print_listing) {
138 mcout << "The condition:\n";
140 mcout << "The decay products:\n";
141 for (unsigned int k = 0; k < el_energy.size(); ++k)
142 mcout << el_energy[k] << "\n";
143 for (unsigned int k = 0; k < ph_energy.size(); ++k)
144 mcout << ph_energy[k] << "\n";
145 }
146 const long qel = el_energy.size();
147 for (long nel = 0; nel < qel; nel++) {
148 vec vel = currpos.dir;
149 if (nel == 0) {
150 // The first in the list should be the photoelectron.
151#ifdef SFER_PHOTOEL
152 if (s_sfer_photoel == 1) {
153 vel.random_sfer_vec();
154 } else {
155 vel = currpos.dir;
156 }
157#else
158 vel = currpos.dir; // direction is OK
159#endif
160 } else {
161 vel.random_sfer_vec();
162 }
163 const double gam_1 = el_energy[nel] / electron_mass_c2;
164 const double inv = 1.0 / (gam_1 + 1.0);
165 const double beta = sqrt(1.0 - inv * inv);
166 const double mod_v = beta * c_light;
167 vel = vel * mod_v;
168 if (s_print_listing) {
169 mcout << "Initializing delta electron\n";
170 Iprint4n(mcout, el_energy[nel], gam_1, beta, mod_v);
171 }
173 new HeedDeltaElectron(currpos.tid.eid[0].getver(), currpos.pt, vel,
174 currpos.time, particle_number, m_fieldMap);
175 secondaries.push_back(hd);
176 }
177 const long qph = ph_energy.size();
178 for (long nph = 0; nph < qph; nph++) {
179 vec vel;
180 vel.random_sfer_vec();
181 vel *= c_light;
182 if (s_print_listing) {
183 mcout << "Initializing photon\n";
184 Iprint2n(mcout, el_energy[nph], vel);
185 }
186 HeedPhoton* hp = new HeedPhoton(currpos.tid.eid[0].getver(), currpos.pt,
188 ph_energy[nph], m_fieldMap);
189 secondaries.push_back(hp);
190 }
191 s_delta_generated = true;
192 s_life = false;
193 if (s_print_listing) mcout << "HeedPhoton::physics_after_new_speed exited\n";
194}
195
196void HeedPhoton::print(std::ostream& file, int l) const {
197 if (l < 0) return;
198 Ifile << "HeedPhoton (l=" << l << "): particle_number=" << particle_number
199 << " energy=" << energy << "MeV\n";
200 if (l == 1) return;
201 indn.n += 2;
202 Ifile << "s_photon_absorbed=" << s_photon_absorbed
203 << " na_absorbing=" << na_absorbing << " ns_absorbing=" << ns_absorbing
204 << " s_delta_generated=" << s_delta_generated
205#ifdef SFER_PHOTOEL
206 << " s_sfer_photoel=" << s_sfer_photoel
207#endif
208 << " parent_particle_number=" << parent_particle_number
209 << " s_print_listing=" << s_print_listing << '\n';
210 gparticle::print(file, l - 1);
211 indn.n -= 2;
212}
213}
#define check_econd11(a, signb, stream)
Definition: FunNameStack.h:155
#define mfunname(string)
Definition: FunNameStack.h:45
PassivePtr< HeedMatterDef > hmd
Definition: EnTransfCS.h:52
PassivePtr< HeedMatterDef > hmd
Retrieve electric and magnetic field from Sensor.
Definition: HeedFieldMap.h:15
std::vector< PassivePtr< const AtomPhotoAbsCS > > apacs
Definition: HeedMatterDef.h:30
PassivePtr< MatterDef > matter
Definition: HeedMatterDef.h:29
virtual void physics(std::vector< gparticle * > &secondaries)
Definition: HeedPhoton.cpp:44
double energy
Photon energy [MeV].
Definition: HeedPhoton.h:37
bool s_photon_absorbed
Definition: HeedPhoton.h:40
virtual void physics_after_new_speed(std::vector< gparticle * > &secondaries)
Definition: HeedPhoton.cpp:112
HeedPhoton()
Default constructor.
Definition: HeedPhoton.h:21
bool s_delta_generated
Flag that delta-electrons are already generated (or cannot be created).
Definition: HeedPhoton.h:50
long particle_number
Definition: HeedPhoton.h:34
virtual void print(std::ostream &file, int l) const
Definition: HeedPhoton.cpp:196
long ns_absorbing
Index of absorbing shell.
Definition: HeedPhoton.h:44
long parent_particle_number
Definition: HeedPhoton.h:35
long na_absorbing
Index of absorbing atom.
Definition: HeedPhoton.h:42
virtual void print(std::ostream &file, int l) const
Definition: gparticle.cpp:200
stvpoint currpos
Definition: gparticle.h:177
stvpoint nextpos
Definition: gparticle.h:178
void up_absref(absref *f)
Definition: volume.cpp:26
std::vector< PassivePtr< manip_absvol > > eid
List of volumes.
Definition: volume.h:37
absvol * G_lavol() const
Get last address of volume.
Definition: volume.cpp:17
Abstract base classs for volume "manipulators".
Definition: volume.h:178
Point.
Definition: vec.h:374
vfloat time
Definition: gparticle.h:47
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:186
vfloat length() const
Definition: vec.h:205
void random_sfer_vec()
Definition: vec.cpp:244
Definition: BGMesh.cpp:5
float chispre(float *x, float *p, float *f, long q)
Definition: chisran.cpp:8
long last_particle_number
Definition: HeedParticle.h:9
float chisran(float flat_random_number, float *x, float *f, long q)
Definition: chisran.cpp:22
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 vfloat
Definition: vfloat.h:16
#define mcout
Definition: prstream.h:126
#define Ifile
Definition: prstream.h:196
#define mcerr
Definition: prstream.h:128
#define Iprintn(file, name)
Definition: prstream.h:205
#define Iprint2n(file, name1, name2)
Definition: prstream.h:220
#define Iprint4n(file, name1, name2, name3, name4)
Definition: prstream.h:244