// Geant4 simulation for MuSR // AUTHOR: Toni SHIROKA, Paul Scherrer Institut, PSI // DATE : 2008-05 // #include "lem4PrimaryGeneratorAction.hh" #include "lem4DetectorConstruction.hh" #include "lem4PrimaryGeneratorMessenger.hh" #include "G4Event.hh" #include "G4ParticleGun.hh" #include "G4ParticleTable.hh" #include "G4ParticleDefinition.hh" #include "Randomize.hh" #include "G4ios.hh" #include "G4ParticleGun.hh" #include "G4UnitsTable.hh" #include "globals.hh" #include "G4Gamma.hh" #include "G4ThreeVector.hh" #include "G4RunManager.hh" #include "time.h" #include #include "lem4RootOutput.hh" //cks for storing some info in the Root output file #include "lem4ErrorMessage.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... lem4PrimaryGeneratorAction::lem4PrimaryGeneratorAction( lem4DetectorConstruction* lem4DC) :lem4Detector(lem4DC), x0(0), y0(0), z0(-124*cm), xSigma(0), ySigma(0), zSigma(0), rMaxAllowed(1e10*mm), zMinAllowed(-1e10*mm), zMaxAllowed(1e10*mm), p0(0), pSigma(0), pMinAllowed(0), pMaxAllowed(1e10*mm), xangle0(0), yangle0(0), xangleSigma(0), yangleSigma(0), pitch(0), UnpolarisedMuonBeam(false), xPolarisIni(1.), yPolarisIni(0.), zPolarisIni(0.), muonDecayTimeMin(-1), muonDecayTimeMax(-1), muonMeanLife(2197.03*ns), takeMuonsFromTurtleFile(false) //, firstCall(true) { G4int n_particle = 1; //cksdel particleGun = new lem4ParticleGun(n_particle); particleGun = new G4ParticleGun(n_particle); //create a messenger for this class gunMessenger = new lem4PrimaryGeneratorMessenger(this); // default particle kinematic G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable(); G4ParticleDefinition* particle= particleTable->FindParticle("mu+"); particleGun->SetParticleDefinition(particle); mu_mass = particle->GetPDGMass(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... lem4PrimaryGeneratorAction::~lem4PrimaryGeneratorAction() { delete particleGun; delete gunMessenger; if (takeMuonsFromTurtleFile) {fclose(fTurtleFile);} } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void lem4PrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent) { // This function is called at the begining of event. // // First of all check the setting of some variables. Do it only once (for the first event). // if (firstCall) { // firstCall=false; // char message[200]; // cout<<"******************** called just once **********************"< // 5*sqrt(xSigma*xSigma+ySigma*ySigma) ) { // sprintf(message,"lem4PrimaryGeneratorAction::GeneratePrimaries: Too strict restriction on the generated radius."); // lem4ErrorMessage::GetInstance()->lem4Error(FATAL,"message",true); // } // // Check that the restriction on the z-coordinate of the generated postion is reasonable: // if ( ((-zMaxAllowed+z0) > 5*fabs(zSigma)) || ((zMinAllowed-z0) > 5*fabs(zSigma)) ) { // sprintf(message,"lem4PrimaryGeneratorAction::GeneratePrimaries: Too strict restriction on the generated z-coordinate."); // lem4ErrorMessage::GetInstance()->lem4Error(FATAL,"message",true); // } // } G4double x, y, z; G4double p;// ke_offset; G4double xangle, yangle; //ke_offset = 3.73*keV; // Kin. energy offset due to a 3.73 kV acceleration at the Carbon foil if (takeMuonsFromTurtleFile) { char line[501]; G4int checkNrOfCounts=0; do { float xTmp, yTmp, xAngleTmp, yAngleTmp, pTmp; if (feof(fTurtleFile)) {rewind(fTurtleFile);G4cout<<"End of Turtle file."<1000) { G4cout<<"lem4PrimaryGeneratorAction::GeneratePrimaries: Too strict requirements on the r position!"<(rMaxAllowed*rMaxAllowed) ); z=z0; // G4cout<<"x,y,z=("<(rMaxAllowed*rMaxAllowed))||(z>zMaxAllowed)||(z0) {p = p0;} // if (E0>0 && p0==0) {p0 = std::sqrt(E0*E0 + 2*mu_mass*E0);} // else if (E0>0 && p0>0) { // G4cout<<"Define either kinetic energy or momentum, but not both!"<0) {p = G4RandGauss::shoot(p0,pSigma);} else {p=p0;} checkNrOfCounts++; if (checkNrOfCounts>1000) { G4cout<<"lem4PrimaryGeneratorAction::GeneratePrimaries: Too strict requirements on the momentum!"<pMaxAllowed)||(p0) { xangle = G4RandGauss::shoot(xangle0,xangleSigma); } else { xangle = xangle0; } // Add the beam tilt, which depends on the distance from the beam centre. if (xSigma>0) {xangle += - pitch * (x-x0)/(1*mm);} //xSigma; } // Changed to absolute units of pitch if (yangleSigma>0) { yangle = G4RandGauss::shoot(yangle0,yangleSigma); } else { yangle = yangle0; } // Add the beam tilt, which depends on the distance from the beam centre. if (ySigma>0) {yangle += - pitch * (y-y0)/(1*mm);} //ySigma; } // Changed to absolute units of pitch } // end of the part specific for the muons generated by random rather then from TURTLE // Calculate the final momentum G4double px, py, pz; px = p*sin(xangle); py = p*sin(yangle); pz = std::sqrt(p*p - px*px - py*py); // Assign spin G4double xpolaris=0, ypolaris=0, zpolaris=0; if (UnpolarisedMuonBeam) { G4cout<<"lem4PrimaryGeneratorAction.cc: Unpolarised muon beam not yet implemented!"< S T O P"<SetParticlePosition(G4ThreeVector(x,y,z)); //particleGun->SetParticleMomentum(G4ThreeVector(px,py,pz)); G4double particleEnergy = std::sqrt(p*p+mu_mass*mu_mass)-mu_mass; //particleGun->SetParticleEnergy(particleEnergy+ke_offset); particleGun->SetParticleEnergy(particleEnergy); particleGun->SetParticleMomentumDirection(G4ThreeVector(px,py,pz)); particleGun->SetParticlePolarization(G4ThreeVector(xpolaris,ypolaris,zpolaris)); particleGun->GeneratePrimaryVertex(anEvent); // G4cout<<"lem4PrimaryGeneratorAction: Parameters:"<0.) { // G4cout<<"muonDecayTimeMin="<muonDecayTimeMax)); // // This algorithm should be much faster then the previous one: G4PrimaryParticle* generatedMuon = anEvent->GetPrimaryVertex(0)->GetPrimary(0); // G4double decayLowerLimit = 1-exp(-muonDecayTimeMin/muonMeanLife); // G4double decayUpperLimit = 1-exp(-muonDecayTimeMax/muonMeanLife); // G4double randomVal = G4UniformRand()*(decayUpperLimit-decayLowerLimit) + decayLowerLimit; // G4double decaytime = -muonMeanLife*log(1-randomVal); // // The following code is numerically more stable compared to the commented lines above: G4double expMin = exp(-muonDecayTimeMin/muonMeanLife); G4double expMax = exp(-muonDecayTimeMax/muonMeanLife); G4double decaytime = -muonMeanLife * log(G4UniformRand()*(expMax-expMin)+expMin); // // G4cout<<"decaytime="<SetProperTime(decaytime); } // Save variables into ROOT output file: lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance(); myRootOutput->SetInitialMuonParameters(x,y,z,px,py,pz,xpolaris,ypolaris,zpolaris); } /////////////////////////////////////////////////////////////////////// // // void lem4PrimaryGeneratorAction::SetInitialMuonPolariz(G4ThreeVector vIniPol) { G4double magnitude=vIniPol.mag(); if(magnitude<0.00000001) { G4cout<< "Unpolarised initial muons"<StoreGeantParameter(2,muonDecayTimeMin/microsecond); myRootOutput->StoreGeantParameter(3,muonDecayTimeMax/microsecond); myRootOutput->StoreGeantParameter(4,muonMeanLife/microsecond); } void lem4PrimaryGeneratorAction::SetTurtleInput(G4String turtleFileName) { takeMuonsFromTurtleFile = true; fTurtleFile = fopen(turtleFileName.c_str(),"r"); if (fTurtleFile==NULL) { G4cout << "E R R O R : Failed to open TURTLE input file \"" << turtleFileName <<"\"."<< G4endl; G4cout << "S T O P F O R C E D" << G4endl; exit(1); } else {G4cout << "Turtle input file \"" << turtleFileName <<"\" opened."<< G4endl;} }