CMS 3D CMS Logo

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