Files
geant4/examples/advanced/medical_linac/src/ML2PrimaryGenerationAction.cc
T
2020-12-04 12:30:43 +01:00

268 lines
8.4 KiB
C++

//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// ^Claudio Andenna claudio.andenna@ispesl.it, claudio.andenna@iss.infn.it
// *Barbara Caccia barbara.caccia@iss.it
// with the support of Pablo Cirrone (LNS, INFN Catania Italy)
// with the contribute of Alessandro Occhigrossi*
//
// ^INAIL DIPIA - ex ISPESL and INFN Roma, gruppo collegato Sanità, Italy
// *Istituto Superiore di Sanità and INFN Roma, gruppo collegato Sanità, Italy
// Viale Regina Elena 299, 00161 Roma (Italy)
// tel (39) 06 49902246
// fax (39) 06 49387075
//
// more information:
// http://g4advancedexamples.lngs.infn.it/Examples/medical-linac
//
//*******************************************************//
#include "ML2PrimaryGenerationAction.hh"
using namespace CLHEP;
CML2PrimaryGenerationAction::CML2PrimaryGenerationAction(void)
:particleGun(0),gamma(0),electron(0),positron(0),primaryParticleData(0),particles(0)
{
}
CML2PrimaryGenerationAction* CML2PrimaryGenerationAction::instance = 0;
CML2PrimaryGenerationAction* CML2PrimaryGenerationAction::GetInstance(void)
{
if (instance == 0)
{
instance = new CML2PrimaryGenerationAction();
}
return instance;
}
void CML2PrimaryGenerationAction::inizialize(SPrimaryParticle *pData)
{
rm = new G4RotationMatrix();
PrimaryGenerationActionMessenger = new CML2PrimaryGenerationActionMessenger(this);
particle = new Sparticle;
nParticle = nPhSpParticles = nRandomParticles = 0;
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
gamma = particleTable->FindParticle("gamma");
electron = particleTable->FindParticle("e-");
positron = particleTable->FindParticle("e+");
particleGun = new G4ParticleGun();
primaryParticleData = pData;
primaryParticleData -> nPrimaryParticle = 0;
primaryParticleData -> partPDGE = 0;
}
void CML2PrimaryGenerationAction::design(G4double aTZ)
{
accTargetZPosition=aTZ;
switch (idParticleSource)
{
case id_randomTarget:
setGunRandom();
break;
case id_phaseSpace:
setGunCalculatedPhaseSpace();
break;
}
}
void CML2PrimaryGenerationAction::setGunRandom()
{
particleGun->SetParticleDefinition(electron);
particleGun->SetNumberOfParticles(1);
idCurrentParticleSource=idParticleSource;
}
void CML2PrimaryGenerationAction::setGunCalculatedPhaseSpace()
{
particles=new Sparticle[nMaxParticlesInRamPhaseSpace];
particleGun->SetNumberOfParticles(1);
idCurrentParticleSource=idParticleSource;
}
CML2PrimaryGenerationAction::~CML2PrimaryGenerationAction(void)
{
delete particleGun;
delete [] particles;
delete particles;
}
void CML2PrimaryGenerationAction::GeneratePrimaries(G4Event *anEvent)
{
static int currentRecycle=nRecycling;
static G4ThreeVector pos0, dir0;
if (currentRecycle==nRecycling)
{
currentRecycle=0;
switch (idCurrentParticleSource)
{
case id_randomTarget:
GenerateFromRandom();
break;
case id_phaseSpace:
GenerateFromCalculatedPhaseSpace();
break;
}
pos0 = pos;
dir0 = dir;
}
currentRecycle++;
pos = pos0;
dir = dir0;
applySourceRotation(); // to follow the accelerator rotation
primaryParticleData->partPDGE = particleGun->GetParticleDefinition()->GetPDGEncoding();
primaryParticleData->nPrimaryParticle++;
particleGun->SetParticleEnergy(ek*MeV);
particleGun->SetParticlePosition(pos*mm);
particleGun->SetParticleMomentumDirection((G4ParticleMomentum)dir);
particleGun->GeneratePrimaryVertex(anEvent);
}
void CML2PrimaryGenerationAction::GenerateFromRandom()
{
sinTheta = RandGauss::shoot(0., 0.003);
cosTheta = std::sqrt(1 - sinTheta*sinTheta);
phi = twopi*G4UniformRand();
dir.set(sinTheta*std::cos(phi), sinTheta*std::sin(phi), cosTheta);
rho = G4UniformRand()*GunRadius;
alpha = G4UniformRand()*twopi;
pos.setX(rho*std::sin(alpha));
pos.setY(rho*std::cos(alpha));
pos.setZ(-(accTargetZPosition +5.)*mm); // the primary electrons are generated 5 mm before the target
ek=RandGauss::shoot(GunMeanEnergy, GunStdEnergy);
nRandomParticles++;
}
void CML2PrimaryGenerationAction::GenerateFromCalculatedPhaseSpace()
{
static bool bFirstTime=true;
if (bFirstTime)
{bFirstTime=false;fillParticlesContainer();}
if (nParticle==nMaxParticlesInRamPhaseSpace) // once all the particles stored in RAM hae been processed a new set is loaded
{
fillParticlesContainer();
nParticle=0;
}
pos=particles[nParticle].pos;
dir=particles[nParticle].dir;
ek=particles[nParticle].kinEnergy;
switch (particles[nParticle].partPDGE)
{
case -11:
particleGun->SetParticleDefinition(positron);
break;
case 11:
particleGun->SetParticleDefinition(electron);
break;
case 22:
particleGun->SetParticleDefinition(gamma);
break;
}
nPhSpParticles++;
nParticle++;
}
void CML2PrimaryGenerationAction::applySourceRotation()
{
pos=*rm*pos;
dir=*rm*dir;
}
void CML2PrimaryGenerationAction::fillParticlesContainer()
{
static int currentFilePosition=0;
static int currentFileSize=0;
int startDataFilePosition;
std::ifstream in;
in.open(calculatedPhaseSpaceFileIN, std::ios::in);
if (in)
{
G4cout << "ERROR phase space file: " << calculatedPhaseSpaceFileIN << " NOT found. Run abort " << G4endl;
G4RunManager::GetRunManager()->AbortRun(true);
}
static bool bFirstTime=true;
if (bFirstTime)
{
in.seekg(-1,std::ios::end);
currentFileSize=in.tellg();
in.seekg(0,std::ios::beg);
bFirstTime=false;
}
char a[1000];
in.getline(a,1000,'\n');
in.getline(a,1000,'\n');
startDataFilePosition=in.tellg();
if (currentFilePosition>0)
{in.seekg(currentFilePosition, std::ios::beg);}
int i;
G4double x,y,z;
G4int d;
static bool checkFileRewind=false;
static bool bRewindTheFile=false;
static int nPhSpFileRewind=0;
for (i=0;i<nMaxParticlesInRamPhaseSpace;i++)
{
if (bRewindTheFile) // to read the phase space file again to fill the container
{
in.close();
in.open(calculatedPhaseSpaceFileIN, std::ios::in);
in.seekg(startDataFilePosition, std::ios::beg);
checkFileRewind=true;
bRewindTheFile=false;
G4cout<<"\n################\nI have reached the end of the phase space file "<<++nPhSpFileRewind <<" times, I rewind the file\n" << G4endl;
G4cout <<"loaded " <<i <<"/"<< nMaxParticlesInRamPhaseSpace<<" particles" << G4endl;
}
in >> d;
in >> x; in >>y; in >> z;
/* G4cout <<"x:" <<x << G4endl;
G4cout <<"y:" <<y << G4endl;
G4cout <<"z:" <<z << G4endl;*/
particles[i].pos.set(x,y,z-accTargetZPosition);
in >> x; in >>y; in >> z;
particles[i].dir.set(x,y,z);
in >> x;
particles[i].kinEnergy=x;
in >> d;
particles[i].partPDGE=d;
in >> d; in >> d;
if (in.eof()) {bRewindTheFile=true;}
if (checkFileRewind) {checkFileRewind=false;}
}
G4cout <<"loaded " <<i <<"/"<< nMaxParticlesInRamPhaseSpace<<" particles" << G4endl;
currentFilePosition=in.tellg(); // to remind the actual position in the phase space file
if (currentFilePosition>=currentFileSize) // to read the phase space file again
{currentFilePosition=startDataFilePosition;}
in.close();
}