musrsim/geant4/LEMuSR/src/lem4SteppingAction.cc
shiroka 00953dad14
2009-01-23 13:21:59 +00:00

343 lines
16 KiB
C++

// Geant4 simulation for MuSR
// AUTHOR: Toni SHIROKA, Paul Scherrer Institut, PSI
// DATE : 2008-05
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "lem4SteppingAction.hh"
//cksdel#include "lem4RunAction.hh"
#include "G4SteppingManager.hh"
#include "G4UnitsTable.hh"
#include "lem4RootOutput.hh"
#include "G4RunManager.hh" // needed for the event nr. comparison
#include "G4Run.hh" // ---------------||------------------
#include "G4MagneticField.hh" // needed for storing the magnetic field to the Root class
#include "G4FieldManager.hh" // ---------------||------------------
#include "G4TransportationManager.hh" // ---------------||------------------
#include "lem4ErrorMessage.hh"
#include "lem4Parameters.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
lem4SteppingAction::lem4SteppingAction() {
pointer=this;
// oldEventID=-1000;
muPlusProcessManager=NULL;
multipleToCoulombScatteringIsPossible=false;
coulombScatteringIsActive=false;
multipleScatteringIndex=1000;
coulombScatteringIndex=1000;
boolIsAnySpecialSaveVolumeDefined = false;
lastActualVolume="Unset";
}
lem4SteppingAction::~lem4SteppingAction() {
}
lem4SteppingAction* lem4SteppingAction::pointer=0;
lem4SteppingAction* lem4SteppingAction::GetInstance()
{
return pointer;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void lem4SteppingAction::DoAtTheBeginningOfEvent() {
// G4cout<<"lem4SteppingAction::DoAtTheBeginningOfEvent: KAMIL"<<G4endl;
radioactiveElectronAlreadySavedInThisEvent=false;
muAlreadyWasInTargetInThisEvent=false;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void lem4SteppingAction::UserSteppingAction(const G4Step* aStep) {
// sleep(1);
// For debugging purposes: To find out the number of steps during one event:
// G4RunManager* fRunManager = G4RunManager::GetRunManager();
// G4int debugEventID = fRunManager->GetCurrentEvent()->GetEventID();
// nrOfSteps++;
// if (debugOldEventID != debugEventID) {
// G4cout<<"lem4SteppingAction: Event nr. "<<debugOldEventID<<" has"<<nrOfSteps<<" steps."<<G4endl;
// nrOfSteps=0;
// debugOldEventID=debugEventID;
// }
G4Track* aTrack = aStep->GetTrack();
// if (nrOfSteps > 100000) {
// G4cout<<"lem4SteppingAction.cc : event nr. "<<debugEventID
// <<": nrOfSteps>100000 ==> KILL THE CURRENT TRACK with"
// <<aTrack->GetDynamicParticle()->GetDefinition()->GetParticleName() <<" at"
// <<aStep->GetPostStepPoint()->GetPosition() <<G4endl;
// G4cout<<"GetCurrentStepNumber()="<<aTrack->GetCurrentStepNumber() <<G4endl;
// aTrack->SetTrackStatus(fStopAndKill); // suspend the track if too many steps have already happened
// // (should be done in a more clever way, but I do not know how yet).
// nrOfSteps=0;
// }
// suspend the track if too many steps have already happened (relevant at high fields)
if (aTrack->GetCurrentStepNumber()>100000) {
lem4ErrorMessage::GetInstance()->lem4Error(WARNING,
"lem4SteppingAction: Current number of steps for the track > 100000 ==> TRACK KILLED",true);
//
// G4cout<<"lem4SteppingAction.cc : event nr. "<<oldEventID
// <<" Current number of steps for the track > 100000 ==> KILL THIS TRACK: " <<G4endl;
// <<aTrack->GetDynamicParticle()->GetDefinition()->GetParticleName() <<" at"
// <<aStep->GetPostStepPoint()->GetPosition()
// <<" E_kin_vertex="<<aTrack->GetVertexKineticEnergy()/MeV<<" MeV."<<G4endl;
//
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
G4double x=aStep->GetPostStepPoint()->GetPosition().x()/mm;
G4double y=aStep->GetPostStepPoint()->GetPosition().y()/mm;
G4double z=aStep->GetPostStepPoint()->GetPosition().z()/mm;
G4double E=aTrack->GetVertexKineticEnergy()/MeV;
myRootOutput->htest1->Fill(x,y);
myRootOutput->htest2->Fill(sqrt(x*x+y*y),z);
myRootOutput->htest3->Fill(E);
aTrack->SetTrackStatus(fStopAndKill);
}
if (aTrack->GetDefinition()) {
G4ParticleDefinition* p_definition = aTrack->GetDynamicParticle()->GetDefinition();
G4String p_name = p_definition->GetParticleName();
// G4ProcessManager* p_manager = p_definition->GetProcessManager();
// G4String p_name=aTrack->GetDynamicParticle()->GetDefinition()->GetParticleName();
G4String actualVolume=aTrack->GetVolume()->GetLogicalVolume()->GetName();
//! First Commented by TS. Currently not in use! or not strictly necessary
// This are the data just for the radioactive decay (when using the radioactive source):
if ((lem4Parameters::boolG4GeneralParticleSource)) {
// &&(!radioactiveElectronAlreadySavedInThisEvent)) {
if (aTrack->GetTrackID() != 1 ){
if (aTrack->GetCreatorProcess()->GetProcessName() == "RadioactiveDecay") {
// if (aStep->GetPostStepPoint()->GetProcessDefinedStep()->GetProcessName() == "RadioactiveDecay") { did not work out
// emitted particles
// if (fTrack->GetDefinition()->GetParticleType() != "nucleus") {
// G4String particleName = fTrack->GetDefinition()->GetParticleName();
if (aTrack->GetDefinition()->GetParticleName()=="e-") {
// G4double particleName = G4double (fTrack->GetDefinition()->GetPDGEncoding());
// G4double time = fStep->GetPreStepPoint()->GetGlobalTime() ;
// //- fStep->GetPreStepPoint()->GetLocalTime();
// G4double weight = fStep->GetPreStepPoint()->GetWeight() ;
// G4double energy = fStep->GetPreStepPoint()->GetKineticEnergy();
//
// exrdmAnalysisManager::getInstance()->AddParticle(particleName, energy, weight, time);
//hovno
// G4cout<<"aTrack->GetCurrentStepNumber()="<<aTrack->GetCurrentStepNumber()<<" ";
if (aTrack->GetCurrentStepNumber()==1) {
G4double electron_kinetic_energy=aStep->GetPreStepPoint()->GetKineticEnergy();
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
myRootOutput->htest4->Fill(electron_kinetic_energy);
// G4cout<<"First kinetic energy="<<aStep->GetPreStepPoint()->GetKineticEnergy()<<" ";
// G4cout<<"GetKineticEnergy()="<<aTrack->GetKineticEnergy()<<G4endl;
}
// // G4ThreeVector radioactivePositronMomentum = aStep->GetPreStepPoint()->GetMomentum();
// G4ThreeVector radioactivePositronMomentum = aTrack->GetMomentum();
// G4double Apx=radioactivePositronMomentum.x();
// G4double Apy=radioactivePositronMomentum.y();
// G4double Apz=radioactivePositronMomentum.z();
// lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
// myRootOutput->SetInitialMuonParameters(0,0,0,Apx,Apy,Apz,0,0,0);
// radioactiveElectronAlreadySavedInThisEvent=true;
// // G4cout<<"Apx,Apy,Apz="<<Apx<<" "<<Apy<<" "<<Apz<<G4endl;
}
}
}
}
//hovno
// Check if in the special
if (boolIsAnySpecialSaveVolumeDefined) {
// G4bool isFirstStepInVolume=aStep->IsFirstStepInVolume();
// This does not work!!! (aStep->IsFirstStepInVolume() is always zero.) I do not understand why!
G4bool isFirstStepInVolume=false;
if (actualVolume!=lastActualVolume) {
lastActualVolume=actualVolume;
isFirstStepInVolume=true;
}
if (isFirstStepInVolume) {
G4int tmpVolumeID=saveVolumeMapping[actualVolume];
if (tmpVolumeID!=0) {
G4int particle_id_save=p_definition->GetPDGEncoding();
G4double ke_save=aStep->GetPreStepPoint()->GetKineticEnergy()/keV;
G4double x_save=aStep->GetPreStepPoint()->GetPosition().x()/mm;
G4double y_save=aStep->GetPreStepPoint()->GetPosition().y()/mm;
G4double z_save=aStep->GetPreStepPoint()->GetPosition().z()/mm;
G4double px_save=aStep->GetPreStepPoint()->GetMomentum().x()/MeV;
G4double py_save=aStep->GetPreStepPoint()->GetMomentum().y()/MeV;
G4double pz_save=aStep->GetPreStepPoint()->GetMomentum().z()/MeV;
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
myRootOutput->SetSaveDetectorInfo(tmpVolumeID,particle_id_save,ke_save,x_save,y_save,z_save,px_save,py_save,pz_save);
}
}
}
// Store information about when mu+ or Mu enter the target for the fist time
// in a given event (i.e. the code has to be called just once during the event).
if ((p_name == "mu+") || (p_name == "Mu")) {
if (actualVolume=="log_target") {
// G4RunManager* fRunManager = G4RunManager::GetRunManager();
// G4int eventID = fRunManager->GetCurrentEvent()->GetEventID();
// if (oldEventID != eventID) {
// oldEventID=eventID;
if (!muAlreadyWasInTargetInThisEvent) {
muAlreadyWasInTargetInThisEvent=true;
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
myRootOutput->SetPolInTarget(aTrack->GetPolarization());
myRootOutput->SetTimeInTarget(aTrack->GetGlobalTime());
//G4cout<<"particle = "<<p_name<<" TOF = "<<(aTrack->GetGlobalTime())/ns<<G4endl;
}
}
}
// Store the pointer to the mu+ process manager, and the indexes of the "msc" and "eCoulombScat" processes.
// This is needed for switching beween the multiple scattering and coulomb scattering in some volumes.
if (p_name == "mu+") {
if (muPlusProcessManager==NULL) { // The muPlusProcessManager should be NULL only once, at the beginning of the run.
muPlusProcessManager = p_definition->GetProcessManager();
G4ProcessVector* v = muPlusProcessManager->GetProcessList();
size_t np = v->size();
for(size_t i=0; i<np; i++) {
// std::cout<<" "<<(*v)[i]->GetProcessName();
if( (*v)[i]->GetProcessName() == "msc" ) {
multipleScatteringIndex = i;
}
if( (*v)[i]->GetProcessName() == "eCoulombScat" ) {
coulombScatteringIndex = i;
}
}
// std::cout<<std::endl;
// std::cout<<"multipleScatteringIndex,coulombScatteringIndex ="<<multipleScatteringIndex<<","<<coulombScatteringIndex<<std::endl;
if ((multipleScatteringIndex<1000)&&(coulombScatteringIndex<1000)) { // Both multiple and Coulomb scattering processes for muon found
multipleToCoulombScatteringIsPossible=true;
std::cout<<"lem4SteppingAction: Switching between Coulomb and multiple scattering processes possible"<<std::endl;
// Ensure that just one of them is active. Let the active one be the multiple scattering at the beginning.
muPlusProcessManager->SetProcessActivation(multipleScatteringIndex, true);
muPlusProcessManager->SetProcessActivation(coulombScatteringIndex, false);
}
else { // At least one of the "multiple scattering" and "coulomb scattering" was not found.
// Perhaps they were not defined in the physics list ?
if (lem4Parameters::GetInstance()->GetMyTypeOfProcesses()=="coulombAndMultiple") {
if (coulombScatteringIndex==1000) {std::cout<<"lem4SteppingAction: Coulomb scattering process for mu+ not found!"<<std::endl;}
if (multipleScatteringIndex==1000) {std::cout<<"lem4SteppingAction: Multiple scattering process for mu+ not found!"<<std::endl;}
lem4ErrorMessage::GetInstance()->lem4Error(SERIOUS,
"lem4SteppingAction: It is not possible to switch between Coulomb and multiple scattering.",true);
muPlusProcessManager->DumpInfo();
}
}
}
// switch between G4MultipleScattering and G4CoulombScattering
if (multipleToCoulombScatteringIsPossible) {
if (strncmp(actualVolume.c_str(),"log_coulomb",11)==0) {
if (!coulombScatteringIsActive) {
// std::cout<<"Activating coulomb; volume= "<<actualVolume<<std::endl;
muPlusProcessManager->SetProcessActivation(multipleScatteringIndex, false);
muPlusProcessManager->SetProcessActivation(coulombScatteringIndex, true);
coulombScatteringIsActive=true;
}
}
else if (coulombScatteringIsActive) {
// std::cout<<"Deactivating coulomb; volume= "<<actualVolume<<std::endl;
muPlusProcessManager->SetProcessActivation(multipleScatteringIndex, true);
muPlusProcessManager->SetProcessActivation(coulombScatteringIndex, false);
coulombScatteringIsActive=false;
}
}
// Store the information about the muon decay into the Root Class.
// Pick up process "DecayWithSpin":
const G4VProcess* process = aStep->GetPostStepPoint()->GetProcessDefinedStep();
if (process!=NULL) {
G4String processName = process->GetProcessName();
if (processName=="DecayWithSpin") {
lem4Parameters::field_DecayWithSpin=true;
// std::cout<<"lem4SteppingAction: DecayWithSpin"<<std::endl;
// store the information about the decaying muon
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
G4double timeOfDecay_tmp=aTrack->GetGlobalTime();
myRootOutput->SetDecayTime(timeOfDecay_tmp);
myRootOutput->SetDecayPolarisation(aTrack->GetPolarization());
G4ThreeVector positionOfDecay_tmp = aStep->GetPostStepPoint()->GetPosition();
myRootOutput->SetDecayPosition(positionOfDecay_tmp);
// store the detector ID in which the muon decayed
myRootOutput->SetDecayDetectorID(actualVolume);
// store the information about the magnetic field at the place where the muon decays
G4double BFieldAtOrigin[6] = {0.,0.,0.,0.,0.,0.};
G4double PointOfDecay[4] ={positionOfDecay_tmp.x(),positionOfDecay_tmp.y(),positionOfDecay_tmp.z(),timeOfDecay_tmp};
G4FieldManager *fMgr=G4TransportationManager::GetTransportationManager()->GetFieldManager();
if (fMgr!=NULL) {
if(!fMgr->DoesFieldChangeEnergy()) { //then we have a magnetic field
fMgr->GetDetectorField()->GetFieldValue(PointOfDecay,BFieldAtOrigin);
myRootOutput->SetBField(BFieldAtOrigin);
}
else{
}
}
// store the information about the emerging positron
G4TrackVector* secondary = fpSteppingManager->GetSecondary();
G4int n_secondaries= (*secondary).size();
for (G4int i=0; i<n_secondaries; i++) {
// G4cout <<"Secondary ["<<i<<"]="<<(*secondary)[i]->GetDefinition()->GetParticleName()<<", ";
if ( ((*secondary)[i]->GetDefinition()->GetParticleName()) == "e+" ) {
myRootOutput->SetInitialPositronMomentum((*secondary)[i]->GetMomentum());
// These two times seem to be equivalent: (*secondary)[i]->GetGlobalTime()
// aTrack->GetGlobalTime()
// G4cout <<"Positron initial momentum="<<(*secondary)[i]->GetMomentum()<<G4endl;
// G4cout <<"Positron time="<<(*secondary)[i]->GetGlobalTime()<<G4endl;
// G4cout <<"astep time="<<aTrack->GetGlobalTime()<<G4endl;
}
}
}
}
//csk
G4ThreeVector position = aStep->GetPostStepPoint()->GetPosition();
// G4double tof=aTrack->GetLocalTime();
// G4double energy=aTrack->GetDynamicParticle()->GetKineticEnergy();
G4ThreeVector polarization=aTrack->GetDynamicParticle()->GetPolarization();
// G4cout << "Stepping action: mu+ properties \n"
// << "position " << G4BestUnit(position,"Length") <<"; \n"
// << "time of flight " << G4BestUnit(tof,"Time") <<"; \n"
// << "kinetic energy "<< G4BestUnit(energy,"Energy") <<"; \n"
// << "polarization "<< polarization <<";\n"
// <<G4endl;
}
else { // particle is not muon
// Delete track if the particle is far away from the detector (i.e. in the "shield" volume).
// There is an example how to delete the track in example/novice/N04.
// It is done in a different way here, because the example/novice/N04 was not doing
// exactly what I wanted.
/* if ((lem4Parameters::killAllPositrons)&&(p_name == "e+")){
aTrack->SetTrackStatus(fStopAndKill); // suspend the track
}
*/
if((actualVolume(0,10)=="log_shield")||(actualVolume(0,10)=="log_Shield")) {
aTrack->SetTrackStatus(fStopAndKill); // suspend the track
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void lem4SteppingAction::SetLogicalVolumeAsSpecialSaveVolume(G4String logicName, G4int volumeID) {
boolIsAnySpecialSaveVolumeDefined = true;
saveVolumeMapping[logicName]=volumeID;
}