A practical introduction to the Geant4 Monte Carlo simulation toolkit Sébastien Incerti IN2P3 / CNRS Université Bordeaux 1 Centre d'Etudes Nucléaires de Bordeaux-Gradignan, France E-mail : incerti@cenbg.in2p3.fr Content Abstract 1. Introduction 2. Overview of Geant4 2.1 General Structure of Geant4 2.2 Units of simulation 2.3 Internal units of Geant4 2.4 The G4 prefix 3. Geant4 installation and user code development 3.1 Geant4 installation 3.2 How to write your own user code a) The main() - mandatory b) Detector Construction - mandatory c) Physics : particles and processes - mandatory d) Primary particles - mandatory e) User actions - optional f) User interface - optional g) Visualization – optional 4. Sample user code in eight steps a) STEP 1 : code edition and compilation b) STEP 2 : the main() c) STEP 3 : define a detector geometry d) STEP 4 : define Physics and particles e) STEP 5 : generation of primary particles f) STEP 6 : collect data g) STEP 7 : run the example h) STEP 8 : data analysis 5. Documentation Acknowledgements Geant4 collaboration publications 1 A practical introduction to the Geant4 Monte Carlo simulation toolkit Abstract This manuscript to users a brief overview of the Geant4 toolkit required fundamentals and proposes them to develop quickly a basic Geant4 simulation application, assuming they already have a reasonable knowledge of C++, so that they can start to work on their own application immediately after the Do Son school Geant4 tutorial. The slides shown at this tutorial present in details a large panel of Geant4 functionalities available to users in all Geant4 application domains. 1. Introduction Simulation plays a fundamental role in various domains and phases of an experimental physics project : design of the experimental set-up, evaluation and definition of the potential physics output of the project, evaluation of potential risks to the project, assessment of the performance of the experiment, development, test and optimization of reconstruction and physics analysis software, contribution to the calculation and validation of physics results… The Geant4 object oriented toolkit is a full set of libraries written in C++ allowing the user to simulate his/her own detector system. Specifying the detector geometry, the software system automatically transports the particles shot into the detector by simulating the particle interactions in matter based on the Monte Carlo method. Such a method searches for solutions to mathematical problems using statistical sampling with random numbers. Geant4 has initially been developed for the simulation of next generation HEP detectors (ATLAS, Alice, CMS, LHCb…), it is used widely today for the simulation of the current generation detectors and also in the space and medical Physics communities. In principle, any experimental system based on particle interactions could be simulated in Geant4, as long as the corresponding interaction processes have been implemented in the toolkit. The toolkit is developed by an international collaboration of physicists and software engineers (about ~100), collaborating all together in a distributed software production and management environment. It started in 1993 at CERN as a R&D phase (RD44) and the first release of the software occurred in December 1998. Since then, two released per year are produced. Geant4 is entirely open, entirely free, regularly updated and can be installed on common computing platforms (Linux, Windows©, Mac©,…) . It contains pedagogical examples and a user forum is available from the Internet at the address: http://cern.ch/geant4, which centralizes all information regarding Geant4. Short, long and specialized Geant4 tutorials are regularly organized worldwide. Geant4 is the successor of Geant3, which was written in Fortran. Its design, use, maintenance and portability follow rigorous object oriented programming rules After a description of the Geant4 structure, we will describe the different steps necessary for the development of a basic Geant4 application. Code samples are provided. 2. Overview of Geant4 2.1 General Structure of Geant4 Particles are generated in Geant4 from a single point; their trajectory in a given material is computed from a modeling of the physics processes applicable to them. Each physics process (e. g. proton ionization in water) is represented through a C++ class, allowing the computation of the probability of interaction (mean free path) via this process as well as the final state generation of the particle through this process. Each process can be described by several complementary models (like ionization parameterized from ICRU reports or from Ziegler’s parameterization) and a single particle can have different processes (like proton excitation in water, proton ionization in water, …). All secondary particles are computed the same way. Tracking occurs till the particles are stopped or leave the simulation volume. Most of the physics quantities (energy, position, energy deposit…) are accessible at anytime during the simulation and can be extracted according to the user’s needs. Many types of particles are available as well as physics processes, mainly classified into electromagnetic processes and hadronic processes. Particles include a “geantino” which is not associated to any interaction process and can be used to check a user-defined geometry. 2 Geant4 consists of 17 class categories, shown in Fig. 1; each is independently developed and maintained by a working group. The Geant4 kernel consists of categories in red. It provides central functionality of the toolkit : handles runs, events, tracks, steps, hits, trajectories, implements Geant4 as a state machine and provides a framework for : physics processes, visualization drivers, GUIs, persistency, histogramming/analysis and user code. . Fig. 1 : class categories Categories at the bottom of the diagram are used by virtually all higher categories and provide the foundation of the toolkit. The global category covers the system of units, constants, numerics and random number handling. The two categories, material and particle implement facilities necessary to describe the physical properties of particles and materials for the simulation of particle-matter interactions. The geometry module offers the ability to describe a geometrical structure and propagate particles efficiently through it. Above these reside categories required to describe the tracking of particles and the physical processes they undergo. The track category contains classes for tracks and steps, used by the processes category, which contains implementations of models of physical interactions: electromagnetic interactions of leptons, photons, hadrons and ions, and hadronic interactions. All processes are invoked by the tracking category, which manages their contribution to the evolution of a track's state and provides information in sensitive volumes for hits and digitization. Above these the event category manages events in terms of their tracks and the run category manages collections of events that share a common beam and detector implementation. A readout category allows the handling of pile-up. 2.2 Units of simulation Several units of simulation are used in Geant4 and must be introduced to the user before starting to build an application. A run The largest unit of simulation in Geant4 is a run. It is represented by the class G4Run. A run is a collection of events which are produced under identical conditions. Within a run, the user cannot change the detector or apparatus geometry, nor the Physics process settings. By analogy to high 3 energy physics, a Geant4 run begins with the command “beamOn”. The detector is inaccessible once the beam is on. At the beginning of a run, the geometry is optimized for navigation, cross sections are calculated according to materials in the setup, low-energy cutoff values are defined. An event At he beginning of processing, an event contains primary particles (from a generator, a particle gun, ...), which are pushed onto a stack. During the processing, each particle is popped from the stack and tracked. When the stack is empty, processing of the event is over. The class G4Event describes an event. At the end of processing, it has the following objects: list of primary vertices and particles (the input), hits collections, trajectory collections (optional), digitization collections (optional). A track A track is a snapshot of a particle within its environment as the particle moves. The quantities in the snapshot change at any particular instance, a track has a position and physical quantities, it is not a collection of steps. A track object (class G4Track) has a lifetime, it is created by a generator or a physics process (e.g. decay) and it is deleted when it leaves the World mother volume, disappears (particle decays or is absorbed), goes to zero energy and no “at rest” process is defined or the user kills it. No track object survives the end of an event (not persistent). The user must take action to store track record in trajectory. A step The step (class G4Step) is the basic unit of simulation; it has two points (pre-step, post-step) – see Fig. 2 – and it contains the incremental particle information (energy loss, elapsed time, etc.). Each point contains volume and material information. If the step is limited by a boundary, the end point stands exactly on the boundary, but is logically part of next volume. Hence boundary processes such as refraction and transition radiation can be simulated. Fig. 2 : step definition In Geant4, each particle has its own list of applicable processes. At the beginning of each step, all of these processes are queried for a proposed physical interaction length. The process with the shortest proposed length (in space-time) is the one that occurs. The chosen process also limits the step size. 2.3 Internal units of Geant4 The internal units system used in Geant4 is completely hidden from the user code and from the Geant4 source code implementation. Each hard-coded number must be multiplied by its proper unit (e.g. radius=10.0*cm; kineticE=1.0*GeV;). To retrieve a number, it must be divided by the desired unit: G4cout << eDep / MeV. Most commonly used units are provided, but user can add new ones. With this system, importing/exporting physical quantities is straightforward and source code is more readable 2.4 The G4 prefix For portability “G4” is prepended to raw C++ type names, like G4int, G4double, .... This way, Geant4 implements correct type for a given architecture. G4cout and G4cerr are ostream objects defined by Geant4 and G4endl is also provided. Some Graphical User Interfaces are buffer output streams so that they display print-outs on another window or provide storing/editing functionality. The user should not use std::cout, etc. Users should not use std::cin for input. Instead use the userdefined commands provided by the intercoms category, e.g. G4UIcmdWithADouble. 3. Geant4 installation and user code development 4 3.1 Geant4 installation The Geant4 installation procedure is entirely described on the Geant4 web site. As an alternative, for users who do not wish to bother with the installation, a useful virtualization configuration based on VMware© can be downloaded freely from http://geant4.in2p3.fr, under the Geant4 for VMware© section. It contains a fully up-to-date and ready-to-use installation of Geant4 under Scientific Linux 4.5 running under Windows© or Mac OS© with many useful tools – see Fig. 3.. Fig. 3 : Geant4 for WMware website 3.2 How to write your own user code The steps leading to the development of a full application are presented hereafter. The user must write a main() which is not provided and needs to use classes to build an application on top of the Geant4 toolkit; the usual classes are: Initialization classes • G4VUserDetectorConstruction • G4VUserPhysicsList Action classes • G4VUserPrimaryGeneratorAction • G4UserRunAction • G4UserEventAction • G4UserStackingAction • G4UserTrackingAction • G4UserSteppingAction Classes names in red bold are mandatory. a) The main() - mandatory Geant4 does not provide a main(). However, many examples are provided in the Application Developers Guide. In main(), you must construct a G4RunManager (or a class derived from it) and provide to G4RunManager pointers to mandatory user classes : G4VUserDetectorConstruction, 5 G4VUserPhysicsList and G4VUserPrimaryGeneratorAction. Manager classes broker transactions between objects within a category and communicate with other managers. They are singletons. The user will have the most contact with G4RunManager. He/she must register the detector geometry, the physics list and the particle generator to it. There are other manager classes: G4EventManager – handles event processing, user actions G4TrackingManager – handles tracks, trajectory storage, user actions G4SteppingManager – handles steps, physics processes, hit scoring, user actions G4VisManager – handles visualization drivers Other optional classes can be defined in main() like (G)UI session to define a (graphical) user interface. b) Detector Construction - mandatory The user must derive his/her own concrete class from G4VUserDetectorConstruction. In the virtual method Construct(), one has to assemble all necessary materials and build the volumes of the detector geometry. Optionally, one may construct sensitive detector classes and assign them to the detector volumes, define regions for any part of the detector (for production ranges), define visualization attributes of detector elements and magnetic (or other) fields. c) Physics : particles and processes - mandatory Geant4 does not have any default particles or processes even particle transportation must be explicitly defined by the user. The user must derive his/her own concrete class from the G4VUserPhysicsList abstract base class, where he defines all necessary particles, defines all necessary processes and assign them to the proper particles and defines production threshold (cutoff) ranges and assign them to the world mother volume and each region. Geant4 provides many utility classes/methods to assist in the above tasks. Example physics lists exist for electromagnetic (EM) and hadronic physics. Cuts are often used in Geant4 applications. A “cut” in Geant4 is a production threshold; it only applies to physics processes which have infrared divergence, it is not a tracking cut. An energy threshold must be determined at which discrete energy loss is replaced by continuous energy loss. Specify range (which is converted to energy for each material) at which continuous energy loss begins, track primary down to zero range. Above specified range create secondaries, below range add to continuous energy loss of primary. d) Primary particles - mandatory For each event, the user must define all details of initial particle. He must derive a concrete class from the G4VUserPrimaryGeneratorAction abstract base class. Geant4 provides several ways to do this: derive your own generator from G4VPrimaryGenerator or use provided generators: G4ParticleGun : user provides number, energy, direction, type of particle G4HEPEvtInterface, G4HepMCInterface : interfaces to high energy generator programs G4GeneralParticleSource : mostly for radioactivity e) User actions - optional Several optional user action classes with specific methods may be used for a large variety of purposes. In particular, the G4USerRunAction, G4UserEventAction and G4UserSteppingAction classes allows the user to access useful stages in the simulation. G4UserRunAction • BeginOfRunAction (define histograms) • EndOfRunAction (fill histograms) G4UserEventAction • BeginOfEventAction (event selection) 6 • EndOfEventAction (analyze event) G4UserTrackingAction • PreUserTrackingAction (create user defined trajectory) • PostUserTrackingAction G4UserSteppingAction • UserSteppingAction (kill, suspend, postpone track) • BeginOfSteppingAction • EndOfSteppingAction G4UserStackingAction • PrepareNewEvent (reset priority control) • ClassifyNewTrack o invoked when new track is pushed o can set track as urgent, waiting, postpone or kill • NewStage o invoked when urgent stack is empty o event filtering f) User interface - optional Geant4 provides several G4UISession concrete classes for user interface functionalities (e. g. terminal like interface to interact with Geant4 kernel). You can select the one that is appropriate for your computing environment. In main(), construct one of them and invoke its sessionStart() method. User Interface sessions provided are : • G4UIterminal : C- and TC-shell like character terminal, widely used • G4GAG : Tcl/Tk of Java PVM based GUI • G4JAG : interface to JAS (Java Analysis Studio) • G4UIBatch : batch job with macro file g) Visualization - optional For visualization of the simulated setup and interactions, the user can derive his/her own concrete class from G4VVisManager according to his/her computing environment. Geant4 provides interfaces to several graphics drivers: • DAWN – Fukui renderer • WIRED – event display • RayTracer – ray tracing by Geant4 tracking • OpenGL – the simplest and most used • OpenInventor • VRML 4. Sample user code in eight steps In this section, we show an implementation of source files that can be used for the construction of a standard simulation application presented during the tutorial, working on the ready-to-use freely downloadable installation of Geant4 (http://geant4.in2p3.fr). This application shows how to calculate dose deposits by incident protons in a liquid water spherical cell – see Fig. 4. Code lines are commented. The corresponding header files are indicated as well. 7 Fig. 4 : graphical output of the proposed user application a) STEP 1 : Code edition and compilation Usually, the simulation code is stored in a dedicated project directory (called “simulation” in this tutorial); in this directory, two subdirectories, “include” and “src”, contain respectively the project header files and the project source files – see Fig. 5. The main is placed in the project directory in the Simulation.cc file, as well as a GNUmakefile file that will be used during compilation and link. Under Linux, the project is simply compiled and linked using the gmake command. in simulation directory Simulation.cc GNUmakefile run.mac DetectorConstruction.hh PrimaryGeneratorAction.hh PhysicsList.hh RunAction.hh EventAction.hh SteppingAction.hh DetectorConstruction.cc PrimaryGeneratorAction.cc PhysicsList.cc RunAction.cc EventAction.cc SteppingAction.cc in simulation/include directory in simulation/src directory Fig. 5 : location of files in the proposed application Sample of GNUmakefile file for the compilation and link of the Simulation project; to be placed in the “simulation” directory: # Add your project executable name name := Simulation G4TARGET := $(name) G4EXLIB := true ifndef G4INSTALL G4INSTALL = ../../.. endif .PHONY: all all: lib bin include $(G4INSTALL)/config/binmake.gmk 8 The project files can be edited with any text editor or Integrated Development Environment tool. In this tutorial, we use the free snavigator© tool (available from http://sourcenav.sourceforge.net/). . b) STEP 2 : the main() Sample of Simulation.cc file to be placed in the “simulation” directory: // Geant4 and user header files to include #include "G4RunManager.hh" #include "G4UImanager.hh" #include "G4UIterminal.hh" #include "G4UItcsh.hh" #include #include #include #include #include #include "DetectorConstruction.hh" "PhysicsList.hh" "PrimaryGeneratorAction.hh" "RunAction.hh" "EventAction.hh" "SteppingAction.hh" // If one wishes to use vizualisation #ifdef G4VIS_USE #include "G4VisExecutive.hh" #endif // Main called with optional arguments int main(int argc,char** argv) { // Construct the default run manager G4RunManager * runManager = new G4RunManager; // Set mandatory user initialization classes DetectorConstruction* detector = new DetectorConstruction; runManager->SetUserInitialization(detector); runManager->SetUserInitialization(new PhysicsList); // Set mandatory user action classes runManager->SetUserAction(new PrimaryGeneratorAction(detector)); PrimaryGeneratorAction* primary = new PrimaryGeneratorAction(detector); // Set optional user action classes RunAction* RunAct = new RunAction(detector); runManager->SetUserAction(RunAct); runManager->SetUserAction(new EventAction(RunAct)); runManager->SetUserAction(new SteppingAction(RunAct,detector,primary)); // Visualization manager #ifdef G4VIS_USE G4VisManager* visManager = new G4VisExecutive; visManager->Initialize(); #endif // Initialize Geant4 kernel runManager->Initialize(); // Remove user output files system ("rm -rf dose.txt"); // Get the pointer to the User Interface manager G4UImanager* UI = G4UImanager::GetUIpointer(); if (argc==1) // Define UI session for interactive mode. { G4UIsession * session = new G4UIterminal(new G4UItcsh); // Use of a command macro file UI->ApplyCommand("/control/execute /home/local1/simulation/run.mac"); session->SessionStart(); delete session; } else // Batch mode 9 { G4String command = "/control/execute "; G4String fileName = argv[1]; UI->ApplyCommand(command+fileName); } #ifdef G4VIS_USE delete visManager; #endif delete runManager; return 0; } There is no corresponding header file. c) STEP 3 : define a detector geometry In the proposed example we define the mandatory mother world volume containing air and a sphere of liquid water. These materials are defined as well as the geometry. Each volume has three mandatory descriptions: solid, logic and physical. Visualization attributes as well as step size limitation are introduced. Sample of DetectorConstruction.cc file to be placed in the “simulation/src” directory: #include "DetectorConstruction.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... DetectorConstruction::DetectorConstruction() {} //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... DetectorConstruction::~DetectorConstruction() {} //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // Mandatory implementation of Construct method G4VPhysicalVolume* DetectorConstruction::Construct() { DefineMaterials(); return ConstructDetector(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void DetectorConstruction::DefineMaterials() { G4String name, symbol; G4double density; G4int ncomponents, natoms; G4double z, a; G4double fractionmass; // Define Elements // Example: G4Element* Notation = new G4Element ("Element", "Notation", z, a); G4Element* H = new G4Element ("Hydrogen", "H", 1. , 1.01*g/mole); G4Element* N = new G4Element ("Nitrogen", "N", 7., 14.01*g/mole); G4Element* O = new G4Element ("Oxygen" , "O", 8. , 16.00*g/mole); // Define Material // Case 1: chemical molecule // Water density = 1.000*g/cm3; G4Material* H2O = new G4Material(name="H2O" H2O->AddElement(H, natoms=2); , density, ncomponents=2); 10 H2O->AddElement(O, natoms=1); // Case 2: mixture by fractional mass // Air density = 1.290*mg/cm3; G4Material* Air = new G4Material(name="Air" Air->AddElement(N, fractionmass=0.7); Air->AddElement(O, fractionmass=0.3); , density, ncomponents=2); // Vacuum standard definition... density = universe_mean_density; G4Material* vacuum = new G4Material(name="Vacuum", z=1., a=1.01*g/mole, density); // Display list of defined materials G4cout << G4endl << *(G4Material::GetMaterialTable()) << G4endl; // Default materials in setup defaultMaterial = Air; waterMaterial = H2O; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4VPhysicalVolume* DetectorConstruction::ConstructDetector() { //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // MANDATORY MOTHER “WORLD” VOLUME WorldSizeX WorldSizeY WorldSizeZ = 50*micrometer; = 50*micrometer; = 50*micrometer; //---Solid solidWorld = new G4Box("World", WorldSizeX/2,WorldSizeY/2,WorldSizeZ/2); //its name //its size //---Logic logicWorld = new G4LogicalVolume(solidWorld, //its solid defaultMaterial, //its material "World"); //its name //---Physical physiWorld = new G4PVPlacement(0, G4ThreeVector(), "World", logicWorld, NULL, false, 0); //no rotation //at (0,0,0) //its name //its logical volume //its mother volume //no boolean operation //copy number // TARGET VOLUME solidTarget = new G4Sphere("Target", 0,10*micrometer, 0,2*M_PI, 0,M_PI); //its name //its minRadius and maxRadius //its phiMin and deltaPhi //its thetaMin and deltaTheta logicTarget = new G4LogicalVolume(solidTarget, waterMaterial, "Target"); //its solid //its material //its name physiTarget = new G4PVPlacement(0, //rotation G4ThreeVector(0,0,0),// transl "Target", //its name logicTarget, //its logical volume physiWorld, //its mother volume false, //no boolean operation 0); //copy number // Visualization attributes 11 G4VisAttributes* worldVisAtt= new G4VisAttributes(G4Colour(1.0,1.0,1.0)); //White worldVisAtt->SetVisibility(true); logicWorld->SetVisAttributes(worldVisAtt); G4VisAttributes* targetVisAtt= new G4VisAttributes(G4Colour(0,1.0,1.0)); //Blue targetVisAtt->SetForceSolid(true); targetVisAtt->SetVisibility(true); logicTarget->SetVisAttributes(targetVisAtt); // User Limits on step size logicWorld->SetUserLimits(new G4UserLimits(1*micrometer)); logicTarget->SetUserLimits(new G4UserLimits(1*micrometer)); return physiWorld; } Sample of DetectorConstruction.hh file to be placed in the “simulation/include” directory: #ifndef DetectorConstruction_h #define DetectorConstruction_h 1 #include #include #include #include #include #include "G4VUserDetectorConstruction.hh" "G4VPhysicalVolume.hh" "G4LogicalVolume.hh" "G4Box.hh" "G4Sphere.hh" "G4Material.hh" #include "G4PVPlacement.hh" #include "G4UserLimits.hh" #include "G4VisAttributes.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // Class deriving from the virtual G4VUserDetectorConstruction class class DetectorConstruction : public G4VUserDetectorConstruction { public: DetectorConstruction(); ~DetectorConstruction(); G4VPhysicalVolume* Construct(); private: G4double G4double G4double WorldSizeX; WorldSizeY; WorldSizeZ; G4VPhysicalVolume* physiWorld; G4LogicalVolume* logicWorld; G4Box* solidWorld; G4VPhysicalVolume* physiTarget; G4LogicalVolume* logicTarget; G4Sphere* solidTarget; G4Material* G4Material* defaultMaterial; waterMaterial; void DefineMaterials(); G4VPhysicalVolume* ConstructDetector(); }; #endif 12 d) STEP 5 : define Physics and particles The following explains how to define particles and associate to them physics processes. Low energy electromagnetic processes for gammas, electrons, positrons and light ions are introduced as well as production cuts. Sample of PhysicsList.cc file to be placed in the “simulation/src” directory: #include "PhysicsList.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... PhysicsList::PhysicsList(): G4VUserPhysicsList() { // Specify production cut for EM processes defaultCutValue = 1*nanometer; cutForGamma = defaultCutValue; cutForElectron = defaultCutValue; cutForPositron = defaultCutValue; cutForProton = defaultCutValue; // Specify verbosity level SetVerboseLevel(1); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... PhysicsList::~PhysicsList() {} //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // ***** Construction of particles void PhysicsList::ConstructParticle() { ConstructBosons(); ConstructLeptons(); ConstructBaryons(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void PhysicsList::ConstructBosons() { // gamma G4Gamma::GammaDefinition(); // optical photon G4OpticalPhoton::OpticalPhotonDefinition(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void PhysicsList::ConstructLeptons() { // leptons G4Electron::ElectronDefinition(); G4Positron::PositronDefinition(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void PhysicsList::ConstructBaryons() { // baryons G4Proton::ProtonDefinition(); G4AntiProton::AntiProtonDefinition(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // ***** Processses and particles void PhysicsList::ConstructProcess() 13 { AddTransportation(); ConstructEM(); ConstructGeneral(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... #include #include #include #include "G4MultipleScattering.hh" "G4eIonisation.hh" "G4eBremsstrahlung.hh" "G4eplusAnnihilation.hh" #include #include #include #include "G4LowEnergyPhotoElectric.hh" "G4LowEnergyCompton.hh" "G4LowEnergyGammaConversion.hh" "G4LowEnergyRayleigh.hh" #include "G4LowEnergyIonisation.hh" #include "G4LowEnergyBremsstrahlung.hh" #include "G4hLowEnergyIonisation.hh" #include "G4StepLimiter.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void PhysicsList::ConstructEM() { theParticleIterator->reset(); while( (*theParticleIterator)() ){ G4ParticleDefinition* particle = theParticleIterator->value(); G4ProcessManager* pmanager = particle->GetProcessManager(); G4String particleName = particle->GetParticleName(); if (particleName == "gamma") { pmanager->AddDiscreteProcess(new G4LowEnergyCompton); G4LowEnergyPhotoElectric * LePeprocess = new G4LowEnergyPhotoElectric(); pmanager->AddDiscreteProcess(LePeprocess); pmanager->AddDiscreteProcess(new G4LowEnergyGammaConversion()); pmanager->AddDiscreteProcess(new G4LowEnergyRayleigh()); // Allow use of step size limitation specified in DetectorConstruction pmanager->AddProcess(new G4StepLimiter(),-1,-1,3); } else if (particleName == "e-") { pmanager->AddProcess(new G4MultipleScattering,-1, 1,1); G4LowEnergyIonisation * LeIoprocess = new G4LowEnergyIonisation("IONI"); pmanager->AddProcess(LeIoprocess, -1, 2, 2); G4LowEnergyBremsstrahlung * LeBrprocess = new G4LowEnergyBremsstrahlung(); pmanager->AddProcess(LeBrprocess, -1, -1, 3); // Allow use of step size limitation specified in DetectorConstruction pmanager->AddProcess(new G4StepLimiter(),-1,-1,3); } else if (particleName == "e+") { pmanager->AddProcess(new pmanager->AddProcess(new pmanager->AddProcess(new pmanager->AddProcess(new G4MultipleScattering,-1, 1,1); G4eIonisation, -1, 2,2); G4eBremsstrahlung, -1,-1,3); G4eplusAnnihilation, 0,-1,4); // Allow use of step size limitation specified in DetectorConstruction pmanager->AddProcess(new G4StepLimiter(),-1,-1,3); } else if ((!particle->IsShortLived()) && (particle->GetPDGCharge() != 0.0) && 14 (particle->GetParticleName() != "chargedgeantino")) { pmanager->AddProcess(new G4MultipleScattering(),-1,1,1); G4hLowEnergyIonisation* hLowEnergyIonisation = new G4hLowEnergyIonisation(); pmanager->AddProcess(hLowEnergyIonisation,-1,2,2); hLowEnergyIonisation->SetElectronicStoppingPowerModel(particle,"ICRU_R49p"); // Allow use of step size limitation specified in DetectorConstruction pmanager->AddProcess(new G4StepLimiter(),-1,-1,3); } } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void PhysicsList::ConstructGeneral() { } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // ***** Set production cuts void PhysicsList::SetCuts() { if (verboseLevel >0) { G4cout << "PhysicsList::SetCuts:"; G4cout << "CutLength : " << G4BestUnit(defaultCutValue,"Length") << G4endl; } // set cut values for gamma at first and for e- second and next for e+, // because some processes for e+/e- need cut values for gamma SetCutValue(cutForGamma, "gamma"); SetCutValue(cutForElectron, "e-"); SetCutValue(cutForPositron, "e+"); // set cut values for proton and anti_proton before all other hadrons // because some processes for hadrons need cut values for proton/anti_proton SetCutValue(cutForProton, "proton"); SetCutValue(cutForProton, "anti_proton"); if (verboseLevel>0) DumpCutValuesTable(); } Sample of PhysicsList.hh file to be placed in the “simulation/include” directory: #ifndef PhysicsList_h #define PhysicsList_h 1 #include "G4VUserPhysicsList.hh" #include "G4ProcessManager.hh" #include "G4ParticleTypes.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... class PhysicsList: public G4VUserPhysicsList { public: PhysicsList(); ~PhysicsList(); void void void void SetGammaCut(G4double); SetElectronCut(G4double); SetPositronCut(G4double); SetProtonCut(G4double); protected: // these methods construct particles void ConstructBosons(); void ConstructLeptons(); void ConstructBarions(); 15 // these methods construct physics processes and register them void ConstructGeneral(); void ConstructEM(); // Construct particle and physics void ConstructParticle(); void ConstructProcess(); // set cuts void SetCuts(); private: G4double G4double G4double G4double cutForGamma; cutForElectron; cutForPositron; cutForProton; }; #endif e) STEP 4 : generation of primary particles This sample shows how to define a simple particle gun shooting protons of 3 MeV just before the target. Sample of PrimaryGeneratorAction.cc file to be placed in the “simulation/src” directory: #include "PrimaryGeneratorAction.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // Specify constructed detector in argument PrimaryGeneratorAction::PrimaryGeneratorAction(DetectorConstruction* DC) :Detector(DC) { // Define particle gun object G4int n_particle = 1; particleGun = new G4ParticleGun(n_particle); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... PrimaryGeneratorAction::~PrimaryGeneratorAction() { delete particleGun; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void PrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent) { // Get simulation current event number G4int numEvent; numEvent=anEvent->GetEventID()+1; G4double x0,y0,z0,theta,phi,xMom0,yMom0,zMom0,e0; // Specify kinetic energy e0 = 3*MeV ; particleGun->SetParticleEnergy(e0); // Specify emission direction theta = 0; phi = 0; xMom0 = std::sin(theta); yMom0 = std::sin(phi); zMom0 = std::sqrt(1.-xMom0*xMom0-yMom0*yMom0); particleGun->SetParticleMomentumDirection(G4ThreeVector(xMom0,yMom0,zMom0)); // x0 y0 z0 Specify emission point = 0; = 0; = -20*micrometer; 16 particleGun->SetParticlePosition(G4ThreeVector(x0,y0,z0)); // Select proton G4ParticleDefinition* particle= G4ParticleTable::GetParticleTable()->FindParticle("proton"); particleGun->SetParticleDefinition(particle); // Example of output display G4cout << "-> Event= " << numEvent << " : Theta (mrad)= " << theta/mrad << " - Phi (mrad)= " << phi/mrad << " - x0 (um)= " << x0/um << " - y0 (um)= " << y0/um << " - z0 (um)= " << z0/um << " - e0 (MeV)= " << e0/MeV << G4endl; // Shoot particleGun->GeneratePrimaryVertex(anEvent); } Sample of PrimaryGeneratorAction.hh file to be placed in the “simulation/include” directory: #ifndef PrimaryGeneratorAction_h #define PrimaryGeneratorAction_h 1 #include #include #include #include #include "G4VUserPrimaryGeneratorAction.hh" "G4ParticleGun.hh" "DetectorConstruction.hh" "G4Event.hh" "G4ParticleTable.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { public: PrimaryGeneratorAction(DetectorConstruction*); ~PrimaryGeneratorAction(); void GeneratePrimaries(G4Event*); private: G4ParticleGun* DetectorConstruction* }; particleGun; Detector; #endif f) STEP 6 : collect data One may use action classes to extract useful information from the simulation. In our example, a run would represent a set of 103 protons sent to the target, an event would represent one proton among these 103 protons, a step would represent any interaction step of a proton or all secondary particles generated in any part of the simulated setup. Then, o o o we calculate the target mass at Run Action, that is when the run starts the total deposited dose by each incident proton as well has the proton beam output position from the target are stored in a text file for later analysis at the end of Event Action, that is after each single shot proton has completely interacted with the setup the dose value is computed for each proton and secondary electrons within the interaction medium at Stepping Action, as well as the linear energy transfer and beam spread at cell exit Let’s first start with the largest unit of the simulation: a run. Sample of RunAction.cc file to be placed in the “simulation/src” directory : 17 #include "RunAction.hh" #include "G4Run.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // Specify constructed detector in argument RunAction::RunAction(DetectorConstruction* det) :Detector(det) { // Initialize total deposited dose doseTarget=0; // Compute target mass G4double radius = 10*1e-6; G4double density = 1000; massTarget=(4/3)*M_PI*pow(radius,3)*density; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... RunAction::~RunAction() {} //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void RunAction::BeginOfRunAction(const G4Run* aRun) { // Display run number G4cout << "---> Run " << (aRun->GetRunID())+1 << " start." << G4endl; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void RunAction::EndOfRunAction(const G4Run*) { } The header file contains accessor methods; these methods are useful when one needs to compute quantities that must be updated at different stages in the simulation. Sample of RunAction.hh file to be placed in the “simulation/include” directory: #ifndef RunAction_h #define RunAction_h 1 #include "DetectorConstruction.hh" #include "G4UserRunAction.hh" #include "globals.hh" #include <iostream> //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... class G4Run; class RunAction : public G4UserRunAction { public: RunAction(DetectorConstruction*); ~RunAction(); void BeginOfRunAction(const G4Run*); void EndOfRunAction(const G4Run*); // Accessor methods for dose computation void AddDoseTarget(G4double dose){ doseTarget += dose;} void SetDoseTarget(G4double dose){ doseTarget = dose;} G4double GetDoseTarget(){return doseTarget;} // Accessor methods for mass computation void SetMassTarget(G4double mT){ massTarget = mT;} G4double GetMassTarget(){return massTarget;} private: 18 DetectorConstruction* Detector; G4double doseTarget; G4double massTarget; }; #endif We now move to the Event simulation unit (one event corresponds to one proton shot). Sample of EventAction.cc file to be placed in the “simulation/src” directory: #include "EventAction.hh" #include "RunAction.hh" #include #include #include #include #include #include "G4Event.hh" "G4EventManager.hh" "G4TrajectoryContainer.hh" "G4Trajectory.hh" "G4VVisManager.hh" "Randomize.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // Specify run action object in argument // Initialize a flag for trajectory drawing on visualization window EventAction::EventAction(RunAction* run) :Run(run),drawFlag("all") {} //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... EventAction::~EventAction() {} //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void EventAction::BeginOfEventAction(const G4Event* /*evt*/) { // Dose is accessed through accessor and is set to zero at beginning of new event Run->SetDoseTarget(0); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void EventAction::EndOfEventAction(const G4Event* evt) { // Dose is written in text file at the end of event if (Run->GetDoseTarget()>0) { FILE* myFile; myFile=fopen("dose.txt","a"); fprintf(myFile,"%e\n",float(Run->GetDoseTarget()) ); fclose (myFile); G4cout << " ===> The incident particle has reached the targeted cell :" << G4endl; G4cout << " -----> total absorbed dose is (Gy) = " << Run->GetDoseTarget() << G4endl; G4cout << G4endl; } else { G4cout << " ===> Sorry, the incident alpha particle has missed the targeted cell !" << G4endl; G4cout << G4endl; } // Mandatory for trajectory drawing in vizualisation window if (G4VVisManager::GetConcreteInstance()) { G4TrajectoryContainer * trajectoryContainer = evt->GetTrajectoryContainer(); 19 G4int n_trajectories = 0; if (trajectoryContainer) n_trajectories = trajectoryContainer->entries(); for (G4int i=0; i<n_trajectories; i++) { G4Trajectory* trj = (G4Trajectory*)((*(evt->GetTrajectoryContainer()))[i]); if (drawFlag == "all") { trj->DrawTrajectory(50); } else if ((drawFlag == "charged")&&(trj->GetCharge() != 0.)) { trj->DrawTrajectory(50); } } } } Sample of EventAction.hh file to be placed in the “simulation/include” directory: #ifndef EventAction_h #define EventAction_h 1 #include "G4UserEventAction.hh" #include "globals.hh" class RunAction; //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... class EventAction : public G4UserEventAction { public: EventAction(RunAction*); ~EventAction(); void BeginOfEventAction(const G4Event*); void EndOfEventAction(const G4Event*); private: RunAction* G4String G4int Run; drawFlag; printModulo; }; #endif Finally, we extract physics quantities at the step level (interaction step of any particle generated in the simulation). Sample of SteppingAction.cc file to be placed in the “simulation/src” directory: #include #include #include #include "SteppingAction.hh" "RunAction.hh" "DetectorConstruction.hh" "PrimaryGeneratorAction.hh" #include "G4SteppingManager.hh" #include "G4VTouchable.hh" #include "G4VPhysicalVolume.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // RunAction, DetectorConstruction, PrimaryGeneratorAction objets in argument SteppingAction::SteppingActio (RunAction* run,DetectorConstruction* det,PrimaryGeneratorAction* pri) :Run(run),Detector(det),Primary(pri) { } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... SteppingAction::~SteppingAction() 20 { } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void SteppingAction::UserSteppingAction(const G4Step* s) { // Dose incrementation if (s->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "Target") { G4double dose = (e_SI*(s->GetTotalEnergyDeposit()/eV))/(Run->GetMassTarget()); Run->AddDoseTarget(dose); } // Beam spread after target if ( (s->GetTrack()->GetDynamicParticle()->GetDefinition() ->GetParticleName() == "proton") && (s->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "Target") && (s->GetPostStepPoint()->GetPhysicalVolume()->GetName() == "World") ) { FILE* myFile; myFile=fopen("dose.txt","a"); fprintf ( myFile,"%e %e %e ", (s->GetTrack()->GetPosition().x())/micrometer, (s->GetTrack()->GetPosition().y())/micrometer, (s->GetTrack()->GetPosition().z())/micrometer ); fclose (myFile); } // Linear energy transfer computation if ( (s->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "Target") && (s->GetPostStepPoint()->GetPhysicalVolume()->GetName() == "World") && (s->GetTrack()->GetDynamicParticle()->GetDefinition() ->GetParticleName() == "proton") ) { FILE *myFile; myFile=fopen("dose.txt","a"); fprintf(myFile,"%e ",(s->GetTotalEnergyDeposit()/keV)/ (s->GetStepLength()/micrometer)); fclose (myFile); } } g) STEP 7 : run the example After the code has been compiled with gmake, it can be executed with the command: $G4WORKDIR/bin/Linux-g++/Simulation As specified in the Simulation.cc code, the user interface will read built-in commands given in the run.mac file located in the “simulation” directory. This file specifies in particular that 103 protons will be shot towards the target. Sample of macro file run.mac file to be placed in the “simulation” directory: # Visualization enabled /vis/scene/create /vis/scene/add/volume /vis/sceneHandler/create OGLIX /vis/viewer/create /vis/viewer/set/viewpointThetaPhi 70 10 # Storing of trajectories /tracking/storeTrajectory 1 /vis/scene/endOfEventAction accumulate 21 # Verbose control /tracking/verbose 0 /run/verbose 0 # Shoot 1000 protons /run/beamOn 1000 A description of all command is accessible by typing help at the prompt in the Geant4 user session. The user can define his/her own commands for a better interactivity with his/her application. h) STEP 8 : data analysis Geant4 does not endorse or support particular analysis packages. However, an abstract analysis interface is provided : AIDA (Abstract Interfaces for Data Analysis). It will be built and linked to your application if the environment variable $G4ANALYSIS_USE is set to 1. AIDA headers must be installed in the code where the analysis is set up, with #include AIDA/AIDA.h. The user must then use AIDA-compliant analysis tools. More AIDA information is available at http://aida.freehep.org. The OpenScientist Lab package is an AIDA-compliant Analysis Package (http://www.lal.in2p3.fr/OpenScientist). An example using Open Scientist can be found in $G4INSTALL/examples/extended/analysis/AnaEx01. It allows in particular the production of result files containing histograms, tuples, …in PAW (hbook) or ROOT (root) format, widely used in the community of high energy physics. This package is already installed on the downloadable VMware© installation of Geant4. Several Geant4 examples (see next paragraph) illustrate how to use these libraries, allowing the creation of such histograms directly in Geant4. In this tutorial, we simply create output result text files directly in the Geant4 application and analyze them with the ROOT package, outside the simulation. For this purpose, we use the simple ROOT macro file plot.C to plot the dose distribution, the linear energy transfer distribution at target exit and the beam spread. Gauss fits are also applied. This macro reads the text file dose.txt created by the application and placed in the “simulation” directory. The plot.C file is located in the “simulation” directory and can be edited with any text editor. Open a ROOT session in the simulation “simulation” by typing root and at prompt and execute the macro file with the command .X plot.C. Typical results are shown in Fig. 6 for 106 incident 3 MeV protons. Fig. 6 : application results analyzed with ROOT The OpenScientist package developed at IN2P3 (http://openscientist.lal.in2p3.fr/) 5. Documentation Extensive Geant4 documentation is available from the Geant4 web site : http://cern.ch/geant4. In particular, a full documentation is accessible from the User Support section (Fig. 7) of this web site, including detailed installation instructions, an application developer guide, a toolkit developer guide, a physics reference manual as well as a software reference manual. An interactive hypernews forum is available for information sharing and question asking as well as a code browser. 22 Seven easy novice examples ranging from very easy to complex are available in the Geant4 source code in the $G4INSTALL/examples directory. They can be used as templates for your own application. Extended examples for testing and validation, demonstrating Geant4 tools, extending Geant4 are also provided. Advanced Examples show practical applications and examples from outside HEP (space, medical, etc. Their description is accessible from the html version of the application developer guide. Fig. 7 : user support section of the Geant4 web site Acknowledgements We would like to thank the Do Son school organizers, in particular Vincent Breton, for their kind invitation to participate to the school. We also would like to thank the whole Geant4 collaboration for the preparation the Geant4 tutorial material from which the presented slides and this manuscript are extracted. This contribution would not have been possible without the support of IN2P3. Geant4 collaboration publications [1] S. Agostinelli et al., Geant4 - a simulation toolkit, Nucl. Instrum. Meth. A 506 (3) (2003) 250-303 [2] J. Allison et al., Geant4 Developments and Applications, IEEE Trans. Nucl. Sci. 53 (1) (2006) 270278 The Geant4 collaboration, Bordeaux, France, 11/2005 23 http://geant4.cern.ch 24