CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2/src/SimG4CMS/Calo/src/HFCherenkov.cc

Go to the documentation of this file.
00001 
00002 // File:  HFCherenkov.cc
00003 // Description: Generate Cherenkov photons for HF
00005 
00006 #include "SimG4CMS/Calo/interface/HFCherenkov.h"
00007 
00008 #include "G4Poisson.hh"
00009 #include "G4ParticleDefinition.hh"
00010 #include "G4NavigationHistory.hh"
00011 #include "TMath.h"
00012 
00013 //#define DebugLog
00014 
00015 HFCherenkov::HFCherenkov(edm::ParameterSet const & m_HF) {
00016 
00017   ref_index       = m_HF.getParameter<double>("RefIndex");
00018   lambda1         = ((m_HF.getParameter<double>("Lambda1"))/pow(double(10),7))*cm;
00019   lambda2         = ((m_HF.getParameter<double>("Lambda2"))/pow(double(10),7))*cm;
00020   aperture        = cos(asin(m_HF.getParameter<double>("Aperture")));
00021   apertureTrap    = cos(asin(m_HF.getParameter<double>("ApertureTrapped")));
00022   aperturetrapped = m_HF.getParameter<double>("CosApertureTrapped");
00023   gain            = m_HF.getParameter<double>("Gain");
00024   checkSurvive    = m_HF.getParameter<bool>("CheckSurvive");
00025   UseNewPMT       = m_HF.getParameter<bool>("UseR7600UPMT");
00026   sinPsimax       = m_HF.getUntrackedParameter<double>("SinPsiMax",0.5);
00027   fibreR          = m_HF.getUntrackedParameter<double>("FibreR",0.3)*mm;
00028 
00029   edm::LogInfo("HFShower") << "HFCherenkov:: initialised with ref_index " 
00030                            << ref_index << " lambda1/lambda2 (cm) " 
00031                            << lambda1/cm << "|" << lambda2/cm
00032                            << " aperture(total/trapped) " << aperture << "|"
00033                            << apertureTrap << "|" << aperturetrapped
00034                            << " Check photon survival in HF " << checkSurvive 
00035                            << " Gain " << gain << " useNewPMT " << UseNewPMT
00036                            << " FibreR " << fibreR;
00037 
00038   clearVectors();
00039 }
00040 
00041 HFCherenkov::~HFCherenkov() {}
00042 
00043 int HFCherenkov::computeNPhTrapped(double pBeta, 
00044                                    double u, double v, double w, 
00045                                    double step_length, double zFiber,
00046                                    double dose, int npe_Dose) {
00047 
00048   if (pBeta < (1/ref_index) || step_length < 0.0001) {return 0;}
00049 
00050   double uv = sqrt(u*u + v*v);
00051   int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
00052 
00053   if (nbOfPhotons < 0) {
00054     return 0;
00055   } else if (nbOfPhotons > 0) {
00056     double w_ph=0;
00057     for (int i = 0; i < nbOfPhotons; i++) {
00058       double rand     = G4UniformRand();
00059       double theta_C  = acos(1./(pBeta*ref_index));
00060       double phi_C    = 2*M_PI*rand;
00061       double sinTheta = sin(theta_C);
00062       double cosTheta = cos(theta_C);
00063       double cosPhi   = cos(phi_C);
00064       //photon momentum
00065       if (uv < 0.001) { // aligned with z-axis
00066         w_ph = cosTheta;
00067       } else { // general case
00068         w_ph = w * cosTheta  - sinTheta * cosPhi * uv;
00069       }
00070       if (w_ph > apertureTrap) { // phton trapped inside fiber
00071         npe_Dose += 1; 
00072       }
00073     }
00074   }
00075   int n_photons = npe_Dose;
00076   return n_photons;
00077 }
00078 
00079 int HFCherenkov::computeNPE(G4Step * aStep, G4ParticleDefinition* pDef,
00080                             double pBeta, double u, double v, double w,
00081                             double step_length, double zFiber,
00082                             double dose, int npe_Dose) {
00083 
00084   clearVectors();
00085   if (!isApplicable(pDef)) {return 0;}
00086   if (pBeta < (1/ref_index) || step_length < 0.0001) {
00087 #ifdef DebugLog
00088     LogDebug("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta 
00089                          << " 1/mu " << (1/ref_index) << " step_length " 
00090                          << step_length;
00091 #endif
00092     return 0;
00093   }
00094    
00095   double uv = sqrt(u*u + v*v);
00096   int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
00097 #ifdef DebugLog
00098   LogDebug("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta 
00099                        << " u/v/w " << u << "/" << v << "/" << w 
00100                        << " step_length " << step_length << " zFib " << zFiber 
00101                        << " nbOfPhotons " << nbOfPhotons;
00102 #endif
00103   if (nbOfPhotons < 0) {
00104     return 0;
00105   } else if (nbOfPhotons > 0) {
00106     G4StepPoint * preStepPoint = aStep->GetPreStepPoint();
00107     G4TouchableHandle theTouchable = preStepPoint->GetTouchableHandle();
00108     G4ThreeVector localprepos = theTouchable->GetHistory()->
00109       GetTopTransform().TransformPoint(aStep->GetPreStepPoint()->GetPosition());
00110     G4ThreeVector localpostpos = theTouchable->GetHistory()->
00111       GetTopTransform().TransformPoint(aStep->GetPostStepPoint()->GetPosition());
00112   
00113     double length=sqrt((localpostpos.x()-localprepos.x())*(localpostpos.x()-localprepos.x())
00114                        +(localpostpos.y()-localprepos.y())*(localpostpos.y()-localprepos.y()));
00115     double yemit = std::sqrt(fibreR*fibreR-length*length/4.);
00116 
00117     double u_ph=0,v_ph=0, w_ph=0;
00118     for (int i = 0; i < nbOfPhotons; i++) {
00119       double rand     = G4UniformRand();
00120       double theta_C  = acos(1./(pBeta*ref_index));
00121       double phi_C    = 2*M_PI*rand;
00122       double sinTheta = sin(theta_C);
00123       double cosTheta = cos(theta_C);
00124       double cosPhi   = cos(phi_C);
00125       double sinPhi   = sin(phi_C);
00126       //photon momentum
00127       if (uv < 0.001) { // aligned with z-axis
00128         u_ph = sinTheta * cosPhi ;
00129         v_ph = sinTheta * sinPhi;
00130         w_ph = cosTheta;
00131       } else { // general case
00132         u_ph = uv * cosTheta + sinTheta * cosPhi * w;
00133         v_ph = sinTheta * sinPhi;
00134         w_ph =  w * cosTheta - sinTheta * cosPhi * uv;
00135       }
00136       double r_lambda = G4UniformRand();
00137       double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda *
00138                                               (lambda2 - lambda1));
00139       double lambda  = (lambda0/cm) * pow(double(10),7); // lambda is in nm
00140       wlini.push_back(lambda);
00141 #ifdef DebugLog
00142       LogDebug("HFShower") << "HFCherenkov::computeNPE: " << i << " lambda "
00143                            << lambda << " w_ph " << w_ph << " aperture "
00144                            << aperture;
00145 #endif
00146 // --------------
00147       double xemit=length*(G4UniformRand()-0.5);
00148       double gam=atan2(yemit,xemit);
00149       double eps=atan2(v_ph,u_ph);
00150       double sinBeta=sin(gam-eps);
00151       double rho=sqrt(xemit*xemit+yemit*yemit);
00152       double sinEta=rho/fibreR*sinBeta;
00153       double cosEta=sqrt(1.-sinEta*sinEta);
00154       double sinPsi=sqrt(1.-w_ph*w_ph);
00155       double cosKsi=cosEta*sinPsi;
00156 #ifdef DebugLog
00157       if (cosKsi < aperturetrapped && w_ph>0.) {
00158         LogDebug("HFShower") << "HFCherenkov::Trapped photon : " << u_ph << " "
00159                              << v_ph << " " << w_ph << " " << xemit << " "
00160                              << gam << " " << eps << " " << sinBeta << " "
00161                              << rho << " " << sinEta << " " << cosEta << " "
00162                              << " " << sinPsi << " " << cosKsi;
00163       } else {
00164         LogDebug("HFShower") << "HFCherenkov::Rejected photon : " << u_ph <<" "
00165                              << v_ph << " " << w_ph << " " << xemit << " "
00166                              << gam << " " << eps << " " << sinBeta << " "
00167                              << rho << " " << sinEta << " " << cosEta << " "
00168                              << " " << sinPsi << " " << cosKsi;
00169       }
00170 #endif
00171       if (cosKsi < aperturetrapped // photon trapped inside fiber
00172           && w_ph>0.               // and moves to PMT
00173           && sinPsi < sinPsimax) { // and is not reflected at fiber end
00174         wltrap.push_back(lambda);
00175         double prob_HF  = 1.0; //photon survived in HF
00176         double a0_inv   = 0.1234;  //meter^-1
00177         double prob_MX  = exp( - 0.5 * a0_inv ); //light mixer
00178         if (checkSurvive) {
00179           double a_inv = a0_inv + 0.14 * pow(dose,0.30);
00180           double z_meters = zFiber;
00181           prob_HF  = exp(-z_meters * a_inv ); //photon survived in HF
00182         }
00183         rand = G4UniformRand();
00184 #ifdef DebugLog
00185         LogDebug("HFShower") << "HFCherenkov::computeNPE: probHF " << prob_HF
00186                              << " prob_MX " << prob_MX << " Random " << rand 
00187                              << " Survive? " << (rand < (prob_HF * prob_MX));
00188 #endif
00189         if (rand < (prob_HF * prob_MX)) { // survived and sent to light mixer
00190           wlatten.push_back(lambda);
00191           rand = G4UniformRand();
00192           double effHEM = computeHEMEff(lambda);
00193 #ifdef DebugLog
00194           LogDebug("HFShower") << "HFCherenkov::computeNPE: w_ph " << w_ph 
00195                                << " effHEM " << effHEM << " Random " << rand 
00196                                << " Survive? " << (w_ph>0.997||(rand<effHEM));
00197 #endif
00198           if (w_ph>0.997 || (rand<effHEM)) { // survived HEM
00199             wlhem.push_back(lambda);
00200             double qEffic = computeQEff(lambda);
00201             rand = G4UniformRand();
00202 #ifdef DebugLog
00203             LogDebug("HFShower") << "HFCherenkov::computeNPE: qEffic "
00204                                  << qEffic << " Random " << rand
00205                                  << " Survive? " <<(rand < qEffic);
00206 #endif
00207             if (rand < qEffic) { // made photoelectron
00208               npe_Dose += 1;
00209               momZ.push_back(w_ph);
00210               wl.push_back(lambda);
00211               wlqeff.push_back(lambda);
00212             } // made pe
00213           } // passed HEM
00214         } // passed fiber
00215       } // end of  if(w_ph < w_aperture), trapped inside fiber
00216     }// end of ++NbOfPhotons
00217   } // end of if(NbOfPhotons)}
00218   int npe =  npe_Dose; // Nb of photoelectrons
00219 #ifdef DebugLog
00220   LogDebug("HFShower") << "HFCherenkov::computeNPE: npe " << npe;
00221 #endif
00222   return npe;
00223 }
00224 
00225 int HFCherenkov::computeNPEinPMT(G4ParticleDefinition* pDef, double pBeta, 
00226                                  double u, double v, double w, 
00227                                  double step_length){
00228   clearVectors();
00229   int npe_ = 0;
00230   if (!isApplicable(pDef)) {return 0;}
00231   if (pBeta < (1/ref_index) || step_length < 0.0001) {
00232 #ifdef DebugLog
00233     LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta 
00234                          << " 1/mu " << (1/ref_index) << " step_length " 
00235                          << step_length;
00236 #endif
00237     return 0;
00238   }
00239    
00240   double uv = sqrt(u*u + v*v);
00241   int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
00242 #ifdef DebugLog
00243   LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta 
00244                        << " u/v/w " << u << "/" << v << "/" << w 
00245                        << " step_length " << step_length  
00246                        << " nbOfPhotons " << nbOfPhotons;
00247 #endif   
00248   if (nbOfPhotons < 0) {
00249     return 0;
00250   } else if (nbOfPhotons > 0) {
00251     double w_ph=0;
00252     for (int i = 0; i < nbOfPhotons; i++) {
00253       double rand     = G4UniformRand();
00254       double theta_C  = acos(1./(pBeta*ref_index));
00255       double phi_C    = 2*M_PI*rand;
00256       double sinTheta = sin(theta_C);
00257       double cosTheta = cos(theta_C);
00258       double cosPhi   = cos(phi_C); 
00259       //photon momentum
00260       if (uv < 0.001) { // aligned with z-axis
00261         w_ph = cosTheta;
00262       } else { // general case
00263         w_ph = w * cosTheta - sinTheta * cosPhi * uv;
00264       }
00265       double r_lambda = G4UniformRand();
00266       double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda *
00267                                               (lambda2 - lambda1));
00268       double lambda  = (lambda0/cm) * pow(double(10),7); // lambda is in nm
00269       wlini.push_back(lambda);
00270 #ifdef DebugLog
00271       LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: " <<i <<" lambda "
00272                            << lambda << " w_ph " << w_ph << " aperture " 
00273                            << aperture;
00274 #endif
00275       if (w_ph > aperture) { // phton trapped inside PMT glass
00276         wltrap.push_back(lambda);
00277         rand = G4UniformRand();
00278 #ifdef DebugLog
00279         LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: Random " << rand
00280                              << " Survive? " << (rand < 1.);
00281 #endif
00282         if (rand < 1.0) { // survived all the times and sent to photo-cathode
00283           wlatten.push_back(lambda);
00284           rand = G4UniformRand();
00285           double qEffic = computeQEff(lambda);//Quantum efficiency of the PMT
00286           rand = G4UniformRand();
00287 #ifdef DebugLog
00288           LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: qEffic " 
00289                                << qEffic << " Random " << rand 
00290                                << " Survive? " <<(rand < qEffic);
00291 #endif
00292           if (rand < qEffic) { // made photoelectron
00293             npe_ += 1;
00294             momZ.push_back(w_ph);
00295             wl.push_back(lambda);
00296             wlqeff.push_back(lambda);
00297           } // made pe
00298         } // accepted all Cherenkov photons
00299       } // end of  if(w_ph < w_aperture), trapped inside glass
00300     }// end of ++NbOfPhotons
00301   } // end of if(NbOfPhotons)}
00302 #ifdef DebugLog
00303   LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: npe " << npe_;
00304 #endif
00305   return npe_;
00306 }
00307 
00308 std::vector<double>  HFCherenkov::getWLIni() {
00309   std::vector<double> v = wlini;
00310   return v;
00311 }
00312 
00313 std::vector<double>  HFCherenkov::getWLTrap() {
00314   std::vector<double> v = wltrap;
00315   return v;
00316 }
00317 
00318 std::vector<double>  HFCherenkov::getWLAtten() {
00319   std::vector<double> v = wlatten;
00320   return v;
00321 }
00322 
00323 std::vector<double>  HFCherenkov::getWLHEM() {
00324   std::vector<double> v  = wlhem;
00325   return v;
00326 }
00327 
00328 std::vector<double>  HFCherenkov::getWLQEff() {
00329   std::vector<double> v = wlqeff;
00330   return v;
00331 }
00332 
00333 std::vector<double>  HFCherenkov::getWL() {
00334   std::vector<double> v = wl;
00335   return v;
00336 }
00337 
00338 std::vector<double>  HFCherenkov::getMom() {
00339   std::vector<double> v = momZ;
00340   return v;
00341 }
00342 
00343 int HFCherenkov::computeNbOfPhotons(double beta, G4double stepL) {
00344 
00345   double pBeta = beta;
00346   double alpha = 0.0073;
00347   double step_length = stepL;
00348   double theta_C = acos(1./(pBeta*ref_index));
00349   double lambdaDiff = (1./lambda1 - 1./lambda2);
00350   double cherenPhPerLength = 2 * M_PI * alpha * lambdaDiff*cm;
00351   double d_NOfPhotons = cherenPhPerLength * sin(theta_C)*sin(theta_C) *  (step_length/cm);
00352   int nbOfPhotons = int(d_NOfPhotons);
00353 #ifdef DebugLog
00354   LogDebug("HFShower") << "HFCherenkov::computeNbOfPhotons: StepLength " 
00355                        << step_length << " theta_C " << theta_C 
00356                        << " lambdaDiff " << lambdaDiff
00357                        << " cherenPhPerLength " << cherenPhPerLength 
00358                        << " Photons " << d_NOfPhotons << " " << nbOfPhotons;
00359 #endif
00360   return nbOfPhotons;
00361 }
00362 
00363 double HFCherenkov::computeQEff(double wavelength) {
00364 
00365   double qeff(0.);
00366   if (UseNewPMT) {
00367     if (wavelength<=350) {
00368       qeff=2.45867*(TMath::Landau(wavelength,353.820,59.1324));
00369     } else if (wavelength>350 && wavelength<500) {
00370       qeff= 0.441989*exp(-pow((wavelength-358.371),2)/(2*pow((138.277),2)));
00371     } else if (wavelength>=500 && wavelength<550) {
00372       qeff= 0.271862*exp(-pow((wavelength-491.505),2)/(2*pow((47.0418),2)));
00373     } else if (wavelength>=550) {
00374       qeff= 0.137297*exp(-pow((wavelength-520.260),2)/(2*pow((75.5023),2)));
00375     }
00376 #ifdef DebugLog
00377     LogDebug("HFShower") << "HFCherenkov:: for new PMT : wavelength === "
00378                          << wavelength << "\tqeff  ===\t" << qeff;
00379 #endif
00380   } else {
00381     double y        = (wavelength - 275.) /180.;
00382     double func     = 1. / (1. + 250.*pow((y/5.),4));
00383     double qE_R7525 = 0.77 * y * exp(-y) * func ;
00384     qeff            = qE_R7525;
00385 #ifdef DebugLog
00386     LogDebug("HFShower") << "HFCherenkov:: for old PMT : wavelength === "
00387                          << wavelength << "; qeff = " << qeff;
00388 #endif
00389   }
00390 
00391 #ifdef DebugLog
00392   LogDebug("HFShower") << "HFCherenkov::computeQEff: wavelength " << wavelength
00393                        << " y/func " << y << "/" << func << " qeff " << qeff;
00394 #endif
00395   return qeff;
00396 }
00397 
00398 double HFCherenkov::computeHEMEff(double wavelength) {
00399 
00400   double hEMEff = 0;
00401   if (wavelength < 400.) {
00402     hEMEff = 0.;
00403   } else if (wavelength >= 400. && wavelength < 410.) {
00404     //hEMEff = .99 * (wavelength - 400.) / 10.;
00405     hEMEff = (-1322.453 / wavelength) + 4.2056;
00406   } else if (wavelength >= 410.) {
00407     hEMEff = 0.99;
00408     if (wavelength > 415. && wavelength < 445.) {
00409       //abs(wavelength - 430.) < 15.
00410       //hEMEff = 0.95;
00411       hEMEff = 0.97;
00412     } else if (wavelength > 550. && wavelength < 600.) {
00413       // abs(wavelength - 575.) < 25.)
00414       //hEMEff = 0.96;
00415       hEMEff = 0.98;
00416     } else if (wavelength > 565. && wavelength <= 635.) { // added later
00417       // abs(wavelength - 600.) < 35.)
00418       hEMEff = (701.7268 / wavelength) - 0.186;
00419     }
00420   }
00421 #ifdef DebugLog
00422   LogDebug("HFShower") << "HFCherenkov::computeHEMEff: wavelength "
00423                        << wavelength << " hEMEff " << hEMEff;
00424 #endif
00425   return hEMEff;
00426 }
00427 
00428 double HFCherenkov::smearNPE(int npe) {
00429 
00430   double pe = 0.;
00431   if (npe > 0) {
00432     for (int i = 0; i < npe; ++i) {
00433       double val =  G4Poisson(gain);
00434       pe += (val/gain) + 0.001*G4UniformRand();
00435     }
00436   }
00437 #ifdef DebugLog
00438   LogDebug("HFShower") << "HFCherenkov::smearNPE: npe " << npe << " pe " << pe;
00439 #endif
00440   return pe;
00441 }
00442 
00443 void HFCherenkov::clearVectors() {
00444 
00445   wl.clear();
00446   wlini.clear();
00447   wltrap.clear();
00448   wlatten.clear();
00449   wlhem.clear();
00450   wlqeff.clear();
00451   momZ.clear();
00452 }
00453 
00454 bool HFCherenkov::isApplicable(const G4ParticleDefinition* aParticleType) {
00455   bool tmp = (aParticleType->GetPDGCharge() != 0);
00456 #ifdef DebugLog
00457   LogDebug("HFShower") << "HFCherenkov::isApplicable: aParticleType " 
00458                        << aParticleType->GetParticleName() << " PDGCharge " 
00459                        << aParticleType->GetPDGCharge() << " Result " << tmp;
00460 #endif
00461   return tmp;
00462 }