CMS 3D CMS Logo

HFCherenkov.cc
Go to the documentation of this file.
1 // File: HFCherenkov.cc
3 // Description: Generate Cherenkov photons for HF
5 
7 
8 #include "G4Poisson.hh"
9 #include "G4ParticleDefinition.hh"
10 #include "G4NavigationHistory.hh"
11 #include "TMath.h"
12 
13 #include "Randomize.hh"
14 
15 #include <CLHEP/Units/SystemOfUnits.h>
16 
17 //#define EDM_ML_DEBUG
18 
20  ref_index = m_HF.getParameter<double>("RefIndex");
21  lambda1 = ((m_HF.getParameter<double>("Lambda1")) / 1.e+7) * CLHEP::cm;
22  lambda2 = ((m_HF.getParameter<double>("Lambda2")) / 1.e+7) * CLHEP::cm;
23  aperture = m_HF.getParameter<double>("Aperture");
24  gain = m_HF.getParameter<double>("Gain");
25  checkSurvive = m_HF.getParameter<bool>("CheckSurvive");
26  UseNewPMT = m_HF.getParameter<bool>("UseR7600UPMT");
27  fibreR = m_HF.getParameter<double>("FibreR") * CLHEP::mm;
28 
30  sinPsimax = 1 / ref_index;
31 
32  edm::LogVerbatim("HFShower") << "HFCherenkov:: initialised with ref_index " << ref_index << " lambda1/lambda2 (cm) "
33  << lambda1 / CLHEP::cm << "|" << lambda2 / CLHEP::cm << " aperture(trapped) " << aperture
34  << "|" << aperturetrapped << " sinPsimax " << sinPsimax
35  << " Check photon survival in HF " << checkSurvive << " Gain " << gain << " useNewPMT "
36  << UseNewPMT << " FibreR " << fibreR;
37 
38  clearVectors();
39 }
40 
42 
43 int HFCherenkov::computeNPE(const G4Step* aStep,
44  const G4ParticleDefinition* pDef,
45  double pBeta,
46  double u,
47  double v,
48  double w,
49  double step_length,
50  double zFiber,
51  double dose,
52  int npe_Dose) {
53  clearVectors();
54  if (!isApplicable(pDef)) {
55  return 0;
56  }
57  if (pBeta < (1 / ref_index) || step_length < 0.0001) {
58 #ifdef EDM_ML_DEBUG
59  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta << " 1/mu " << (1 / ref_index)
60  << " step_length " << step_length;
61 #endif
62  return 0;
63  }
64 
65  double uv = std::sqrt(u * u + v * v);
66  int nbOfPhotons = computeNbOfPhotons(pBeta, step_length) * aStep->GetTrack()->GetWeight();
67 #ifdef EDM_ML_DEBUG
68  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta << " u/v/w " << u << "/" << v << "/" << w
69  << " step_length " << step_length << " zFib " << zFiber << " nbOfPhotons "
70  << nbOfPhotons;
71 #endif
72  if (nbOfPhotons < 0) {
73  return 0;
74  } else if (nbOfPhotons > 0) {
75  G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
76  const G4TouchableHandle& theTouchable = preStepPoint->GetTouchableHandle();
77  G4ThreeVector localprepos =
78  theTouchable->GetHistory()->GetTopTransform().TransformPoint(aStep->GetPreStepPoint()->GetPosition());
79  G4ThreeVector localpostpos =
80  theTouchable->GetHistory()->GetTopTransform().TransformPoint(aStep->GetPostStepPoint()->GetPosition());
81 
82  double length = std::sqrt((localpostpos.x() - localprepos.x()) * (localpostpos.x() - localprepos.x()) +
83  (localpostpos.y() - localprepos.y()) * (localpostpos.y() - localprepos.y()));
84  double yemit = std::sqrt(fibreR * fibreR - length * length / 4.);
85 
86  double u_ph = 0, v_ph = 0, w_ph = 0;
87  for (int i = 0; i < nbOfPhotons; i++) {
88  double rand = G4UniformRand();
89  double theta_C = acos(1. / (pBeta * ref_index));
90  double phi_C = 2 * M_PI * rand;
91  double sinTheta = sin(theta_C);
92  double cosTheta = cos(theta_C);
93  double cosPhi = cos(phi_C);
94  double sinPhi = sin(phi_C);
95  //photon momentum
96  if (uv < 0.001) { // aligned with z-axis
97  u_ph = sinTheta * cosPhi;
98  v_ph = sinTheta * sinPhi;
99  w_ph = cosTheta;
100  } else { // general case
101  u_ph = uv * cosTheta + sinTheta * cosPhi * w;
102  v_ph = sinTheta * sinPhi;
103  w_ph = w * cosTheta - sinTheta * cosPhi * uv;
104  }
105  double r_lambda = G4UniformRand();
106  double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda * (lambda2 - lambda1));
107  double lambda = (lambda0 / CLHEP::cm) * 1.e+7; // lambda is in nm
108  wlini.push_back(lambda);
109 #ifdef EDM_ML_DEBUG
110  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: " << i << " lambda " << lambda << " w_ph " << w_ph;
111 #endif
112  // --------------
113  double xemit = length * (G4UniformRand() - 0.5);
114  double gam = atan2(yemit, xemit);
115  double eps = atan2(v_ph, u_ph);
116  double sinBeta = sin(gam - eps);
117  double rho = std::sqrt(xemit * xemit + yemit * yemit);
118  double sinEta = rho / fibreR * sinBeta;
119  double cosEta = std::sqrt(1. - sinEta * sinEta);
120  double sinPsi = std::sqrt(1. - w_ph * w_ph);
121  double cosKsi = cosEta * sinPsi;
122 
123 #ifdef EDM_ML_DEBUG
124  if (cosKsi < aperturetrapped && w_ph > 0.) {
125  edm::LogVerbatim("HFShower") << "HFCherenkov::Trapped photon : " << u_ph << " " << v_ph << " " << w_ph << " "
126  << xemit << " " << gam << " " << eps << " " << sinBeta << " " << rho << " "
127  << sinEta << " " << cosEta << " "
128  << " " << sinPsi << " " << cosKsi;
129  } else {
130  edm::LogVerbatim("HFShower") << "HFCherenkov::Rejected photon : " << u_ph << " " << v_ph << " " << w_ph << " "
131  << xemit << " " << gam << " " << eps << " " << sinBeta << " " << rho << " "
132  << sinEta << " " << cosEta << " "
133  << " " << sinPsi << " " << cosKsi;
134  }
135 #endif
136  if (cosKsi < aperturetrapped // photon is trapped inside fiber
137  && w_ph > 0. // and moves to PMT
138  && sinPsi < sinPsimax) { // and is not reflected at fiber end
139  wltrap.push_back(lambda);
140  double prob_HF = 1.0;
141  if (checkSurvive) {
142  double a0_inv = 0.1234; //meter^-1
143  double a_inv = a0_inv + 0.14 * pow(dose, 0.30); // ?
144  double z_meters = zFiber;
145  prob_HF = exp(-z_meters * a_inv);
146  }
147  rand = G4UniformRand();
148 #ifdef EDM_ML_DEBUG
149  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: probHF " << prob_HF << " Random " << rand
150  << " Survive? " << (rand < prob_HF);
151 #endif
152  if (rand < prob_HF) { // survived in HF
153  wlatten.push_back(lambda);
154  double effHEM = computeHEMEff(lambda);
155  // compute number of bounces in air guide
156  rand = G4UniformRand();
157  double phi = 0.5 * M_PI * rand;
158  double rad_bundle = 19.; // bundle radius
159  double rad_lg = 25.; // light guide radius
160  rand = G4UniformRand();
161  double rad = rad_bundle * std::sqrt(rand);
162  double rho = rad * sin(phi);
163  double tlength = 2. * std::sqrt(rad_lg * rad_lg - rho * rho);
164  double length_lg = 430;
165  double sin_air = sinPsi * 1.46;
166  double tang = sin_air / std::sqrt(1. - sin_air * sin_air);
167  int nbounce = length_lg / tlength * tang + 0.5;
168  double eff = pow(effHEM, nbounce);
169  rand = G4UniformRand();
170 #ifdef EDM_ML_DEBUG
171  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: w_ph " << w_ph << " effHEM " << effHEM << " eff "
172  << eff << " Random " << rand << " Survive? " << (rand < eff);
173 #endif
174  if (rand < eff) { // survived HEM
175  wlhem.push_back(lambda);
176  double qEffic = computeQEff(lambda);
177  rand = G4UniformRand();
178 #ifdef EDM_ML_DEBUG
179  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: qEffic " << qEffic << " Random " << rand
180  << " Survive? " << (rand < qEffic);
181 #endif
182  if (rand < qEffic) { // made photoelectron
183  npe_Dose += 1;
184  momZ.push_back(w_ph);
185  wl.push_back(lambda);
186  wlqeff.push_back(lambda);
187  } // made pe
188  } // passed HEM
189  } // passed fiber
190  } // end of if(w_ph < w_aperture), trapped inside fiber
191  } // end of ++NbOfPhotons
192  } // end of if(NbOfPhotons)}
193  int npe = npe_Dose; // Nb of photoelectrons
194 #ifdef EDM_ML_DEBUG
195  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: npe " << npe;
196 #endif
197  return npe;
198 }
199 
201  const G4ParticleDefinition* pDef, double pBeta, double u, double v, double w, double step_length) {
202  clearVectors();
203  int npe_ = 0;
204  if (!isApplicable(pDef)) {
205  return 0;
206  }
207  if (pBeta < (1 / ref_index) || step_length < 0.0001) {
208 #ifdef EDM_ML_DEBUG
209  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta << " 1/mu " << (1 / ref_index)
210  << " step_length " << step_length;
211 #endif
212  return 0;
213  }
214 
215  double uv = std::sqrt(u * u + v * v);
216  int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
217 #ifdef EDM_ML_DEBUG
218  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta << " u/v/w " << u << "/" << v << "/"
219  << w << " step_length " << step_length << " nbOfPhotons " << nbOfPhotons;
220 #endif
221  if (nbOfPhotons < 0) {
222  return 0;
223  } else if (nbOfPhotons > 0) {
224  double w_ph = 0;
225  for (int i = 0; i < nbOfPhotons; i++) {
226  double rand = G4UniformRand();
227  double theta_C = acos(1. / (pBeta * ref_index));
228  double phi_C = 2 * M_PI * rand;
229  double sinTheta = sin(theta_C);
230  double cosTheta = cos(theta_C);
231  double cosPhi = cos(phi_C);
232  //photon momentum
233  if (uv < 0.001) { // aligned with z-axis
234  w_ph = cosTheta;
235  } else { // general case
236  w_ph = w * cosTheta - sinTheta * cosPhi * uv;
237  }
238  double r_lambda = G4UniformRand();
239  double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda * (lambda2 - lambda1));
240  double lambda = (lambda0 / CLHEP::cm) * 1.e+7; // lambda is in nm
241  wlini.push_back(lambda);
242 #ifdef EDM_ML_DEBUG
243  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: " << i << " lambda " << lambda << " w_ph " << w_ph
244  << " aperture " << aperture;
245 #endif
246  if (w_ph > aperture) { // phton trapped inside PMT glass
247  wltrap.push_back(lambda);
248  rand = G4UniformRand();
249 #ifdef EDM_ML_DEBUG
250  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: Random " << rand << " Survive? " << (rand < 1.);
251 #endif
252  if (rand < 1.0) { // survived all the times and sent to photo-cathode
253  wlatten.push_back(lambda);
254  double qEffic = computeQEff(lambda); //Quantum efficiency of the PMT
255  rand = G4UniformRand();
256 #ifdef EDM_ML_DEBUG
257  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: qEffic " << qEffic << " Random " << rand
258  << " Survive? " << (rand < qEffic);
259 #endif
260  if (rand < qEffic) { // made photoelectron
261  npe_ += 1;
262  momZ.push_back(w_ph);
263  wl.push_back(lambda);
264  wlqeff.push_back(lambda);
265  } // made pe
266  } // accepted all Cherenkov photons
267  } // end of if(w_ph < w_aperture), trapped inside glass
268  } // end of ++NbOfPhotons
269  } // end of if(NbOfPhotons)}
270 #ifdef EDM_ML_DEBUG
271  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: npe " << npe_;
272 #endif
273  return npe_;
274 }
275 
276 std::vector<double> HFCherenkov::getWLIni() {
277  std::vector<double> v = wlini;
278  return v;
279 }
280 
281 std::vector<double> HFCherenkov::getWLTrap() {
282  std::vector<double> v = wltrap;
283  return v;
284 }
285 
286 std::vector<double> HFCherenkov::getWLAtten() {
287  std::vector<double> v = wlatten;
288  return v;
289 }
290 
291 std::vector<double> HFCherenkov::getWLHEM() {
292  std::vector<double> v = wlhem;
293  return v;
294 }
295 
296 std::vector<double> HFCherenkov::getWLQEff() {
297  std::vector<double> v = wlqeff;
298  return v;
299 }
300 
301 std::vector<double> HFCherenkov::getWL() {
302  std::vector<double> v = wl;
303  return v;
304 }
305 
306 std::vector<double> HFCherenkov::getMom() {
307  std::vector<double> v = momZ;
308  return v;
309 }
310 
311 int HFCherenkov::computeNbOfPhotons(double beta, G4double stepL) {
312  double pBeta = beta;
313  double alpha = 0.0073;
314  double step_length = stepL;
315  double theta_C = acos(1. / (pBeta * ref_index));
316  double lambdaDiff = (1. / lambda1 - 1. / lambda2);
317  double cherenPhPerLength = 2 * M_PI * alpha * lambdaDiff * CLHEP::cm;
318  double d_NOfPhotons = cherenPhPerLength * sin(theta_C) * sin(theta_C) * (step_length / CLHEP::cm);
319  int nbOfPhotons = int(d_NOfPhotons);
320 #ifdef EDM_ML_DEBUG
321  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNbOfPhotons: StepLength " << step_length << " theta_C "
322  << theta_C << " lambdaDiff " << lambdaDiff << " cherenPhPerLength " << cherenPhPerLength
323  << " Photons " << d_NOfPhotons << " " << nbOfPhotons;
324 #endif
325  return nbOfPhotons;
326 }
327 
328 double HFCherenkov::computeQEff(double wavelength) {
329  double qeff(0.);
330  if (UseNewPMT) {
331  if (wavelength <= 350) {
332  qeff = 2.45867 * (TMath::Landau(wavelength, 353.820, 59.1324));
333  } else if (wavelength > 350 && wavelength < 500) {
334  qeff = 0.441989 * exp(-pow((wavelength - 358.371), 2) / (2 * pow((138.277), 2)));
335  } else if (wavelength >= 500 && wavelength < 550) {
336  qeff = 0.271862 * exp(-pow((wavelength - 491.505), 2) / (2 * pow((47.0418), 2)));
337  } else if (wavelength >= 550) {
338  qeff = 0.137297 * exp(-pow((wavelength - 520.260), 2) / (2 * pow((75.5023), 2)));
339  }
340 #ifdef EDM_ML_DEBUG
341  edm::LogVerbatim("HFShower") << "HFCherenkov:: for new PMT : wavelength === " << wavelength << "\tqeff ===\t"
342  << qeff;
343 #endif
344  } else {
345  double y = (wavelength - 275.) / 180.;
346  double func = 1. / (1. + 250. * pow((y / 5.), 4));
347  double qE_R7525 = 0.77 * y * exp(-y) * func;
348  qeff = qE_R7525;
349 #ifdef EDM_ML_DEBUG
350  edm::LogVerbatim("HFShower") << "HFCherenkov::computeQEff: wavelength " << wavelength << " y/func " << y << "/"
351  << func << " qeff " << qeff;
352  edm::LogVerbatim("HFShower") << "HFCherenkov:: for old PMT : wavelength === " << wavelength << "; qeff = " << qeff;
353 #endif
354  }
355  return qeff;
356 }
357 
358 double HFCherenkov::computeHEMEff(double wavelength) {
359  double hEMEff = 0;
360  if (wavelength < 400.) {
361  hEMEff = 0.;
362  } else if (wavelength >= 400. && wavelength < 410.) {
363  //hEMEff = .99 * (wavelength - 400.) / 10.;
364  hEMEff = (-1322.453 / wavelength) + 4.2056;
365  } else if (wavelength >= 410.) {
366  hEMEff = 0.99;
367  if (wavelength > 415. && wavelength < 445.) {
368  //abs(wavelength - 430.) < 15.
369  //hEMEff = 0.95;
370  hEMEff = 0.97;
371  } else if (wavelength > 550. && wavelength < 600.) {
372  // abs(wavelength - 575.) < 25.)
373  //hEMEff = 0.96;
374  hEMEff = 0.98;
375  } else if (wavelength > 565. && wavelength <= 635.) { // added later
376  // abs(wavelength - 600.) < 35.)
377  hEMEff = (701.7268 / wavelength) - 0.186;
378  }
379  }
380 #ifdef EDM_ML_DEBUG
381  edm::LogVerbatim("HFShower") << "HFCherenkov::computeHEMEff: wavelength " << wavelength << " hEMEff " << hEMEff;
382 #endif
383  return hEMEff;
384 }
385 
386 double HFCherenkov::smearNPE(int npe) {
387  double pe = 0.;
388  if (npe > 0) {
389  for (int i = 0; i < npe; ++i) {
390  double val = G4Poisson(gain);
391  pe += (val / gain) + 0.001 * G4UniformRand();
392  }
393  }
394 #ifdef EDM_ML_DEBUG
395  edm::LogVerbatim("HFShower") << "HFCherenkov::smearNPE: npe " << npe << " pe " << pe;
396 #endif
397  return pe;
398 }
399 
401  wl.clear();
402  wlini.clear();
403  wltrap.clear();
404  wlatten.clear();
405  wlhem.clear();
406  wlqeff.clear();
407  momZ.clear();
408 }
409 
410 bool HFCherenkov::isApplicable(const G4ParticleDefinition* aParticleType) {
411  bool tmp = (aParticleType->GetPDGCharge() != 0);
412 #ifdef EDM_ML_DEBUG
413  edm::LogVerbatim("HFShower") << "HFCherenkov::isApplicable: aParticleType " << aParticleType->GetParticleName()
414  << " PDGCharge " << aParticleType->GetPDGCharge() << " Result " << tmp;
415 #endif
416  return tmp;
417 }
Log< level::Info, true > LogVerbatim
double computeQEff(double wavelength)
Definition: HFCherenkov.cc:328
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
virtual ~HFCherenkov()
Definition: HFCherenkov.cc:41
double fibreR
Definition: HFCherenkov.h:61
double aperturetrapped
Definition: HFCherenkov.h:60
T w() const
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
HFCherenkov(edm::ParameterSet const &p)
Definition: HFCherenkov.cc:19
std::vector< double > wlqeff
Definition: HFCherenkov.h:72
void clearVectors()
Definition: HFCherenkov.cc:400
bool UseNewPMT
Definition: HFCherenkov.h:63
std::vector< double > wlini
Definition: HFCherenkov.h:68
double computeHEMEff(double wavelength)
Definition: HFCherenkov.cc:358
double smearNPE(G4int Npe)
Definition: HFCherenkov.cc:386
double sinPsimax
Definition: HFCherenkov.h:61
std::vector< double > getWL()
Definition: HFCherenkov.cc:301
std::vector< double > getWLQEff()
Definition: HFCherenkov.cc:296
T sqrt(T t)
Definition: SSEVec.h:23
std::vector< double > wltrap
Definition: HFCherenkov.h:69
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
double aperture
Definition: HFCherenkov.h:60
std::vector< double > wlhem
Definition: HFCherenkov.h:71
std::vector< double > getMom()
Definition: HFCherenkov.cc:306
#define M_PI
std::vector< double > getWLIni()
Definition: HFCherenkov.cc:276
int computeNbOfPhotons(double pBeta, double step_length)
Definition: HFCherenkov.cc:311
std::vector< double > getWLTrap()
Definition: HFCherenkov.cc:281
std::vector< double > getWLAtten()
Definition: HFCherenkov.cc:286
bool isApplicable(const G4ParticleDefinition *aParticleType)
Definition: HFCherenkov.cc:410
std::vector< double > wlatten
Definition: HFCherenkov.h:70
double gain
Definition: HFCherenkov.h:61
double lambda1
Definition: HFCherenkov.h:59
int computeNPE(const G4Step *step, const G4ParticleDefinition *pDef, double pBeta, double u, double v, double w, double step_length, double zFiber, double Dose, int Npe_Dose)
Definition: HFCherenkov.cc:43
double lambda2
Definition: HFCherenkov.h:59
bool checkSurvive
Definition: HFCherenkov.h:62
tmp
align.sh
Definition: createJobs.py:716
std::vector< double > momZ
Definition: HFCherenkov.h:67
int computeNPEinPMT(const G4ParticleDefinition *pDef, double pBeta, double u, double v, double w, double step_length)
Definition: HFCherenkov.cc:200
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
double ref_index
Definition: HFCherenkov.h:58
std::vector< double > getWLHEM()
Definition: HFCherenkov.cc:291
std::vector< double > wl
Definition: HFCherenkov.h:66