Software/Geant4/Introduction
Introduction
GEANT4 is a software toolkit based on C++. In your code you have to define:
- Your experimental setup: geometry, materials and primary particles.
- Which physics process you are interested in.
- Take actions during the simulation to inspect and store results.
The interaction with GEANT4 is done via base classes.
Mandatory Classes
- G4VUserDetectorConstruction
- Describe the experimental setup, geometry and materials.
- G4VUserPhysicsList
- Define particles, physics processes and range cuts.
- G4VUserPrimaryGeneratorAction
- Describe particle source, source dimensions, initial position, energy spectrum, angular distributions.
Optional Classes
- G4UserRunAction
- Define and store histograms.
- G4UserEventAction
- Event selection and analysis of simulation data.
- G4UserStackingAction
- Customize priority of tracks.
- G4UserTrackingAction
- Decide whether a trajectory should be stored or not.
- G4UserSteppingAction
- Kill, suspend, postpone a track.
Manager Class
- G4RunManager
- Manages processing the run.
Useful terminology
- Step
- The smallest unit of Geant4 simulation, a particle is transported from one point to another.
- Trajectory and TrajectoryPoint
- Collection of steps and step points.
- Process
- Physics along the step.
- Track
- A snapshot of a particle at some point along its path (not the same as trajectory).
- Event
- A collection of information from tracks and trajectories.
- Run
- A collection of events.
The function main()
The function main()
defines the skeleton of your simulation code.
Inside the function you instantiate G4RunManager
and notify it of your mandatory and optional classes.
This is an example main()
function, where MyDetectorConstruction
, MyPhysicsList
, MyPrimaryGeneratorAction
, MyEventAction
and MyRunAction
are derived classes from the GEANT4 base classes:
int main() { // Run manager construction G4RunManager* runManager = new G4RunManager; // mandatory user initialization classes runManager->SetUserInitialization(new MyDetectorConstruction); runManager->SetUserInitialization(new MyPhysicsList); // mandatory user action classes runManager->SetUserAction(new MyPrimaryGeneratorAction); // optional user action classes runManager->SetUserAction(new MyEventAction); runManager->SetUserAction(new MyRunAction); ... }
Experimental setup
You derive your own class from the G4VUserDetectorConstruction
base class.
In the derived class you will:
- Describe the shape and the size of your detector using
G4VSolid
; - Construct materials and electromagnetic fields using
G4Logical Volume
; - Place volumes of your detector geometry using
G4VPhysical Volume
;
Simple example of class MyDetectorConstruction
class MyDetectorConstruction:public G4VUserDetectorConstruction { public: MyDetectorConstruction(); ~MyDetectorConstruction(); virtual G4VPhysicalVolume* Construct(); private: void DefineMaterials(); };
Detector Construction
Now construct the detector. Your detector is always placed in a mother volume called the world volume.
G4PhysicalVolume* MyDetectorConstruction::Construct() { ... // World volume G4VSolid* pWorld = new G4Box("World",5*m,5*m,5*m); G4LogicalVolume* pWorldLog = new G4LogicalVolume(pWorld,vacuum, "World"); G4VPhysicalVolume* pWorldPhys = new G4PVPlacement(0,G4ThreeVector(),pWorldLog,"World",0,false,0); // Water box G4VSolid* pBoxSolid = new G4Box(“WaterBox”, 1.*m, 2.*m, 3.*m); G4LogicalVolume* pBoxLog = new G4LogicalVolume( pBoxSolid, water, “WaterBox”); G4VPhysicalVolume* aBoxPhys = new G4PVPlacement( pRotation, G4ThreeVector(posX, posY, posZ), pBoxLog, “WaterBox”, pWorldLog, false, copyNo); ... }
Define Elements and Materials
The elements and materials are defined using classes G4Element
and G4Material
.
For example water, hydrogen and oxygen are defined as:
void MyDetectorConstruction::DefineMaterials() { ... G4Element* H = new G4Element("Hydrogen","H",z=1.,a= 1.01*g/mole); G4Element* O = new G4Element("Oxygen","O",z=8.,a=16.00*g/mole); density = 1.000*g/cm3; G4Material* water = new G4Material("Water",density,ncomp=2); water->AddElement(H, natoms=2); water->AddElement(O, natoms=1); ...}
You can find more examples of DetectorConstruction classes on the Geant4 website.
Physics Processes
You can build your own physics list or chose from already built physics lists. To build your own physics lists, you can use two base physics list classes: G4VUserPhysicsList
and G4ModularPhysicsList
.
The class G4VUserPhysicsList
is used for simple physics lists while G4ModularPhysicsList
is used to build more complex physics lists.
There also exist already built pre-packaged physics lists.
Simple physics lists
If the particles in your simulation undergo a discrete number of physics processes you can use the class G4VUserPhysicsList
to define them.
This class has three methods:
- ConstructParticles()
- Define all necessary particles.
- ConstructProcesses()
- Define all necessary processes and assign them to corresponding particles.
- SetCuts()
- Define production thresholds in terms of range.
Simple example of class MyPhysicsList
class MyPhysicsList:public G4VUserPhysicsList() { public: MyPhysicsList(); ~MyPhysicsList(); void ConstructParticle(); void ConstructProcess(); void SetCuts(); }
Implement ConstructParticle()
, ConstructProcess()
and SetCuts()
methods
void MyPhysicsList::ConstructParticle() { // Define the particles G4Electron::ElectronDefinition(); G4Positron::PositronDefinition(); G4Proton::ProtonDefinition(); G4Neutron::NeutronDefinition(); G4Gamma::GammaDefinition(); ... }
Relevant physics processes
GEANT4 provides a variety of physics processes. These processes are decoupled from one another and you can select those which are relevant to your simulation. The processes are grouped in seven categories:
- Electromagnetic
- Hadronic
- Decay
- Photolepton-hadron
- Optical
- Parameterization
- Transportation
and their list is available on the Geant4 website.
For each particle in ConstructParticle()
assign all the physics processes you want to consider in your simulation:
void MyPhysicsList::ConstructProcess() { AddTransportation(); // Assign transportation process to all particles ConstructEM(); // Electromagnetic processes ConstructGeneral(); // Other processes }
In methods ConstructEM()
and ConstructGeneral()
assign the physics processes to the corresponding particles:
void MyPhysicsList::ConstructEM() { aParticleIterator->reset(); while((*aParticleIterator)()){ G4ParticleDefinition* particle = aParticleIterator->value(); G4ProcessManager* pmanager = particle->GetProcessManager(); G4String particleName = particle->GetParticleName(); if (particleName == "gamma") { pmanager->AddDiscreteProcess(new G4GammaConversion); ...}
void MyPhysicsList::ConstructGeneral() { G4Decay* theDecayProcess = new G4Decay() aParticleIterator->reset(); while((*aParticleIterator)()) { G4ParticleDefinition* particle = aParticleIterator->value(); G4ProcessManager* pmanager = particle->GetProcessManager(); if theDecayProcess->IsApplicable(*particle)) { pmanager->AddProcess(theDecayProcess); pmanager->SetProcessOrdering(theDecayProcess,idxPostStep); pmanager->SetProcessOrdering(theDecayProcess,idxAtRest); }}}
This is the full list of physics processes available for every particle.
Finally, in method SetCuts()
you can define cuts on the particles:
void MyPhysicsList::SetCuts() { defaultCutValue = 1.0*mm; SetCutValue(defaultCutValue, "gamma"); SetCutValue(defaultCutValue, "e+"); SetCutValue(defaultCutValue, "e-");
See the Computed Tomography tutorial to learn more about simple physics lists.
Detailed Physics Lists
If you want to build more realistic physics list you have to use the class G4VModularPhysicsList
.
In G4VModularPhysicsList
you can group the physics processes into separate modules which are already pre-build physics list and later chose one of those modules.
Simple example of class MyPhysicsList
class MyPhysicsList:public G4VModularPhysicsList { public: MyPhysicsList(); ~MyPhysicsList(); virtual void ConstructParticle(); virtual void SetCuts(); void AddPhysicsList(const G4String& name); virtual void ConstructProcess(); private: G4String fEmName; G4VPhysicsConstructor* fEmPhysicsList; G4VPhysicsConstructor* fDecPhysicsList; std::vector<G4VPhysicsConstructor*> fHadronPhysicsList; };
Now build the physics lists
void MyPhysicsList::AddPhysicsList(const G4String& name) { ... if (name == "emstandard_opt3") { fEmName = name; delete fEmPhysicsList; fEmPhysicsList = new G4EmStandardPhysics_option3(); } else if (name == "emlivermore") { fEmName = name; delete fEmPhysicsList; fEmPhysicsList = new G4EmLivermorePhysics(); } else if (name == "empenelope") { fEmName = name; delete fEmPhysicsList; fEmPhysicsList = new G4EmPenelopePhysics(); } else if (name == "HElastic") { fHadronPhysicsList.push_back( new G4HadronHElasticPhysics()); } else if (name == "HInelastic") { fHadronPhysicsList.push_back(new G4HadronInelasticQBBC()); } ... }
and
void MyPhysicsList::ConstructProcess() { AddTransportation(); // transportation fEmPhysicsList->ConstructProcess(); // electromagnetic physics list fDecPhysicsList->ConstructProcess(); // decay physics list for(size_t i=0; i<fHadronPhys.size(); i++) { // hadronic physics lists fHadronPhys[i]->ConstructProcess(); } }
See the Monoenergetic Proton Pencil Beam tutorial to learn more about detailed physics lists.
Pre-Packaged Physics Lists
Some built-in pre-packaged physics lists are available here.
You can use them as a starting point of your simulation.
Here is a simple example of a pre-packaged physics list.
In function main()
:
G4PhysListFactory factory* physListFactory = new G4PhysListFactory(); G4VUserPhysicsList* physicsList = physListFactory->GetReferencePhysList(“FTFP_BERT”); runManager->SetUserInitialization(physicsList);
For example, if you want to simulate clinical proton beam of energy 150 MeV you can use a pre-packaged physics list e.g. QGSP_BIC
, QGSP_BERT
and FTFP_BERT
.
If you are interested in Bragg curve physics, use a physics list ending in EMV or EMX e.g. QGSP_BERT_EMV
.
Generate Primary Particles
You derive your own class from the G4VUserPrimaryGeneratorAction
base class.
The actual generation of primary particles is done via the classes G4ParticleGun
and G4GeneralParticleSource
.
- G4ParticleGun
- Used to simulate a beam of particles. It shoots a primary particle of a certain energy and direction from a given point at a given time.
- G4GeneralParticleSource
- Simulates a beam of particles and the primary vertex is randomly chosen on the surface of a given volume with pre-defined energy spectra, spatial and angular distribution.
Simple example of class MyPrimaryGeneratorAction
using particle gun:
class MyPrimaryGeneratorAction:public G4VUserPrimaryGeneratorAction { public: MyPrimaryGeneratorAction( const G4String& particleName = "proton", G4double energy = 1.*CLHEP::MeV, G4ThreeVector position= G4ThreeVector(0,0,0), G4ThreeVector momentumDirection = G4ThreeVector(0,0,1)); ~MyPrimaryGeneratorAction(); virtual void GeneratePrimaries(G4Event*); private: G4ParticleGun* fParticleGun; };
Simple example of class MyPrimaryGeneratorAction
using general particle source:
class MyPrimaryGeneratorAction:public G4VUserPrimaryGeneratorAction { public: MyPrimaryGeneratorAction(); ~MyPrimaryGeneratorAction(); virtual void GeneratePrimaries(G4Event*); private: static const G4String ParticleName; static const G4double ParticleEnergy; G4GeneralParticleSource* fGeneralParticleSource; };
Instructions on how to implement the MyPrimaryGeneratorAction
class in your code can be found on the Geant4 website.
The Monoenergetic Photon Pencil Beam example uses the G4ParticleGun
class.
The Proton Beam With Realistic Geometry tutorial uses G4GeneralParticleSource
.
Optional User Classes
Run
You can derive your own class from the G4UserRunAction
base class where you may book results of the run.
The run starts with "Beam On" and within a run you can not change the detector geometry and physics processes.
The run is represented by the class G4Run
.
You can find examples of user defined RunAction classes on the Geant4 website.
Event
Event is the basic GEANT4 unit.
At the beginning of an event are generated primary tracks which are pushed into a stack.
The tracks from the stack are analyzed one by one.
The primary tracks might lead to secondary tracks which are also pushed into the stack.
When the stack becomes empty the processing of the event is over.
The event is represented by the G4Event
class which gives hits and trajectory collections as output.
You can derive your own class from the G4UserEventAction
base class where you can select and analyse data.
Examples of user defined EventAction
classes can be found on the Geant4 website.
Track
Track is a snapshot of a particle and it is represented by the G4Track
class.
At the end of the event the track objects do not exist.
Tracks are pushed step by step.
Moving by one step is called stepping and this can be controlled by the G4UserSteppingAction
class (see below).
At the end of each step the state of a track can be changed (killed, suspended, postponed).
Step
Step is defined by two points: it also contains information about the particle e.g. energy loss on the step.
A step is represented by the G4Step
and G4StepPoint
classes.
G4UserSteppingAction
is an optional class where you can kill, suspend, postpone a track.
Status is attached to each G4StepPoint
to show how each step was determined.
You can use PostStepPoint to get the status of the current step and PreStepPoint to get the status of the previous step.
For example to get the "x" coordinate of a step you do the following:
G4StepPoint* prePoint = step->GetPreStepPoint(); G4double x1 = prePoint->GetPosition().x();
Trajectory
Trajectories are represented by the classes G4Trajectory
and G4TrajectoryPoint
.
The G4Trajectory
class copies some of the G4Track
class information.
G4TrajectoryPoint
is the class which copies some of the G4Step
information.