GEMC  1.8
Geant4 Monte-Carlo Framework
MPrimaryGeneratorAction.cc
Go to the documentation of this file.
1 // %%%%%%%%%%
2 // G4 headers
3 // %%%%%%%%%%
4 #include "G4Event.hh"
5 #include "G4ParticleGun.hh"
6 #include "G4ParticleTable.hh"
7 #include "G4ParticleDefinition.hh"
8 #include "Randomize.hh"
9 #include "G4UnitsTable.hh"
10 
11 // %%%%%%%%%%%%%
12 // gemc headers
13 // %%%%%%%%%%%%%
15 #include "detector.h"
16 
17 // %%%%%%%%%%%
18 // C++ headers
19 // %%%%%%%%%%%
20 #include <iostream>
21 using namespace std;
22 
24 {
25  gemcOpt = opts;
26  hd_msg = gemcOpt->args["LOG_MSG"].args + " Beam Settings >> " ;
27  input_gen = gemcOpt->args["INPUT_GEN_FILE"].args;
28  GEN_VERBOSITY = gemcOpt->args["GEN_VERBOSITY"].arg;
29 
30  particleTable = G4ParticleTable::GetParticleTable();
31 
32  setBeam();
33 
34  particleGun = new G4ParticleGun(1);
35 
36  if(input_gen == "gemc_internal")
37  {
38  cout << endl << hd_msg << " Beam Type: " << Particle->GetParticleName() << endl;
39  cout << hd_msg << " Beam Momentum: " << G4BestUnit(mom, "Energy") ;
40  if(dmom > 0) cout << " +- " << G4BestUnit(dmom, "Energy") ;
41  cout << endl;
42  cout << hd_msg << " Beam Direction: (theta, phi) = (" << theta/deg << ", " << phi/deg << ")" ;
43  if(dtheta > 0 || dphi > 0) cout << " +- (" << dtheta/deg << ", " << dphi/deg << ")" ;
44  cout << " deg " << endl;
45  cout << hd_msg << " Beam Vertex: (" << vx/cm << ", " << vy/cm << ", " << vz/cm << ")" ;
46  if(dvr + dvz > 0) cout << " (radius, z-spread) = (" << dvr/cm << ", " << dvz/cm << ")" ;
47  cout << " cm " << endl;
48  cout << hd_msg << " Beam polarization: " << polDeg << "%" ;
49  cout << endl ;
50  cout << hd_msg << " Polarization Direction: (theta, phi) = (" << polTheta/deg << ", " << polPhi/deg << ")" ;
51  cout << endl;
52  }
53 
54 
55  if(NP>0)
56  {
57  cout << endl << hd_msg << " Luminosity Particle Type: " << L_Particle->GetParticleName() << endl;
58  cout << hd_msg << " Luminosity Particle Momentum: " << G4BestUnit(L_Mom, "Energy") ;
59  cout << endl;
60  cout << hd_msg << " Luminosity Particle Direction: (theta, phi) = (" << L_Theta/deg << ", " << L_Phi/deg << ")" ;
61  cout << " deg " << endl;
62  cout << hd_msg << " Luminosity Particle Vertex: (" << L_vx/cm << ", " << L_vy/cm << ", " << L_vz/cm << ")" ;
63  if(L_dvr + L_dvz > 0) cout << " (radius, z-spread) = (" << L_dvr/cm << ", " << L_dvz/cm << ")" ;
64  cout << " cm " << endl;
65  cout << hd_msg << " Number of Luminosity Particles: " << NP << endl;
66  cout << hd_msg << " Luminosity Time Window: " << TWINDOW/ns << " nanoseconds." << endl ;
67  cout << hd_msg << " Luminosity Time Between Bunches: " << TBUNCH/ns << " nanoseconds." << endl;
68  }
69 
70  if(NP2>0)
71  {
72  cout << endl << hd_msg << " Luminosity Particle 2 Type: " << L2_Particle->GetParticleName() << endl;
73  cout << hd_msg << " Luminosity Particle 2 Momentum: " << G4BestUnit(L2_Mom, "Energy") ;
74  cout << endl;
75  cout << hd_msg << " Luminosity Particle 2 Direction: (theta, phi) = (" << L2_Theta/deg << ", " << L2_Phi/deg << ")" ;
76  cout << " deg " << endl;
77  cout << hd_msg << " Luminosity Particle Vertex: (" << L2_vx/cm << ", " << L2_vy/cm << ", " << L2_vz/cm << ")" ;
78  if(L2_dvr + L2_dvz > 0) cout << " (radius, z-spread) = (" << L2_dvr/cm << ", " << L2_dvz/cm << ")" ;
79  cout << " cm " << endl;
80  cout << hd_msg << " Number of Luminosity Particles 2: " << NP2 << endl;
81  cout << hd_msg << " Luminosity Time Between Bunches: " << TBUNCH2/ns << " nanoseconds." << endl;
82  }
83 
84 }
85 
86 
88 {
89  // internal generator. Particle defined by command line
90  if(input_gen == "gemc_internal")
91  {
92  // redefining particle if in graphic mode
93  if( gemcOpt->args["USE_QT"].arg > 0)
94  setBeam();
95 
96  // Primary Particle
97  particleGun->SetParticleDefinition(Particle);
98 
99  // 4-momenta
100  Mom = mom/MeV + (2.0*G4UniformRand()-1.0)*dmom/MeV;
101  Theta = theta/rad + (2.0*G4UniformRand()-1.0)*dtheta/rad;
102  Phi = phi/rad + (2.0*G4UniformRand()-1.0)*dphi/rad;
103  double mass = Particle->GetPDGMass();
104  double akine = sqrt(Mom*Mom + mass*mass) - mass ;
105  if(gemcOpt->args["ALIGN_ZAXIS"].args == "no")
106  beam_dir = G4ThreeVector(cos(Phi/rad)*sin(Theta/rad), sin(Phi/rad)*sin(Theta/rad), cos(Theta/rad));
107  else if(gemcOpt->args["ALIGN_ZAXIS"].args == "beamp")
108  {
109  beam_dir = G4ThreeVector(cos(phi/rad)*sin(theta/rad), sin(phi/rad)*sin(theta/rad), cos(theta/rad));
110  const G4ThreeVector beam_axis(cos(phi/rad)*sin(theta/rad), sin(phi/rad)*sin(theta/rad), cos(theta/rad));
111  const G4ThreeVector rotx1(cos(phi/rad), -sin(phi/rad), 0);
112  beam_dir.rotate((2.0*G4UniformRand()-1.0)*dtheta/rad, rotx1);
113  beam_dir.rotate((2.0*G4UniformRand()-1.0)*dphi/rad, beam_axis);
114  }
115  else
116  {
117  beam_dir = G4ThreeVector(cos(cphi/rad)*sin(ctheta/rad), sin(cphi/rad)*sin(ctheta/rad), cos(ctheta/rad));
118  // const G4ThreeVector beam_axis(cos(cphi/rad)*sin(ctheta/rad), sin(cphi/rad)*sin(ctheta/rad), cos(ctheta/rad));
119  const G4ThreeVector beam_axis(beam_dir);
120  const G4ThreeVector rotx1(cos(cphi/rad), -sin(cphi/rad), 0);
121  beam_dir.rotate(Theta, rotx1);
122  beam_dir.rotate(Phi, beam_axis);
123  }
124 
125  particleGun->SetParticleEnergy(akine);
126  particleGun->SetParticleMomentumDirection(beam_dir);
127 
128  // vertex
129  double VR = sqrt(G4UniformRand())*dvr/mm;
130  double PHI = 2.0*pi*G4UniformRand();
131  Vx = vx/mm + VR*cos(PHI);
132  Vy = vy/mm + VR*sin(PHI);
133  Vz = vz/mm + (2.0*G4UniformRand()-1.0)*dvz/mm;
134  beam_vrt = G4ThreeVector(Vx, Vy, Vz);
135  particleGun->SetParticlePosition(beam_vrt);
136 
137  // polarization
138  double partPol = 0.0;
139  double polCast = 100.0 * G4UniformRand();
140  if( polCast <= polDeg ) partPol = 1;
141  double polX = partPol * sin( polTheta/rad ) * cos( polPhi/rad );
142  double polY = partPol * sin( polTheta/rad ) * sin( polPhi/rad );
143  double polZ = partPol * cos( polTheta/rad );
144  beam_pol = G4ThreeVector( polX, polY, polZ );
145  particleGun->SetParticlePolarization(beam_pol);
146 
147  // Primary particle generated int the middle of Time window
148  particleGun->SetParticleTime(TWINDOW/2);
149  particleGun->GeneratePrimaryVertex(anEvent);
150  if(GEN_VERBOSITY > 3) {
151  cout << hd_msg << " Particle id=" << Particle->GetParticleName()
152  << " Vertex=" << beam_vrt << "cm, momentum=" << Mom/GeV << " GeV, theta="
153  << Theta/deg << " degrees, phi=" << Phi/deg << " degrees" << endl;
154  if( partPol > 0 ) cout << hd_msg << " with polarization angles: polar - " << polTheta/deg << " degrees, "
155  "azimuthal - " << polPhi/deg << " degrees " ;
156  cout << endl;
157  }
158  }
159  else
160  // external generator: input file
161  {
162  // LUND format:
163  // Header (Event Info):
164  // 1 2 3 4 5 6 7 8 9 10
165  // # of Particles, # of Target Nucleons, # of Target Protons, Pol. of Target, Pol. of Electron, x, y, W2, Q2, nu
166  //
167  // Body (Particle Info):
168  // 1 2 3 4 5 6 7 8 9 10 11 12 13 14
169  // index, charge, type, particle id, parent, daughter, p_x, p_y, p_z, p_t, mass, x vertex, y vertex, z vertex
170  // type is 1 for particles in the detector
171  if(gformat == "LUND" && !gif.eof())
172  {
173  double tmp, px, py, pz;
174  int NPART, pdef, type, parent, daughter;
175  gif >> NPART >> tmp >> tmp >> targetPol >> beamPol >> tmp >> tmp >> tmp >> tmp >> tmp;
176  for(int p=0; p<NPART; p++)
177  {
178  gif >> tmp >> tmp >> type >> pdef >> parent >> daughter >> px >> py >> pz >> tmp >> tmp >> Vx >> Vy >> Vz;
179  if(type == 1)
180  {
181  // Primary Particle
182  Particle = particleTable->FindParticle(pdef);
183  if(!Particle)
184  {
185  cout << hd_msg << " Particle id " << pdef << " not found in G4 table." << endl << endl;
186 
187  return;
188  }
189  particleGun->SetParticleDefinition(Particle);
190 
191  // 4-momenta
192  G4ThreeVector pmom(px*GeV, py*GeV, pz*GeV);
193  Mom = pmom.mag();
194  Phi = pmom.getPhi();
195  Theta = pmom.getTheta();
196  double mass = Particle->GetPDGMass();
197  double akine = sqrt(Mom*Mom + mass*mass) - mass ;
198 
199  beam_dir = G4ThreeVector(cos(Phi/rad)*sin(Theta/rad), sin(Phi/rad)*sin(Theta/rad), cos(Theta/rad));
200  particleGun->SetParticleEnergy(akine);
201  particleGun->SetParticleMomentumDirection(beam_dir);
202 
203  // vertex
204  beam_vrt = G4ThreeVector(Vx*cm, Vy*cm, Vz*cm);
205  particleGun->SetParticlePosition(beam_vrt);
206 
207 
208  // beam polarization only along the beam
209  // only for the first particle
210  if(p==0)
211  {
212  beam_pol = G4ThreeVector( 0, 0, beamPol );
213  particleGun->SetParticlePolarization(beam_pol);
214  }
215 
216  // Primary particle generated int the middle of Time window
217  particleGun->SetParticleTime(TWINDOW/2);
218  particleGun->GeneratePrimaryVertex(anEvent);
219  if(GEN_VERBOSITY > 3)
220  cout << hd_msg << " Particle Number: " << p << ", id=" << pdef << "(" << Particle->GetParticleName() << ")"
221  << " Vertex=" << beam_vrt << "cm, momentum=" << pmom/GeV << " GeV" << endl;
222  }
223  }
224  }
225  }
226 
227 
228 
229  // Luminosity Particles
230  int NBUNCHES = (int) floor(TWINDOW/TBUNCH);
231  int PBUNCH = (int) floor((double)NP/NBUNCHES);
232 
233  particleGun->SetParticleDefinition(L_Particle);
234  particleGun->SetParticlePosition(L_beam_vrt);
235  double L_mass = L_Particle->GetPDGMass();
236  double L_akine = sqrt(L_Mom*L_Mom + L_mass*L_mass) - L_mass ;
237 
238  particleGun->SetParticleEnergy(L_akine);
239  particleGun->SetParticleMomentumDirection(L_beam_dir);
240  for(int b=0; b<NBUNCHES; b++)
241  {
242  for(int p=0; p<PBUNCH; p++)
243  {
244  // luminosity vertex
245  double L_VR = G4UniformRand()*L_dvr/mm;
246  double L_PHI = 2.0*pi*G4UniformRand();
247  L_vx = L_beam_vrt.x()/mm + L_VR*cos(L_PHI);
248  L_vy = L_beam_vrt.y()/mm + L_VR*sin(L_PHI);
249  L_vz = L_beam_vrt.z()/mm + (2.0*G4UniformRand()-1.0)*L_dvz/mm;
250  G4ThreeVector LUMI_V(L_vx, L_vy, L_vz);
251  particleGun->SetParticlePosition(LUMI_V);
252  particleGun-> SetParticleTime(TBUNCH*b);
253  particleGun->GeneratePrimaryVertex(anEvent);
254  }
255  }
256 
257 
258  // Luminosity Particles2
259  int NBUNCHES2 = (int) floor(TWINDOW/TBUNCH2);
260  int PBUNCH2 = (int) floor((double)NP2/NBUNCHES2);
261 
262  particleGun->SetParticleDefinition(L2_Particle);
263  particleGun->SetParticlePosition(L2_beam_vrt);
264  double L2_mass = L2_Particle->GetPDGMass();
265  double L2_akine = sqrt(L2_Mom*L2_Mom + L2_mass*L2_mass) - L2_mass ;
266 
267 
268  particleGun->SetParticleEnergy(L2_akine);
269  particleGun->SetParticleMomentumDirection(L2_beam_dir);
270  for(int b=0; b<NBUNCHES2; b++)
271  {
272  for(int p=0; p<PBUNCH2; p++)
273  {
274  // luminosity vertex 2
275  double L2_VR = G4UniformRand()*L2_dvr/mm;
276  double L2_PHI = 2.0*pi*G4UniformRand();
277  L2_vx = L2_beam_vrt.x()/mm + L2_VR*cos(L2_PHI);
278  L2_vy = L2_beam_vrt.y()/mm + L2_VR*sin(L2_PHI);
279  L2_vz = L2_beam_vrt.z()/mm + (2.0*G4UniformRand()-1.0)*L2_dvz/mm;
280  G4ThreeVector LUMI2_V(L2_vx, L2_vy, L2_vz);
281  particleGun->SetParticlePosition(LUMI2_V);
282 
283  particleGun-> SetParticleTime(TBUNCH2*b);
284  particleGun->GeneratePrimaryVertex(anEvent);
285  }
286  }
287 
288 }
289 
290 
291 
292 void MPrimaryGeneratorAction::setBeam()
293 {
294  string hd_msg = gemcOpt->args["LOG_MSG"].args + " Beam Settings >> " ;
295 
296  // vector of string - filled from the various option
297  vector<string> values;
298  string units;
299 
300  if(input_gen == "gemc_internal")
301  {
302 
303  // %%%%%%%%%%%%
304  // Primary Beam
305  // %%%%%%%%%%%%
306 
307  // Getting particle name, momentum from option value
308  values = get_info(gemcOpt->args["BEAM_P"].args);
309 
310  string pname = TrimSpaces(values[0]);
311  mom = get_number(values[1]);
312  theta = get_number(values[2]);
313  phi = get_number(values[3]);
314 
315 
316  // making sure the particle exists
317  Particle = particleTable->FindParticle(pname);
318  if(!Particle)
319  {
320  // it may be the "show_all" option. In this case print all available particle names
321  if(pname == "show_all")
322  {
323  for(int i=0; i<particleTable->entries(); i++)
324  cout << hd_msg << " g4 particle: " << particleTable->GetParticleName(i)
325  << " pdg encoding: " << particleTable->GetParticle(i)->GetPDGEncoding() << endl;
326  }
327  // otherwise it's not found. Need to exit here.
328  else
329  cout << hd_msg << " Particle " << pname << " not found in G4 table. Exiting" << endl << endl;
330 
331  exit(0);
332  }
333 
334  // Getting custom beam direction if it's set
335  values = get_info(gemcOpt->args["ALIGN_ZAXIS"].args);
336  string align = TrimSpaces(values[0]);
337  if(align == "custom")
338  {
339  ctheta = get_number(values[1]);
340  cphi = get_number(values[2]);
341  }
342 
343  // Getting momentum spread from option value
344  values = get_info(gemcOpt->args["SPREAD_P"].args);
345  dmom = get_number(values[0]);
346  dtheta = get_number(values[1]);
347  dphi = get_number(values[2]);
348 
349  // Getting vertex from option value
350  values = get_info(gemcOpt->args["BEAM_V"].args);
351  units = TrimSpaces(values[3]);
352  vx = get_number(values[0] + "*" + units);
353  vy = get_number(values[1] + "*" + units);
354  vz = get_number(values[2] + "*" + units);
355 
356 
357  // Getting vertex spread from option value
358  values = get_info(gemcOpt->args["SPREAD_V"].args);
359  units = TrimSpaces(values[2]);
360  dvr = get_number(values[0] + "*" + units);
361  dvz = get_number(values[1] + "*" + units);
362 
363  // Getting polarization from option value
364  values = get_info(gemcOpt->args["POLAR"].args);
365  polDeg = get_number(values[0]);
366  polTheta = get_number(values[1]);
367  polPhi = get_number(values[2]);
368 
369 
370  }
371  else
372  {
373  gformat.assign( input_gen, 0, input_gen.find(",")) ;
374  gfilename.assign(input_gen, input_gen.find(",") + 1, input_gen.size()) ;
375  cout << hd_msg << " Opening " << gformat << " file: " << TrimSpaces(gfilename).c_str() << endl;
376  gif.open(TrimSpaces(gfilename).c_str());
377  if(!gif)
378  {
379  cerr << hd_msg << " Can't open input file " << TrimSpaces(gfilename).c_str() << ". Exiting. " << endl;
380  exit(1);
381  }
382  }
383 
384 
385  // %%%%%%%%%%%%%%%
386  // Luminosity Beam
387  // %%%%%%%%%%%%%%%
388 
389  // Getting particle name, momentum from option value
390  values = get_info(gemcOpt->args["LUMI_P"].args);
391  string L_pname = TrimSpaces(values[0]);
392  L_Mom = get_number(values[1]);
393  L_Theta = get_number(values[2]);
394  L_Phi = get_number(values[3]);
395  L_beam_dir = G4ThreeVector(cos(L_Phi/rad)*sin(L_Theta/rad), sin(L_Phi/rad)*sin(L_Theta/rad), cos(L_Theta/rad));
396 
397  // making sure the particle exists
398  L_Particle = particleTable->FindParticle(L_pname);
399  if(!L_Particle)
400  {
401  // it may be the "show_all" option. In this case print all available particle names
402  if(L_pname == "show_all")
403  {
404  for(int i=0; i<particleTable->entries(); i++)
405  cout << hd_msg << " g4 particle: " << particleTable->GetParticleName(i) << endl;
406  }
407  // otherwise it's not found. Need to exit here.
408  else
409  cout << hd_msg << " Particle " << L_pname << " not found in G4 table. Exiting" << endl << endl;
410 
411  exit(0);
412  }
413 
414  // Getting vertex from option value
415  values = get_info(gemcOpt->args["LUMI_V"].args);
416  units = TrimSpaces(values[3]);
417  L_vx = get_number(values[0] + "*" + units);
418  L_vy = get_number(values[1] + "*" + units);
419  L_vz = get_number(values[2] + "*" + units);
420  L_beam_vrt = G4ThreeVector(L_vx, L_vy, L_vz);
421 
422  // Getting vertex spread from option value
423  values = get_info(gemcOpt->args["LUMI_SPREAD_V"].args);
424  units = TrimSpaces(values[2]);
425  L_dvr = get_number(values[0] + "*" + units);
426  L_dvz = get_number(values[1] + "*" + units);
427 
428  // Getting parameters from option value
429  values = get_info(gemcOpt->args["LUMI_EVENT"].args);
430  NP = (int) get_number(values[0]);
431  TWINDOW = get_number(values[1]);
432  TBUNCH = get_number(values[2]);
433 
434 
435 
436  // %%%%%%%%%%%%%%%%%
437  // Luminosity Beam 2
438  // %%%%%%%%%%%%%%%%%
439 
440  // Getting particle name, momentum from option value
441  values = get_info(gemcOpt->args["LUMI2_P"].args);
442  string L2_pname = TrimSpaces(values[0]);
443  L2_Mom = get_number(values[1]);
444  L2_Theta = get_number(values[2]);
445  L2_Phi = get_number(values[3]);
446  L2_beam_dir = G4ThreeVector(cos(L2_Phi/rad)*sin(L2_Theta/rad), sin(L2_Phi/rad)*sin(L2_Theta/rad), cos(L2_Theta/rad));
447 
448  // making sure the particle exists
449  L2_Particle = particleTable->FindParticle(L2_pname);
450  if(!L2_Particle)
451  {
452  // it may be the "show_all" option. In this case print all available particle names
453  if(L_pname == "show_all")
454  {
455  for(int i=0; i<particleTable->entries(); i++)
456  cout << hd_msg << " g4 particle: " << particleTable->GetParticleName(i) << endl;
457  }
458  // otherwise it's not found. Need to exit here.
459  else
460  cout << hd_msg << " Particle " << L2_pname << " not found in G4 table. Exiting" << endl << endl;
461 
462  exit(0);
463  }
464 
465  // Getting vertex from option value
466  values = get_info(gemcOpt->args["LUMI2_V"].args);
467  units = TrimSpaces(values[3]);
468  L2_vx = get_number(values[0] + "*" + units);
469  L2_vy = get_number(values[1] + "*" + units);
470  L2_vz = get_number(values[2] + "*" + units);
471  L2_beam_vrt = G4ThreeVector(L2_vx, L2_vy, L2_vz);
472 
473 
474  // Getting vertex spread from option value
475  values = get_info(gemcOpt->args["LUMI2_SPREAD_V"].args);
476  units = TrimSpaces(values[2]);
477  L2_dvr = get_number(values[0] + "*" + units);
478  L2_dvz = get_number(values[1] + "*" + units);
479 
480  // Getting parameters from option value
481  values = get_info(gemcOpt->args["LUMI2_EVENT"].args);
482  NP2 = (int) get_number(values[0]);
483  TBUNCH2 = get_number(values[1]);
484 
485 }
486 
487 
489 {
490  delete particleGun;
491  gif.close();
492 }
493 
494 
495 
496 
497 
498 
499 
500 
501 
502 
vector< string > get_info(string input)
get information from strings such as "5*GeV, 2*deg, 10*deg"
STL namespace.
Definition: usage.h:43
double pi
Definition: dc12geom.h:24
void GeneratePrimaries(G4Event *anEvent)
map< string, opts > args
Options map.
Definition: usage.h:68
string TrimSpaces(string in)
Removes leading and trailing spaces.
double get_number(string)
Returns dimension from string, i.e. 100*cm.