LBNEPrimaryGeneratorAction.cc
Go to the documentation of this file.
1 //----------------------------------------------------------------------
2 // $Id
3 //----------------------------------------------------------------------
4 
5 #include <iostream>
6 #include <fstream>
7 #include <iomanip>
8 
10 
11 #include <math.h>
12 #include <map>
13 #include "G4Event.hh"
14 #include "G4ParticleGun.hh"
15 #include "G4ParticleTable.hh"
16 #include "G4ParticleDefinition.hh"
17 #include "G4ThreeVector.hh"
18 #include "globals.hh"
19 #include "Randomize.hh"
20 #include "G4UImanager.hh"
21 
22 #include "LBNEPrimaryMessenger.hh"
23 #include "LBNERunManager.hh"
24 #include "LBNEParticleCode.hh"
25 #include "LBNEAnalysis.hh"
26 #include "LBNEVolumePlacements.hh"
27 
28 
29 #include "TROOT.h"
30 #include <TFile.h>
31 #include <TTree.h>
32 #include <TLeaf.h>
33 #include <TSystem.h>
34 #include "TH1.h"
35 #include "TRandom3.h"
36 #include "TF1.h"
37 #include "TMath.h"
38 #include "Math/IFunction.h"
39 
40 using namespace std;
41 
43  fRunManager(0),
44  fPrimaryMessenger(0),
45  fParticleGun(0),
46 
47  fInputFile(0),
48  fInputTree(0),
49  lineForFluka(0),
50 
51  fProtonN(0),
52  fNoOfPrimaries(0),
53  fCurrentPrimaryNo(0),
54 
55  //fTunnelPos(0),
56 
57  fProtonMomentumMag(120.0*CLHEP::GeV),
58  fProtonOrigin(0),
59  fProtonMomentum(0),
60  fProtonIntVertex(0),
61  fParticleMomentum(0),
62  fParticlePosition(0),
63 
64  fTgen(-99),
65  fType(-99),
66  fMuGeantinoCnt(0),
67  fWeight(1.0),
68  fCorrectForAngle(true),
69  fBeamOnTarget(false),
70  fBeamOffsetX(0.0),
71  fBeamOffsetY(0.0),
72  fBeamOffsetZ(-3.6*CLHEP::m), // beam divergence assumed to be very small...
73  // If old way of defining the beam!.. See below.
74  // Should place well in front of the baffle,
75  // hopefully not too much air in the way..
76  fBeamMaxValX(1.0*CLHEP::m), // No truncation of the beam by default.
77  fBeamMaxValY(1.0*CLHEP::m), // No truncation of the beam by default.
78  fBeamSigmaX(1.3*CLHEP::mm),
79  fBeamSigmaY(1.3*CLHEP::mm),
80  fBeamAngleTheta(0.0),
81  fBeamAnglePhi(0.0),
82  fUseCourantSniderParams(true),
83  fUseJustSigmaCoord(false),
84  fRadiusAnnularBeam(-1.0), // default is the usual
85  fSigmaForAnnularbeam(-1.0),
86  fBeamEmittanceX(20.), // In pi mm mRad (Fermi units of emittance)
87  fBeamEmittanceY(20.),
88  fBeamBetaFunctionX(64.842), // in meter, assuming a 120 GeV beam
89  fBeamBetaFunctionY(64.842), // in meter, assuming a 120 GeV beam // John Jonstone, e-mail, Oct 11
90  fBeamBetaFunctionAt120(64.842), // in meter, assuming a 120 GeV beam For the 0.7 MW option!....
91  fBeamBetaFunctionAt80(43.228), // in meter, assuming a 120 GeV beam
92  fBeamBetaFunctionAt60(32.421), // in meter, assuming a 120 GeV beam
93 
94  fUseGeantino(false),
95  fUseMuonGeantino(false),
96  fUseChargedGeantino(false),
97  fZOriginGeantino(-515.), // Upstream of target.
98  fSigmaZOriginGeantino(100.), // Upstream of target.
99  fPolarAngleGeantino(.005),
100  fPolarAngleGeantinoMin(0.),
101  fZOriginForMuGeantino(G4ThreeVector(0., 0., 0.)),
102  fYOriginForMuGeantino(G4ThreeVector(0., 0., 0.)),
103  fMomentumForMuGeantino(G4ThreeVector(7.5, 0., 0.)),
104  fAngleForMuGeantino(G4ThreeVector(0.01, 0., 0.))
105 {
106  fRunManager =(LBNERunManager*)LBNERunManager::GetRunManager();
108  G4int n_particle = 1;
109  fParticleGun = new G4ParticleGun(n_particle);
110  //
111  // New default situation: for the 1.2 MW option..
112  //
113  fBeamSigmaX = 1.7*CLHEP::mm; fBeamSigmaY = 1.7*CLHEP::mm; fBeamBetaFunctionX = 110.9; fBeamBetaFunctionY = 110.9;
114  //
115  // Test the estimate fo the beta function
116  //
117 // std::cerr << " Pz BetaFunc " << std::endl;
118 // for (int iPz=0; iPz !=100; iPz++)
119 // std::cerr << " " << (50.0 + iPz*1.0) << " " <<
120 // GetBetaFunctionvsBeamEnergy((50.0 + iPz*1.0)) << std:: endl;
121 //
122  // Other CourantSnider functions set down below.
123 }
124 //---------------------------------------------------------------------------------------
126 {
127  delete fPrimaryMessenger;
128  delete fParticleGun;
129  if (lineForFluka != 0) free(lineForFluka);
130 }
131 //---------------------------------------------------------------------------------------
133 {
134 
135  // Make sure we have a consistent way to define the beam
136 
138  G4Exception("LBNEPrimaryGeneratorAction::SetProtonBeam", " ",
139  FatalErrorInArgument,
140  "Attempting to refdefined both CourantSnider parameters and beam spot size. Please choose one!..." );
141  }
142  G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
143 
144  if (fUseGeantino) {
145  fParticleGun->SetParticleDefinition(particleTable->FindParticle("geantino"));
146  }
147  else if (fUseMuonGeantino) {
148  fParticleGun->SetParticleDefinition(particleTable->FindParticle("mu+"));
149  }
150  else if (fUseChargedGeantino) {
151  fParticleGun->SetParticleDefinition(particleTable->FindParticle("chargedgeantino"));
152  }
153  else fParticleGun->SetParticleDefinition(particleTable->FindParticle("proton"));
154 
155  const double eBeam = std::sqrt(fProtonMomentumMag*fProtonMomentumMag + 0.938272*CLHEP::GeV*0.938272*CLHEP::GeV);
156  const double pEkin = eBeam - 0.938272*CLHEP::GeV;
157  fParticleGun->SetParticleEnergy(pEkin);
158  // This needs to be implemented via data cards!!!
159  G4ThreeVector beamPosition(0., 0., fBeamOffsetZ);
160 
161  fParticleGun->SetParticlePosition(beamPosition);
162  G4ThreeVector beamDirection(1,0,0);
163  beamDirection.setTheta(fBeamAngleTheta);
164  beamDirection.setPhi(fBeamAnglePhi);
165  G4cout << "Beam direction of " << beamDirection[0] << " " <<
166  beamDirection[1] << " " << beamDirection[2] << endl;
167  fParticleGun->SetParticleMomentumDirection(beamDirection);
168 
170 
171 // LBNEVolumePlacements* volP=LBNEVolumePlacements::Instance();
172 // bool use1p2MW = volP->GetUse1p2MW();
173  // Upgrade the beam sigma April 17: also the beam emittance!
174 // if (use1p2MW) { fBeamSigmaX = 1.7*CLHEP::mm; fBeamSigmaY = 1.7*CLHEP::mm; fBeamBetaFunctionX = 110.9; fBeamBetaFunctionY = 110.9;}
175 
176 
177  G4String spaces = " ";
178  std::cout << spaces << "Configuring the Proton beam..." << std::endl
179  << spaces << " Momentum = " << fParticleGun->GetParticleMomentum()/CLHEP::GeV << " GeV/c" << std::endl
180  << spaces << " Kinetic Energy = " << fParticleGun->GetParticleEnergy()/CLHEP::GeV << " GeV" << std::endl
181  << spaces << " Beam Offset, X = " << fBeamOffsetX/CLHEP::mm << " mm" << std::endl
182  << spaces << " Beam Offset, Y = " << fBeamOffsetY/CLHEP::mm << " mm" << std::endl
183  << spaces << " Beam Offset, Z = " << fBeamOffsetZ/CLHEP::m << " m" << std::endl
184  << spaces << " Beam Sigma, X = " << fBeamSigmaX/CLHEP::mm << " mm" << std::endl
185  << spaces << " Beam Sigma, Y = " << fBeamSigmaY/CLHEP::mm << " mm" << std::endl
186  << spaces << " Beam Max. d|X| = " << fBeamMaxValX/CLHEP::mm << " mm" << std::endl
187  << spaces << " Beam Max, d|Y| = " << fBeamMaxValY/CLHEP::mm << " mm" << std::endl
188  << spaces << " Direction = " << fParticleGun->GetParticleMomentumDirection() << std::endl;
189 
191 
192  const double gammaLorentz = eBeam/(0.938272*CLHEP::GeV);
193  const double betaLorentz = std::sqrt(1.0 - 1.0/(gammaLorentz*gammaLorentz));
194  const double betaGammaLorentz = gammaLorentz*betaLorentz;
195 
196  const double betaFuncStarX = (std::abs(fProtonMomentumMag - 120.*CLHEP::GeV) < 0.1) ?
198  GetBetaFunctionvsBeamEnergy(fProtonMomentumMag/CLHEP::GeV); // in meters, not mm
199  const double betaFuncStarY = (std::abs(fProtonMomentumMag - 120.*CLHEP::GeV) < 0.1) ?
202 
203  fBeamAlphaFunctionX = -(fBeamOffsetZ/CLHEP::m)/betaFuncStarX;
204  fBeamAlphaFunctionY = -(fBeamOffsetZ/CLHEP::m)/betaFuncStarY;
205 
206  fBeamBetaFuncGenX = betaFuncStarX + ((fBeamOffsetZ/CLHEP::m)*(fBeamOffsetZ/CLHEP::m))/betaFuncStarX;// in meters
207  fBeamBetaFuncGenY = betaFuncStarY + ((fBeamOffsetZ/CLHEP::m)*(fBeamOffsetZ/CLHEP::m))/betaFuncStarY;
208 
209  fBeamSigmaX = std::sqrt( 1.0e3 * fBeamBetaFuncGenX/CLHEP::m * fBeamEmittanceX/ (6.0*betaGammaLorentz)); // in mm
210  fBeamSigmaY = std::sqrt( 1.0e3 * fBeamBetaFuncGenY/CLHEP::m * fBeamEmittanceY/ (6.0*betaGammaLorentz));
211  std::cout << spaces << "Re-Configuring the Proton beam using Courant-Snider parameters " << std::endl;
212  std::cout << spaces << " Beta function X at Point of creation " << fBeamBetaFuncGenX << " m " << std::endl;
213  std::cout << spaces << " Beta function Y at Point of creation " << fBeamBetaFuncGenY << " m " << std::endl;
214  std::cout << spaces << " Alpha function X at Point of creation " << fBeamAlphaFunctionX << std::endl;
215  std::cout << spaces << " Alpha function Y at Point of creation " << fBeamAlphaFunctionY << std::endl;
216  std::cout << spaces << " Sigma X at Point of creation " << fBeamSigmaX << " mm " << std::endl;
217  std::cout << spaces << " Sigma Y at Point of creation " << fBeamSigmaY << " mm " << std::endl;
218 
219  }
220  if (fRadiusAnnularBeam > 1.0e-6) {
221  // We will be using some of the ROOT math utilities, namely generating
222  // random number from a histogram. But we need to control the seed....
223  // The following statement may cause havoc in other part of the code where
224  // The root Random generator is called..
225  //
226  int startSeed = CLHEP::HepRandom::getTheSeed();
227  startSeed += 1267; // a bit arbitrary.
228  gRandom = new TRandom3(0);
229  gRandom->SetSeed(startSeed);
231  std::cout << spaces << " But.. but we will be using an annular beam, defined as follow " << std::endl;
232  std::cout << spaces << " f(r; R, sigma) = d^2N/drdTheta = " << std::endl;
233  std::cout << spaces << " = 1/(2*pi*sigma^2) * exp[(-r^2-R^2)/(2*sigma^2)] * I0(rR/sigma^2) " << std::endl;
234  std::cout << spaces << " with R = " << fRadiusAnnularBeam << " and sigma = "
236  std::cout << spaces << " This sigma is derived from Sigma X and Sigma Y, stated above " << std::endl;
237  // Prepare the distirbution.
238  theModBesselFunc1rstKind = new TF1("I_0", "TMath::BesselI0(x)", 0., 10.);
239  histAnnularRadial = new TH1F("AN1", "Annular beam, radial", 1000, 0., 6.*fRadiusAnnularBeam);
240  const double fSigSq = fSigmaForAnnularbeam*fSigmaForAnnularbeam;
241  const double RSq = fRadiusAnnularBeam*fRadiusAnnularBeam;
242  const double stepR = 6.*fRadiusAnnularBeam/1000.;
243  for (int kR=0.; kR != 1000; kR++) {
244  const double r = 0.49*stepR + kR*stepR;
245  const double f = (1.0/(2.0*M_PI*fSigSq)) * std::exp((-r*r -RSq)/(2.*fSigSq)) *
246  theModBesselFunc1rstKind->Eval(r*fRadiusAnnularBeam/fSigSq);
247  histAnnularRadial->Fill(r, r*f);
248  }
249  }
250 
251 }
253 {
254  if (fFlukaASCII.is_open()) fFlukaASCII.close();
255  fFlukaASCII.open(ntupleName.c_str());
256  if (!fFlukaASCII.is_open()) {
257  G4Exception("LBNEPrimaryGeneratorAction::OpenNtupleFLUKAASCII", " ",
258  FatalErrorInArgument, " Fluka Input file is not open, unexpected and fatal " );
259  }
260  maxLengthForFlukaLine = 1000;
261  lineForFluka = static_cast<char*>(malloc(maxLengthForFlukaLine));
263  if (!fFlukaASCII.good()) {
264  G4Exception("LBNEPrimaryGeneratorAction::OpenNtupleFLUKAASCII", " ",
265  FatalErrorInArgument, " Fluka Input file no longer accessible " );
266  }
267  if (fFlukaASCII.eof()) {
268  fFlukaASCII.close();
269  G4Exception("LBNEPrimaryGeneratorAction::GenerateFlukaPrimary", " ",
270  FatalErrorInArgument, " Fluka Input file is empty.... " );
271  }
272  //
273  // The first line if the Header for R..
274  //
275  return true;
276 
277 }
278 //---------------------------------------------------------------------------------------
279 G4bool LBNEPrimaryGeneratorAction::OpenNtuple(G4String ntupleName)
280 {
281  G4String message("Input Ntuple");
282  message += ntupleName + G4String("Not yet supported");
283  G4Exception("LBNEPrimaryGeneratorAction::OpenNtuple", " ",
284  FatalErrorInArgument, message.c_str());
285  /*
286  fCurrentPrimaryNo=0;
287 
288  G4bool fIsOpen=false;
289  fInputFile=new TFile(ntupleName,"READ");
290  if (!fInputFile->IsZombie())
291  {
292 
293  //fInputTree=(TTree*)(fInputFile->Get("h3"));
294  fInputTree=(TTree*)(fInputFile->Get((fLBNEData->GetInputNtpTreeName()).c_str()));
295 
296  if(!fInputTree)
297  {
298  //G4cout<<"LBNEPrimaryGeneratorAction: Can't find tree "<< G4endl;
299  G4cout<<"LBNEPrimaryGeneratorAction: Can't find tree with name "
300  << fLBNEData->GetInputNtpTreeName() << G4endl;
301  }
302 
303  fCurrentPrimaryNo=0;
304  G4int entries = fInputTree->GetEntries();
305  if(fLBNEData->GetNEvents() > 0 && fLBNEData->GetNEvents() < entries)
306  fNoOfPrimaries = fLBNEData->GetNEvents();
307  else
308  fNoOfPrimaries = fInputTree->GetEntries();
309 
310 
311  fIsOpen=true;
312  }
313  else
314  {
315  G4cout<<"LBNEPrimaryGeneratorAction: Input (fluka/mars) root file doesn't exist"
316  <<" Aborting run"<<G4endl;
317  fIsOpen=false;
318  }
319  return fIsOpen;
320  */
321  return false;
322 }
323 //---------------------------------------------------------------------------------------
325 {
326  if (fFlukaASCII.is_open()) fFlukaASCII.close();
327  if(!fInputFile) return;
328 
329  if(fInputFile && fInputFile -> IsOpen())
330  {
331  fInputFile->Close();
332  if(fInputFile->IsOpen())
333  {
334  std::cout << " PROBLEM: Failed to close Input Ntuple " << fInputFile -> GetName() << std::endl;
335  }
336  else
337  {
338  std::cout << " Sucessfully closed Input Ntuple " << fInputFile -> GetName() << std::endl;
339  }
340  }
341 
342  std::cout << "LBNEPrimaryGeneratorAction::CloseNtuple() - " << std::endl;
343  std::cout << " Used " << fProtonN << " protons from input file" << endl;
344 
345 
346 
347 
349 }
350 
352 
353  // quadratic interpolation, based on the e-mail from
354  // John Jostone.
355  G4Exception("LBNEPrimaryGeneratorAction::GetBetaFunctionvsBeamEnergy", "", FatalException,
356  " With the current 1.2 MW option, the use of Courand Snider params and a beam energy != 120 GeV is prohibited ");
357 
358  // Define and slove a set of quadratic equation.
359  const double betaSecond80 = (fBeamBetaFunctionAt120 + 2.0*fBeamBetaFunctionAt60 -
360  3.0*fBeamBetaFunctionAt80)/2400.;
361  const double betaPrime80 = (1.0/40.)*(fBeamBetaFunctionAt120 - fBeamBetaFunctionAt80 - betaSecond80*1600.);
362 
363  const double dp = pz - 80.;
364  std::cerr << " Using LBNEPrimaryGeneratorAction::GetBetaFunctionvsBeamEnergy... fBeamBetaFunctionAt120 " <<
366  << " fBeamBetaFunctionAt60 " << fBeamBetaFunctionAt60 << std::endl;
367  return (fBeamBetaFunctionAt80 + betaPrime80*dp + betaSecond80*dp*dp);
368 }
369 //---------------------------------------------------------------------------------------
371 {
372  int verboseLevel = G4EventManager::GetEventManager()->GetVerboseLevel();
373  if(verboseLevel > 1)
374  {
375  std::cout << "Event " << anEvent->GetEventID() << ": LBNEPrimaryGeneratorAction::GeneratePrimaries() Called." << std::endl;
376  }
377 
378 
379  G4int totNoPrim=fRunManager->GetNumberOfEvents();
380  if (totNoPrim>20)
381  {
382  if (fCurrentPrimaryNo%(totNoPrim/20)==0)
383  G4cout<<"Processing particles #: "
384  <<fCurrentPrimaryNo<<" to "<< fCurrentPrimaryNo+(totNoPrim/20) <<G4endl;
385  }
386 
387  {
388 /*
389  if (fLBNEData->GetUseFlukaInput() || fLBNEData->GetUseMarsInput())
390  {
391  LBNEPrimaryGeneratorAction::GenerateBeamFromInput(anEvent);
392  }
393 */
396  }
397  else if (fFlukaASCII.is_open()) {
399  } else {
401  }
402 
403  }
404 
405  //fCurrentPrimaryNo++;
407 }
408 
409 
410 
411 //---------------------------------------------------------------------------------------
412 //---------------------------------------------------------------------------------------
413 //---------------------------------------------------------------------------------------
414 //---------------------------------------------------------------------------------------
415 
416 //---------------------------------------------------------------------------------------
418 {
419 
420 // If nothing else is set, use a proton beam
421  G4double x0 = 0.;
422  G4double y0 = 0.;
423  G4double z0 = 0.;
424 
425  do
426  {
427  x0 = G4RandGauss::shoot(0.0, fBeamSigmaX);
428  }
429  while(std::abs(x0) > fBeamMaxValX);
430  do
431  {
432  y0 = G4RandGauss::shoot(0.0, fBeamSigmaY);
433  }
434  while(std::abs(y0) > fBeamMaxValY);
435 
436  const double xFromEmitt = x0;
437  const double yFromEmitt = y0;
438  z0 = fBeamOffsetZ;
439 
440  if(!fBeamOnTarget){
441  // b.c. if fBeamOnTarget, all offsets are ignored.
442  x0 += fBeamOffsetX;
443  y0 += fBeamOffsetY;
444  }
445 
446  G4double dx=0.;
447  G4double dy=0.;
448  G4double dz=0.;
449 
450  if(fabs(fBeamAngleTheta) > 1e-6){
451  dx += sin(fBeamAngleTheta)*cos(fBeamAnglePhi);
452  dy += sin(fBeamAngleTheta)*sin(fBeamAnglePhi);
453  }
454  dz = std::sqrt(1.0 - (dx*dx + dy*dy));
455  G4ThreeVector direction(dx, dy, dz);
456 
458  x0 += (dx/dz)*z0;
459  y0 += (dy/dz)*z0;
460  }
461  double phaseX = 0.;
462  double phaseY = 0.;
463  if (fUseCourantSniderParams) { // The tails in the dx, dy distribution not quite Gaussian,
464  // but this is small error.
465  phaseX = 2.0*M_PI*G4RandFlat::shoot();
466  const double amplX = xFromEmitt/std::cos(phaseX);
467  dx += (std::sin(phaseX)*amplX - fBeamAlphaFunctionX*xFromEmitt)/(fBeamBetaFuncGenX*CLHEP::m); // in radian (mm/mm)
468  phaseY = 2.0*M_PI*G4RandFlat::shoot();
469  const double amplY = yFromEmitt/std::cos(phaseY);
470  dy += (std::sin(phaseY)*amplY - fBeamAlphaFunctionY*yFromEmitt)/(fBeamBetaFuncGenY*CLHEP::m);
471  dz = std::sqrt(1.0 - (dx*dx + dy*dy));
472  direction = G4ThreeVector(dx, dy, dz);
473  }
474  if (fRadiusAnnularBeam > 1.0e-6) {
475  const double r = histAnnularRadial->GetRandom();
476  const double phi = 2.0*M_PI*G4RandFlat::shoot();
477  x0 = r*std::cos(phi);
478  y0 = r*std::sin(phi);
479  }
480 
481 // if (std::abs(y0) > 5.0) {
482 // std::cerr << " !!!!!.... Anomalously large y0 " << y0 << " dy " << dy << " Phase y " << phaseY << std::endl;
483 // }
484 
486  fProtonOrigin = G4ThreeVector(x0, y0, z0);
487  fProtonMomentum = G4ThreeVector(dx*fProtonMomentumMag, dy*fProtonMomentumMag, dz*fProtonMomentumMag);
488  fProtonIntVertex = G4ThreeVector(-9999.,-9999.,-9999.);
489  fWeight=1.; //for primary protons set weight and tgen
490  fTgen=0;
491 
492  fParticleGun->SetParticlePosition(G4ThreeVector(x0,y0,z0));
493  fParticleGun->SetParticleMomentumDirection(direction);
494  //
495  // Backdoor to create lots of beam particle, records data on where we are on the target..
496  //
497  // G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
498  // fParticleGun->SetParticleDefinition(particleTable->FindParticle("geantino"));
499  fParticleGun->GeneratePrimaryVertex(anEvent);
500 }
501 //
502 // Used to begug geometry, and/or, Radiography of the detector.
503 //
505 {
506 
507 
508 
509 // If nothing else is set, use a proton beam
510 
511  const double dr = fPolarAngleGeantinoMin +
512  (fPolarAngleGeantino - fPolarAngleGeantinoMin)*G4RandFlat::shoot();
513 // Back door to study tile of Horn1 via magentic effect. Take a point source at = 0.
514 // double dPhi = M_PI/2.;
515 // while (((dPhi > M_PI/4.) && (dPhi < 3.0*M_PI/4.)) ||
516 // ((dPhi > (M_PI + M_PI/4.)) && (dPhi < (2.0*M_PI - M_PI/4.))))
517 // dPhi = 2.0*M_PI*G4RandFlat::shoot();
518 
519  // Back door to test limits in case of Helium tube misalignments.
520  const double dPhi = 2.0*M_PI*G4RandFlat::shoot();
521 // const double dPhi = 0.;
522 // const double dPhi = -M_PI/2. + 0.07893; // Shooting in a fixed direction.. Temporary
523 // const double dPhi = -M_PI/2.; // Shooting in a fixed direction.. Temporary
524  double dx = dr*std::cos(dPhi);
525 // if (dx < 0.) dx *=-1.0; // Studying the right side (x > 0.);
526  double dy = dr*std::sin(dPhi);
527  double dz = sqrt(1.0 - (dx*dx + dy*dy));
528  G4ThreeVector direction(dx, dy, dz);
529 // std::cerr << " ... dr " << dr << " direction " << direction << std::endl;
530 //
531 // Store it a proton internally to lbne d/s ... Messy:
533 
534  fTgen=0;
535 // const double x = G4RandGauss::shoot(0.0, 1.3);
536 // const double y = G4RandGauss::shoot(0.0, 1.3);
537 // Back door to study tile of Horn1 via magentic effect. Take a point source at = 0.
538  double x = G4RandGauss::shoot(0.0, 1.3e-10);
539  double y = G4RandGauss::shoot(0.0, 1.3e-10);
540 // x = 1.5; y = 0.; // off center, to study the height
541 // Back door to study effect of overlap
542 // const double dPhiPos = 2.0*M_PI*G4RandFlat::shoot();
543 // const double x = G4RandGauss::shoot(0.0, 0.00001) + 26.0 * std::sin(dPhiPos);
544 // const double y = G4RandGauss::shoot(0.0, 0.00001) + 26.0 * std::cos(dPhiPos);
545 // const double x = 0.040*CLHEP::mm;
546  double z = fZOriginGeantino + G4RandGauss::shoot(0.0, fSigmaZOriginGeantino);
547  //
548  // November 2014: scan in either Z, Y, angle or momentum.
549  //
550  bool doScanInZPos = (fZOriginForMuGeantino[2] > 0.001);
551  bool doScanInYPos = (fYOriginForMuGeantino[2] > 0.001);
552  bool doScanInMomentum = (fMomentumForMuGeantino[2] > 0.001);
553  bool doScanInAngle = (fAngleForMuGeantino[2] > 0.001);
554  if (doScanInZPos || doScanInYPos || doScanInMomentum || doScanInAngle) {
555  const int evtId = fMuGeantinoCnt;
556  direction[0] = 0.;
557  dy = fAngleForMuGeantino[0];
558  if (doScanInAngle) dy += (evtId)*fAngleForMuGeantino[1];
559  dz = std::sqrt(1.0 - dy*dy);
560  direction = G4ThreeVector(0., dy, dz);
561  x = 0.;
562  y = fYOriginForMuGeantino[0];
563  if (doScanInYPos) y += (evtId)*fYOriginForMuGeantino[1];
564  z = fZOriginForMuGeantino[0];
565  if (doScanInZPos) z += (evtId)*fZOriginForMuGeantino[1];
566  double pMu = fMomentumForMuGeantino[0];
567  if (doScanInMomentum) pMu += (evtId)*fMomentumForMuGeantino[1];
568  fProtonMomentumMag = std::sqrt(pMu*pMu + (105.658*105.658*CLHEP::MeV*CLHEP::MeV)); // misnomer..
569  if (fPtForMuGeantino[2] > 1.) { // Per request from Jim H. and Alberto, scan either in Z position of momentum,
570  // but at a fixed Pt
571  const double Pt = fPtForMuGeantino[0];
572  const double pTotal = std::sqrt(pMu*pMu + Pt*Pt); // pMu is Pz, here..
573  direction = G4ThreeVector(0., Pt/pTotal, pMu/pTotal);
574  fProtonMomentumMag = std::sqrt(pTotal*pTotal + (105.658*105.658*CLHEP::MeV*CLHEP::MeV)); // misnomer..
575  }
576  fMuGeantinoCnt++;
577 // std::cerr << " fAngleForMuGeantino .. " << fAngleForMuGeantino << " dy " << dy << std::endl;
578  }
579 // std::cerr << " Z Particle position.. .. " << z << std::endl;
580  fParticleGun->SetParticlePosition(G4ThreeVector(x, y, z));
581  fParticleGun->SetParticleMomentumDirection(direction);
582 // std::cerr << " Muon Vertex " << G4ThreeVector(x, y, z) << " direction " << direction << std::endl;
584  if (fUseChargedGeantino)
585  fParticleGun->SetParticleEnergy(fProtonMomentumMag);
586  else
587  fParticleGun->SetParticleEnergy(fProtonMomentumMag - (105.658*CLHEP::MeV));
588 // std::cerr << " I am indeed calling for muon .. and quit " << std::endl; exit(2);
589  }
590  // back door use of the proton momentum data card.,
591  // or see above, for scanning on pMu..This is the kinetic energy of the gun, not the total energy. .
592  fParticleGun->GeneratePrimaryVertex(anEvent);
593 }
594 
595 
596 
597 //---------------------------------------------------------------------------------------
598 //
599 // Old interface...
600 //
602 {
603  /*
604  Fluka and Mars input variables:
605  FLUKA MARS
606  -----------------------------------------------------------------------------------------------
607  TYPE TYPE - type of particle (see LBNEAnalysis::GetParticleName())
608  X, Y, Z X,Y,Z - particle coordinates
609  PX, PY, PZ PX, PY, PZ - particle momentum
610  WEIGHT WEIGHT - particle weight
611  GENER GENER - particle generation
612  PROTVX, PROTVY, PROTVZ PVTXX, PVTXY, PVTXZ - proton interaction vertex
613  PROTX, PROTY, PROTZ PROTX, PROTY, PROTZ - proton initial coordinates
614  PROTPX, PROTPY, PROTPZ PROTPX, PROTPY, PROTPZ - proton initial momentum
615  MOMPX,MOMPY,MOMPZ PPX, PPY, PPZ - ???
616  MOMTYPE PTYPE - ???
617  */
618 
619  G4Exception("LBNEPrimaryGeneratorAction::GenerateBeamFromInput", " ",
620  FatalErrorInArgument, " Input Ntuple not yet supported ");
621  //
622  //Need to create a new Gun each time
623  //so Geant v4.9 doesn't complain
624  //about momentum not match KE
625  //
626  if(fParticleGun){ delete fParticleGun; fParticleGun = 0;}
627  fParticleGun = new G4ParticleGun(1);
628  fParticleGun->SetParticleEnergy(0.0*CLHEP::GeV);
629 
630  G4double x0,y0,z0,px,py,pz;
631  G4String particleName;
632  fInputTree->GetEntry(fCurrentPrimaryNo);
633 
634  fProtonN = fInputTree->GetLeaf("event")->GetValue();
635 
636  x0 = fInputTree->GetLeaf("x")->GetValue()*CLHEP::cm;
637  y0 = fInputTree->GetLeaf("y")->GetValue()*CLHEP::cm;
638  z0 = fBeamOffsetZ; // fixed translation!!! Input file not yet supported anyways...
639 // z0 = fInputTree->GetLeaf("z")->GetValue()*CLHEP::cm+fLBNEData->GetTargetZ0(0)+fLBNEData->GetExtraFlukaNumiTargetZShift();
640  //z0 = fInputTree->GetLeaf("z")->GetValue()*CLHEP::cm+fLBNEData->TargetZ0+fLBNEData->GetExtraFlukaNumiTargetZShift();
641 
642  px = fInputTree->GetLeaf("px")->GetValue()*CLHEP::GeV;
643  py = fInputTree->GetLeaf("py")->GetValue()*CLHEP::GeV;
644  pz = fInputTree->GetLeaf("pz")->GetValue()*CLHEP::GeV;
645 
646  fParticlePosition=G4ThreeVector(x0,y0,z0);
647  fParticleMomentum=G4ThreeVector(px,py,pz);
648 
649  fWeight = fInputTree->GetLeaf("weight")->GetValue();
650  fType = G4int(fInputTree->GetLeaf("type")->GetValue());
651  fTgen = G4int(fInputTree->GetLeaf("gener")->GetValue());
653  fProtonOrigin = G4ThreeVector(fInputTree->GetLeaf("protx")->GetValue()*CLHEP::cm,
654  fInputTree->GetLeaf("proty")->GetValue()*CLHEP::cm,
655  fInputTree->GetLeaf("protz")->GetValue()*CLHEP::cm);
656  fProtonMomentum = G4ThreeVector(fInputTree->GetLeaf("protpx")->GetValue()*CLHEP::cm,
657  fInputTree->GetLeaf("protpy")->GetValue()*CLHEP::cm,
658  fInputTree->GetLeaf("protpz")->GetValue()*CLHEP::cm);
659 
660 /*
661  if (fLBNEData->GetUseMarsInput()){
662  fProtonIntVertex = G4ThreeVector(fInputTree->GetLeaf("pvtxx")->GetValue()*CLHEP::cm,
663  fInputTree->GetLeaf("pvtxy")->GetValue()*CLHEP::cm,
664  fInputTree->GetLeaf("pvtxz")->GetValue()*CLHEP::cm);
665  }
666  else if (fLBNEData->GetUseFlukaInput()){
667  fProtonIntVertex = G4ThreeVector(fInputTree->GetLeaf("protvx")->GetValue()*CLHEP::cm,
668  fInputTree->GetLeaf("protvy")->GetValue()*CLHEP::cm,
669  fInputTree->GetLeaf("protvz")->GetValue()*CLHEP::cm);
670  }
671 */
672  G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
673  fParticleGun->SetParticleDefinition(particleTable->FindParticle(particleName));
674  //G4double mass=particleTable->FindParticle(particleName)->GetPDGMass();
675 
676  //fParticleGun->SetParticleEnergy(sqrt(mass*CLHEP::mass+px*px+py*py+pz*pz)-mass);
677  fParticleGun->SetParticlePosition(G4ThreeVector(x0,y0,z0));
678  fParticleGun->SetParticleMomentum(G4ThreeVector(px,py,pz));
679  fParticleGun->GeneratePrimaryVertex(anEvent);
680 
681 }
682 //
683 // New Fluka interface
684 //
686  if (!fFlukaASCII.is_open()) {
687  G4Exception("LBNEPrimaryGeneratorAction::GenerateFlukaPrimary", " ",
688  FatalErrorInArgument, " Fluka Input file is not open, unexpected and fatal " );
689  }
691  if (!fFlukaASCII.good()) {
692  G4Exception("LBNEPrimaryGeneratorAction::GenerateFlukaPrimary", " ",
693  RunMustBeAborted, " Fluka Input file no longer accessible " );
694  return;
695  }
696  if (fFlukaASCII.eof()) {
697  fFlukaASCII.close();
698  G4Exception("LBNEPrimaryGeneratorAction::GenerateFlukaPrimary", " ",
699  RunMustBeAborted, " Fluka Input file at EOF, no more events to generate " );
700  return;
701  }
702  std::string llStr(lineForFluka);
703  std::istringstream llStrStr(llStr);
704  G4ThreeVector beamPosition(0., 0., 0.);
705  for (size_t k=0; k !=3; k++) { llStrStr >> beamPosition[k]; beamPosition[k] *= 1.0*CLHEP::cm; }
706  fParticleGun->SetParticlePosition(beamPosition);
707  G4ThreeVector partMomentum(0.,0.,0.);
708  for (size_t k=0; k !=3; k++) { llStrStr >> partMomentum[k]; partMomentum[k] *= 1.0*CLHEP::GeV; }
709  G4ThreeVector beamDirection(partMomentum);
710  double pTotTmp = beamDirection.mag();
711  for (size_t k=0; k !=3; k++) beamDirection[k] /= pTotTmp;
712  fParticleGun->SetParticleMomentumDirection(beamDirection);
713  int particleID = 0;
714  llStrStr >> particleID;
715  G4ParticleTable *pTable=G4ParticleTable::GetParticleTable();
716  G4ParticleDefinition* pDef = pTable->FindParticle(particleID);
717  fParticleGun->SetParticleDefinition(pDef);
718  const double pMass = pDef->GetPDGMass();
719  const double eTot = std::sqrt(pMass*pMass + pTotTmp*pTotTmp);
720  fParticleGun->SetParticleEnergy(eTot - pMass);
721  // Note: In the original version of fluka user routine fluscw.f, the weight was determined as:
722  //
723  // if ((totp.gt.30.) .or. (totp .lt. pmin1)) then ! calculate weight
724  // mywei = 1.
725  // else
726  // mywei = 30./totp
727  // endif
728  // Where totp is the total momentum of the particle.
729  // Not sure if this is still relevant..!
730  //
731  fWeight = 1.0;
732  fParticleGun->GeneratePrimaryVertex(anEvent);
733 
734 
735 }
736 
G4bool OpenNtupleFLUKAASCII(G4String ntupleName)
std::string string
Definition: nybbler.cc:12
void GenerateBeamFromInput(G4Event *anEvent)
STL namespace.
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:45
LBNEParticleCode_t IntToEnum(G4int particleInt)
G4int GetNumberOfEvents()
double y
T abs(T value)
G4bool OpenNtuple(G4String ntupleName)
double z
void GeneratePrimaries(G4Event *anEvent)
G4String AsString(LBNEParticleCode_t pCode)
LBNEPrimaryMessenger * fPrimaryMessenger
list x
Definition: train.py:276
void GenerateG4ProtonBeam(G4Event *anEvent)
void GenerateFlukaPrimary(G4Event *anEvent)
QTextStream & endl(QTextStream &s)