CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/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 
00011 //#define DebugLog
00012 
00013 HFCherenkov::HFCherenkov(edm::ParameterSet const & m_HF) {
00014 
00015   //Simple configurables
00016   //static SimpleConfigurable<double> p1(1.459, "HFCherenkov:RefIndex");
00017   //static SimpleConfigurable<double> p2(280.0, "HFCherenkov:Lambda1");
00018   //static SimpleConfigurable<double> p3(700.0, "HFCherenkov:Lambda2");
00019   //static SimpleConfigurable<double> p4(0.33,  "HFCherenkov:Aperture");
00020   //static SimpleConfigurable<double> p5(0.22,  "HFCherenkov:ApertureTrapped");
00021   //static SimpleConfigurable<double> p6(0.33,  "HFCherenkov:Gain");
00022   //static SimpleConfigurable<bool>   p7(false, "HFCherenkov:CheckSurvive");
00023 
00024   ref_index    = m_HF.getParameter<double>("RefIndex");
00025   lambda1      = ((m_HF.getParameter<double>("Lambda1"))/pow(double(10),7))*cm;
00026   lambda2      = ((m_HF.getParameter<double>("Lambda2"))/pow(double(10),7))*cm;
00027   aperture     = cos(asin(m_HF.getParameter<double>("Aperture")));
00028   apertureTrap = cos(asin(m_HF.getParameter<double>("ApertureTrapped")));
00029   gain         = m_HF.getParameter<double>("Gain");
00030   checkSurvive = m_HF.getParameter<bool>("CheckSurvive");
00031 
00032   edm::LogInfo("HFShower") << "HFCherenkov:: initialised with ref_index " 
00033                            << ref_index << " lambda1/lambda2 (cm) " 
00034                            << lambda1/cm << "/" << lambda2/cm
00035                            << " aperture(total/trapped) " << aperture << "/"
00036                            << apertureTrap << " Check photon survival in HF " 
00037                            << checkSurvive << " Gain " << gain;
00038 
00039   clearVectors();
00040 }
00041 
00042 HFCherenkov::~HFCherenkov() {}
00043 
00044 int HFCherenkov::computeNPhTrapped(double pBeta, 
00045                                    double u, double v, double w, 
00046                                    double step_length, double zFiber,
00047                                    double dose, int npe_Dose) {
00048 
00049   if (pBeta < (1/ref_index) || step_length < 0.0001) {return 0;}
00050 
00051   double uv = sqrt(u*u + v*v);
00052   int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
00053 
00054   if (nbOfPhotons < 0) {
00055     return 0;
00056   } else if (nbOfPhotons > 0) {
00057     double u_ph, v_ph, w_ph=0;
00058     for (int i = 0; i < nbOfPhotons; i++) {
00059       double rand     = G4UniformRand();
00060       double theta_C  = acos(1./(pBeta*ref_index));
00061       double phi_C    = 2*M_PI*rand;
00062       double sinTheta = sin(theta_C);
00063       double cosTheta = cos(theta_C);
00064       double sinPhi   = sin(phi_C);
00065       double cosPhi   = cos(phi_C);
00066       //photon momentum
00067       if (uv < 0.001) { // aligned with z-axis
00068         u_ph = sinTheta * cosPhi;
00069         v_ph = sinTheta * sinPhi;
00070         w_ph = cosTheta;
00071       } else { // general case
00072         u_ph = u * cosTheta  + sinTheta * (v*sinPhi + u*w*cosPhi)/ uv;
00073         v_ph = v * cosTheta  + sinTheta * (-u*sinPhi + v*w*cosPhi)/ uv;
00074         w_ph = w * cosTheta  - sinTheta * cosPhi * uv;
00075       }
00076       if (w_ph > apertureTrap) { // phton trapped inside fiber
00077         npe_Dose += 1; 
00078       }
00079     }
00080   }
00081   int n_photons = npe_Dose;
00082   return n_photons;
00083 }
00084 
00085 int HFCherenkov::computeNPE(G4ParticleDefinition* pDef, double pBeta,
00086                             double u, double v, double w,
00087                             double step_length, double zFiber,
00088                             double dose, int npe_Dose) {
00089 
00090   clearVectors();
00091   if (!isApplicable(pDef)) {return 0;}
00092   if (pBeta < (1/ref_index) || step_length < 0.0001) {
00093 #ifdef DebugLog
00094     LogDebug("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta 
00095                          << " 1/mu " << (1/ref_index) << " step_length " 
00096                          << step_length;
00097 #endif
00098     return 0;
00099   }
00100    
00101   double uv = sqrt(u*u + v*v);
00102   int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
00103 #ifdef DebugLog
00104   LogDebug("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta 
00105                        << " u/v/w " << u << "/" << v << "/" << w 
00106                        << " step_length " << step_length << " zFib " << zFiber 
00107                        << " nbOfPhotons " << nbOfPhotons;
00108 #endif
00109   if (nbOfPhotons < 0) {
00110     return 0;
00111   } else if (nbOfPhotons > 0) {
00112     double u_ph, v_ph, w_ph=0;
00113     for (int i = 0; i < nbOfPhotons; i++) {
00114       double rand     = G4UniformRand();
00115       double theta_C  = acos(1./(pBeta*ref_index));
00116       double phi_C    = 2*M_PI*rand;
00117       double sinTheta = sin(theta_C);
00118       double cosTheta = cos(theta_C);
00119       double sinPhi   = sin(phi_C);
00120       double cosPhi   = cos(phi_C);
00121       //photon momentum
00122       if (uv < 0.001) { // aligned with z-axis
00123         u_ph = sinTheta * cosPhi;
00124         v_ph = sinTheta * sinPhi;
00125         w_ph = cosTheta;
00126       } else { // general case
00127         u_ph = u * cosTheta  + sinTheta * (v*sinPhi + u*w*cosPhi)/ uv;
00128         v_ph = v * cosTheta  + sinTheta * (-u*sinPhi + v*w*cosPhi)/ uv;
00129         w_ph = w * cosTheta - sinTheta * cosPhi * uv;
00130       }
00131       double r_lambda = G4UniformRand();
00132       double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda *
00133                                               (lambda2 - lambda1));
00134       double lambda  = (lambda0/cm) * pow(double(10),7); // lambda is in nm
00135       wlini.push_back(lambda);
00136 #ifdef DebugLog
00137       LogDebug("HFShower") << "HFCherenkov::computeNPE: " << i << " lambda "
00138                            << lambda << " w_ph " << w_ph << " aperture "
00139                            << aperture;
00140 #endif
00141       if (w_ph > aperture) { // phton trapped inside fiber
00142         wltrap.push_back(lambda);
00143         double prob_HF  = 1.0; //photon survived in HF
00144         double a0_inv   = 0.1234;  //meter^-1
00145         double prob_MX  = exp( - 0.5 * a0_inv ); //light mixer
00146         if (checkSurvive) {
00147           double a_inv = a0_inv + 0.14 * pow(dose,0.30);
00148           double z_meters = zFiber;
00149           prob_HF  = exp(-z_meters * a_inv ); //photon survived in HF
00150         }
00151         rand = G4UniformRand();
00152 #ifdef DebugLog
00153         LogDebug("HFShower") << "HFCherenkov::computeNPE: probHF " << prob_HF
00154                              << " prob_MX " << prob_MX << " Random " << rand 
00155                              << " Survive? " << (rand < (prob_HF * prob_MX));
00156 #endif
00157         if (rand < (prob_HF * prob_MX)) { // survived and sent to light mixer
00158           wlatten.push_back(lambda);
00159           rand = G4UniformRand();
00160           double effHEM = computeHEMEff(lambda);
00161 #ifdef DebugLog
00162           LogDebug("HFShower") << "HFCherenkov::computeNPE: w_ph " << w_ph 
00163                                << " effHEM " << effHEM << " Random " << rand 
00164                                << " Survive? " << (w_ph>0.997||(rand<effHEM));
00165 #endif
00166           if (w_ph>0.997 || (rand<effHEM)) { // survived HEM
00167             wlhem.push_back(lambda);
00168             double qEffic = computeQEff(lambda);
00169             rand = G4UniformRand();
00170 #ifdef DebugLog
00171             LogDebug("HFShower") << "HFCherenkov::computeNPE: qEffic "
00172                                  << qEffic << " Random " << rand
00173                                  << " Survive? " <<(rand < qEffic);
00174 #endif
00175             if (rand < qEffic) { // made photoelectron
00176               npe_Dose += 1;
00177               momZ.push_back(w_ph);
00178               wl.push_back(lambda);
00179               wlqeff.push_back(lambda);
00180             } // made pe
00181           } // passed HEM
00182         } // passed fiber
00183       } // end of  if(w_ph < w_aperture), trapped inside fiber
00184     }// end of ++NbOfPhotons
00185   } // end of if(NbOfPhotons)}
00186   int npe =  npe_Dose; // Nb of photoelectrons
00187 #ifdef DebugLog
00188   LogDebug("HFShower") << "HFCherenkov::computeNPE: npe " << npe;
00189 #endif
00190   return npe;
00191 }
00192 
00193 int HFCherenkov::computeNPEinPMT(G4ParticleDefinition* pDef, double pBeta, 
00194                                  double u, double v, double w, 
00195                                  double step_length){
00196   clearVectors();
00197   int npe_ = 0;
00198   if (!isApplicable(pDef)) {return 0;}
00199   if (pBeta < (1/ref_index) || step_length < 0.0001) {
00200 #ifdef DebugLog
00201     LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta 
00202                          << " 1/mu " << (1/ref_index) << " step_length " 
00203                          << step_length;
00204 #endif
00205     return 0;
00206   }
00207    
00208   double uv = sqrt(u*u + v*v);
00209   int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
00210 #ifdef DebugLog
00211   LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta 
00212                        << " u/v/w " << u << "/" << v << "/" << w 
00213                        << " step_length " << step_length  
00214                        << " nbOfPhotons " << nbOfPhotons;
00215 #endif   
00216   if (nbOfPhotons < 0) {
00217     return 0;
00218   } else if (nbOfPhotons > 0) {
00219     double u_ph, v_ph, w_ph=0;
00220     for (int i = 0; i < nbOfPhotons; i++) {
00221       double rand     = G4UniformRand();
00222       double theta_C  = acos(1./(pBeta*ref_index));
00223       double phi_C    = 2*M_PI*rand;
00224       double sinTheta = sin(theta_C);
00225       double cosTheta = cos(theta_C);
00226       double sinPhi   = sin(phi_C);
00227       double cosPhi   = cos(phi_C); 
00228       //photon momentum
00229       if (uv < 0.001) { // aligned with z-axis
00230         u_ph = sinTheta * cosPhi;
00231         v_ph = sinTheta * sinPhi;
00232         w_ph = cosTheta;
00233       } else { // general case
00234         u_ph = u * cosTheta  + sinTheta * (v*sinPhi + u*w*cosPhi)/ uv;
00235         v_ph = v * cosTheta  + sinTheta * (-u*sinPhi + v*w*cosPhi)/ uv;
00236         w_ph = w * cosTheta - sinTheta * cosPhi * uv;
00237       }
00238       double r_lambda = G4UniformRand();
00239       double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda *
00240                                               (lambda2 - lambda1));
00241       double lambda  = (lambda0/cm) * pow(double(10),7); // lambda is in nm
00242       wlini.push_back(lambda);
00243 #ifdef DebugLog
00244       LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: " <<i <<" lambda "
00245                            << lambda << " w_ph " << w_ph << " aperture " 
00246                            << aperture;
00247 #endif
00248       if (w_ph > aperture) { // phton trapped inside PMT glass
00249         wltrap.push_back(lambda);
00250         rand = G4UniformRand();
00251 #ifdef DebugLog
00252         LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: Random " << rand
00253                              << " Survive? " << (rand < 1.);
00254 #endif
00255         if (rand < 1.0) { // survived all the times and sent to photo-cathode
00256           wlatten.push_back(lambda);
00257           rand = G4UniformRand();
00258           double qEffic = computeQEff(lambda);//Quantum efficiency of the PMT
00259           rand = G4UniformRand();
00260 #ifdef DebugLog
00261           LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: qEffic " 
00262                                << qEffic << " Random " << rand 
00263                                << " Survive? " <<(rand < qEffic);
00264 #endif
00265           if (rand < qEffic) { // made photoelectron
00266             npe_ += 1;
00267             momZ.push_back(w_ph);
00268             wl.push_back(lambda);
00269             wlqeff.push_back(lambda);
00270           } // made pe
00271         } // accepted all Cherenkov photons
00272       } // end of  if(w_ph < w_aperture), trapped inside glass
00273     }// end of ++NbOfPhotons
00274   } // end of if(NbOfPhotons)}
00275 #ifdef DebugLog
00276   LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: npe " << npe_;
00277 #endif
00278   return npe_;
00279 }
00280 
00281 std::vector<double>  HFCherenkov::getWLIni() {
00282   std::vector<double> v = wlini;
00283   return v;
00284 }
00285 
00286 std::vector<double>  HFCherenkov::getWLTrap() {
00287   std::vector<double> v = wltrap;
00288   return v;
00289 }
00290 
00291 std::vector<double>  HFCherenkov::getWLAtten() {
00292   std::vector<double> v = wlatten;
00293   return v;
00294 }
00295 
00296 std::vector<double>  HFCherenkov::getWLHEM() {
00297   std::vector<double> v  = wlhem;
00298   return v;
00299 }
00300 
00301 std::vector<double>  HFCherenkov::getWLQEff() {
00302   std::vector<double> v = wlqeff;
00303   return v;
00304 }
00305 
00306 std::vector<double>  HFCherenkov::getWL() {
00307   std::vector<double> v = wl;
00308   return v;
00309 }
00310 
00311 std::vector<double>  HFCherenkov::getMom() {
00312   std::vector<double> v = momZ;
00313   return v;
00314 }
00315 
00316 int HFCherenkov::computeNbOfPhotons(double beta, G4double stepL) {
00317 
00318   double pBeta = beta;
00319   double alpha = 0.0073;
00320   double step_length = stepL;
00321   double theta_C = acos(1./(pBeta*ref_index));
00322   double lambdaDiff = (1./lambda1 - 1./lambda2);
00323   double cherenPhPerLength = 2 * M_PI * alpha * lambdaDiff*cm;
00324   double d_NOfPhotons = cherenPhPerLength * sin(theta_C)*sin(theta_C) *  (step_length/cm);
00325   int nbOfPhotons = int(d_NOfPhotons);
00326 #ifdef DebugLog
00327   LogDebug("HFShower") << "HFCherenkov::computeNbOfPhotons: StepLength " 
00328                        << step_length << " theta_C " << theta_C 
00329                        << " lambdaDiff " << lambdaDiff
00330                        << " cherenPhPerLength " << cherenPhPerLength 
00331                        << " Photons " << d_NOfPhotons << " " << nbOfPhotons;
00332 #endif
00333   return nbOfPhotons;
00334 }
00335 
00336 double HFCherenkov::computeQEff(double wavelength) {
00337 
00338   double y        = (wavelength - 275.) /180.;
00339   double func     = 1. / (1. + 250.*pow((y/5.),4));
00340   double qE_R7525 = 0.77 * y * exp(-y) * func ;
00341   double qeff     = qE_R7525;
00342 #ifdef DebugLog
00343   LogDebug("HFShower") << "HFCherenkov::computeQEff: wavelength " << wavelength
00344                        << " y/func " << y << "/" << func << " qeff " << qeff;
00345 #endif
00346   return qeff;
00347 }
00348 
00349 double HFCherenkov::computeHEMEff(double wavelength) {
00350 
00351   double hEMEff = 0;
00352   if (wavelength < 400.) {
00353     hEMEff = 0.;
00354   } else if (wavelength >= 400. && wavelength < 410.) {
00355     //hEMEff = .99 * (wavelength - 400.) / 10.;
00356     hEMEff = (-1322.453 / wavelength) + 4.2056;
00357   } else if (wavelength >= 410.) {
00358     hEMEff = 0.99;
00359     if (wavelength > 415. && wavelength < 445.) {
00360       //abs(wavelength - 430.) < 15.
00361       //hEMEff = 0.95;
00362       hEMEff = 0.97;
00363     } else if (wavelength > 550. && wavelength < 600.) {
00364       // abs(wavelength - 575.) < 25.)
00365       //hEMEff = 0.96;
00366       hEMEff = 0.98;
00367     } else if (wavelength > 565. && wavelength <= 635.) { // added later
00368       // abs(wavelength - 600.) < 35.)
00369       hEMEff = (701.7268 / wavelength) - 0.186;
00370     }
00371   }
00372 #ifdef DebugLog
00373   LogDebug("HFShower") << "HFCherenkov::computeHEMEff: wavelength "
00374                        << wavelength << " hEMEff " << hEMEff;
00375 #endif
00376   return hEMEff;
00377 }
00378 
00379 double HFCherenkov::smearNPE(int npe) {
00380 
00381   double pe = 0.;
00382   if (npe > 0) {
00383     for (int i = 0; i < npe; ++i) {
00384       double val =  G4Poisson(gain);
00385       pe += (val/gain) + 0.001*G4UniformRand();
00386     }
00387   }
00388 #ifdef DebugLog
00389   LogDebug("HFShower") << "HFCherenkov::smearNPE: npe " << npe << " pe " << pe;
00390 #endif
00391   return pe;
00392 }
00393 
00394 void HFCherenkov::clearVectors() {
00395 
00396   wl.clear();
00397   wlini.clear();
00398   wltrap.clear();
00399   wlatten.clear();
00400   wlhem.clear();
00401   wlqeff.clear();
00402   momZ.clear();
00403 }
00404 
00405 bool HFCherenkov::isApplicable(const G4ParticleDefinition* aParticleType) {
00406   bool tmp = (aParticleType->GetPDGCharge() != 0);
00407 #ifdef DebugLog
00408   LogDebug("HFShower") << "HFCherenkov::isApplicable: aParticleType " 
00409                        << aParticleType->GetParticleName() << " PDGCharge " 
00410                        << aParticleType->GetPDGCharge() << " Result " << tmp;
00411 #endif
00412   return tmp;
00413 }