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 
71  // LED-System mode
72  case 40:
74  break;
75 
76  default:
77  G4cerr << "Not valid mode! Standard mode is selected!" << G4endl;
78  fModeType = 10;
80  }
81 
82  // Finally generate the primary vertex
83  fParticleGun->GeneratePrimaryVertex(anEvent);
84 }
85 
86 
87 
89 {
90  // Set position at the center
91  G4ThreeVector pos(0., 0., 0.);
92 
93  // Sample the momentum direction uniformly within the given range
94  G4double fThetaMax = std::atan(fRadiusSpread/GS::zFrontFaceScintillator);
95  G4double fCosThetaMax = std::cos(fThetaMax);
96 
97  G4double cosTheta = 1-G4UniformRand()*(1-fCosThetaMax);
98  G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
99  G4double phi = CLHEP::twopi*G4UniformRand();
100 
101  G4double ux = sinTheta*std::cos(phi);
102  G4double uy = sinTheta*std::sin(phi);
103  G4double uz = cosTheta;
104 
105  G4ThreeVector mom(ux, uy, uz);
106 
107  // Set fParticleGun
108  fParticleGun->SetParticlePosition(pos);
109  fParticleGun->SetParticleMomentumDirection(mom);
110 }
111 
112 
113 
115 {
116  G4double posR = fRadiusCircle*std::sqrt(G4UniformRand());
117  G4double posPhi = CLHEP::twopi*G4UniformRand();
118 
119  G4ThreeVector pos(posR*std::cos(posPhi), posR*std::sin(posPhi), 0);
120 
121  fParticleGun->SetParticlePosition(pos);
122  fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0., 0., 1.));
123 }
124 
125 
126 
128 {
129  // Set gamma as primary particle
130  G4ParticleDefinition *particle = G4ParticleTable::GetParticleTable()->FindParticle("gamma");
131  fParticleGun->SetParticleDefinition(particle);
132 
133  // Sample the energy from Gaus
134  G4double energy = G4RandGauss::shoot(fMeanEnergy, fSigmaEnergy);
135  fParticleGun->SetParticleEnergy(energy);
136 
137  switch(fModeType)
138  {
139  case 10: // Pointlike beam
140  break;
141  case 11: // Spread beam
143  break;
144  case 12: // Circle beam
146  break;
147  }
148 }
149 
150 
151 
153 {
154  G4ThreeVector posLed;
155  G4ThreeVector momLed;
156 
157  // Which face
158  G4double posZLed;
161  else
162  {
163  G4cerr << "Option for detector face not valid. 'Front' has been setted" << G4endl;
165  }
166 
167  // Which LED
168  if(fSwitchOnLED=="u") posLed = G4ThreeVector(0, GS::radiusLightGuide-GS::depthLED, posZLed);
169  else if(fSwitchOnLED=="d") posLed = G4ThreeVector(0, -GS::radiusLightGuide+GS::depthLED, posZLed);
170  else if(fSwitchOnLED=="l") posLed = G4ThreeVector(GS::radiusLightGuide-GS::depthLED, 0, posZLed);
171  else if(fSwitchOnLED=="r") posLed = G4ThreeVector(-GS::radiusLightGuide+GS::depthLED, 0, posZLed);
172  else
173  {
174  G4cerr << "Option for LED not valid. 'up' has been setted" << G4endl;
175  posLed = G4ThreeVector(0, GS::radiusLightGuide-GS::depthLED, posZLed);
176  }
177 
178  // Isotropic emission (not accurate, should be Lambert's cosine law,
179  // but need G4GeneralParticleSource for this)
180  G4double cosTheta = 2*G4UniformRand() - 1.;
181  G4double phi = CLHEP::twopi*G4UniformRand();
182  G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
183  G4double ux = sinTheta*std::cos(phi);
184  G4double uy = sinTheta*std::sin(phi);
185  G4double uz = cosTheta;
186  momLed = G4ThreeVector(ux,uy,uz);
187 
188  // Set everything in fParticleGun
189  G4ParticleDefinition* particle = G4ParticleTable::GetParticleTable()->FindParticle("opticalphoton");
190  fParticleGun->SetParticleDefinition(particle);
191  fParticleGun->SetParticlePosition(posLed);
192  fParticleGun->SetParticleMomentumDirection(momLed); fParticleGun->SetParticleEnergy(GS::energyLED);
193 }
194 
195 
196 
198 {
199  G4ThreeVector posDecay;
200  G4ThreeVector momDecay;
201  G4double posZ, posR, posPhi;
202 
203  switch(fModeType)
204  {
205  case 20: // Default
206  // Compute random position inside crystal
207  posZ = GS::zScintillator + 2*(G4UniformRand()-0.5)*GS::halfheightScintillator;
208  posR = GS::radiusScintillator*std::sqrt(G4UniformRand());
209  posPhi = CLHEP::twopi*G4UniformRand();
210  posDecay = G4ThreeVector(posR*std::cos(posPhi), posR*std::sin(posPhi), posZ);
211  break;
212  case 21: // Fixed position
213  posDecay = fPosFixedDecay;
214  break;
215  case 22: // Si trigger test
216  //Compute random position near ch57-Front
217  // Very situational mode, it's fine to be hard-coded
218  posDecay = G4ThreeVector(0.*mm, 0.*mm, GS::zFrontFaceScintillator+G4UniformRand()*25.*mm);
219  //posDecay = G4ThreeVector(2*(G4UniformRand()-0.5)*4*mm, 2*(G4UniformRand()-0.5)*4*mm, (150.2+2*(G4UniformRand()-0.5)*0.2)*mm);
220  break;
221  }
222 
223  // Isotropic emission
224  G4double cosTheta = 2*G4UniformRand() - 1.;
225  G4double phi = CLHEP::twopi*G4UniformRand();
226  G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
227  G4double ux = sinTheta*std::cos(phi);
228  G4double uy = sinTheta*std::sin(phi);
229  G4double uz = cosTheta;
230 
231  momDecay = G4ThreeVector(ux,uy,uz);
232 
233  // Set everything in fParticleGun
234  G4int Z = 71, A = 176;
235  G4ParticleDefinition* ion = G4IonTable::GetIonTable()->GetIon(Z, A, 0.*keV);
236  fParticleGun->SetParticleDefinition(ion);
237  fParticleGun->SetParticleCharge(0.*eplus);
238  fParticleGun->SetParticlePosition(posDecay);
239  fParticleGun->SetParticleMomentumDirection(momDecay);
240  fParticleGun->SetParticleEnergy(1*eV);
241 }
242 
243 
244 
246 {
247  G4ThreeVector posRay;
248  G4ThreeVector momRay;
249 
250  // Compute initial random position in the up detector
251  G4double posX = GS::xCosmicRayDetector + 2*(G4UniformRand()-0.5)*GS::halfZXsideCosmicRayDetector;
252  G4double posY = GS::yCosmicRayDetector + GS::halfYsideCosmicRayDetector;
253  G4double posZ = GS::zCosmicRayDetector + 2*(G4UniformRand()-0.5)*GS::halfZXsideCosmicRayDetector;
254 
255  posRay = G4ThreeVector(posX, posY, posZ);
256 
257  // Compute initial cosmic ray direction
258  G4double cosTheta = -G4UniformRand(); // Note that cosine is in [-1, 0] now
259  G4double cosThetaa = G4UniformRand(); // On the image of cos^2(Theta)
260  G4double phi = CLHEP::twopi*G4UniformRand();
261  G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
262  G4double uz = sinTheta*std::cos(phi); // Remember the axis orientation
263  G4double ux = sinTheta*std::sin(phi);
264  G4double uy = cosTheta; // Y is vertical
265 
266  momRay = G4ThreeVector(ux, uy, uz);
267 
268  while(std::abs(ProjectOnBottomDetector(posRay, momRay).x() - GS::xCosmicRayDetector) > GS::halfZXsideCosmicRayDetector || std::abs(ProjectOnBottomDetector(posRay, momRay).z() - GS::zCosmicRayDetector) > GS::halfZXsideCosmicRayDetector) // Conditions on trigger
269  {
270  posX = GS::xCosmicRayDetector + 2*(G4UniformRand()-0.5)*GS::halfZXsideCosmicRayDetector;
271  posZ = GS::zCosmicRayDetector + 2*(G4UniformRand()-0.5)*GS::halfZXsideCosmicRayDetector;
272 
273  posRay = G4ThreeVector(posX, posY, posZ);
274 
275  cosTheta = -G4UniformRand(); // Note that cosine is in [-1, 0] now
276  cosThetaa = G4UniformRand(); // On the image of cos^2(Theta)
277  phi = CLHEP::twopi*G4UniformRand();
278  while(cosThetaa > (cosTheta*cosTheta)) // Mom-dir generation
279  {
280  cosTheta = -G4UniformRand();
281  cosThetaa = G4UniformRand();
282 
283  phi = CLHEP::twopi*G4UniformRand();
284  }
285  sinTheta = std::sqrt(1. - cosTheta*cosTheta);
286  uz = sinTheta*std::cos(phi);
287  ux = sinTheta*std::sin(phi);
288  uy = cosTheta;
289 
290  momRay = G4ThreeVector(ux, uy, uz);
291  }
292 
293 
294  // Cosmic ray energy
295  G4double energy = 999.;
296  G4double energyy = 1.; // On the image of pdf(E)
297  G4double emin = 0.; // kinetic energy
298  G4double emax = 1.*TeV;
299 
300  while(energyy > PDF_E_CosmicRay(energy))
301  { // Accept-Reject method
302  energy = emin + emax*G4UniformRand();
303  // Note that the maximum probability is at minimum energy
304  energyy = PDF_E_CosmicRay(emin)*G4UniformRand();
305  }
306 
307  // Set everything in fParticleGun
308  G4ParticleDefinition* particle = nullptr;
309  if(G4UniformRand() < 0.5)
310  particle = G4ParticleTable::GetParticleTable()->FindParticle("mu-");
311  else
312  particle = G4ParticleTable::GetParticleTable()->FindParticle("mu+");
313 
314  fParticleGun->SetParticleDefinition(particle);
315  fParticleGun->SetParticlePosition(posRay);
316  fParticleGun->SetParticleMomentumDirection(momRay); fParticleGun->SetParticleEnergy(energy);
317 }
318 
319 
320 
321 G4double MyPrimaryGenerator::PDF_E_CosmicRay(G4double energy)
322 {
323  if(energy < 3.4*GeV)
324  {
325  return std::pow(3.4*GeV, -2.7);
326  }
327  else
328  {
329  return std::pow(energy, -2.7);
330  }
331 }
332 
333 
334 
335 G4ThreeVector MyPrimaryGenerator::ProjectOnBottomDetector(G4ThreeVector pos0, G4ThreeVector mom0)
336 {
337  G4double y_b = -(GS::yCosmicRayDetector + GS::halfYsideCosmicRayDetector);
338  G4double x_b, z_b;
339  G4double t = (y_b - pos0.y())/mom0.y();
340 
341  x_b = pos0.x() + mom0.x()*t;
342  z_b = pos0.z() + mom0.z()*t;
343 
344  return G4ThreeVector(x_b, y_b, z_b);
345 };
346 
347 
348 
350 {
351  // Define my UD-messenger for mode selection
352  fMessenger_Mode = new G4GenericMessenger(this, "/MC_LYSO/", "Commands for MC_LYSO run");
353  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");
354 
355  // Define my UD-messenger for primary gamma
356  fMessenger_Gun = new G4GenericMessenger(this, "/MC_LYSO/myGun/", "Cinematical settings for primary particle");
357  fMessenger_Gun->DeclarePropertyWithUnit("meanEnergy", "MeV", fMeanEnergy, "Mean of the gaussian distribution of initial gamma energy");
358  fMessenger_Gun->DeclarePropertyWithUnit("sigmaEnergy", "MeV", fSigmaEnergy, "Sigma of the gaussian distribution of initial gamma energy");
359  fMessenger_Gun->DeclarePropertyWithUnit("radiusSpread", "mm", fRadiusSpread, "Set radius of the spread on the front face of scintillator");
360  fMessenger_Gun->DeclarePropertyWithUnit("radiusCircle", "mm", fRadiusCircle, "Set radius of the beam (in 'Circle' case)");
361  fMessenger_Gun->DeclarePropertyWithUnit("posLuDecay", "mm", fPosFixedDecay, "Set position for Lu decay in fixed position mode");
362 
363  // Define my UD-messenger for LED mode
364  fMessenger_Calib = new G4GenericMessenger(this, "/MC_LYSO/myGun/LED-System/", "Settings for LED-system calibration");
365  fMessenger_Calib->DeclareProperty("FrontOrBack", fChooseFrontorBack, "Choose side of detector you want to calibrate: F(ront) or B(ack)");
366  fMessenger_Calib->DeclareProperty("switchOnLED", fSwitchOnLED, "Choose which LED turn ON: u(p), d(own), r(ight), l(eft)");
367 }
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:82
void PrimariesForSpreadBeam()
Generate primaries auxiliary function for spread beam.
Definition: generator.cc:88
void PrimariesForCosmicRaysMode()
Generate primaries auxiliary function for Cosmic rays mode.
Definition: generator.cc:245
G4double fSigmaEnergy
Sigma of the gaussian distribution of the energy of the primary particle.
Definition: generator.hh:81
void PrimariesForLuDecayMode()
Generate primaries auxiliary function for Lu decay mode.
Definition: generator.cc:197
G4GenericMessenger * fMessenger_Calib
Generic messenger for the calibration mode.
Definition: generator.hh:75
G4GenericMessenger * fMessenger_Mode
Generic messenger for mode selection.
Definition: generator.hh:73
void PrimariesForStandardMode()
Generate primaries auxiliary function for Standard mode.
Definition: generator.cc:127
G4double fRadiusCircle
Radius of the beam profile in circle type.
Definition: generator.hh:83
G4double fMeanEnergy
Mean of the gaussian distribution of the energy of the primary particle.
Definition: generator.hh:80
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:85
G4int fModeType
Flag indicating the mode type.
Definition: generator.hh:78
void PrimariesForCircleBeam()
Generate primaries auxiliary function for circle beam.
Definition: generator.cc:114
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:70
G4GenericMessenger * fMessenger_Gun
Generic messenger for the standard gamma mode.
Definition: generator.hh:74
~MyPrimaryGenerator() override
Destructor of the class.
Definition: generator.cc:38
G4String fSwitchOnLED
Flag indicating which LED has to be switched ON.
Definition: generator.hh:86
G4ThreeVector fPosFixedDecay
Position of 176Lu isotope for fixed-position mode.
Definition: generator.hh:84
void DefineCommands()
Defines new user commands for primary particle generation.
Definition: generator.cc:349
void PrimariesForLEDMode()
Generate primaries auxiliary function for LED mode.
Definition: generator.cc:152
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.