|
| 1 | +// Copyright CERN and copyright holders of ALICE O2. This software is |
| 2 | +// distributed under the terms of the GNU General Public License v3 (GPL |
| 3 | +// Version 3), copied verbatim in the file "COPYING". |
| 4 | +// |
| 5 | +// See http://alice-o2.web.cern.ch/license for full licensing information. |
| 6 | +// |
| 7 | +// In applying this license CERN does not waive the privileges and immunities |
| 8 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 9 | +// or submit itself to any jurisdiction. |
| 10 | + |
| 11 | +// Class to generate spectators for ZDC simulations |
| 12 | + |
| 13 | +#include <TCanvas.h> |
| 14 | +#include <TClonesArray.h> |
| 15 | +#include <TDatabasePDG.h> |
| 16 | +#include <TLorentzVector.h> |
| 17 | +#include <TMath.h> |
| 18 | +#include <TPDGCode.h> |
| 19 | +#include <TParticle.h> |
| 20 | +#include <TParticlePDG.h> |
| 21 | +#include <TRandom.h> |
| 22 | +#include <assert.h> |
| 23 | + |
| 24 | +#include "GeneratorSpectators.h" |
| 25 | + |
| 26 | +ClassImp(GeneratorSpectators) |
| 27 | + |
| 28 | +//_____________________________________________________________________________ |
| 29 | +GeneratorSpectators::GeneratorSpectators() |
| 30 | + :TGenerator("GeneratorSpectators", "GeneratorSpectators"), fDebug(0), |
| 31 | + fPDGcode(0), fPmax(0), fPseudoRapidity(0), fCosx(0), fCosy(0), fCosz(0), |
| 32 | + fFermiflag(1),fBeamDiv(0), fBeamCrossAngle(0), fBeamCrossPlane(0) { |
| 33 | + // |
| 34 | + // Default constructor |
| 35 | +} |
| 36 | + |
| 37 | +//_____________________________________________________________________________ |
| 38 | +GeneratorSpectators::GeneratorSpectators(Int_t npart) |
| 39 | + :TGenerator("GeneratorSpectators", "GeneratorSpectators"){ |
| 40 | + // |
| 41 | + // Standard constructor |
| 42 | + // |
| 43 | + fName = "GeneratorSpectators"; |
| 44 | + fTitle = "Generation of Test Particles for ZDCs"; |
| 45 | + fDebug = 0; |
| 46 | + SetParticle(); |
| 47 | + SetMomentum(); |
| 48 | + SetDirection(); |
| 49 | + SetFermi(); |
| 50 | + SetDivergence(); |
| 51 | + SetCrossing(); |
| 52 | + |
| 53 | + for(Int_t i=0; i<201; i++){ |
| 54 | + fProbintp[i] = 0; |
| 55 | + fProbintn[i] = 0; |
| 56 | + fPp[i] = 0; |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +//_____________________________________________________________________________ |
| 61 | +void GeneratorSpectators::Init() |
| 62 | +{ |
| 63 | + //Initialize Fermi momentum distributions for Pb-Pb |
| 64 | + // |
| 65 | + printf("\n **** GeneratorSpectators initialization:\n"); |
| 66 | + printf(" ParticlePDG: %d, Track: cosx = %f cosy = %f cosz = %f \n", fPDGcode, fCosx, fCosy, fCosz); |
| 67 | + printf(" Fermi flag: %d, Beam divergence: %f, Crossing angle: %f, plane: %d\n\n", |
| 68 | + fFermiflag, fBeamDiv, fBeamCrossAngle, fBeamCrossPlane); |
| 69 | + |
| 70 | + FermiTwoGaussian(208.); |
| 71 | +} |
| 72 | + |
| 73 | +//_____________________________________________________________________________ |
| 74 | +void GeneratorSpectators::GenerateEvent() |
| 75 | +{ |
| 76 | + // |
| 77 | + // Generate one trigger particle (n or p) |
| 78 | + // |
| 79 | + //printf("GeneratorSpectators::GenerateEvent()\n"); |
| 80 | + fParticles->Clear(); |
| 81 | + |
| 82 | + Double_t pLab[3] = {0.,0.,0.}; |
| 83 | + Double_t fP[3] = {0.,0.,0.}, fBoostP[3] = {0.,0.,0.}; |
| 84 | + Double_t ptot = fPmax; |
| 85 | + if(fPseudoRapidity==0.){ |
| 86 | + pLab[0] = ptot*fCosx; |
| 87 | + pLab[1] = ptot*fCosy; |
| 88 | + pLab[2] = ptot*fCosz; |
| 89 | + } |
| 90 | + else{ |
| 91 | + Float_t scang = 2*TMath::ATan(TMath::Exp(-(fPseudoRapidity))); |
| 92 | + pLab[0] = -ptot*TMath::Sin(scang); |
| 93 | + pLab[1] = 0.; |
| 94 | + pLab[2] = ptot*TMath::Cos(scang); |
| 95 | + } |
| 96 | + for(int i=0; i<3; i++) fP[i] = pLab[i]; |
| 97 | + if(fDebug==1) printf("\n Particle momentum before divergence and crossing: "); |
| 98 | + if(fDebug==1) printf(" pLab = (%f, %f, %f)\n", pLab[0], pLab[1], pLab[2]); |
| 99 | + |
| 100 | + // Beam divergence and crossing angle |
| 101 | + if(TMath::Abs(fBeamCrossAngle)>0.) { |
| 102 | + BeamCrossing(pLab); |
| 103 | + for(int i=0; i<3; i++) fP[i] = pLab[i]; |
| 104 | + } |
| 105 | + if(TMath::Abs(fBeamDiv)>0.) { |
| 106 | + BeamDivergence(pLab); |
| 107 | + for(int i=0; i<3; i++) fP[i] = pLab[i]; |
| 108 | + } |
| 109 | + |
| 110 | + Double_t mass = TDatabasePDG::Instance()->GetParticle(fPDGcode)->Mass(); |
| 111 | + Double_t ddp[3] = {0.,0.,0.}, dddp[3] = {0.,0.,0.}; |
| 112 | + Double_t fP0 = 0., dddp0 = 0.; |
| 113 | + // If required apply the Fermi momentum |
| 114 | + if(fFermiflag==1){ |
| 115 | + if((fPDGcode==kProton) || (fPDGcode==kNeutron)) ExtractFermi(fPDGcode, ddp); |
| 116 | + fP0 = TMath::Sqrt(fP[0]*fP[0] + fP[1]*fP[1] + fP[2]*fP[2] + mass*mass); |
| 117 | + for(int i=0; i<3; i++) dddp[i] = ddp[i]; |
| 118 | + dddp0 = TMath::Sqrt(dddp[0]*dddp[0] + dddp[1]*dddp[1] + dddp[2]*dddp[2] + mass*mass); |
| 119 | + |
| 120 | + TVector3 b(fP[0]/fP0, fP[1]/fP0, fP[2]/fP0); |
| 121 | + TLorentzVector pFermi(dddp[0], dddp[1], dddp[2], dddp0); |
| 122 | + |
| 123 | + pFermi.Boost(b); |
| 124 | + for(int i=0; i<3; i++){ |
| 125 | + fBoostP[i] = pFermi[i]; |
| 126 | + fP[i] = pFermi[i]; |
| 127 | + } |
| 128 | + |
| 129 | + } |
| 130 | + if(fDebug==1) printf(" ### Particle momentum = (%f, %f, %f)\n", fP[0], fP[1], fP[2]); |
| 131 | + |
| 132 | + Double_t energy = TMath::Sqrt(fP[0]*fP[0]+fP[1]*fP[1]+fP[2]*fP[2]+mass*mass); |
| 133 | + |
| 134 | + auto part = new TParticle(fPDGcode, 1, -1, -1, -1, -1, fP[0], fP[1], fP[2], energy, |
| 135 | + 0., 0., 0., 0.); |
| 136 | + fParticles->Add(part); |
| 137 | +} |
| 138 | + |
| 139 | +// ----------------------------------------------------------------------- |
| 140 | +int GeneratorSpectators::ImportParticles(TClonesArray *particles, Option_t *option) { |
| 141 | + if (particles == 0) return 0; |
| 142 | + TClonesArray &clonesParticles = *particles; |
| 143 | + clonesParticles.Clear(); |
| 144 | + Int_t numpart = fParticles->GetEntries(); |
| 145 | + for (int i = 0; i < numpart; i++) { |
| 146 | + TParticle *particle = (TParticle *)fParticles->At(i); |
| 147 | + new (clonesParticles[i]) TParticle(*particle); |
| 148 | + } |
| 149 | + return numpart; |
| 150 | +} |
| 151 | + |
| 152 | +//_____________________________________________________________________________ |
| 153 | +void GeneratorSpectators::FermiTwoGaussian(Float_t A) |
| 154 | +{ |
| 155 | +// |
| 156 | +// Momenta distributions according to the "double-gaussian" |
| 157 | +// distribution (Ilinov) - equal for protons and neutrons |
| 158 | +// |
| 159 | + Double_t sig1 = 0.113; |
| 160 | + Double_t sig2 = 0.250; |
| 161 | + Double_t alfa = 0.18*(TMath::Power((A/12.), (Float_t)1/3)); |
| 162 | + Double_t xk = (2*TMath::TwoPi())/((1.+alfa)*(TMath::Power(TMath::TwoPi(),1.5))); |
| 163 | + |
| 164 | + for(Int_t i=1; i<201; i++){ |
| 165 | + Double_t p = i*0.005; |
| 166 | + fPp[i] = p; |
| 167 | + Double_t e1 = (p*p)/(2.*sig1*sig1); |
| 168 | + Double_t e2 = (p*p)/(2.*sig2*sig2); |
| 169 | + Double_t f1 = TMath::Exp(-(e1)); |
| 170 | + Double_t f2 = TMath::Exp(-(e2)); |
| 171 | + Double_t probp = xk*p*p*(f1/(TMath::Power(sig1,3.))+ |
| 172 | + alfa*f2/(TMath::Power(sig2,3.)))*0.005; |
| 173 | + fProbintp[i] = fProbintp[i-1] + probp; |
| 174 | + fProbintn[i] = fProbintp[i]; |
| 175 | + } |
| 176 | + if(fDebug==1) printf(" Initialization of Fermi momenta distribution \n"); |
| 177 | +} |
| 178 | +//_____________________________________________________________________________ |
| 179 | +void GeneratorSpectators::ExtractFermi(Int_t id, Double_t *ddp) |
| 180 | +{ |
| 181 | + // |
| 182 | + // Compute Fermi momentum for spectator nucleons |
| 183 | + // |
| 184 | + Int_t index=0; |
| 185 | + Float_t xx = gRandom->Rndm(); |
| 186 | + assert ( id==kProton || id==kNeutron ); |
| 187 | + if(id==kProton){ |
| 188 | + for(Int_t i=1; i<201; i++){ |
| 189 | + if((xx>=fProbintp[i-1]) && (xx<fProbintp[i])) break; |
| 190 | + index = i; |
| 191 | + } |
| 192 | + } |
| 193 | + else { |
| 194 | + for(Int_t i=1; i<201; i++){ |
| 195 | + if((xx>=fProbintn[i-1]) && (xx<fProbintn[i])) break; |
| 196 | + index = i; |
| 197 | + } |
| 198 | + } |
| 199 | + Float_t pext = fPp[index]+0.001; |
| 200 | + Float_t phi = TMath::TwoPi()*(gRandom->Rndm()); |
| 201 | + Float_t cost = (1.-2.*(gRandom->Rndm())); |
| 202 | + Float_t tet = TMath::ACos(cost); |
| 203 | + ddp[0] = pext*TMath::Sin(tet)*TMath::Cos(phi); |
| 204 | + ddp[1] = pext*TMath::Sin(tet)*TMath::Sin(phi); |
| 205 | + ddp[2] = pext*cost; |
| 206 | + |
| 207 | + if(fDebug==1) printf(" Fermi momentum: p = (%f, %f, %f )\n\n",ddp[0],ddp[1],ddp[2]); |
| 208 | +} |
| 209 | +//_____________________________________________________________________________ |
| 210 | +void GeneratorSpectators::BeamCrossing(Double_t *pLab) |
| 211 | +{ |
| 212 | + // Applying beam crossing angle |
| 213 | + // |
| 214 | + pLab[1] = pLab[2]*TMath::Sin(fBeamCrossAngle)+pLab[1]*TMath::Cos(fBeamCrossAngle); |
| 215 | + pLab[2] = pLab[2]*TMath::Cos(fBeamCrossAngle)-pLab[1]*TMath::Sin(fBeamCrossAngle); |
| 216 | + // |
| 217 | + if(fDebug==1) printf(" Beam crossing angle = %f mrad -> ", fBeamCrossAngle*1000.); |
| 218 | + if(fDebug==1) printf(" p = (%f, %f, %f)\n",pLab[0],pLab[1],pLab[2]); |
| 219 | + |
| 220 | +} |
| 221 | +//_____________________________________________________________________________ |
| 222 | +void GeneratorSpectators::BeamDivergence(Double_t *pLab) |
| 223 | +{ |
| 224 | + // Applying beam divergence and crossing angle |
| 225 | + // |
| 226 | + Double_t pmq = 0.; |
| 227 | + for(int i=0; i<3; i++) pmq = pmq+pLab[i]*pLab[i]; |
| 228 | + Double_t pmod = TMath::Sqrt(pmq); |
| 229 | + |
| 230 | + Double_t rvec = gRandom->Gaus(0.0,1.0); |
| 231 | + Double_t tetdiv = fBeamDiv * TMath::Abs(rvec); |
| 232 | + Double_t fidiv = (gRandom->Rndm())*TMath::TwoPi(); |
| 233 | + |
| 234 | + Double_t tetpart = TMath::ATan2(TMath::Sqrt(pLab[0]*pLab[0]+pLab[1]*pLab[1]),pLab[2]); |
| 235 | + Double_t fipart = 0.; |
| 236 | + if(pLab[1]!=0. || pLab[0]!=0.) fipart = TMath::ATan2(pLab[1],pLab[0]); |
| 237 | + else fipart = 0.; |
| 238 | + if(fipart<0.) {fipart = fipart+TMath::TwoPi();} |
| 239 | + tetdiv = tetdiv*TMath::RadToDeg(); |
| 240 | + fidiv = fidiv*TMath::RadToDeg(); |
| 241 | + tetpart = tetpart*TMath::RadToDeg(); |
| 242 | + fipart = fipart*TMath::RadToDeg(); |
| 243 | + Double_t angleSum[2] = {0., 0.}; |
| 244 | + AddAngle(tetpart,fipart,tetdiv,fidiv,angleSum); |
| 245 | + Double_t tetsum = angleSum[0]; |
| 246 | + Double_t fisum = angleSum[1]; |
| 247 | + tetsum = tetsum*TMath::DegToRad(); |
| 248 | + fisum = fisum*TMath::DegToRad(); |
| 249 | + pLab[0] = pmod*TMath::Sin(tetsum)*TMath::Cos(fisum); |
| 250 | + pLab[1] = pmod*TMath::Sin(tetsum)*TMath::Sin(fisum); |
| 251 | + pLab[2] = pmod*TMath::Cos(tetsum); |
| 252 | + // |
| 253 | + if(fDebug==1) printf(" Beam divergence = %f mrad -> ", fBeamDiv*1000.); |
| 254 | + if(fDebug==1) printf(" p = (%f, %f, %f)\n",pLab[0],pLab[1],pLab[2]); |
| 255 | +} |
| 256 | + |
| 257 | +//_____________________________________________________________________________ |
| 258 | +void GeneratorSpectators::AddAngle(Double_t theta1, Double_t phi1, Double_t theta2, |
| 259 | + Double_t phi2, Double_t *angleSum) |
| 260 | +{ |
| 261 | + // Calculating the sum of 2 angles |
| 262 | + Double_t temp = -1.; |
| 263 | + Double_t conv = 180./TMath::ACos(temp); |
| 264 | + Double_t ct1 = TMath::Cos(theta1/conv); |
| 265 | + Double_t st1 = TMath::Sin(theta1/conv); |
| 266 | + Double_t cp1 = TMath::Cos(phi1/conv); |
| 267 | + Double_t sp1 = TMath::Sin(phi1/conv); |
| 268 | + Double_t ct2 = TMath::Cos(theta2/conv); |
| 269 | + Double_t st2 = TMath::Sin(theta2/conv); |
| 270 | + Double_t cp2 = TMath::Cos(phi2/conv); |
| 271 | + Double_t sp2 = TMath::Sin(phi2/conv); |
| 272 | + Double_t cx = ct1*cp1*st2*cp2+st1*cp1*ct2-sp1*st2*sp2; |
| 273 | + Double_t cy = ct1*sp1*st2*cp2+st1*sp1*ct2+cp1*st2*sp2; |
| 274 | + Double_t cz = ct1*ct2-st1*st2*cp2; |
| 275 | + |
| 276 | + Double_t rtetsum = TMath::ACos(cz); |
| 277 | + Double_t tetsum = conv*rtetsum; |
| 278 | + Double_t fisum = 0; |
| 279 | + if (tetsum == 0. || tetsum == 180.) |
| 280 | + { |
| 281 | + fisum = 0.; |
| 282 | + return; |
| 283 | + } |
| 284 | + temp = cx/TMath::Sin(rtetsum); |
| 285 | + if(temp>1.) temp=1.; |
| 286 | + else if (temp < -1.) temp = -1.; |
| 287 | + fisum = conv*TMath::ACos(temp); |
| 288 | + if(cy<0) {fisum = 360.-fisum;} |
| 289 | + angleSum[0] = tetsum; |
| 290 | + angleSum[1] = fisum; |
| 291 | +} |
0 commit comments