COINCIDENCES BETWEEN NEUTRONS AND...
Transcript of COINCIDENCES BETWEEN NEUTRONS AND...
COINCIDENCES BETWEEN NEUTRONS AND
GAMMAS
July 21, 2019
Josefine Sjöberg
Uppsala University
Abstract
The neutron is a valuable tool in many fields of science due to its properties regarding electric
charge and magnetic moment. However, these properties also makes it difficult to detect.
Through simulation one can optimize the detector environment to best correspond with
the needs for a specific experiment. In this project, a detector environment is simulated,
consisting of a neutron and gamma point source and one detector for each type of particle.
The simulated results were in good agreement with the underlying theory and the simulation
can, therefore, be used in future work.
Contents
1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1 Interaction of gamma rays . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.1 Photoelectric absorption . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.2 Compton scattering . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.3 Pair production . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Interaction of fast neutrons . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.1 Cross-section . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Time of flight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3 Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.1 Technical specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2 Simulation build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3 Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4 Result and analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.1 Mono-energetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.2 Uniform spectrum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Appendix 18
A PrimaryGeneratorAction.h 19
B PrimaryGeneratorAction.ccp 20
C DetectorConstruction.h 22
D DetectorConstruction.cpp 23
E EventAction.h 28
1
2
F EventAction.cpp 30
G RunAction.h 34
H RunAction.cpp 35
I G4PSTime.h 37
J G4PSTime.cpp 38
K Analysis.h 40
L Main.cpp 41
3
1 INTRODUCTION
The goal of this project was to simulate a detector environment where the detectors reg-
ister both the deposited energy and the time of interaction for neutrons and gammas in
coincidence. A neutron source and two scintillator detectors are simulated, one made of
vinyl-toluene for neutrons and a barium-fluoride detector for gammas. The source is a point
source which emits neutrons and gammas in opposite directions simultaneously and if both
the particles deposit energy into the detector, they are in coincidence. The neutron-gamma
coincidence requirement was implemented to verify the simulated result with theory. The
simulation was done for two special cases regarding the neutron energy, mono-energetic 2.4
MeV neutrons and neutrons with a uniform distribution between 2 and 4 MeV. The energy
of the gamma quanta is 4.4 MeV in both cases. In the first case, the source is set to energies
corresponding to an americium-beryllium source, which is the source to be used in a contin-
uation of this project. The simulation can later be used to optimize the detector environment
by testing different geometries, materials and neutron energy distributions and also to test
different shielding materials and geometries. The simulation was done with the open source
simulation tool kit GEANT4.
The properties of the neutron make it an important probe of matter and is consequently a
valuable tool in many fields of science [2]. The neutron carries no electric charge and can
therefore probe deeply into matter, since it will not be influenced by Coulomb interactions.
Instead, it interacts with the nuclei through mostly elastic scattering for 2.4 MeV neutrons,
where the scattering cross sections have a high isotope and element dependency. This means
that the neutron is ideal for probing the isotope or element composition of samples. Further,
the neutron has a small magnetic moment which makes it possible to investigate the mag-
netic properties of materials. The downside with these properties is that they also make the
neutron difficult to detect. Since the neutron does not have a charge it can not be detected by
direct ionization of the detector material, as charged particles. Only by studying the inter-
actions of the neutron with its surroundings can conclusions be drawn about its properties,
for example its energy. These interactions are primarily absorption, elastic scattering and
activation.
Scintillator detectors are widely used for detecting fast neutrons and they rely to a large
extent on the elastic scattering interaction. The recoiling nuclei will ionize and excite further
atoms through collisions and scintillation light is sent out in the de-excitation process. The
4
challenge when using this type of detector is to distinguish the scintillation light signals
produced by neutrons from signals produced by gamma radiation in the same detector.
2 THEORY
2.1 Interaction of gamma rays
The information in this section is extracted from Radiation Detection and Measurement [1].
The three major gamma-ray interactions are photoelectric absorption, Compton scattering
and pair production. The photoelectric absorption is dominant for lower energy photons,
Compton scattering for mid-energy photons and pair production for high energy photons.
2.1.1 Photoelectric absorption
The photoelectric absorption is when a photon is absorbed by an atom which then ejects an
electron, called a photoelectron, if the photon energy is high enough. Electrons are bound to
the nucleus with a specific energy, the binding energy, and this energy needs to be overcome
for the electron to leave the atom. Therefore the incoming photon must have an energy above
the electrons binding energy for the interaction to take place. The resulting photoelectron
energy is:
Ee− = Ep −Eb . (1)
where Ep is the energy of the incoming photon and Eb is the binding energy of the photoelec-
tron in its original shell.
When the photoelectron is emitted from the atom it leaves a vacancy in one of the shells,
making the atom excited. This vacancy is filled by the atom capturing a free electron or by
rearranging the remaining electrons. In this process, characteristic x-ray photons, Auger
electrons or scintillation light may be emitted, carrying away the atomic excitation energy.
2.1.2 Compton scattering
Compton scattering is when a photon is scattered by an electron, transferring some of its
energy. If the electron is bound to an atom, the atom will be ionized. The energy transferred
in the scattering event depends on the angle which the photon is scattered through, where 0°
is zero energy and 180° maximum energy. In Figure 1, a photon of wavelength λ comes in
5
from the left, collides with a target at rest, and a new photon of wavelength λ′ emerges at an
angle θ. The target recoils, carrying away an angle-dependent amount of the incident energy.
The relationship between wavelength and energy for photons is given by E = hcλ , where h is
Planck’s constant and c the speed of light in vacuum.
Figure 1: Schematic over a Compton scattering event [3].
The amount of energy exchanged in a Compton scattering event is given by the formula:
1
E ′ −1
E= 1
me c2(1− cosθ), (2)
or
E′ = E
1+ Eme c2 (1− cosθ)
(3)
where E′
and E is the outgoing and incoming photon energy, me c2 is the electron rest mass
and θ is the scattering angle defined in Figure 1. The energy transferred to the electron is the
outgoing photon energy subtracted from the incoming photon energy:
Ee− = E −E′ = E − E
1+ Eme c2 (1− cosθ)
, (4)
The maximum energy that can be transferred in a Compton scattering event is called the
Compton edge and it is found by using θ = 180, giving:
ECompton_ed g e = E − E
1+ 2Eme c2
. (5)
2.1.3 Pair production
When an incoming high energy photon is in the proximity of a nucleus, i.e. in the Coulomb
field of a nucleus, pair production can take place. In this process, the photon is transformed
to a electron-positron pair: γ→ e−+ e+. For the production to occur, the photon needs to
have an energy higher than 1.022 MeV, which is the rest mass of the electron and the positron
6
together. Any energy above this threshold becomes kinetic energy of both the electron-
positron pair and the nucleus, which recoil. When the positron slows down, it will bind
itself with an available electron in the material and subsequently annihilate, creating two
annihilation photons in the process. There are three possible outcomes after the annihilation:
both photons deposit their energy in the detector, one deposit its energy and one escape
the detector or both escapes the detector. The two last outcomes result in two peaks in the
gamma spectrum, one at -511 keV and one at -1022 keV from the photopeak, which is caused
by the lost photons. The photopeak is the peak formed due to the complete absorption of the
photon energy in the detector
2.2 Interaction of fast neutrons
2.2.1 Cross-section
The cross-section is a probability measure for an interaction or reaction to occur between two
particles. The neutron scintillator detector in this project consists of the plastic vinyl-toluene
which is composed of hydrogen and carbon. Between fast neutrons and these two elements
the most occurring interaction is elastic scattering, which has an energy dependent cross-
section. In Figure 2 and Figure 3 these cross-sections for neutrons on carbon and hydrogen
are shown respectively, i.e the probability for an elastic scattering event to occur with these
elements for different neutron energies.
7
Figure 2: Elastic scattering cross section for neutrons on carbon [4].
Figure 3: Elastic scattering cross section for neutrons on hydrogen [4].
8
2.3 Time of flight
There are two set quantities in the simulation, the energy of the emitted source particles
and the source distance to the detectors. These can be used to verify the results from the
simulations, by theoretically calculate the expected times of interaction. For this, two funda-
mental equations are needed. The first equation describes the relationship between distance,
velocity and time:
s = v · t → t = s
v, (6)
where s is the source distance to the detector, v the velocity of the emitted particles and t the
time it takes for a particle to travel the distance s. The velocity can be found using the second
equation needed, which describes the relationship between velocity and kinetic energy:
E = 1
2·m · v2 → v =
√2 ·E
m, (7)
where E is the kinetic energy, m the mass of the particle and v the velocity of the particle.
Substituting equation 7 in to equation 6 gives the equation for the time of flight:
t = s√2·Em
. (8)
3 METHOD
3.1 Technical specifications
Operating system used in this project was OS X Yosemite. All simulations were done with
GEANT4 version 10.3 and the data was processed in MATLAB version 2014b. GEANT4 was
built with cmake version 3.12.2 and the simulations were run with XQuartz terminal version
2.7.11.
3.2 Simulation build
GEANT4 uses a Monte-Carlo algorithm to simulate particle transport through matter. The
environment is object-oriented and using the programming language C++.
The source used in the simulation was a point source in origin, emitting one neutron and one
gamma quanta in the directions (0, 0, 1) and (0, 0, -1) respectively, in the Cartesian coordinate
9
system (x,y,z). The gamma quanta energy was held at 4.4 MeV during all simulations while
the neutrons were set to 2.4 MeV mono-energetic or with a uniform distribution between 2
and 4 MeV.
Two detectors were simulated, one for neutrons and one for gammas. The neutron detector
consisted of the organic plastic scintillator material vinyl-toluene and the gamma detector of
the crystalline barium-fluoride. Both detectors were shaped like cylinders where the neutron
detector had a diameter of 94 mm and a length of 62 mm and the gamma detector had 51
mm for both diameter and length. The neutron detectors center was placed at (0, 0, -1.05) m
and the gamma detector at (0, 0, 0.1) m. Both the detector sizes and placements are arbitrary.
The detector environment is illustrated in Figure 4.
The detectors register the energy that is deposited into the detectors and at what time this
energy transfer is occurring, i.e. the time of interaction, being the average of the time of the
first interaction and the last. In a real experiment, the time it takes for the neutron to reach
the detector, the time of flight, is determined by using the interaction in the gamma detector
as a start signal and the interaction in the neutron detector as a stop signal. This process is
not necessary in a simulation, but to see how the result would look in a real experiment the
gamma time of interaction was subtracted from the neutron time of interaction, giving the
time of flight. The neutron detector has a proton filter added and the gamma detector an
electron, positron and gamma filter. These filters result in the output energy being the sum
of the energy transferred between only the source particle and the particles in the filter. The
reason for the proton filter is to simplify the simulation by disregarding the elastic scattering
events on carbon. Since carbon is much heavier than hydrogen, the scintillation light output
is less for the same amount of energy transferred from the neutron. To include carbon
scattering events, a response function would have to be added in the code. The filter on the
gamma detector was added for future use in the continuation of this project.
10
Figure 4: Visual of the simulation build.
3.3 Code
When building this simulation there were three challenges, how to send out two different
particles from one source, how to register both energy deposition and time of interaction in a
detector and lastly how to ensure that the neutron and gamma quantum were in coincidence.
The source in this project should send out two different particles at the same time. Preferably
this should be done within the same event, but how to achieve that was not found during this
project. The solution instead was to send out one particle in one event and the other particle
in the next event. By using a private boolean variable particle, see Appendix A and B, it was
possible to keep track of which particle was last emitted. This could be done since the time
of interaction is the time it takes for the particle to reach the detector, and is therefore not
dependent on when the particle leaves the source.
The time of flight of the neutrons can be retrieved by taking the difference in time of inter-
action of the energy deposition for the neutrons and gammas. However, GEANT4 does not
have a built-in scorer for time registration and therefore one was needed to be written, see
Appendix J. A function GetTime was added to handle the scorer, see Appendix F.
To get a realistic time of flights of the neutrons, it was important that the registered neutrons
and gammas were in coincidence. To ensure this the gamma energies and times were saved
higher up in the code hierarchy, see Appendix H, and then retrieved and added to the same
line as the neutron energy and time in the data file. When the data then was processed in
MATLAB, only the data with positive energies for both gammas and neutrons was used for
the result.
11
4 RESULT AND ANALYSIS
4.1 Mono-energetic
The energy deposition from gammas and neutrons in coincidence for the mono-energetic
case is seen in Figure 5 and Figure 6 respectively. In the gamma energy spectrum, Figure
5, there is a large peak at 4.4 MeV. This peak, the photopeak, is formed in the case of full
absorption of the gamma quanta’s energy in the detector due to photoelectric absorption,
see section 2.1.1. At approximately 4.2 MeV one can see the Compton edge described in
section 2.1.2. Using equation 5, the theoretical value of the Compton edge should be at 4.16
MeV, which is in good agreement with the simulated result shown in the figure. The region
between 0 MeV and the Compton edge is the Compton continuum. This region contains the
Compton scattering events with scattering angles between 0° and 180°, where 180° gives the
Compton edge. The peaks at 3.4 MeV and 3.9 MeV are the double and single escape peaks
caused by pair production, see section 2.1.3. Theoretically, these two peaks should be at -511
keV and -1022 keV from the photopeak which is 3.889 MeV and 3.378 MeV. This is also in
good agreement with the simulated result.
Figure 5: Energy deposition in gamma detector.
In the mono-energetic neutron energy spectrum, Figure 6, there is a large peak at 2.4 MeV
which is the incident energy of the neutrons. This means that the neutrons deposited all their
energy into the detector, due to elastic scattering with hydrogen. The tail of energies that
follows is fractions of the initial energy, meaning the neutrons only deposited some of their
energy in the detector before they escaped.
12
In a real detector, the neutron energy spectrum is more the shape of a rectangle, due to the
non-linear response function of the scintillator material [5]. In most organic scintillators
the scintillation light output does not increase linearly with deposited energy. Instead, the
translation between the proton energy and the scintillation light output is dependent on a
response function which is vital to know it if one is to inquire information about an unknown
incident neutron energy. This function is unique for most detectors as it depends on many
variables like material, size and external factors such as scratches and dirt. No response
function was added to the detector in this project, instead the neutron energy registered by
the detector is the sum of the recoiling proton energies:
Etot =N∑
i=1E i
P , (9)
where Etot is the total neutron energy deposited for one neutron and E iP is the proton energy
from different elastic scattering events in the detector. If there was a response function, the
registered neutron energy would instead be:
Ltot =N∑
i=1L(E i
P ), (10)
where Ltot is the total scintillation light output caused by a neutron interacting with hydrogen
producing recoil protons and L(E iP ) is the response function translating the proton energy to
scintillation light output.
Figure 6: Energy deposition in neutron detector.
13
The time of interaction for gammas and mono-energetic neutrons in coincidence are seen in
Figure 7 and Figure 8 respectively. Due to the size of the detectors, there is a distribution in
time in the time of interactions. The particle interaction might be at the beginning or the end
of the detector and everything in between, and this causes the time distribution.
In the gamma time of interaction, there is a time distribution from approximately 0.25 ns
to 0.42 ns. The theoretical values gained from equation 6 was found to be 0.249 ns and
0.419 ns, which is in good agreement with the simulation. It is unclear what origin the large
peak at roughly 0.42 ns has, but a possibility is that it is a result of the code that handles the
interaction times. This needs to be looked into more.
Figure 7: Time of interaction in gamma detector.
In Figure 8, the neutron time of interaction is displayed. The distribution in time is between
approximately 47.6 ns and 50.5 ns in the figure. These values are in good agreement with the
theoretical values which was found to be 47.5 ns and 50.4 ns according to equation 8.
The rounded slope between 47.6 ns and 50.5 ns and the tail of counts after 50.5 ns in Figure
8 is caused by the slowing down of the neutrons in the detector. Since the neutron loses
energy in its interactions with the detector material, it will slow down after each interaction.
There are also fewer counts at the end of the detector since some neutrons deposit all of their
energy into the detector before they reach the end of the detector.
14
Figure 8: Time of interaction in neutron detector.
To get the time of flight of the neutrons, the time of interaction for the gamma is subtracted
from the neutron time of interaction, and the result is seen in Figure 9. In the figure, the
spectrum is slightly shifted to the left and the edges are slightly more curved. This slight
difference between the time of interaction of the neutrons, Figure 8, and the time of flight is
because the gamma time of interaction, Figure 7, is small in comparison. This is due to the
placement of the gamma detector, which is close to the source and that the gamma quanta
is much faster than the neutrons. This also makes the distribution in the gamma time of
interaction relatively small, which is preferable since this distribution gives an uncertainty in
the time of flight of the neutrons.
Figure 9: Time of flight of the neutrons.
15
4.2 Uniform spectrum
In the uniform distribution neutron energy spectrum, Figure 10, the energy with the most
counts is 2 MeV and then it falls off to 0 and 4 MeV. This shape is explained by the uniform
distribution since the same amount of 2 MeV and 4 MeV neutrons are sent out from the
source and since 4 MeV neutrons can deposit a larger variation of energies, the counts will be
more spread out. In other words, the integral of the contribution from the 2 MeV neutrons
is close to the same as the integral from the 4 MeV neutrons. The difference between the
integrals is caused by the cross-section for the different neutron energies. Looking at the
cross-section for incoming neutrons on hydrogen, Figure 3, it decreases with higher energies.
For 2 MeV neutrons the cross-section is approximately 3 barns and for 4 MeV neutrons it is 2
barns. As the probability for the neutrons to scatter from the hydrogen decreases with the
energy it will result in fewer counts for higher energies.
Also, in the uniform distribution neutron energy spectrum, Figure 10, there is a dip in counts
at approximately 2.1 MeV and 2.9 MeV. These dips might be explained by the elastic scattering
cross-section for carbon, Figure 2. Looking at 2.1, 2.8 and 2.9 MeV in Figure 2 there are large
spikes in the carbon cross-section, meaning the probability for the neutrons to react with the
carbon in the detector is a lot higher at those energies. If the neutrons scatter from carbon
instead of hydrogen, the energy transferred will not be registered by the detector since it has a
proton filter and it will therefore be fewer counts for these energies. This is a valid assumption
due to the large difference in scintillation response between protons and carbon.
Figure 10: Energy deposition in neutron detector.
16
In Figure 11 the time of interaction for the neutrons is seen. In the figure, the time distribution
is roughly between 37 ns and 55 ns. Using equation 7, the theoretical values were found to be
36.8 ns and 55.2 ns which again is in good agreement with the simulation.
Figure 11: Time of interaction in neutron detector.
The reason for the shape of the spectrum is not as clear as for the mono-energetic neutrons.
One could expect more counts at the end of the spectrum since the probability for elastic
scattering on protons to take place is higher for lower energies, see Figure 3. However, the
distribution is smaller for higher energies since the higher energy neutrons travel faster, see
Table 1. The values were calculated, using equation 8. The counts for the higher energy
neutrons will therefore be more gathered, resulting in more counts at the beginning of the
spectrum.
Energy (MeV) Distribution Length2 52.1 to 55.2 ns 3.2 ns3 42.5 to 45.1 ns 2.6 ns4 36.8 to 39.1 ns 2.2 ns
Table 1: Distribution in time for different neutron incident energies.
The time of flight for the neutrons with the uniform energy distribution is seen in Figure
12. Again, this figure is obtained by subtracting the gamma time of interactions from the
neutron time of interactions. Notice the slight shift to lower times as in the time of flight for
the mono-energetic neutrons.
17
Figure 12: Time of flight of the neutrons.
5 CONCLUSION
In this project, I have begun to implement a simulation code of a detector environment
which later can be used to optimize geometries and materials of a detector set up for different
neutron energies. The detector environment consisted of two detectors, one for neutrons
and one for gammas, and a neutron and gamma source. The gamma detector was placed
close to the source and acts as a start signal for when a neutron is sent out. When the neutron
interacts with the neutron detector, placed much further from the source, an end signal is
acquired. With this detector set up, the time of flight and ultimately the initial energy of the
neutrons can be obtained. For this to work, the neutron and gamma quanta need to be in
coincidence so that the start and stop signal correspond with each other.
The results from the simulation are in good agreement with the underlying theory and can
therefore be used and further expanded in future work. In the continuation of this project, an
isotropic AmBe neutron source is going to be simulated and scintillator response functions
will be added to the detectors. The simulation will then be used to optimize the detector
environment geometry and shielding, for optimal neutron detection.
Bibliography
[1] Glenn F. Knoll, Radiation Detection and Measurement, 3rd edition, ( Ann Arbor, Michigan,
2000), 48-53.
[2] Heinz Maier-Liebnitz Zentrum. (2019). Neutrons used as a probe
https://www.mlz-garching.de/englisch/neutron-research/
neutrons-as-a-probe.html
[3] Wikipedia. (2019). Compton scattering
https://en.wikipedia.org/wiki/Compton_scattering
[4] https://www-nds.iaea.org/
[5] Glenn F. Knoll, Radiation Detection and Measurement, 559-561.
18
Appendix A
PrimaryGeneratorAction.h
#ifndef MaSPrimaryGeneratorAction_h
#define MaSPrimaryGeneratorAction_h 1
#include "G4VUserPrimaryGeneratorAction.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4ParticleGun.hh"
#include "G4Event.hh"
#include "G4ParticleDefinition.hh"
#include "G4GeneralParticleSource.hh"
class MaSPrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction
{
public:
MaSPrimaryGeneratorAction ();
virtual ~MaSPrimaryGeneratorAction ();
virtual void GeneratePrimaries(G4Event* );
private:
G4ParticleGun* fParticleGun;
bool particle = true;
G4ParticleDefinition* particleDefinition1;
G4ParticleDefinition* particleDefinition2;
};
#endif
19
Appendix B
PrimaryGeneratorAction.ccp
#include "MaSPrimaryGeneratorAction.h"
#include "G4Event.hh"
#include "G4ParticleGun.hh"
#include "G4ParticleTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4SystemOfUnits.hh"
#include "Randomize.hh"
MaSPrimaryGeneratorAction :: MaSPrimaryGeneratorAction ()
: G4VUserPrimaryGeneratorAction ()
{
G4int nofParticles = 1;
fParticleGun = new G4ParticleGun(nofParticles);
particleDefinition1
= G4ParticleTable :: GetParticleTable ()->FindParticle("gamma");
particleDefinition2
= G4ParticleTable :: GetParticleTable ()->FindParticle("neutron");
}
MaSPrimaryGeneratorAction ::~ MaSPrimaryGeneratorAction ()
{
delete fParticleGun;
}
20
21
void MaSPrimaryGeneratorAction :: GeneratePrimaries(G4Event *anEvent)
{
if(particle){
fParticleGun ->SetParticleDefinition(particleDefinition1);
fParticleGun ->SetParticleMomentumDirection(G4ThreeVector (0. ,0. ,1.))
;
fParticleGun ->SetParticlePosition(G4ThreeVector (0., 0., 0.));
fParticleGun ->SetParticleEnergy (4.4* MeV);
particle = false;
}else{
fParticleGun ->SetParticleDefinition(particleDefinition2);
fParticleGun ->SetParticleMomentumDirection(G4ThreeVector (0.,0.,-1.)
);
fParticleGun ->SetParticlePosition(G4ThreeVector (0., 0., 0.));
fParticleGun ->SetParticleEnergy (2.4* MeV);
// fParticleGun ->SetParticleEnergy ((2+2* G4UniformRand ())*MeV);
particle = true;
}
fParticleGun ->GeneratePrimaryVertex(anEvent);
}
Appendix C
DetectorConstruction.h
#ifndef MaSDetectorConstruction_h
#define MaSDetectorConstruction_h 1
#include "globals.hh"
#include "G4VUserDetectorConstruction.hh"
#include "G4VPhysicalVolume.hh"
#include "G4LogicalVolume.hh"
class MaSDetectorConstruction : public G4VUserDetectorConstruction
{
public:
MaSDetectorConstruction ();
virtual ~MaSDetectorConstruction ();
virtual G4VPhysicalVolume* Construct ();
private:
G4VPhysicalVolume* fWorldP;
G4LogicalVolume* detectorL1;
G4LogicalVolume* detectorL2;
G4Material *fWorldMaterial;
G4Material *fDetectorMaterial1;
G4Material *fDetectorMaterial2;
};
#endif
22
Appendix D
DetectorConstruction.cpp
#include "MaSDetectorConstruction.h"
#include "G4PSTime.h"
#include "G4Material.hh"
#include "G4NistManager.hh"
#include "G4Box.hh"
#include "G4Tubs.hh"
#include "G4LogicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4SystemOfUnits.hh"
#include "G4SDManager.hh"
#include "G4MultiFunctionalDetector.hh"
#include "G4VPrimitiveScorer.hh"
#include "G4PSEnergyDeposit.hh"
#include <G4SDParticleFilter.hh>
#include "G4VisAttributes.hh"
#include "G4Colour.hh"
MaSDetectorConstruction :: MaSDetectorConstruction () :
G4VUserDetectorConstruction ()
{}
MaSDetectorConstruction ::~ MaSDetectorConstruction ()
{}
23
24
G4VPhysicalVolume* MaSDetectorConstruction :: Construct ()
{
G4cout << "Construct" << G4endl;
G4NistManager* nistManager = G4NistManager :: Instance ();
G4bool fromIsotopes = false;
// Creating the world solid volume with G4box.
G4double world_hx = 1.5*m;
G4double world_hy = 1.0*m;
G4double world_hz = 2.0*m;
G4Box* worldS = new G4Box("WorldS", world_hx , world_hy , world_hz);
// Create a world logical volume composted of air
fWorldMaterial = nistManager ->FindOrBuildMaterial("G4_AIR",
fromIsotopes);
G4LogicalVolume* worldL = new G4LogicalVolume(worldS , fWorldMaterial , "
worldL");
//Place the world logical volume
fWorldP = new G4PVPlacement (0, G4ThreeVector (), worldL , "World", 0,
false , 0, false);
// Create the active detector solid volumes
//BaF2
G4double innerRadiusBaF2 = 0.*cm;
G4double outerRadiusBaF2 = 51.*mm;
G4double hzBaF2 = 51.*mm;
G4double startAngleBaF2 = 0.*deg;
G4double spanningAngleBaF2 = 360.* deg;
G4Tubs* detectorS1 = new G4Tubs("detectorS1",
innerRadiusBaF2 /2,
outerRadiusBaF2 /2,
hzBaF2/2,
startAngleBaF2 ,
spanningAngleBaF2);
fDetectorMaterial1 = nistManager -> FindOrBuildMaterial("
G4_BARIUM_FLUORIDE",fromIsotopes);
25
// vinyltoluene
G4double innerRadiusVinyl = 0.*cm;
G4double outerRadiusVinyl = 94.*mm;
G4double hzVinyl = 62.*mm;
G4double startAngleVinyl = 0.*deg;
G4double spanningAngleVinyl = 360.* deg;
G4Tubs* detectorS2 = new G4Tubs("detectorS2",
innerRadiusVinyl /2,
outerRadiusVinyl /2,
hzVinyl/2,
startAngleVinyl ,
spanningAngleVinyl);
fDetectorMaterial2 = nistManager -> FindOrBuildMaterial("
G4_PLASTIC_SC_VINYLTOLUENE",fromIsotopes);
// Create the active detector logical volumes
//BaF2
detectorL1 = new G4LogicalVolume(detectorS1 , fDetectorMaterial1 , "
detectorL1");
G4double detectorBaF2_X = 0.0*cm;
G4double detectorBaF2_Y = 0.0*cm;
G4double detectorBaF2_Z = 10.0*cm;
new G4PVPlacement (0, G4ThreeVector(detectorBaF2_X ,
detectorBaF2_Y ,
detectorBaF2_Z), detectorL1 , "
detectorBaF2", worldL ,false ,0,
false);
// Vinyltoluene
detectorL2 = new G4LogicalVolume(detectorS2 , fDetectorMaterial2 , "
detectorL2");
G4double detectorVinyl_X = 0.0*cm;
G4double detectorVinyl_Y = 0.0*cm;
G4double detectorVinyl_Z = -1.05*m;
26
new G4PVPlacement (0, G4ThreeVector(detectorVinyl_X ,
detectorVinyl_Y ,
detectorVinyl_Z), detectorL2 , "
detectorPlastic", worldL ,false
,0,false);
// Create sensitve detectors of the active logical volumes
G4MultiFunctionalDetector* gDetector = new G4MultiFunctionalDetector("
gDetector");
G4MultiFunctionalDetector* nDetector = new G4MultiFunctionalDetector("
nDetector");
G4VPrimitiveScorer* Edep1 = new G4PSEnergyDeposit("Edep1");
G4VPrimitiveScorer* Edep2 = new G4PSEnergyDeposit("Edep2");
G4VPrimitiveScorer* Time1 = new G4PSTime("Time1");
G4VPrimitiveScorer* Time2 = new G4PSTime("Time2");
G4SDParticleFilter* protonFilter = new G4SDParticleFilter("protonFilter
");
protonFilter -> add("proton");
G4SDParticleFilter* electronFilter = new G4SDParticleFilter("
electronFilter");
electronFilter -> add("e-");
electronFilter -> add("e+");
electronFilter -> add("gamma");
Edep1 -> SetFilter(electronFilter);
Edep2 -> SetFilter(protonFilter);
Time1 -> SetFilter(electronFilter);
Time2 -> SetFilter(protonFilter);
gDetector ->RegisterPrimitive(Edep1);
nDetector ->RegisterPrimitive(Edep2);
gDetector ->RegisterPrimitive(Time1);
nDetector ->RegisterPrimitive(Time2);
G4SDManager :: GetSDMpointer ()->AddNewDetector(gDetector);
G4SDManager :: GetSDMpointer ()->AddNewDetector(nDetector);
27
detectorL1 -> SetSensitiveDetector(gDetector);
detectorL2 -> SetSensitiveDetector(nDetector);
//This part give different colours to world logical volume and the
logical volume
G4VisAttributes* worldVisAtt = new G4VisAttributes(G4Colour (.5 ,.5 ,.5));
worldVisAtt ->SetVisibility(true);
worldL -> SetVisAttributes(worldVisAtt);
G4VisAttributes* detVisAtt1= new G4VisAttributes(G4Colour (1.0 ,0.0 ,0.0))
;
detVisAtt1 ->SetVisibility(true);
detectorL1 -> SetVisAttributes(detVisAtt1);
G4VisAttributes* detVisAtt2= new G4VisAttributes(G4Colour (0.0 ,1.0 ,0.0))
;
detVisAtt2 ->SetVisibility(true);
detectorL2 -> SetVisAttributes(detVisAtt2);
// Return the geometry
return fWorldP;
}
Appendix E
EventAction.h
#ifndef MaSEventAction_h
#define MaSEventAction_h 1
#include "G4UserEventAction.hh"
#include "globals.hh"
#include "G4THitsMap.hh"
#include "MaSRunAction.h"
class MaSEventAction : public G4UserEventAction
{
public:
MaSEventAction(MaSRunAction* );
virtual ~MaSEventAction ();
virtual void BeginOfEventAction(const G4Event* );
virtual void EndOfEventAction(const G4Event* );
void SetPrintModulo(G4int value);
private:
G4THitsMap <G4double >* GetHitsCollection(const G4String& hcName ,
const G4Event* event) const;
G4double GetSum(G4THitsMap <G4double >* hitsMap) const;
void PrintEventStatistics(G4double Edep);
G4int fPrintModulo;
G4double GetTime(G4THitsMap <G4double >* hitsMap) const;
G4double Edep1save;
G4double Time1save;
G4int countSave;
G4int count;
MaSRunAction* arun;
28
29
};
inline void MaSEventAction :: SetPrintModulo(G4int value)
{
fPrintModulo = value;
}
#endif
Appendix F
EventAction.cpp
#include "MaSEventAction.h"
#include "MaSAnalysis.h"
#include "G4SDManager.hh"
#include "G4Event.hh"
#include "G4HCofThisEvent.hh"
#include "G4UnitsTable.hh"
#include "Randomize.hh"
MaSEventAction :: MaSEventAction(MaSRunAction* run):G4UserEventAction (),
fPrintModulo (10000){
Edep1save = run -> GetEdepSave ();
Time1save = run -> GetTimeSave ();
countSave = run -> GetCountSave ();
count = run -> GetCount ();
arun = run;
}
MaSEventAction ::~ MaSEventAction ()
{;}
G4THitsMap <G4double >*
MaSEventAction :: GetHitsCollection(const G4String& hcName ,const G4Event*
event) const
{
G4int hcID = G4SDManager :: GetSDMpointer () -> GetCollectionID(hcName);
30
31
G4THitsMap <G4double >* hitsCollection = static_cast <G4THitsMap <G4double
>*>(event -> GetHCofThisEvent () -> GetHC(hcID));
if (! hitsCollection) {
G4cerr << "Cannot access hitsCollection " << hcName << G4endl;
exit (1);
}
return hitsCollection;
}
G4double MaSEventAction :: GetSum(G4THitsMap <G4double >* hitsMap) const
{
G4double sumValue = 0;
std::map <G4int , G4double *>:: iterator it;
for ( it = hitsMap -> GetMap () -> begin(); it != hitsMap -> GetMap () ->
end(); it++) {
sumValue += *(it -> second);
}
return sumValue;
}
G4double MaSEventAction :: GetTime(G4THitsMap <G4double >* hitsMap) const
{
G4double sumValue = 0.;
std::map <G4int , G4double *>:: iterator it;
G4int size = hitsMap -> GetMap () -> size();
if(size > 0){
it = hitsMap -> GetMap () -> begin();
sumValue = *(it -> second);
it = hitsMap -> GetMap () -> end();
it --;
sumValue += *(it -> second);
}
return sumValue /2.;
}
32
void MaSEventAction :: PrintEventStatistics(G4double Edep)
{
G4cout
<< " Edetector: total energy: "
<< std::setw (7) << G4BestUnit(Edep , "Energy")
<< G4endl;
}
void MaSEventAction :: BeginOfEventAction(const G4Event* event)
{
G4int eventID = event ->GetEventID ();
if ( eventID % fPrintModulo == 0) {
G4cout << "\n---> Begin of event: " << eventID << G4endl;
}
}
void MaSEventAction :: EndOfEventAction(const G4Event* event)
{
//Get the values from the last event
Edep1save = arun -> GetEdepSave ();
Time1save = arun -> GetTimeSave ();
countSave = arun -> GetCountSave ();
count = arun -> GetCount ();
//Get the values from the current event
G4double Edep1 = GetSum(GetHitsCollection("gDetector/Edep1", event));
G4double Time1 = GetTime(GetHitsCollection("gDetector/Time1", event));
G4double Edep2 = GetSum(GetHitsCollection("nDetector/Edep2", event));
G4double Time2 = GetTime(GetHitsCollection("nDetector/Time2", event));
count ++;
//Save the new values to RunAction
arun -> SetCount(count);
arun -> SetAll(Edep1 , Time1 , count);
G4int temp = ++ countSave;
//Save data to output file
if((Edep2 > 0.0 || Edep1 > 0.0) && count == temp){
G4AnalysisManager* analysisManager = G4AnalysisManager :: Instance ();
analysisManager ->FillNtupleDColumn (0, 0, Edep1save);
analysisManager ->FillNtupleDColumn (0, 1, Time1save);
33
analysisManager ->FillNtupleDColumn (0, 2, Edep2);
analysisManager ->FillNtupleDColumn (0, 3, Time2);
analysisManager ->AddNtupleRow ();
arun -> SetAll (0,0,0);
}
G4int eventID = event ->GetEventID ();
if ( eventID % fPrintModulo == 0) {
G4cout << "---> End of event: " << eventID << G4endl;
PrintEventStatistics(Edep1);
}
}
Appendix G
RunAction.h
#ifndef MaSRunAction_h
#define MaSRunAction_h 1
#include "G4UserRunAction.hh"
#include "globals.hh"
#include "G4Run.hh"
class MaSRunAction : public G4UserRunAction
{
public:
MaSRunAction ();
virtual ~MaSRunAction ();
virtual void BeginOfRunAction(const G4Run* run);
virtual void EndOfRunAction(const G4Run* run);
void SetAll(G4double Edep , G4double Time , G4int count);
void SetCount(G4int count);
G4double GetEdepSave ();
G4double GetTimeSave ();
G4int GetCountSave ();
G4int GetCount ();
private:
G4double Edep1save = 0;
G4double Time1save = 0;
G4int countSave = 0;
G4int count = 0;
};
#endif
34
Appendix H
RunAction.cpp
#include "MaSRunAction.h"
#include "MaSAnalysis.h"
#include "G4Run.hh"
#include "G4RunManager.hh"
#include "G4UnitsTable.hh"
MaSRunAction :: MaSRunAction ():G4UserRunAction ()
{;}
MaSRunAction ::~ MaSRunAction ()
{;}
void MaSRunAction :: BeginOfRunAction(const G4Run* aRun)
{
Edep1save = 0;
Time1save = 0;
countSave = 0;
G4cout << "### Run " << aRun -> GetRunID () << " start." << G4endl;
G4AnalysisManager* analysisManager = G4AnalysisManager :: Instance ();
char RunId [10];
sprintf(RunId , "%d", aRun -> GetRunID ());
G4String fileName = "Run";
fileName += RunId;
fileName += "depE";
analysisManager ->OpenFile(fileName);
analysisManager ->CreateNtuple("Hit","Hit");
analysisManager ->CreateNtupleDColumn("gEdep");
35
36
analysisManager ->CreateNtupleDColumn("gTime");
analysisManager ->CreateNtupleDColumn("nEdep");
analysisManager ->CreateNtupleDColumn("nTime");
analysisManager ->FinishNtuple ();
}
void MaSRunAction :: EndOfRunAction(const G4Run* aRun)
{
G4int nofEvents = aRun ->GetNumberOfEvent ();
if ( nofEvents == 0 ) return;
G4AnalysisManager* analysisManager = G4AnalysisManager :: Instance ();
analysisManager ->Write();
analysisManager ->CloseFile ();
delete G4AnalysisManager :: Instance ();
}
void MaSRunAction :: SetAll(G4double Edep , G4double Time , G4int count1){
Edep1save = Edep;
Time1save = Time;
countSave = count1;
}
void MaSRunAction :: SetCount(G4int count1){
count = count1;
}
G4double MaSRunAction :: GetEdepSave (){
return Edep1save;
}
G4double MaSRunAction :: GetTimeSave (){
return Time1save;
}
G4int MaSRunAction :: GetCountSave (){
return countSave;
}
G4int MaSRunAction :: GetCount (){
return count;
}
Appendix I
G4PSTime.h
#ifndef G4PSTime_h
#define G4PSTime_h 1
#include "G4VPrimitiveScorer.hh"
#include "G4THitsMap.hh"
class G4PSTime : public G4VPrimitiveScorer
{
public: // with description
G4PSTime(G4String name , G4int depth =0); // default unit
virtual ~G4PSTime ();
protected: // with description
virtual G4bool ProcessHits(G4Step*,G4TouchableHistory *);
public:
virtual void Initialize(G4HCofThisEvent *);
virtual void EndOfEvent(G4HCofThisEvent *);
virtual void clear();
private:
G4int HCID;
G4THitsMap <G4double >* EvtMap;
G4int steps;
};
#endif
37
Appendix J
G4PSTime.cpp
#include "G4PSTime.h"
#include "G4UnitsTable.hh"
G4PSTime :: G4PSTime(G4String name , G4int depth)
:G4VPrimitiveScorer(name ,depth),HCID(-1),EvtMap (0)
{
SetUnit("ns");
steps = 0;
}
G4PSTime ::~ G4PSTime ()
{;}
G4bool G4PSTime :: ProcessHits(G4Step *aStep , G4TouchableHistory *)
{
G4double time = aStep ->GetPreStepPoint ()->GetGlobalTime ();
G4double edep = aStep ->GetTotalEnergyDeposit ();
if(edep ==0.) return FALSE;
G4int index = GetIndex(aStep);
EvtMap -> set(index , time);
return TRUE;
}
void G4PSTime :: Initialize(G4HCofThisEvent* HCE)
{
EvtMap = new G4THitsMap <G4double >( GetMultiFunctionalDetector ()->GetName ()
, GetName ());
if(HCID < 0) {HCID = GetCollectionID (0);}
HCE ->AddHitsCollection(HCID , (G4VHitsCollection *) EvtMap);
38
39
steps = 0;
}
void G4PSTime :: EndOfEvent(G4HCofThisEvent *)
{;}
void G4PSTime ::clear()
{
EvtMap ->clear();
}
Appendix K
Analysis.h
#ifndef Analysis_h
#define Analysis_h 1
#include "g4analysis_defs.hh"
using namespace G4Csv;
//using namespace G4Root;
#endif
40
Appendix L
Main.cpp
#include "DetectorConstruction.h"
#include "PrimaryGeneratorAction.h"
#include "RunAction.h"
#include "EventAction.h"
#include "G4PhysListFactory.hh"
#include "G4VModularPhysicsList.hh"
#include "G4RunManager.hh"
#include "G4UImanager.hh"
#include "QGSP_BERT_HP.hh"
#include "G4SystemOfUnits.hh"
#ifdef G4VIS_USE
#include "G4VisExecutive.hh"
#endif
#ifdef G4UI_USE
#include "G4UIExecutive.hh"
#endif
#include "Randomize.hh"
int main(int argc , char** argv)
{
G4RunManager * runManager = new G4RunManager;
runManager -> SetUserInitialization(new DetectorConstruction ());
41
42
G4PhysListFactory factory;
G4VModularPhysicsList* physicsList = factory.GetReferencePhysList("
QGSP_BERT_HP");
physicsList -> SetVerboseLevel (1);
physicsList -> SetDefaultCutValue (.01*mm);
runManager -> SetUserInitialization(physicsList);
runManager -> SetUserAction(new PrimaryGeneratorAction ());
RunAction* run = new RunAction ();
runManager -> SetUserAction(run);
runManager -> SetUserAction(new EventAction(run));
runManager -> Initialize ();
#ifdef G4VIS_USE
G4VisManager* visManager = new G4VisExecutive;
visManager ->Initialize ();
#endif
G4UImanager* UImanager = G4UImanager :: GetUIpointer ();
if (argc != 1) {
G4String command = "/control/execute ";
G4String fileName = argv [1];
G4cout <<argv[1]<<G4endl;
UImanager ->ApplyCommand(command+fileName);
}
else {
#ifdef G4UI_USE
G4UIExecutive* ui = new G4UIExecutive(argc , argv);
#ifdef G4VIS_USE
UImanager ->ApplyCommand("/control/execute init_vis.mac");
#else
UImanager ->ApplyCommand("/control/execute init.mac");
#endif
ui->SessionStart ();
delete ui;
#endif
}
43
#ifdef G4VIS_USE
delete visManager;
#endif
delete runManager;
return 0;
}