Monte Carlo LYSO
Geant4 simulation for the LYSO calorimeter prototype
generator.cc
Go to the documentation of this file.
1 
5 #include "generator.hh"
6 
8 {
10 
11  // Default values
12  fModeType = 10;
13 
14  fMeanEnergy = 1.*MeV;
15  fSigmaEnergy = 0.01*MeV;
16 
17  // Spread and Circle beam
18  fRadiusSpread = 10*mm;
19  fRadiusCircle = 10*mm;
20 
21  // 176Lu decay
22  fPosFixedDecay = G4ThreeVector(0., 0., 200.*mm);
23 
24  // LED mode
25  fChooseFrontorBack = "F";
26  fSwitchOnLED = "u";
27 
28 
29  // Construct the Particle Gun
30  fParticleGun = new G4ParticleGun(1);
31 
32  fParticleGun->SetParticlePosition(G4ThreeVector(0., 0., 0.));
33  fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0., 0., 1.));
34 }
35 
36 
37 
39 {
40  delete fMessenger_Mode;
41  delete fMessenger_Gun;
42  delete fMessenger_Calib;
43  delete fParticleGun;
44 }
45 
46 
47 
49 {
50  switch(fModeType)
51  {
52  // Standard mode
53  case 10: // Pointlike beam
54  case 11: // Spread beam
55  case 12: // Circle beam
57  break;
58 
59  // Lu decay mode
60  case 20:
61  case 21: // Fixed position
62  case 22: // Si trigger
64  break;
65 
66  // Cosmic rays mode
67  case 30:
69  break;
70  case 31: // Counting
71  PrimariesForCountingCosmicRaysMode();
72  break;
73  // LED-System mode
74  case 40:
76  break;
77 
78  default:
79  G4cerr << "Not valid mode! Standard mode is selected!" << G4endl;
80  fModeType = 10;
82  }
83 
84  // Finally generate the primary vertex
85  fParticleGun->GeneratePrimaryVertex(anEvent);
86 }
87 
88 
89 
91 {
92  // Set position at the center
93  G4ThreeVector pos(0., 0., 0.);
94 
95  // Sample the momentum direction uniformly within the given range
96  G4double fThetaMax = std::atan(fRadiusSpread/GS::zFrontFaceScintillator);
97  G4double fCosThetaMax = std::cos(fThetaMax);
98 
99  G4double cosTheta = 1-G4UniformRand()*(1-fCosThetaMax);
100  G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
101  G4double phi = CLHEP::twopi*G4UniformRand();
102 
103  G4double ux = sinTheta*std::cos(phi);
104  G4double uy = sinTheta*std::sin(phi);
105  G4double uz = cosTheta;
106 
107  G4ThreeVector mom(ux, uy, uz);
108 
109  // Set fParticleGun
110  fParticleGun->SetParticlePosition(pos);
111  fParticleGun->SetParticleMomentumDirection(mom);
112 }
113 
114 
115 
117 {
118  G4double posR = fRadiusCircle*std::sqrt(G4UniformRand());
119  G4double posPhi = CLHEP::twopi*G4UniformRand();
120 
121  G4ThreeVector pos(posR*std::cos(posPhi), posR*std::sin(posPhi), 0);
122 
123  fParticleGun->SetParticlePosition(pos);
124  fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0., 0., 1.));
125 }
126 
127 
128 
130 {
131  // Set gamma as primary particle
132  G4ParticleDefinition *particle = G4ParticleTable::GetParticleTable()->FindParticle("gamma");
133  fParticleGun->SetParticleDefinition(particle);
134 
135  // Sample the energy from Gaus
136  G4double energy = G4RandGauss::shoot(fMeanEnergy, fSigmaEnergy);
137  fParticleGun->SetParticleEnergy(energy);
138 
139  switch(fModeType)
140  {
141  case 10: // Pointlike beam
142  break;
143  case 11: // Spread beam
145  break;
146  case 12: // Circle beam
148  break;
149  }
150 }
151 
152 
153 
155 {
156  G4ThreeVector posLed;
157  G4ThreeVector momLed;
158 
159  // Which face
160  G4double posZLed;
163  else
164  {
165  G4cerr << "Option for detector face not valid. 'Front' has been setted" << G4endl;
167  }
168 
169  // Which LED
170  if(fSwitchOnLED=="u") posLed = G4ThreeVector(0, GS::radiusLightGuide-GS::depthLED, posZLed);
171  else if(fSwitchOnLED=="d") posLed = G4ThreeVector(0, -GS::radiusLightGuide+GS::depthLED, posZLed);
172  else if(fSwitchOnLED=="l") posLed = G4ThreeVector(GS::radiusLightGuide-GS::depthLED, 0, posZLed);
173  else if(fSwitchOnLED=="r") posLed = G4ThreeVector(-GS::radiusLightGuide+GS::depthLED, 0, posZLed);
174  else
175  {
176  G4cerr << "Option for LED not valid. 'up' has been setted" << G4endl;
177  posLed = G4ThreeVector(0, GS::radiusLightGuide-GS::depthLED, posZLed);
178  }
179 
180  // Isotropic emission (not accurate, should be Lambert's cosine law,
181  // but need G4GeneralParticleSource for this)
182  G4double cosTheta = 2*G4UniformRand() - 1.;
183  G4double phi = CLHEP::twopi*G4UniformRand();
184  G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
185  G4double ux = sinTheta*std::cos(phi);
186  G4double uy = sinTheta*std::sin(phi);
187  G4double uz = cosTheta;
188  momLed = G4ThreeVector(ux,uy,uz);
189 
190  // Set everything in fParticleGun
191  G4ParticleDefinition* particle = G4ParticleTable::GetParticleTable()->FindParticle("opticalphoton");
192  fParticleGun->SetParticleDefinition(particle);
193  fParticleGun->SetParticlePosition(posLed);
194  fParticleGun->SetParticleMomentumDirection(momLed); fParticleGun->SetParticleEnergy(GS::energyLED);
195 }
196 
197 
198 
200 {
201  G4ThreeVector posDecay;
202  G4ThreeVector momDecay;
203  G4double posZ, posR, posPhi;
204 
205  switch(fModeType)
206  {
207  case 20: // Default
208  // Compute random position inside crystal
209  posZ = GS::zScintillator + 2*(G4UniformRand()-0.5)*GS::halfheightScintillator;
210  posR = GS::radiusScintillator*std::sqrt(G4UniformRand());
211  posPhi = CLHEP::twopi*G4UniformRand();
212  posDecay = G4ThreeVector(posR*std::cos(posPhi), posR*std::sin(posPhi), posZ);
213  break;
214  case 21: // Fixed position
215  posDecay = fPosFixedDecay;
216  break;
217  case 22: // Si trigger test
218  //Compute random position near ch57-Front
219  // Very situational mode, it's fine to be hard-coded
220  posDecay = G4ThreeVector(0.*mm, 0.*mm, GS::zFrontFaceScintillator+G4UniformRand()*25.*mm);
221  //posDecay = G4ThreeVector(2*(G4UniformRand()-0.5)*4*mm, 2*(G4UniformRand()-0.5)*4*mm, (150.2+2*(G4UniformRand()-0.5)*0.2)*mm);
222  break;
223  }
224 
225  // Isotropic emission
226  G4double cosTheta = 2*G4UniformRand() - 1.;
227  G4double phi = CLHEP::twopi*G4UniformRand();
228  G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
229  G4double ux = sinTheta*std::cos(phi);
230  G4double uy = sinTheta*std::sin(phi);
231  G4double uz = cosTheta;
232 
233  momDecay = G4ThreeVector(ux,uy,uz);
234 
235  // Set everything in fParticleGun
236  G4int Z = 71, A = 176;
237  G4ParticleDefinition* ion = G4IonTable::GetIonTable()->GetIon(Z, A, 0.*keV);
238  fParticleGun->SetParticleDefinition(ion);
239  fParticleGun->SetParticleCharge(0.*eplus);
240  fParticleGun->SetParticlePosition(posDecay);
241  fParticleGun->SetParticleMomentumDirection(momDecay);
242  fParticleGun->SetParticleEnergy(1*eV);
243 }
244 
245 
246 
248 {
249  G4ThreeVector posRay;
250  G4ThreeVector momRay;
251 
252  // Compute initial random position in the up detector
253  G4double posX = GS::xCosmicRayDetector + 2*(G4UniformRand()-0.5)*GS::halfZXsideCosmicRayDetector;
254  G4double posY = GS::yCosmicRayDetector + GS::halfYsideCosmicRayDetector;
255  G4double posZ = GS::zCosmicRayDetector + 2*(G4UniformRand()-0.5)*GS::halfZXsideCosmicRayDetector;
256 
257  posRay = G4ThreeVector(posX, posY, posZ);
258 
259  // Compute initial cosmic ray direction
260  G4double cosTheta = -G4UniformRand(); // Note that cosine is in [-1, 0] now
261  G4double cosThetaa = G4UniformRand(); // On the image of cos^2(Theta)
262  G4double phi = CLHEP::twopi*G4UniformRand();
263  G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
264  G4double uz = sinTheta*std::cos(phi); // Remember the axis orientation
265  G4double ux = sinTheta*std::sin(phi);
266  G4double uy = cosTheta; // Y is vertical
267 
268  momRay = G4ThreeVector(ux, uy, uz);
269 
270  while(std::abs(ProjectOnBottomDetector(posRay, momRay).x() - GS::xCosmicRayDetector) > GS::halfZXsideCosmicRayDetector || std::abs(ProjectOnBottomDetector(posRay, momRay).z() - GS::zCosmicRayDetector) > GS::halfZXsideCosmicRayDetector) // Conditions on trigger
271  {
272  posX = GS::xCosmicRayDetector + 2*(G4UniformRand()-0.5)*GS::halfZXsideCosmicRayDetector;
273  posZ = GS::zCosmicRayDetector + 2*(G4UniformRand()-0.5)*GS::halfZXsideCosmicRayDetector;
274 
275  posRay = G4ThreeVector(posX, posY, posZ);
276 
277  cosTheta = -G4UniformRand(); // Note that cosine is in [-1, 0] now
278  cosThetaa = G4UniformRand(); // On the image of cos^2(Theta)
279  phi = CLHEP::twopi*G4UniformRand();
280  while(cosThetaa > (cosTheta*cosTheta)) // Mom-dir generation
281  {
282  cosTheta = -G4UniformRand();
283  cosThetaa = G4UniformRand();
284 
285  phi = CLHEP::twopi*G4UniformRand();
286  }
287  sinTheta = std::sqrt(1. - cosTheta*cosTheta);
288  uz = sinTheta*std::cos(phi);
289  ux = sinTheta*std::sin(phi);
290  uy = cosTheta;
291 
292  momRay = G4ThreeVector(ux, uy, uz);
293  }
294 
295 
296  // Cosmic ray energy
297  G4double energy = 999.;
298  G4double energyy = 1.; // On the image of pdf(E)
299  G4double emin = 0.; // kinetic energy
300  G4double emax = 1.*TeV;
301 
302  while(energyy > PDF_E_CosmicRay(energy))
303  { // Accept-Reject method
304  energy = emin + emax*G4UniformRand();
305  // Note that the maximum probability is at minimum energy
306  energyy = PDF_E_CosmicRay(emin)*G4UniformRand();
307  }
308 
309  // Set everything in fParticleGun
310  G4ParticleDefinition* particle = nullptr;
311  if(G4UniformRand() < 0.5)
312  particle = G4ParticleTable::GetParticleTable()->FindParticle("mu-");
313  else
314  particle = G4ParticleTable::GetParticleTable()->FindParticle("mu+");
315 
316  fParticleGun->SetParticleDefinition(particle);
317  fParticleGun->SetParticlePosition(posRay);
318  fParticleGun->SetParticleMomentumDirection(momRay); fParticleGun->SetParticleEnergy(energy);
319 }
320 
321 
322 
323 void MyPrimaryGenerator::PrimariesForCountingCosmicRaysMode()
324 {
325  G4ThreeVector posRay;
326  G4ThreeVector momRay;
327 
328  // Compute initial random position in the up detector
329  G4double posX = GS::xCosmicRayDetector + (G4UniformRand()-0.5) * 10*cm;
330  G4double posY = GS::yCosmicRayDetector + GS::halfYsideCosmicRayDetector;
331  G4double posZ = GS::zCosmicRayDetector + (G4UniformRand()-0.5) * 10*cm;
332 
333  posRay = G4ThreeVector(posX, posY, posZ);
334 
335  // Compute initial cosmic ray direction
336  G4double cosTheta = -G4UniformRand(); // Note that cosine is in [-1, 0] now
337  G4double cosThetaa = G4UniformRand(); // On the image of cos^2(Theta)
338  while(cosThetaa > (cosTheta*cosTheta)) // Mom-dir generation
339  {
340  cosTheta = -G4UniformRand();
341  cosThetaa = G4UniformRand();
342 
343  }
344  G4double phi = CLHEP::twopi*G4UniformRand();
345  G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
346  G4double uz = sinTheta*std::cos(phi);
347  G4double ux = sinTheta*std::sin(phi);
348  G4double uy = cosTheta;
349 
350  momRay = G4ThreeVector(ux, uy, uz);
351 
352  // Cosmic ray energy
353  G4double energy = 999.;
354  G4double energyy = 1.; // On the image of pdf(E)
355  G4double emin = 0.; // kinetic energy
356  G4double emax = 1.*TeV;
357 
358  while(energyy > PDF_E_CosmicRay(energy))
359  { // Accept-Reject method
360  energy = emin + emax*G4UniformRand();
361  // Note that the maximum probability is at minimum energy
362  energyy = PDF_E_CosmicRay(emin)*G4UniformRand();
363  }
364 
365  // Set everything in fParticleGun
366  G4ParticleDefinition* particle = nullptr;
367  if(G4UniformRand() < 0.5)
368  particle = G4ParticleTable::GetParticleTable()->FindParticle("mu-");
369  else
370  particle = G4ParticleTable::GetParticleTable()->FindParticle("mu+");
371 
372  fParticleGun->SetParticleDefinition(particle);
373  fParticleGun->SetParticlePosition(posRay);
374  fParticleGun->SetParticleMomentumDirection(momRay); fParticleGun->SetParticleEnergy(energy);
375 }
376 
377 
378 
379 G4double MyPrimaryGenerator::PDF_E_CosmicRay(G4double energy)
380 {
381  if(energy < 3.4*GeV)
382  {
383  return std::pow(3.4*GeV, -2.7);
384  }
385  else
386  {
387  return std::pow(energy, -2.7);
388  }
389 }
390 
391 
392 
393 G4ThreeVector MyPrimaryGenerator::ProjectOnBottomDetector(G4ThreeVector pos0, G4ThreeVector mom0)
394 {
395  G4double y_b = -(GS::yCosmicRayDetector + GS::halfYsideCosmicRayDetector);
396  G4double x_b, z_b;
397  G4double t = (y_b - pos0.y())/mom0.y();
398 
399  x_b = pos0.x() + mom0.x()*t;
400  z_b = pos0.z() + mom0.z()*t;
401 
402  return G4ThreeVector(x_b, y_b, z_b);
403 };
404 
405 
406 
408 {
409  // Define my UD-messenger for mode selection
410  fMessenger_Mode = new G4GenericMessenger(this, "/MC_LYSO/", "Commands for MC_LYSO run");
411  fMessenger_Mode->DeclareProperty("Mode", fModeType, "Available modes are: 10 = Standard with pointlike beam, 11 = Standard with spread beam, 12 = Standard with circle beam, 20 = Lu decay, 21 = Lu decay with fixed position, 22 = Lu decay with Si trigger test, 30 = Cosmic Rays, 40 = LED-system");
412 
413  // Define my UD-messenger for primary gamma
414  fMessenger_Gun = new G4GenericMessenger(this, "/MC_LYSO/myGun/", "Cinematical settings for primary particle");
415  fMessenger_Gun->DeclarePropertyWithUnit("meanEnergy", "MeV", fMeanEnergy, "Mean of the gaussian distribution of initial gamma energy");
416  fMessenger_Gun->DeclarePropertyWithUnit("sigmaEnergy", "MeV", fSigmaEnergy, "Sigma of the gaussian distribution of initial gamma energy");
417  fMessenger_Gun->DeclarePropertyWithUnit("radiusSpread", "mm", fRadiusSpread, "Set radius of the spread on the front face of scintillator");
418  fMessenger_Gun->DeclarePropertyWithUnit("radiusCircle", "mm", fRadiusCircle, "Set radius of the beam (in 'Circle' case)");
419  fMessenger_Gun->DeclarePropertyWithUnit("posLuDecay", "mm", fPosFixedDecay, "Set position for Lu decay in fixed position mode");
420 
421  // Define my UD-messenger for LED mode
422  fMessenger_Calib = new G4GenericMessenger(this, "/MC_LYSO/myGun/LED-System/", "Settings for LED-system calibration");
423  fMessenger_Calib->DeclareProperty("FrontOrBack", fChooseFrontorBack, "Choose side of detector you want to calibrate: F(ront) or B(ack)");
424  fMessenger_Calib->DeclareProperty("switchOnLED", fSwitchOnLED, "Choose which LED turn ON: u(p), d(own), r(ight), l(eft)");
425 }
G4double fRadiusSpread
Radius of the area on the front face of the crystal that could be hit by primary gamma when spread is...
Definition: generator.hh:83
void PrimariesForSpreadBeam()
Generate primaries auxiliary function for spread beam.
Definition: generator.cc:90
void PrimariesForCosmicRaysMode()
Generate primaries auxiliary function for Cosmic rays mode.
Definition: generator.cc:247
G4double fSigmaEnergy
Sigma of the gaussian distribution of the energy of the primary particle.
Definition: generator.hh:82
void PrimariesForLuDecayMode()
Generate primaries auxiliary function for Lu decay mode.
Definition: generator.cc:199
G4GenericMessenger * fMessenger_Calib
Generic messenger for the calibration mode.
Definition: generator.hh:76
G4GenericMessenger * fMessenger_Mode
Generic messenger for mode selection.
Definition: generator.hh:74
void PrimariesForStandardMode()
Generate primaries auxiliary function for Standard mode.
Definition: generator.cc:129
G4double fRadiusCircle
Radius of the beam profile in circle type.
Definition: generator.hh:84
G4double fMeanEnergy
Mean of the gaussian distribution of the energy of the primary particle.
Definition: generator.hh:81
MyPrimaryGenerator()
Constructor of the class.
Definition: generator.cc:7
G4String fChooseFrontorBack
Flag indicating on which face of the crystal a LED has to be switched ON.
Definition: generator.hh:86
G4int fModeType
Flag indicating the mode type.
Definition: generator.hh:79
void PrimariesForCircleBeam()
Generate primaries auxiliary function for circle beam.
Definition: generator.cc:116
void GeneratePrimaries(G4Event *anEvent) override
It generates the primary vertex of the event.
Definition: generator.cc:48
G4ParticleGun * fParticleGun
Pointer to the G4ParticleGun object.
Definition: generator.hh:71
G4GenericMessenger * fMessenger_Gun
Generic messenger for the standard gamma mode.
Definition: generator.hh:75
~MyPrimaryGenerator() override
Destructor of the class.
Definition: generator.cc:38
G4String fSwitchOnLED
Flag indicating which LED has to be switched ON.
Definition: generator.hh:87
G4ThreeVector fPosFixedDecay
Position of 176Lu isotope for fixed-position mode.
Definition: generator.hh:85
void DefineCommands()
Defines new user commands for primary particle generation.
Definition: generator.cc:407
void PrimariesForLEDMode()
Generate primaries auxiliary function for LED mode.
Definition: generator.cc:154
Declaration of the class MyPrimaryGenerator.
constexpr G4double zScintillator
z-position of the scintillator crystal.
constexpr G4double radiusScintillator
Radius of the scintillator crystal.
constexpr G4double zBackFaceScintillator
z-position of the back face of the scintillator crystal.
constexpr G4double zFrontFaceScintillator
z-position of the front face of the scintillator crystal.
constexpr G4double halfheightLightGuide
Half the height of the light guide.
constexpr G4double radiusLightGuide
Radius of the light guide.
constexpr G4double halfheightScintillator
Half the height of the scintillator crystal.
constexpr G4double energyLED
Energy of the optical photons emitted by the LED.
constexpr G4double depthLED
Depth of the LED inside the hole.