CMS 3D CMS Logo

GflashHadronShowerProfile.cc

Go to the documentation of this file.
00001 #include "SimG4Core/GFlash/interface/GflashHadronShowerProfile.h"
00002 #include "SimG4Core/GFlash/interface/GflashEnergySpot.h"
00003 #include "SimG4Core/GFlash/interface/GflashHistogram.h"
00004 
00005 #include "FWCore/ServiceRegistry/interface/Service.h"
00006 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00007 
00008 #include "CLHEP/GenericFunctions/IncompleteGamma.hh"
00009 #include "CLHEP/GenericFunctions/LogGamma.hh"
00010 #include "Randomize.hh"
00011 
00012 //#include "SimG4Core/GFlash/interface/GflashTrajectory.h"
00013 #include "SimG4Core/GFlash/interface/GflashTrajectoryPoint.h"
00014 
00015 #include <math.h>
00016 
00017 GflashHadronShowerProfile::GflashHadronShowerProfile(G4Region* envelope)
00018 {
00019   showerType   = 0;
00020   jCalorimeter = Gflash::kNULL;
00021   theHelix = new GflashTrajectory;
00022   theHisto = GflashHistogram::instance();
00023 
00024   edm::Service<edm::RandomNumberGenerator> rng;
00025   if ( ! rng.isAvailable()) {
00026     throw cms::Exception("Configuration")
00027       << "GflashHadronShowerProfile requires RandomNumberGeneratorService\n"
00028       << "which is not present in the configuration file. "
00029       << "You must add the service\n in the configuration file or "
00030       << "remove the modules that require it.";
00031   }
00032   theRandGauss = new CLHEP::RandGaussQ(rng->getEngine());
00033   theRandGamma = new CLHEP::RandGamma(rng->getEngine());
00034 
00035   //correllation and fluctuation matrix
00036   fillFluctuationVector();
00037 }
00038 
00039 GflashHadronShowerProfile::~GflashHadronShowerProfile()
00040 {
00041   //  delete theGflashStep;
00042   delete theHelix;
00043   delete theRandGauss;
00044   delete theRandGamma;
00045 }
00046 
00047 Gflash::CalorimeterNumber GflashHadronShowerProfile::getCalorimeterNumber(const G4ThreeVector position)
00048 {
00049   Gflash::CalorimeterNumber index = Gflash::kNULL;
00050   G4double eta = position.getEta();
00051 
00052   //central
00053   if (fabs(eta) < Gflash::EtaMax[Gflash::kESPM] || fabs(eta) < Gflash::EtaMax[Gflash::kHB]) {
00054     if(position.getRho() > Gflash::Rmin[Gflash::kESPM] && 
00055        position.getRho() < Gflash::Rmax[Gflash::kESPM] ) {
00056       index = Gflash::kESPM;
00057     }
00058     if(position.getRho() > Gflash::Rmin[Gflash::kHB] && 
00059        position.getRho() < Gflash::Rmax[Gflash::kHB]) {
00060       index = Gflash::kHB;
00061     }
00062   }
00063   //forward
00064   else if (fabs(eta) > Gflash::EtaMin[Gflash::kENCA] || fabs(eta) > Gflash::EtaMin[Gflash::kHE]) {
00065     if( fabs(position.getZ()) > Gflash::Zmin[Gflash::kENCA] &&  
00066         fabs(position.getZ()) < Gflash::Zmax[Gflash::kENCA] ) {
00067       index = Gflash::kENCA;
00068     }
00069     if( fabs(position.getZ()) > Gflash::Zmin[Gflash::kHE] &&  
00070         fabs(position.getZ()) < Gflash::Zmax[Gflash::kHE] ) {
00071       index = Gflash::kHE;
00072     }
00073   }
00074   return index;
00075 }
00076 
00077 void GflashHadronShowerProfile::hadronicParameterization(const G4FastTrack& fastTrack)
00078 {
00079   // The skeleton of this method is based on the fortran code gfshow.F originally written  
00080   // by S. Peters and G. Grindhammer (also see NIM A290 (1990) 469-488), but longitudinal
00081   // parameterizations of hadron showers are significantly modified for the CMS calorimeter  
00082 
00083   // unit convention: energy in [GeV] and length in [cm]
00084 
00085   // maximum number of energy spots 
00086   const G4int    maxNumberOfSpots = 10000;  
00087 
00088   // low energy cutoff (unit in GeV)
00089   //  const G4double energyCutoff     = 0.01; 
00090 
00091   // intrinsic properties of hadronic showers (lateral shower profile)
00092   const G4double maxShowerDepthforR50 = 10.0;
00093 
00094   G4double rShower = 0.;
00095   G4double rGauss = theRandGauss->fire();
00096 
00097   // The shower starting point is the PostStepPoint of Hadronic Inelestic interaction;
00098   // see GflashHadronShowerModel::ModelTrigger
00099                                                                                                    
00100   G4double einc = fastTrack.GetPrimaryTrack()->GetKineticEnergy()/GeV;
00101   G4ThreeVector positionShower = fastTrack.GetPrimaryTrack()->GetPosition()/cm;
00102   G4ThreeVector momentumShower = fastTrack.GetPrimaryTrack()->GetMomentum()/GeV;
00103 
00104   //find the calorimeter at the shower starting point
00105   jCalorimeter = getCalorimeterNumber(positionShower);
00106 
00107   //get all necessary parameters for hadronic shower profiles including energyToDeposit
00108   loadParameters(fastTrack);
00109 
00110   // The direction of shower is assumed to be along the showino trajectory 
00111   // inside the magnetic field;
00112 
00113   const G4double bField = 4.0*tesla; 
00114 
00115   double charge = fastTrack.GetPrimaryTrack()->GetStep()->GetPreStepPoint()->GetCharge();
00116 
00117   theHelix->initializeTrajectory(momentumShower,positionShower,charge,bField/tesla);
00118 
00119   //path Length from the origin to the shower starting point in cm
00120 
00121   G4double pathLength0 = 0;
00122   G4double transDepth = 0;
00123 
00124   // The step length left is the total path length from the shower starting point to
00125   // the maximum distance inside paramerized envelopes
00126 
00127   //distance to the end of HB/HB now 
00128   //@@@extend the trajectory outside bField and HO later
00129   G4double stepLengthLeft = 0.0;
00130 
00131   if(jCalorimeter == Gflash::kESPM || jCalorimeter == Gflash::kHB ) {
00132     pathLength0 = theHelix->getPathLengthAtRhoEquals(positionShower.getRho());
00133     stepLengthLeft = theHelix->getPathLengthAtRhoEquals(Gflash::Rmax[Gflash::kHB])
00134       - theHelix->getPathLengthAtRhoEquals(positionShower.getRho());
00135     if(showerType == 3 ) {
00136       transDepth = theHelix->getPathLengthAtRhoEquals(Gflash::Rmin[Gflash::kHB]) - pathLength0;
00137     }
00138   }
00139   else if (jCalorimeter == Gflash::kENCA || jCalorimeter == Gflash::kHE ) {
00140     pathLength0 = theHelix->getPathLengthAtZ(positionShower.getZ());
00141     stepLengthLeft = theHelix->getPathLengthAtRhoEquals(Gflash::Zmax[Gflash::kHE])
00142       - theHelix->getPathLengthAtRhoEquals(positionShower.getZ());
00143     if ( showerType ==7 ) {
00144       transDepth = theHelix->getPathLengthAtZ(Gflash::Zmin[Gflash::kHE]) - pathLength0;
00145     }
00146   }
00147   else { 
00148     //@@@extend for HF later
00149     stepLengthLeft = 200.0;
00150   }
00151   
00152   G4double pathLength  = pathLength0; // this will grow along the shower development
00153 
00154   // Limit number of spots to maxNumberOfSpots
00155   G4int numberOfSpots = std::max( 50, static_cast<int>(800.*std::log(einc)+50.));
00156   numberOfSpots = std::min(numberOfSpots,maxNumberOfSpots);
00157 
00158   // Spot energy to simulate sampling fluctuations (SampleEnergySpot) and
00159   // number of spots needed to fullfill geometry constraints(TotalNumberOfSpots):
00160 
00161   G4double  spotEnergy = energyToDeposit/numberOfSpots;
00162 
00163   // The step size of showino along the helix trajectory in cm unit
00164   const G4double divisionStep = 1.0; 
00165   G4double deltaStep = 0.0;
00166   G4double showerDepth = 0.0;
00167 
00168 
00169   G4int totalNumberOfSpots = 0;
00170 
00171   //empty energy spot vector for a new track
00172   aEnergySpotList.clear();
00173 
00174   double scaleLateral = 0.0;
00175   const double rMoliere = 2.19; //Moliere Radius in [cm]
00176 
00177   while(stepLengthLeft > 0.0) {
00178 
00179     // update shower depth and stepLengthLeft
00180     if ( stepLengthLeft < divisionStep ) {
00181       deltaStep = stepLengthLeft;
00182       stepLengthLeft  = 0.0;
00183     }
00184     else {
00185       deltaStep = divisionStep;
00186       stepLengthLeft -= deltaStep;
00187     }
00188 
00189     showerDepth += deltaStep;
00190     pathLength  += deltaStep;
00191 
00192     // energy in this deltaStep along the longitudinal shower profile
00193     double deltaEnergy = 0.;
00194 
00195     double heightProfile = longitudinalProfile(showerDepth,pathLength,transDepth);
00196     //    deltaEnergy =  longitudinalProfile(showerDepth)*divisionStep*energyToDeposit;    
00197     deltaEnergy =  heightProfile*divisionStep*energyToDeposit;    
00198     
00199     //@@@ When depthShower is inside Hcal, the sampling fluctuation for deposited
00200     //    energy will be treated in SD.  However we should put some scale factor 
00201     //    to relate the spot energy to the energy deposited in each geant4 step. 
00202 
00203     double hadronicFraction = 1.0;
00204     G4double fluctuatedEnergy = deltaEnergy;
00205     G4int nSpotsInStep = std::max(1,static_cast<int>(fluctuatedEnergy/spotEnergy));
00206     G4double sampleSpotEnergy = hadronicFraction*fluctuatedEnergy/nSpotsInStep;
00207 
00208     // Sampling fluctuations determine the number of spots:
00209     //    if (insideSampling(positionShower)) samplingFluctuation(fluctuatedEnergy,einc); 
00210     //    G4double hadSpotEnergy = std::max(0.,sampleSpotEnergy * hadronicFraction);
00211     //    G4double emSpotEnergy  = std::max(0.,sampleSpotEnergy - hadSpotEnergy);
00212     //    hadSpotEnergy *= Gflash::PBYMIP[jCalorimeter];
00213 
00214     
00215     //@@@this part of code may not be not need, but leave it for further consideration
00216 
00217     // Lateral shape and fluctuations
00218 
00219     double showerDepthR50 = std::min(showerDepth/20.7394, maxShowerDepthforR50);
00220 
00221     double R50          = lateralPar[0] + lateralPar[1] * showerDepthR50;
00222     double varinanceR50 = std::pow((lateralPar[2] + lateralPar[3] * showerDepthR50) * R50, 2);
00223 
00224     // Simulation of lognormal distribution
00225 
00226     double sigmaSq  = std::log(varinanceR50/(R50*R50)+1.0);
00227     double sigmaR50 = std::sqrt(sigmaSq);
00228     double meanR50  = std::log(R50) - (sigmaSq/2.);
00229 
00230     R50    = std::exp(rGauss*sigmaR50 + meanR50);
00231 
00232     // Averaging lateral scale in terms of Moliere radius
00233     //    const G4double  rMoliere = Gflash::RLTHAD[jCalorimeter];
00234 
00235     //@@@this should be each spot basis
00236     if(showerType == 4 || showerType == 8) {
00237       scaleLateral = (3.5+1.0*showerDepth)*rMoliere;
00238     }
00239     else {
00240       //@@@need better division for showerDepth arosse the Hcal front face
00241       if(showerDepthR50 < 2.0 ) {
00242         scaleLateral = (5.5-0.4*std::log(einc))*rMoliere;
00243       }
00244       else {
00245         scaleLateral = ( 14-1.5*std::log(einc))*rMoliere;
00246       }
00247     }
00248     // region0 && inside Ecal: scaleLateral = (5.5-0.4*logEinc)*rMoliere;
00249     // region0 && inside Hcal: scaleLateral = (14-1.5*logEinc)*rMoliere;
00250     // region1                 
00251 
00252     R50 *= scaleLateral;
00253 
00254     GflashEnergySpot eSpot;
00255 
00256     for (G4int ispot = 0 ;  ispot < nSpotsInStep ; ispot++) {
00257 
00258       totalNumberOfSpots++;
00259 
00260       // Smearing in r according to f(r)= 2.*r*R50**2/(r**2+R50**2)**2
00261       G4double rnunif = G4UniformRand();
00262       G4double rxPDF  = std::sqrt(rnunif/(1.-rnunif));
00263       rShower  = R50 * rxPDF;
00264 
00265       // Uniform smearing in phi, for 66% of lateral containm.
00266       G4double azimuthalAngle = 0.0; 
00267 
00268       azimuthalAngle = twopi*G4UniformRand(); 
00269 
00270       // Compute global position of generated spots with taking into account magnetic field
00271       // Divide deltaStep into nSpotsInStep and give a spot a global position
00272       G4double incrementPath = (deltaStep/nSpotsInStep)*(ispot+0.5 - 0.5*nSpotsInStep);
00273 
00274       // trajectoryPoint give a spot an imaginary point along the shower development
00275       GflashTrajectoryPoint trajectoryPoint;
00276       theHelix->getGflashTrajectoryPoint(trajectoryPoint,pathLength+incrementPath);
00277 
00278       // actual spot position by adding a radial vector to a trajectoryPoint
00279       G4ThreeVector SpotPosition = trajectoryPoint.getPosition() +
00280         rShower*std::cos(azimuthalAngle)*trajectoryPoint.getOrthogonalUnitVector() +
00281         rShower*std::sin(azimuthalAngle)*trajectoryPoint.getCrossUnitVector();
00282 
00283       //convert unit of energy to geant4 default MeV
00284       //      eSpot.setEnergy((hadSpotEnergy+emSpotEnergy)*GeV);
00285       eSpot.setEnergy(sampleSpotEnergy*GeV);
00286       eSpot.setPosition(SpotPosition*cm);
00287       aEnergySpotList.push_back(eSpot);
00288 
00289       //@@@debugging histograms
00290       if(theHisto->getStoreFlag()) {
00291         theHisto->rshower->Fill(rShower);
00292         theHisto->lateralx->Fill(rShower*std::cos(azimuthalAngle));
00293         theHisto->lateraly->Fill(rShower*std::sin(azimuthalAngle));
00294         theHisto->gfhlongProfile->Fill(pathLength+incrementPath-pathLength0,positionShower.getRho(),eSpot.getEnergy()*GeV);
00295       }
00296     }
00297   }
00298 
00299 }
00300 
00301 void GflashHadronShowerProfile::loadParameters(const G4FastTrack& fastTrack)
00302 {
00303   // Initialization of longitudinal and lateral parameters for 
00304   // hadronic showers. Simulation of the intrinsic fluctuations
00305 
00306   G4double einc = fastTrack.GetPrimaryTrack()->GetKineticEnergy()/GeV;
00307 
00308   // type of hadron showers subject to the shower starting point (ssp)
00309 
00310   // showerType =  0 : default (invalid) 
00311   // showerType =  1 : ssp before EB
00312   // showerType =  2 : ssp inside EB
00313   // showerType =  3 : ssp after  EB before HB
00314   // showerType =  4 : ssp inside HB
00315   // showerType =  5 : ssp before EE 
00316   // showerType =  6 : ssp inside EE 
00317   // showerType =  7 : ssp after  EE before HE
00318   // showerType =  8 : ssp inside HE
00319     
00320   G4TouchableHistory* touch = (G4TouchableHistory*)(fastTrack.GetPrimaryTrack()->GetTouchable());
00321   G4LogicalVolume* lv = touch->GetVolume()->GetLogicalVolume();
00322   std::size_t pos1 = lv->GetName().find("EBRY");
00323   std::size_t pos2 = lv->GetName().find("EFRY");
00324 
00325   G4ThreeVector position = fastTrack.GetPrimaryTrack()->GetPosition()/cm;
00326 
00327   showerType = 0;
00328 
00329   G4double correctionAsDepth = 0.0;
00330 
00331   //central
00332   if (jCalorimeter == Gflash::kESPM || jCalorimeter == Gflash::kHB ) {
00333 
00334     G4double posRho = position.getRho();
00335 
00336     if(pos1 != std::string::npos) {
00337       showerType = 2;
00338     }
00339     else {
00340       if(jCalorimeter == Gflash::kESPM) {
00341         showerType = 3;
00342         if( posRho < 129.0 ) showerType = 1;
00343       }
00344       else showerType = 4;
00345     }
00346 
00347     if ( posRho < 150.0 ) {
00348       correctionAsDepth = 0.01-2.0/((posRho-150.)*(posRho-150.) +5.4*5.4);
00349     }
00350     else {
00351       correctionAsDepth = 0.03-2.0/((posRho-150.)*(posRho-150.) +4.7*4.7);
00352     }
00353   }
00354   //forward
00355   else if (jCalorimeter == Gflash::kENCA || jCalorimeter == Gflash::kHE) {
00356     if(pos2 != std::string::npos) {
00357       showerType = 6;
00358     }
00359     else {
00360       if(jCalorimeter == Gflash::kENCA) {
00361         showerType = 7;
00362         if(fabs(position.getZ()) < 330.0 ) showerType = 5;
00363       }
00364       else showerType = 8;
00365     }
00366     //@@@need z-dependent correction on the mean energy reponse
00367   }
00368 
00369   
00370   // total energy to deposite
00371   //@@@ need additional parameterization by the shower starting point
00372   G4double fractionEnergy  = 1.0;
00373   G4double sigmaEnergy = 0.0;
00374 
00375   if( showerType == 4 || showerType == 8) { 
00376     //Mip-like particle
00377     fractionEnergy = 0.7125 + 0.0812*std::tanh(0.9040*(std::log(einc) - 2.6307));
00378     sigmaEnergy = 0.0257/std::sqrt(einc) + 0.0734;
00379   }
00380   else {
00381     fractionEnergy = 0.7125 + 0.0812*std::tanh(0.9040*(std::log(einc) - 2.6307));
00382     sigmaEnergy = 0.0844/std::sqrt(einc) + 0.0592;
00383   }
00384 
00385   energyToDeposit = fractionEnergy*(1.0+correctionAsDepth)*einc*(1.0+sigmaEnergy*theRandGauss->fire());
00386   energyToDeposit = std::max(0.0,energyToDeposit);
00387 
00388   // parameters for the longitudinal profiles
00389   //@@@check longitudinal profiles of endcaps for possible varitations
00390   //@@@need to add fluctuation and correlation for individual shower
00391 
00392   longPar[0][0] = 1.41*std::max(0.0,-5.96481e-03 + 0.18231*std::tanh(0.55451*(std::log(einc)-0.458775))) ;
00393   longPar[0][1] = std::max(0.0,2.01611 + 1.77483 * std::tanh(0.75719*(std::log(einc) - 2.58172)));
00394   longPar[0][2] = std::max(0.0,0.21261 + 0.24168 * std::tanh(0.76962*(std::log(einc) - 2.11936)));
00395   longPar[0][3] = std::max(0.0,1.05577e-02 + 1.00807  * std::tanh(-6.31044e-04*(std::log(einc) - 4.60658)));
00396   longPar[0][4] = 0.87*std::max(0.0,1.19845e-01 + 6.87070e-02 * std::tanh(-8.23888e-01*(std::log(einc) - 2.90178)));
00397   longPar[0][5] = std::max(0.0,2.49694e+01 + 1.10258e+01 * std::tanh(6.16435e-01*(std::log(einc) - 3.56012)));
00398 
00399   longSigma[0][0] = 0.02;
00400   longSigma[0][1] = 0.16;
00401   longSigma[0][2] = 0.02;
00402   longSigma[0][3] = 0.01;
00403   longSigma[0][4] = 0.03;
00404   longSigma[0][5] = 2.50;
00405   
00406   longPar[1][0] = 0.1126;
00407   longPar[1][1] = 1.3857;
00408   longPar[1][2] = std::max(0.0,1.1353 + 0.4997*std::tanh(-0.6382*(std::log(einc) - 2.0035)));
00409   longPar[1][3] = 0.2300;
00410   longPar[1][4] = 3.5018;
00411   longPar[1][5] = std::max(0.0,0.6151 - 0.0561*std::log(einc));
00412 
00413   longSigma[1][0] = 0.01;
00414   longSigma[1][1] = 0.44;
00415   longSigma[1][2] = 0.01;
00416   longSigma[1][3] = 0.01;
00417   longSigma[1][4] = 0.20;
00418   longSigma[1][5] = 0.04;
00419 
00420   longPar[2][0] = std::max(0.0,-1.55624e+01+1.56831e+01*std::tanh(5.93651e-01*(std::log(einc) + 4.89902)));
00421   longPar[2][1] = std::max(0.0,7.28995e-01+ 7.71148e-01*std::tanh(4.77898e-01*(std::log(einc) - 1.69087)));
00422   longPar[2][2] = std::max(0.0,1.23387+ 7.34778e-01*std::tanh(-3.14958e-01*(std::log(einc) - 0.529206)));
00423   longPar[2][3] = std::max(0.0,1.02070e+02+1.01873e+02*std::tanh(-4.99805e-01*(std::log(einc) + 5.04012)));
00424   longPar[2][4] = std::max(0.0,3.59765+8.53358e-01*std::tanh( 8.47277e-01*(std::log(einc) - 3.36548)));
00425   longPar[2][5] = std::max(0.0,4.27294e-01+1.62535e-02*std::tanh(-2.26278*(std::log(einc) - 1.81308)));
00426 
00427   longSigma[2][0] = 0.01;
00428   longSigma[2][1] = 0.44;
00429   longSigma[2][2] = 0.01;
00430   longSigma[2][3] = 0.01;
00431   longSigma[2][4] = 0.20;
00432   longSigma[2][5] = 0.04;
00433 
00434   double normalZ[Gflash::NxN];
00435   for (int i = 0; i < Gflash::NxN ; i++) normalZ[i] = theRandGauss->fire();
00436   
00437   for(int k = 0 ; k < Gflash::NRegion ; k++) {
00438     for(int i = 0 ; i < Gflash::NxN ; i++) {
00439       double correlationSum = 0.0;
00440       for(int j = 0 ; j < Gflash::NxN ; j++) {
00441         correlationSum += correlationVector[Gflash::NStart[Gflash::NRegion]+(i+1)/2+j]*normalZ[i];
00442       }
00443       longPar[k][i] = std::max(0.0,longPar[k][i]+longSigma[k][i]*correlationSum);
00444     }
00445   }
00446 
00447   // parameters for the lateral profile
00448 
00449   lateralPar[0] = 0.20;
00450   lateralPar[1] = std::max(0.0,0.40 -0.06*std::log(einc));
00451   lateralPar[2] = 0.70 - 0.05*std::max(0.,std::log(einc));
00452   lateralPar[3] = 0.20 * lateralPar[2];
00453 }
00454 
00455 G4double GflashHadronShowerProfile::longitudinalProfile(G4double showerDepth, G4double pathLength, G4double transDepth){
00456 
00457   G4double heightProfile = 0;
00458 
00459   // Energy in a delta step (dz) = (energy to deposite)*[Gamma(z+dz)-Gamma(z)]*dz
00460   // where the incomplete Gamma function gives an intergrate probability of the longitudinal 
00461   // shower u[ to the shower depth (z).
00462   // Instead, we use approximated energy; energy in dz = (energy to deposite)*gamma(z)*dz
00463   // where gamma is the Gamma-distributed probability function
00464 
00465   Genfun::LogGamma lgam;
00466   GflashTrajectoryPoint tempPoint;
00467   theHelix->getGflashTrajectoryPoint(tempPoint,pathLength);
00468 
00469   double x = 0.0;
00470   //get parameters
00471   if(showerType == 1 || showerType == 2 ) {
00472     //    std::cout << " pathLength tempPoint.getPosition().getRho()=  "  << pathLength << " "  << tempPoint.getPosition().getRho() << std::endl;
00473     if(tempPoint.getPosition().getRho() < 150.0 ) { 
00474       x = showerDepth*longPar[0][2];
00475       heightProfile = longPar[0][0]*std::pow(x,longPar[0][1]-1.0)*std::exp(-x)/std::exp(lgam(longPar[0][1]))+longPar[0][3];
00476     }
00477     else if (tempPoint.getPosition().getRho() > Gflash::Rmin[Gflash::kHB] ){
00478       x = showerDepth;
00479       heightProfile = longPar[0][4]*std::exp(-x/longPar[0][5]);
00480       heightProfile *= Gflash::ScaleSensitive;
00481     }
00482     else heightProfile = 0.;
00483   }  
00484   else if(showerType == 5 || showerType == 6){
00485     //@@@use new parameterization for EE/HE
00486     if(std::abs(tempPoint.getPosition().getZ()) < Gflash::Zmin[Gflash::kENCA]+23.0 ) { 
00487       x = showerDepth*longPar[0][2];
00488       heightProfile = longPar[0][0]*std::pow(x,longPar[0][1]-1.0)*std::exp(-x)/std::exp(lgam(longPar[0][1]))+longPar[0][3];
00489     }
00490     else if (std::abs(tempPoint.getPosition().getZ()) > Gflash::Rmin[Gflash::kHE] ){
00491       x = showerDepth;
00492       heightProfile = longPar[0][4]*std::exp(-x/longPar[0][5]);
00493       heightProfile *= Gflash::ScaleSensitive;
00494     }
00495     else heightProfile = 0.;
00496   }  
00497   else if (showerType == 3 || showerType == 7 ) {
00498     //two gammas between crystal and Hcal
00499     if((showerDepth - transDepth) > 0.0) {
00500       double x1 = (showerDepth-transDepth)*longPar[1][2]/16.42;
00501       double x2 = (showerDepth-transDepth)*longPar[1][5]/1.49;
00502 
00503       heightProfile = longPar[1][3]*std::pow(x1,longPar[1][1]-1.0)*std::exp(-x1)/std::exp(lgam(longPar[1][1]))
00504         + (1.0-longPar[1][3])*std::pow(x2,longPar[1][4]-1.0)*std::exp(-x2)/std::exp(lgam(longPar[1][4]));
00505       heightProfile = std::max(0.0,longPar[1][0]*heightProfile);
00506       heightProfile *= Gflash::ScaleSensitive;
00507     }
00508     else heightProfile = 0.;
00509   }
00510   else if (showerType == 4 || showerType == 8 ) {
00511     //two gammas inside Hcal
00512     double x1 = showerDepth*longPar[2][2]/16.42;
00513     double x2 = showerDepth*longPar[2][5]/1.49;
00514     heightProfile = longPar[2][3]*std::pow(x1,longPar[2][1]-1.0)*std::exp(-x1)/std::exp(lgam(longPar[2][1]))
00515                   + (1.0-longPar[2][3])*std::pow(x2,longPar[2][4]-1.0)*std::exp(-x2)/std::exp(lgam(longPar[2][4]));
00516     heightProfile = std::max(0.0,longPar[2][0]*heightProfile);
00517     heightProfile *= Gflash::ScaleSensitive;
00518   }
00519 
00520   return heightProfile;
00521 }
00522 
00523 void GflashHadronShowerProfile::samplingFluctuation(G4double &de, G4double einc){
00524 
00525   G4double spot[Gflash::NDET];
00526 
00527   for(G4int i = 0 ; i < Gflash::NDET ; i++) {
00528     spot[i] = std::pow(Gflash::SAMHAD[0][i],2) // resolution 
00529       + std::pow(Gflash::SAMHAD[1][i],2)/einc  // noisy
00530       + std::pow(Gflash::SAMHAD[2][i],2)*einc; // constant 
00531   }
00532   G4double ein = de * (energyToDeposit/einc);
00533 
00534   de = (ein > 0 ) ?  
00535     theRandGamma->fire(ein/spot[jCalorimeter],1.0)*spot[jCalorimeter] : ein;
00536 }
00537 
00538 G4bool GflashHadronShowerProfile::insideSampling(const G4ThreeVector pos) {
00539   G4bool issampling = false;
00540 
00541   if((jCalorimeter == Gflash::kHB) || (jCalorimeter == Gflash::kHE) ||            
00542      ((jCalorimeter == Gflash::kESPM) && ((pos.rho()/cm - 177.5) > 0)) ||     
00543      ((jCalorimeter == Gflash::kENCA) && ( fabs(pos.z()/cm - 391.95) > 0 ))) issampling = true;
00544   return issampling;
00545 }
00546 
00547 void GflashHadronShowerProfile::fillFluctuationVector() {
00548   //  G4double RMX[186]; //21*6 = 186
00549 
00550   for(G4int k = 0 ; k < Gflash::NRegion ; k++) {
00551     const G4int dim = Gflash::NDim[k];
00552     G4double **xr   = new G4double *[dim];
00553     G4double **xrho = new G4double *[dim];
00554     
00555     for(G4int j=0;j<dim;j++) {
00556       xr[j]   = new G4double [dim];
00557       xrho[j] = new G4double [dim];
00558     }
00559     
00560     for(G4int i = 0; i < dim; i++) {
00561       for(G4int j = 0; j < i+1 ; j++) {
00562         xrho[i][j] = Gflash::rho[i+Gflash::NRegion*k][j];
00563         xrho[i][j] = Gflash::rho[i][j];
00564         xrho[j][i] = xrho[i][j];
00565       }
00566     }
00567     
00568     doCholeskyReduction(xrho,xr,dim);
00569 
00570     for(G4int i = 0 ; i < dim ; i++) {
00571       for (G4int j = 0 ; j < i+1 ; j++){
00572         correlationVector[Gflash::NStart[k]+i*(i+1)/2 + j] = xr[i][j];
00573       }
00574     }
00575 
00576     std::cout << "this should be calcuated at constructor" << std::endl;
00577     for(int i = 0; i < 21 ; i++) std::cout << correlationVector[i] << std::endl;
00578     
00579     for(G4int j=0;j<dim;j++) delete [] xr[j];
00580     delete [] xr;
00581     for(G4int j=0;j<dim;j++) delete [] xrho[j];
00582     delete [] xrho;
00583   }
00584 }
00585 
00586 void GflashHadronShowerProfile::doCholeskyReduction(double **vv, double **cc, const int ndim) {
00587 
00588   G4double sumCjkSquare;
00589   G4double vjjLess;
00590   G4double sumCikjk;
00591 
00592   cc[0][0] = std::sqrt(vv[0][0]);
00593 
00594   for(G4int j=1 ; j < ndim ; j++) {
00595     cc[j][0] = vv[j][0]/cc[0][0];
00596   }
00597 
00598   for(G4int j=1 ; j < ndim ; j++) {
00599 
00600     sumCjkSquare = 0.0;
00601     for (G4int k=0 ; k < j ; k++) sumCjkSquare += cc[j][k]*cc[j][k];
00602 
00603     vjjLess =  vv[j][j] - sumCjkSquare;
00604 
00605     if ( vjjLess < 0. ) {
00606       std::cout << "GflashHadronShowerProfile::CholeskyReduction failed " << std::endl;
00607     }
00608     else {
00609       cc[j][j] = std::sqrt(std::fabs(vjjLess));
00610 
00611       for (G4int i=j+1 ; i < ndim ; i++) {
00612         sumCikjk = 0.;
00613         for(G4int k=0 ; k < j ; k++) sumCikjk += cc[i][k]*cc[j][k];
00614         cc[i][j] = (vv[i][j] - sumCikjk)/cc[j][j];
00615       }
00616     }
00617   }
00618 }

Generated on Tue Jun 9 17:47:05 2009 for CMSSW by  doxygen 1.5.4