Import Geant4 11.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2022-12-09 14:43:28 +01:00
parent c07cea1fe0
commit 9f34590941
3810 changed files with 200490 additions and 182326 deletions
@@ -1,8 +1,7 @@
///\file "ParticleFluence/.README.txt"
///\brief ParticleFluence set-ups
/*! \page Set-ups-ParticleFluence Category "ParticleFluence"
/*! \page Examples_ParticleFluence Category "hadronic/ParticleFluence"
Examples in this directory demonstrate specific set-ups in
which to evaluate particle fluence.
@@ -1,7 +1,7 @@
///\file "hadronic/ParticleFluence/Calo/.README.txt"
///\brief Example ParticleFluence/Calo README page
/*! \page ExampeParticleFluenceCalo Example Calo
/*! \page ExampleCalo Example Calo
In this example, the particle fluence is evaluated for simplified,
cylindrical hadronic calorimeters with axis along the z-direction,
@@ -18,6 +18,10 @@ cases) or a thin hemisphere shell (for the "side" case) filled up with
G4_Galactic (very low density gas) material, immediately outside the
calorimeter - and then dividing for the cubic volume of such scoring volume.
Complementary information on average multiplicity, average kinetic energy,
and average total energy flow (i.e. sum of kinetic energies) for the
particles produced in the calorimeter are also computed.
The particle fluence is evaluated for the following 11 particle types:
- all
- electron + positron
@@ -47,14 +51,18 @@ physics list is used).
To build this example:
mkdir Build; cd Build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DGeant4_DIR=/path-to-geant4-libraries ../.
make
\verbatim
mkdir Build; cd Build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DGeant4_DIR=/path-to-geant4-libraries ../.
make
\endverbatim
To run it:
./Calo atlasHec.g4
\verbatim
./Calo atlasHec.g4
\endverbatim
which shoots 50 GeV pion- on a simplified ATLAS HEC hadronic calorimeter,
in one run of 100 events, and print out some information on the particle
View File
File diff suppressed because it is too large Load Diff
View File
@@ -5,6 +5,12 @@ which **must** added in reverse chronological order (newest at the top). It must
be used as a substitute for writing good git commit messages!
## 2022-09-07 Alberto Ribon (exhadrParticleFluenceCalo-V11-00-02)
- Added complementary information on particle production (multiplicity,
kinetic energy, and total energy flow) in the calorimeter.
## 2022-08-26 Alberto Ribon (exhadrParticleFluenceCalo-V11-00-01)
- SteppingAction : introduced protection on the value of the array index.
## 2021-06-10 Alberto Ribon (exhadrParticleFluenceCalo-V11-00-00)
- Created the Calo variant of the ParticleFluence example.
@@ -13,6 +13,10 @@ cases) or a thin hemisphere shell (for the "side" case) filled up with
G4_Galactic (very low density gas) material, immediately outside the
calorimeter - and then dividing for the cubic volume of such scoring volume.
Complementary information on average multiplicity, average kinetic energy,
and average total energy flow (i.e. sum of kinetic energies) for the
particles produced in the calorimeter are also computed.
The particle fluence is evaluated for the following 11 particle types:
- all
- electron + positron
@@ -43,9 +43,9 @@ class DetectorConstruction;
class ActionInitialization : public G4VUserActionInitialization {
public:
ActionInitialization( const DetectorConstruction* inputDetectorConstruction = nullptr );
virtual ~ActionInitialization();
virtual void BuildForMaster() const override;
virtual void Build() const override;
~ActionInitialization() override = default;
void BuildForMaster() const override;
void Build() const override;
private:
const DetectorConstruction* fPtrDetectorConstruction = nullptr;
};
+1 -1
View File
@@ -84,7 +84,7 @@ class DetectorConstruction : public G4VUserDetectorConstruction {
G4VPhysicalVolume* ConstructCalorimeter();
// To be invoked each time the geometry needs to be updated.
G4bool areParametersOK();
G4bool AreParametersOK();
// Return true if all the parameters are sensible, false otherwise.
void PrintParameters();
@@ -37,6 +37,7 @@
#include "G4Run.hh"
#include "G4ThreeVector.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include <array>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -45,55 +46,70 @@ class Run : public G4Run {
// This class accumulates relevant quantities related to particle fluence collected during
// the run.
// ( Note: these information are provided via calls of accessor methods of this Run class
// made by SteppingAction::UserSteppingAction. )
// At the end of a run, the printInfo method is called by the run-action to print out
// made by SteppingAction::UserSteppingAction
// and TrackingAction::PreUserTrackingAction. )
// At the end of a run, the PrintInfo method is called by the run-action to print out
// some summary information about these quantities.
// In multithreaded (MT) mode, an object of this class is filled up for each working thread,
// and then merged (automatically by the Geant4 kernel) into another object (of this class)
// owned by the master class; the printInfo method is then called only for the latter run
// owned by the master class; the PrintInfo method is then called only for the latter run
// object.
// Note that, for simplicity and brevity, we avoid histograms and print-out instead some
// statistics (compute by ourself) at the end of the run.
public:
Run();
~Run();
~Run() override = default;
virtual void RecordEvent( const G4Event* anEvent ) override;
void RecordEvent( const G4Event* anEvent ) override;
// This method is called automatically by the Geant4 kernel (not by the user!) at the end
// of each event. In the case of multithreaded mode, it is called only for the working thread
// that handled that event.
virtual void Merge( const G4Run* aRun ) override;
void Merge( const G4Run* aRun ) override;
// This method is called automatically by the Geant4 kernel (not by the user!) only in the
// case of multithreaded mode and only for working threads.
void printInfo() const;
void PrintInfo() const;
// This method is called by RunAction::EndOfRunAction : in the case of multithreaded mode,
// only the master thread calls it.
void setPrimaryParticleId( const G4int inputValue ) { fPrimaryParticleId = inputValue; }
void setPrimaryParticleEnergy( const G4double inputValue )
void SetPrimaryParticleId( const G4int inputValue ) { fPrimaryParticleId = inputValue; }
void SetPrimaryParticleEnergy( const G4double inputValue )
{ fPrimaryParticleEnergy = inputValue; }
void setPrimaryParticleDirection( const G4ThreeVector &inputValue )
void SetPrimaryParticleDirection( const G4ThreeVector &inputValue )
{ fPrimaryParticleDirection = inputValue; }
void setAbsorberMaterialName( const G4String &inputValue )
void SetAbsorberMaterialName( const G4String &inputValue )
{ fAbsorberMaterialName = inputValue; }
void setActiveMaterialName( const G4String &inputValue ) { fActiveMaterialName = inputValue; }
void setCubicVolumeScoringUpDown( const G4double inputValue )
void SetActiveMaterialName( const G4String &inputValue ) { fActiveMaterialName = inputValue; }
void SetCubicVolumeScoringUpDown( const G4double inputValue )
{ fCubicVolumeScoringUpDown = inputValue; }
void setCubicVolumeScoringSide( const G4double inputValue )
void SetCubicVolumeScoringSide( const G4double inputValue )
{ fCubicVolumeScoringSide = inputValue; }
G4int getPrimaryParticleId() const { return fPrimaryParticleId; }
G4double getPrimaryParticleEnergy() const { return fPrimaryParticleEnergy; }
G4ThreeVector getPrimaryParticleDirection() const { return fPrimaryParticleDirection; }
G4String getAbsorberMaterialName() const { return fAbsorberMaterialName; }
G4String getActiveMaterialName() const { return fActiveMaterialName; }
G4double getCubicVolumeScoringUpDown() const { return fCubicVolumeScoringUpDown; }
G4double getCubicVolumeScoringSide() const { return fCubicVolumeScoringSide; }
void setArray( const std::array< G4double, SteppingAction::numberCombinations >& inputArray );
std::array< G4double, SteppingAction::numberCombinations > getArray() const { return fArray; }
G4int GetPrimaryParticleId() const { return fPrimaryParticleId; }
G4double GetPrimaryParticleEnergy() const { return fPrimaryParticleEnergy; }
G4ThreeVector GetPrimaryParticleDirection() const { return fPrimaryParticleDirection; }
G4String GetAbsorberMaterialName() const { return fAbsorberMaterialName; }
G4String GetActiveMaterialName() const { return fActiveMaterialName; }
G4double GetCubicVolumeScoringUpDown() const { return fCubicVolumeScoringUpDown; }
G4double GetCubicVolumeScoringSide() const { return fCubicVolumeScoringSide; }
void SetSteppingArray( const std::array< G4double,
SteppingAction::fkNumberCombinations >& inputArray );
std::array< G4double, SteppingAction::fkNumberCombinations > GetSteppingArray() const
{ return fSteppingArray; }
// Accessor methods useful to transfer information collected by the stepping-action
// into this Run class
// into this Run class
void SetTrackingArray1( const std::array< G4int,
TrackingAction::fkNumberCombinations >& inputArray );
std::array< G4int, TrackingAction::fkNumberCombinations > GetTrackingArray1() const
{ return fTrackingArray1; }
void SetTrackingArray2( const std::array< G4double,
TrackingAction::fkNumberCombinations >& inputArray );
std::array< G4double, TrackingAction::fkNumberCombinations > GetTrackingArray2() const
{ return fTrackingArray2; }
// Accessor methods useful to transfer information collected by the tracking-action
// into this Run class
private:
G4int fNumEvents;
@@ -104,7 +120,9 @@ class Run : public G4Run {
G4String fActiveMaterialName;
G4double fCubicVolumeScoringUpDown;
G4double fCubicVolumeScoringSide;
std::array< G4double, SteppingAction::numberCombinations > fArray;
std::array< G4double, SteppingAction::fkNumberCombinations > fSteppingArray;
std::array< G4int, TrackingAction::fkNumberCombinations > fTrackingArray1;
std::array< G4double, TrackingAction::fkNumberCombinations > fTrackingArray2;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+8 -5
View File
@@ -38,18 +38,21 @@
class G4Run;
class SteppingAction;
class TrackingAction;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class RunAction: public G4UserRunAction {
public:
RunAction( SteppingAction* steppingAction = nullptr );
virtual ~RunAction();
virtual void BeginOfRunAction( const G4Run* aRun ) override;
virtual void EndOfRunAction( const G4Run* aRun ) override;
virtual G4Run* GenerateRun() override;
RunAction( SteppingAction* steppingAction = nullptr,
TrackingAction* trackingAction = nullptr );
~RunAction() override = default;
void BeginOfRunAction( const G4Run* aRun ) override;
void EndOfRunAction( const G4Run* aRun ) override;
G4Run* GenerateRun() override;
private:
SteppingAction* fSteppingAction;
TrackingAction* fTrackingAction;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+16 -16
View File
@@ -46,9 +46,9 @@ class Run;
class SteppingAction : public G4UserSteppingAction {
public:
SteppingAction();
virtual ~SteppingAction();
~SteppingAction() override = default;
virtual void UserSteppingAction( const G4Step* ) override;
void UserSteppingAction( const G4Step* ) override;
// This is the main method where the step lengths of particles inside
// the scoring volumes are collected, and then the corresponding fluences
// are filled up in the Run object where they are stored (and then
@@ -56,35 +56,35 @@ class SteppingAction : public G4UserSteppingAction {
// (For simplicity and brevity, we avoid histograms and compute instead
// some statistics ourself, which will be print-out at the end of the run.)
void initialize();
void Initialize();
// This method is called by RunAction::BeginOfRunAction for the
// initialization of the stepping-action at the beginning of each Run.
// This is necessary because different runs can have different primary particle
// types, kinetic energies, and detector configurations.
void setRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
void SetRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
// This method is called by RunAction::BeginOfRunAction for providing to the
// stepping-action the pointer to the run object at the beginning of each Run.
// This pointer is then used to pass the information collected by the stepping-action
// to the run object.
G4double getCubicVolumeScoringUpDown() const { return fCubicVolumeScoringUpDown; }
G4double getCubicVolumeScoringSide() const { return fCubicVolumeScoringSide; }
G4double GetCubicVolumeScoringUpDown() const { return fCubicVolumeScoringUpDown; }
G4double GetCubicVolumeScoringSide() const { return fCubicVolumeScoringSide; }
// The cubic-volumes of the scoring volumes are needed to get the fluence from
// the sum of step lengths in those scoring volumes.
// Notice that two of the three scoring volumes - upstream and downstream -
// have the same cubic-volume, that we call "fCubicVolumeScoringUpDown".
static const G4int numberScoringVolumes = 3; // downstream, side, upstream
static const G4int numberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int numberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
static const G4int fkNumberScoringVolumes = 3; // downstream, side, upstream
static const G4int fkNumberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int fkNumberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
// other-mesons, other-baryons
static const G4int numberCombinations =
numberScoringVolumes*numberKinematicRegions*numberParticleTypes;
static const std::array< G4String, numberScoringVolumes > arrayScoringVolumeNames;
static const std::array< G4String, numberKinematicRegions > arrayKinematicRegionNames;
static const std::array< G4String, numberParticleTypes > arrayParticleTypeNames;
static G4int getIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
static const G4int fkNumberCombinations =
fkNumberScoringVolumes*fkNumberKinematicRegions*fkNumberParticleTypes;
static const std::array< G4String, fkNumberScoringVolumes > fkArrayScoringVolumeNames;
static const std::array< G4String, fkNumberKinematicRegions > fkArrayKinematicRegionNames;
static const std::array< G4String, fkNumberParticleTypes > fkArrayParticleTypeNames;
static G4int GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType );
private:
@@ -102,7 +102,7 @@ class SteppingAction : public G4UserSteppingAction {
G4double fCubicVolumeScoringUpDown;
G4double fCubicVolumeScoringSide;
std::array< G4double, numberCombinations > fArraySumStepLengths;
std::array< G4double, fkNumberCombinations > fArraySumStepLengths;
// Array to collect the sum of step lengths in the scoring volumes for the whole run,
// according to the various cases (kinematical region and particle type).
// Note that the fluence in a scoring volume is defined as sum of step lengths
@@ -0,0 +1,92 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file TrackingAction.hh
/// \brief Definition of the TrackingAction class
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef TrackingAction_h
#define TrackingAction_h 1
#include "globals.hh"
#include "G4UserTrackingAction.hh"
#include <array>
class Run;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class TrackingAction : public G4UserTrackingAction {
// We are using this class to monitor the average multiplicity, the average
// kinetic energy, and the average total energy flow (i.e. sum of the
// kinetic energies) of different particle types as they are produced
// inside the calorimeter.
// The aim is then to try to correlate some changes in these (more primitive)
// quantities with the observed changes in the (more indirect and complex)
// particle fluences.
public:
TrackingAction();
~TrackingAction() override = default;
void PreUserTrackingAction( const G4Track* ) override;
void PostUserTrackingAction( const G4Track* ) override;
void Initialize();
// This method is called by RunAction::BeginOfRunAction for the
// initialization of the tracking-action at the beginning of each Run.
void SetRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
// This method is called by RunAction::BeginOfRunAction for providing to the
// tracking-action the pointer to the run object at the beginning of each Run.
// This pointer is then used to pass the information collected by the tracking-action
// to the run object.
static const G4int fkNumberScoringVolumes = 1; // calorimeter
static const G4int fkNumberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int fkNumberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
// other-mesons, other-baryons
static const G4int fkNumberCombinations =
fkNumberScoringVolumes*fkNumberKinematicRegions*fkNumberParticleTypes;
static const std::array< G4String, fkNumberScoringVolumes > fkArrayScoringVolumeNames;
static const std::array< G4String, fkNumberKinematicRegions > fkArrayKinematicRegionNames;
static const std::array< G4String, fkNumberParticleTypes > fkArrayParticleTypeNames;
static G4int GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType );
private:
Run* fRunPtr; // Pointer to the Run object
std::array< G4int, fkNumberCombinations > fArrayMultiplicities;
std::array< G4double, fkNumberCombinations > fArraySumKineticEnergies;
// Keep record of the fkNumber of particles and their kinetic energy at production,
// according to the particle type and their kinetic energy range (below/above 20 MeV).
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif
@@ -35,6 +35,7 @@
#include "PrimaryGeneratorAction.hh"
#include "RunAction.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include "Run.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -45,10 +46,6 @@ ActionInitialization( const DetectorConstruction* inputDetectorConstruction ) :
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
ActionInitialization::~ActionInitialization() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void ActionInitialization::BuildForMaster() const {
// This is NOT called in SEQ-mode, while in the MT-mode is called only for the Master thread.
SetUserAction( new RunAction );
@@ -61,7 +58,9 @@ void ActionInitialization::Build() const {
SetUserAction( new PrimaryGeneratorAction( fPtrDetectorConstruction ) );
SteppingAction* steppingAction = new SteppingAction;
SetUserAction( steppingAction );
SetUserAction( new RunAction( steppingAction ) );
TrackingAction* trackingAction = new TrackingAction;
SetUserAction( trackingAction );
SetUserAction( new RunAction( steppingAction, trackingAction ) );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+8 -8
View File
@@ -276,7 +276,7 @@ void DetectorConstruction::DefineMaterials() {
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VPhysicalVolume* DetectorConstruction::ConstructCalorimeter() {
if ( ! areParametersOK() ) {
if ( ! AreParametersOK() ) {
G4cout << " DetectorConstruction::ConstructCalorimeter() : ***ERROR*** "
<< G4endl << "\t PARAMETERS NOT WELL-DEFINED! GEOMETRY UNCHANGED."
<< G4endl;
@@ -517,34 +517,34 @@ G4VPhysicalVolume* DetectorConstruction::ConstructCalorimeter() {
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool DetectorConstruction::areParametersOK() {
G4bool DetectorConstruction::AreParametersOK() {
bool isOk = true;
if ( ! fAbsorberMaterial ) {
isOk = false;
G4cout << " DetectorConstruction::areParametersOK() : UNDEFINED absorber material" << G4endl;
G4cout << " DetectorConstruction::AreParametersOK() : UNDEFINED absorber material" << G4endl;
}
if ( ! fActiveMaterial ) {
isOk = false;
G4cout << " DetectorConstruction::areParametersOK() : UNDEFINED active material" << G4endl;
G4cout << " DetectorConstruction::AreParametersOK() : UNDEFINED active material" << G4endl;
}
if ( fAbsorberTotalLength <= 0.0 ) {
isOk = false;
G4cout << " DetectorConstruction::areParametersOK() : fAbsorberTotalLength = "
G4cout << " DetectorConstruction::AreParametersOK() : fAbsorberTotalLength = "
<< fAbsorberTotalLength << G4endl;
}
if ( fCalorimeterRadius <= 0.0 ) {
isOk = false;
G4cout << " DetectorConstruction::areParametersOK() : fCalorimeterRadius = "
G4cout << " DetectorConstruction::AreParametersOK() : fCalorimeterRadius = "
<< fCalorimeterRadius << G4endl;
}
if ( fActiveLayerNumber <= 0 ) {
isOk = false;
G4cout << " DetectorConstruction::areParametersOK() : fActiveLayerNumber = "
G4cout << " DetectorConstruction::AreParametersOK() : fActiveLayerNumber = "
<< fActiveLayerNumber << G4endl;
}
if ( fActiveLayerSize <= 0.0 ) {
isOk = false;
G4cout << " DetectorConstruction::areParametersOK() : fActiveLayerSize = "
G4cout << " DetectorConstruction::AreParametersOK() : fActiveLayerSize = "
<< fActiveLayerSize << G4endl;
}
return isOk;
@@ -44,15 +44,13 @@ Run::Run() : G4Run(), fNumEvents( 0 ),
fAbsorberMaterialName( "" ), fActiveMaterialName( "" ),
fCubicVolumeScoringUpDown( 1.0 ), fCubicVolumeScoringSide( 1.0 )
{
for ( G4int i = 0; i < SteppingAction::numberCombinations; ++i ) fArray[i] = 0.0;
fSteppingArray.fill( 0.0 );
fTrackingArray1.fill( 0 );
fTrackingArray2.fill( 0.0 );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Run::~Run() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::RecordEvent( const G4Event* anEvent ) {
// This method is called automatically by the Geant4 kernel (not by the user!) at the end
// of each event : in MT-mode, it is called only for the working thread that handled the event.
@@ -67,23 +65,27 @@ void Run::Merge( const G4Run* aRun ) {
// This method is called automatically by the Geant4 kernel (not by the user!) only in the case
// of multithreaded mode and only for working threads.
const Run* localRun = static_cast< const Run* >( aRun );
fPrimaryParticleId = localRun->getPrimaryParticleId();
fPrimaryParticleEnergy = localRun->getPrimaryParticleEnergy();
fPrimaryParticleDirection = localRun->getPrimaryParticleDirection();
fAbsorberMaterialName = localRun->getAbsorberMaterialName();
fActiveMaterialName = localRun->getActiveMaterialName();
fCubicVolumeScoringUpDown = localRun->getCubicVolumeScoringUpDown();
fCubicVolumeScoringSide = localRun->getCubicVolumeScoringSide();
fPrimaryParticleId = localRun->GetPrimaryParticleId();
fPrimaryParticleEnergy = localRun->GetPrimaryParticleEnergy();
fPrimaryParticleDirection = localRun->GetPrimaryParticleDirection();
fAbsorberMaterialName = localRun->GetAbsorberMaterialName();
fActiveMaterialName = localRun->GetActiveMaterialName();
fCubicVolumeScoringUpDown = localRun->GetCubicVolumeScoringUpDown();
fCubicVolumeScoringSide = localRun->GetCubicVolumeScoringSide();
fNumEvents += localRun->GetNumberOfEvent();
for ( G4int i = 0; i < SteppingAction::numberCombinations; ++i ) {
fArray[i] += localRun->getArray()[i];
for ( G4int i = 0; i < SteppingAction::fkNumberCombinations; ++i ) {
fSteppingArray[i] += localRun->GetSteppingArray()[i];
}
for ( G4int i = 0; i < TrackingAction::fkNumberCombinations; ++i ) {
fTrackingArray1[i] += localRun->GetTrackingArray1()[i];
fTrackingArray2[i] += localRun->GetTrackingArray2()[i];
}
G4Run::Merge( aRun );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::printInfo() const {
void Run::PrintInfo() const {
// This method is called by RunAction::EndOfRunAction. In MT-mode, only the master thread
// calls it.
const G4double floatingNumberOfEvents =
@@ -96,7 +98,7 @@ void Run::printInfo() const {
const G4double factorSide =
conversionFactor / ( fCubicVolumeScoringSide*floatingNumberOfEvents );
G4cout << std::setprecision(6) << G4endl << G4endl
<< " =============== Run::printInfo() =============== \t RunID = " << GetRunID()
<< " =============== Run::PrintInfo() =============== \t RunID = " << GetRunID()
<< G4endl
<< " Primary particle PDG code = " << fPrimaryParticleId << G4endl
<< " Primary particle kinetic energy = " << fPrimaryParticleEnergy / CLHEP::GeV
@@ -109,30 +111,70 @@ void Run::printInfo() const {
<< " Number of events = " << floatingNumberOfEvents << G4endl
<< " Conversion factor: fluence from mm^-2 to cm^-2 = " << conversionFactor << G4endl
<< " Particle fluence in unit of cm^-2 :" << G4endl;
for ( G4int i = 0; i < SteppingAction::numberScoringVolumes; ++i ) {
for ( G4int i = 0; i < SteppingAction::fkNumberScoringVolumes; ++i ) {
G4double factor = ( i == 1 ? factorSide : factorUpDown );
for ( G4int j = 0; j < SteppingAction::numberKinematicRegions; ++j ) {
for ( G4int k = 0; k < SteppingAction::numberParticleTypes; ++k ) {
G4int index = SteppingAction::getIndex( i, j, k );
for ( G4int j = 0; j < SteppingAction::fkNumberKinematicRegions; ++j ) {
for ( G4int k = 0; k < SteppingAction::fkNumberParticleTypes; ++k ) {
G4int index = SteppingAction::GetIndex( i, j, k );
//G4cout << "(i, j, k)=(" << i << ", " << j << ", " << k << ") ->" << index;
G4cout << " case=" << std::setw(3) << index
<< " " << std::setw(12) << SteppingAction::arrayScoringVolumeNames[i]
<< " " << std::setw(12) << SteppingAction::arrayKinematicRegionNames[j]
<< " " << std::setw(12) << SteppingAction::arrayParticleTypeNames[k]
<< " " << factor*fArray[index] << G4endl;
<< " " << std::setw(12) << SteppingAction::fkArrayScoringVolumeNames[i]
<< " " << std::setw(12) << SteppingAction::fkArrayKinematicRegionNames[j]
<< " " << std::setw(12) << SteppingAction::fkArrayParticleTypeNames[k]
<< " " << std::setw( 8) << factor*fSteppingArray[index] << G4endl;
}
}
}
G4cout << " ------------------------------------------------------------- " << G4endl
<< " Extra information: particle production \t \t <N> <E_kin> <Sum_Ekin> [MeV]"
<< G4endl;
const G4double normalization = 1.0 / floatingNumberOfEvents;
for ( G4int i = 0; i < TrackingAction::fkNumberScoringVolumes; ++i ) {
for ( G4int j = 0; j < TrackingAction::fkNumberKinematicRegions; ++j ) {
for ( G4int k = 0; k < TrackingAction::fkNumberParticleTypes; ++k ) {
G4int index = TrackingAction::GetIndex( i, j, k );
//G4cout << "(i, j, k)=(" << i << ", " << j << ", " << k << ") ->" << index;
G4cout << " case=" << std::setw(3) << index
<< " " << std::setw(12) << TrackingAction::fkArrayScoringVolumeNames[i]
<< " " << std::setw(12) << TrackingAction::fkArrayKinematicRegionNames[j]
<< " " << std::setw(12) << TrackingAction::fkArrayParticleTypeNames[k]
<< " " << std::setw( 8) << normalization * fTrackingArray1[index]
<< " " << std::setw( 8) << ( fTrackingArray1[index] > 0 ?
fTrackingArray2[index] / fTrackingArray1[index] :
0.0 )
<< " " << std::setw( 8) << normalization * fTrackingArray2[index]
<< G4endl;
}
}
}
G4cout << " ============================================================= " << G4endl << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::setArray( const std::array< G4double,
SteppingAction::numberCombinations >& inputArray ) {
for ( G4int i = 0; i < SteppingAction::numberCombinations; ++i ) {
fArray[i] = inputArray[i];
}
void Run::SetSteppingArray( const std::array< G4double,
SteppingAction::fkNumberCombinations >& inputArray ) {
for ( G4int i = 0; i < SteppingAction::fkNumberCombinations; ++i ) {
fSteppingArray[i] = inputArray[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::SetTrackingArray1( const std::array< G4int,
TrackingAction::fkNumberCombinations >& inputArray ) {
for ( G4int i = 0; i < TrackingAction::fkNumberCombinations; ++i ) {
fTrackingArray1[i] = inputArray[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::SetTrackingArray2( const std::array< G4double,
TrackingAction::fkNumberCombinations >& inputArray ) {
for ( G4int i = 0; i < TrackingAction::fkNumberCombinations; ++i ) {
fTrackingArray2[i] = inputArray[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+13 -11
View File
@@ -36,16 +36,13 @@
#include "G4Run.hh"
#include "Run.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include "G4RunManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
RunAction::RunAction( SteppingAction* steppingAction ) :
G4UserRunAction(), fSteppingAction( steppingAction ) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
RunAction::~RunAction() {}
RunAction::RunAction( SteppingAction* steppingAction, TrackingAction* trackingAction ) :
G4UserRunAction(), fSteppingAction( steppingAction ), fTrackingAction( trackingAction ) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -57,10 +54,15 @@ G4Run* RunAction::GenerateRun() {
void RunAction::BeginOfRunAction( const G4Run* aRun ) {
G4cout << "### Run " << aRun->GetRunID() << " starts." << G4endl;
if ( fSteppingAction ) {
fSteppingAction->initialize();
Run* run = const_cast< Run* >( static_cast< const Run* >( aRun ) );
if ( run != nullptr ) fSteppingAction->setRunPointer( run );
Run* run = const_cast< Run* >( static_cast< const Run* >( aRun ) );
if ( run == nullptr ) return;
if ( fSteppingAction != nullptr ) {
fSteppingAction->Initialize();
fSteppingAction->SetRunPointer( run );
}
if ( fTrackingAction != nullptr ) {
fTrackingAction->Initialize();
fTrackingAction->SetRunPointer( run );
}
}
@@ -69,7 +71,7 @@ void RunAction::BeginOfRunAction( const G4Run* aRun ) {
void RunAction::EndOfRunAction( const G4Run* aRun ) {
const Run* run = static_cast< const Run* >( aRun );
if ( run == nullptr || run->GetNumberOfEvent() == 0 ) return;
if ( IsMaster() ) run->printInfo();
if ( IsMaster() ) run->PrintInfo();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+42 -42
View File
@@ -46,28 +46,32 @@
#include "G4SystemOfUnits.hh"
#include "Run.hh"
const std::array< G4String, SteppingAction::numberScoringVolumes >
SteppingAction::arrayScoringVolumeNames = { "downstream", "side", "upstream" };
const std::array< G4String, SteppingAction::fkNumberScoringVolumes >
SteppingAction::fkArrayScoringVolumeNames = { "downstream", "side", "upstream" };
const std::array< G4String, SteppingAction::numberKinematicRegions >
SteppingAction::arrayKinematicRegionNames = { "", "below 20 MeV", "above 20 MeV" };
const std::array< G4String, SteppingAction::fkNumberKinematicRegions >
SteppingAction::fkArrayKinematicRegionNames = { "", "below 20 MeV", "above 20 MeV" };
const std::array< G4String, SteppingAction::numberParticleTypes >
SteppingAction::arrayParticleTypeNames = { "all", "electron", "gamma", "muon", "neutrino",
"pion", "neutron", "proton", "ion", "otherMeson",
"otherBaryon" };
const std::array< G4String, SteppingAction::fkNumberParticleTypes >
SteppingAction::fkArrayParticleTypeNames = { "all", "electron", "gamma", "muon", "neutrino",
"pion", "neutron", "proton", "ion", "otherMeson",
"otherBaryon" };
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int SteppingAction::getIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
G4int SteppingAction::GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType ) {
G4int index = -1;
if ( iScoringVolume >= 0 && iScoringVolume < numberScoringVolumes &&
iKinematicRegion >= 0 && iKinematicRegion < numberKinematicRegions &&
iParticleType >= 0 && iParticleType < numberParticleTypes ) {
index = iScoringVolume * numberKinematicRegions * numberParticleTypes +
iKinematicRegion * numberParticleTypes +
iParticleType;
if ( iScoringVolume >= 0 && iScoringVolume < fkNumberScoringVolumes &&
iKinematicRegion >= 0 && iKinematicRegion < fkNumberKinematicRegions &&
iParticleType >= 0 && iParticleType < fkNumberParticleTypes ) {
index = iScoringVolume * fkNumberKinematicRegions * fkNumberParticleTypes +
iKinematicRegion * fkNumberParticleTypes +
iParticleType;
}
if ( index < 0 || index >= fkNumberCombinations ) {
G4cerr << "SteppingAction::GetIndex : WRONG index=" << index << " set it to 0 !" << G4endl;
index = 0;
}
return index;
}
@@ -75,16 +79,12 @@ G4int SteppingAction::getIndex( const G4int iScoringVolume, const G4int iKinemat
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
SteppingAction::SteppingAction() :G4UserSteppingAction() {
initialize();
Initialize();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
SteppingAction::~SteppingAction() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void SteppingAction::initialize() {
void SteppingAction::Initialize() {
// Initialization needed at the beginning of each Run
fPrimaryParticleId = 0;
fPrimaryParticleEnergy = 0.0;
@@ -98,16 +98,16 @@ void SteppingAction::initialize() {
fIsFirstStepInScoringSide = true;
fCubicVolumeScoringUpDown = 1.0;
fCubicVolumeScoringSide = 1.0;
for ( G4int i = 0; i < numberCombinations; ++i ) {
for ( G4int i = 0; i < fkNumberCombinations; ++i ) {
fArraySumStepLengths[i] = 0.0;
}
/*
for ( G4int i = 0; i < numberCombinations; ++i ) fArraySumStepLengths[i] = 999.9;
G4cout << " numberCombinations=" << numberCombinations << G4endl;
for ( G4int i = 0; i < numberScoringVolumes; ++i ) {
for ( G4int j = 0; j < numberKinematicRegions; ++j ) {
for ( G4int k = 0; k < numberParticleTypes; ++k ) {
G4int index = getIndex( i, j, k );
for ( G4int i = 0; i < fkNumberCombinations; ++i ) fArraySumStepLengths[i] = 999.9;
G4cout << " fkNumberCombinations=" << fkNumberCombinations << G4endl;
for ( G4int i = 0; i < fkNumberScoringVolumes; ++i ) {
for ( G4int j = 0; j < fkNumberKinematicRegions; ++j ) {
for ( G4int k = 0; k < fkNumberParticleTypes; ++k ) {
G4int index = GetIndex( i, j, k );
G4cout << "(i, j, k)=(" << i << ", " << j << ", " << k << ") ->" << index;
if ( fArraySumStepLengths[ index ] < 1.0 ) G4cout << " <=== REPEATED!";
else fArraySumStepLengths[ index ] = 0.0;
@@ -115,7 +115,7 @@ void SteppingAction::initialize() {
}
}
}
for ( G4int i = 0; i < numberCombinations; ++i ) {
for ( G4int i = 0; i < fkNumberCombinations; ++i ) {
if ( fArraySumStepLengths[i] > 999.0 ) G4cout << " i=" << i << " NOT COVERED !" << G4endl;
}
*/
@@ -131,9 +131,9 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
fPrimaryParticleEnergy = theStep->GetPreStepPoint()->GetKineticEnergy();
fPrimaryParticleDirection = theStep->GetPreStepPoint()->GetMomentumDirection();
if ( fRunPtr ) {
fRunPtr->setPrimaryParticleId( fPrimaryParticleId );
fRunPtr->setPrimaryParticleEnergy( fPrimaryParticleEnergy );
fRunPtr->setPrimaryParticleDirection( fPrimaryParticleDirection );
fRunPtr->SetPrimaryParticleId( fPrimaryParticleId );
fRunPtr->SetPrimaryParticleEnergy( fPrimaryParticleEnergy );
fRunPtr->SetPrimaryParticleDirection( fPrimaryParticleDirection );
}
fIsFirstStepOfTheEvent = false;
}
@@ -142,13 +142,13 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInAbsorberLayer &&
theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "physiAbsorber" ) {
fAbsorberMaterialName = theStep->GetPreStepPoint()->GetMaterial()->GetName();
if ( fRunPtr ) fRunPtr->setAbsorberMaterialName( fAbsorberMaterialName );
if ( fRunPtr ) fRunPtr->SetAbsorberMaterialName( fAbsorberMaterialName );
fIsFirstStepInAbsorberLayer = false;
}
if ( fIsFirstStepInActiveLayer &&
theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "physiActive" ) {
fActiveMaterialName = theStep->GetPreStepPoint()->GetMaterial()->GetName();
if ( fRunPtr ) fRunPtr->setActiveMaterialName( fActiveMaterialName );
if ( fRunPtr ) fRunPtr->SetActiveMaterialName( fActiveMaterialName );
fIsFirstStepInActiveLayer = false;
}
// Get information on step lengths in the scoring volumes
@@ -158,7 +158,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInScoringUpDown ) {
fCubicVolumeScoringUpDown =
theStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetSolid()->GetCubicVolume();
if ( fRunPtr ) fRunPtr->setCubicVolumeScoringUpDown( fCubicVolumeScoringUpDown );
if ( fRunPtr ) fRunPtr->SetCubicVolumeScoringUpDown( fCubicVolumeScoringUpDown );
fIsFirstStepInScoringUpDown = false;
}
} else if ( theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "physiScoringSide" ) {
@@ -166,7 +166,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInScoringSide ) {
fCubicVolumeScoringSide =
theStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetSolid()->GetCubicVolume();
if ( fRunPtr ) fRunPtr->setCubicVolumeScoringSide( fCubicVolumeScoringSide );
if ( fRunPtr ) fRunPtr->SetCubicVolumeScoringSide( fCubicVolumeScoringSide );
fIsFirstStepInScoringSide = false;
}
} else if ( theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() ==
@@ -175,7 +175,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInScoringUpDown ) {
fCubicVolumeScoringUpDown =
theStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetSolid()->GetCubicVolume();
if ( fRunPtr ) fRunPtr->setCubicVolumeScoringUpDown( fCubicVolumeScoringUpDown );
if ( fRunPtr ) fRunPtr->SetCubicVolumeScoringUpDown( fCubicVolumeScoringUpDown );
fIsFirstStepInScoringUpDown = false;
}
}
@@ -221,18 +221,18 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
else if ( absPdg > 1000 ) iParticleType = 10; // other baryons (e.g. hyperons, anti-hyperons,
// etc.)
// Consider the specific case : scoring volume, kinematic region and particle type
G4int index = getIndex( iScoringVolume, iKinematicRegion, iParticleType );
G4int index = GetIndex( iScoringVolume, iKinematicRegion, iParticleType );
fArraySumStepLengths[index] += stepLength;
// Consider the "all" particle case, with the same scoring volume and kinematic region
index = getIndex( iScoringVolume, iKinematicRegion, 0 );
index = GetIndex( iScoringVolume, iKinematicRegion, 0 );
fArraySumStepLengths[index] += stepLength;
// Consider the "any" kinematic region case, with the same scoring volume and particle type
index = getIndex( iScoringVolume, 0, iParticleType );
index = GetIndex( iScoringVolume, 0, iParticleType );
fArraySumStepLengths[index] += stepLength;
// Consider the "any" kinematic region and "all" particle, with the same scoring volume
index = getIndex( iScoringVolume, 0, 0 );
index = GetIndex( iScoringVolume, 0, 0 );
fArraySumStepLengths[index] += stepLength;
if ( fRunPtr ) fRunPtr->setArray( fArraySumStepLengths );
if ( fRunPtr ) fRunPtr->SetSteppingArray( fArraySumStepLengths );
}
}
@@ -0,0 +1,146 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file TrackingAction.cc
/// \brief Implementation of the TrackingAction class
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "TrackingAction.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleTypes.hh"
#include "G4IonTable.hh"
#include "G4StepPoint.hh"
#include "G4SystemOfUnits.hh"
#include "Run.hh"
const std::array< G4String, TrackingAction::fkNumberScoringVolumes >
TrackingAction::fkArrayScoringVolumeNames = { "calorimeter" };
const std::array< G4String, TrackingAction::fkNumberKinematicRegions >
TrackingAction::fkArrayKinematicRegionNames = { "", "below 20 MeV", "above 20 MeV" };
const std::array< G4String, TrackingAction::fkNumberParticleTypes >
TrackingAction::fkArrayParticleTypeNames = { "all", "electron", "gamma", "muon", "neutrino",
"pion", "neutron", "proton", "ion", "otherMeson",
"otherBaryon" };
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int TrackingAction::GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType ) {
G4int index = -1;
if ( iScoringVolume >= 0 && iScoringVolume < fkNumberScoringVolumes &&
iKinematicRegion >= 0 && iKinematicRegion < fkNumberKinematicRegions &&
iParticleType >= 0 && iParticleType < fkNumberParticleTypes ) {
index = iScoringVolume * fkNumberKinematicRegions * fkNumberParticleTypes +
iKinematicRegion * fkNumberParticleTypes +
iParticleType;
}
return index;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
TrackingAction::TrackingAction() : G4UserTrackingAction() {
Initialize();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void TrackingAction::Initialize() {
// Initialization needed at the beginning of each Run
fArrayMultiplicities.fill( 0 );
fArraySumKineticEnergies.fill( 0.0 );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void TrackingAction::PreUserTrackingAction( const G4Track* aTrack ) {
// This method is called not only once when a particle is created,
// but also each time it is resumed, in the case the track gets suspended,
// as it happens in the case of neutrons with _HP Physics Lists.
// To be sure that we collect information about a track one and only once,
// we require that the current step be the first one.
if ( aTrack == nullptr ||
aTrack->GetCurrentStepNumber() != 0 ||
aTrack->GetDefinition() == nullptr ||
aTrack->GetLogicalVolumeAtVertex() == nullptr ||
( aTrack->GetLogicalVolumeAtVertex()->GetName() != "logicAbsorber" &&
aTrack->GetLogicalVolumeAtVertex()->GetName() != "logicActive" ) ) {
return;
}
G4int iScoringVolume = 0;
// Three kinematical regions: [0] : any value ; [1] : below 20 MeV ; [2] : above 20 MeV
G4int iKinematicRegion = aTrack->GetKineticEnergy() < 20.0 ? 1 : 2;
G4int absPdg = std::abs( aTrack->GetDefinition()->GetPDGEncoding() );
G4int iParticleType = -1;
if ( absPdg == 11 ) iParticleType = 1; // electron (and positron)
else if ( absPdg == 22 ) iParticleType = 2; // gamma
else if ( absPdg == 13 ) iParticleType = 3; // muons (mu- and mu+)
else if ( absPdg == 12 || absPdg == 14 || absPdg == 16 ) iParticleType = 4;
// neutrinos (and anti-neutrinos), all flavors
else if ( absPdg == 111 || absPdg == 211 ) iParticleType = 5; // (charged) pions
else if ( absPdg == 2112 ) iParticleType = 6; // neutron (and anti-neutron)
else if ( absPdg == 2212 ) iParticleType = 7; // proton (and anti-proton)
else if ( G4IonTable::IsIon( aTrack->GetDefinition() ) ||
G4IonTable::IsAntiIon( aTrack->GetDefinition() ) ) iParticleType = 8;
// ions (and anti-ions)
else if ( absPdg < 1000 ) iParticleType = 9; // other mesons (e.g. kaons)
// (Note: this works in most cases, but not always!)
else if ( absPdg > 1000 ) iParticleType = 10; // other baryons (e.g. hyperons,
// anti-hyperons, etc.)
// Consider the specific case : scoring volume, kinematic region and particle type
G4int index = GetIndex( iScoringVolume, iKinematicRegion, iParticleType );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
// Consider the "all" particle case, with the same scoring volume and kinematic region
index = GetIndex( iScoringVolume, iKinematicRegion, 0 );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
// Consider the "any" kinematic region case, with the same scoring volume and particle type
index = GetIndex( iScoringVolume, 0, iParticleType );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
// Consider the "any" kinematic region and "all" particle, with the same scoring volume
index = GetIndex( iScoringVolume, 0, 0 );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
if ( fRunPtr ) {
fRunPtr->SetTrackingArray1( fArrayMultiplicities );
fRunPtr->SetTrackingArray2( fArraySumKineticEnergies );
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void TrackingAction::PostUserTrackingAction( const G4Track* /* aTrack */ ) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -1,7 +1,7 @@
///\file "hadronic/ParticleFluence/ConcentricSpheres/.README.txt"
///\brief Example ParticleFluence/ConcentricSpheres README page
/*! \page ExampeParticleFluenceConcentricSpheres Example ConcentricSpheres
/*! \page ExampleConcentricSpheres Example ConcentricSpheres
In this example, the particle fluence is evaluated for a set-up made
of one target solid sphere, at the center of which a particle is shot
@@ -25,6 +25,10 @@ The particle fluence is estimated by summing the track length in a
(very low density gas) material, immediately outside one of the targets -
and then dividing for the cubic volume of such scoring volume.
Complementary information on average multiplicity, average kinetic energy,
and average total energy flow (i.e. sum of kinetic energies) for the
particles produced in the three targets are also computed.
The particle fluence is evaluated for the following 11 particle types:
- all
- electron + positron
@@ -54,14 +58,18 @@ physics list is used).
To build this example:
mkdir Build; cd Build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DGeant4_DIR=/path-to-geant4-libraries ../.
make
\verbatim
mkdir Build; cd Build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DGeant4_DIR=/path-to-geant4-libraries ../.
make
\endverbatim
To run it:
./ConcentricSpheres all_together.g4
\verbatim
./ConcentricSpheres all_together.g4
\endverbatim
which shoots 50 GeV pion- on three different configurations
(Scintillator-PbWO4-Copper, LiquidArgon-Lead-Iron, Silicon-Tungsten-Tungsten),
@@ -5,6 +5,12 @@ which **must** added in reverse chronological order (newest at the top). It must
be used as a substitute for writing good git commit messages!
## 2022-09-07 Alberto Ribon (exhadrParticleFluenceConcentricSpheres-V11-00-02)
- Added complementary information on particle production (multiplicity,
kinetic energy, and total energy flow) in each of the three targets.
## 2022-08-26 Alberto Ribon (exhadrParticleFluenceConcentricSpheres-V11-00-01)
- SteppingAction : introduced protection on the value of the array index.
## 2021-06-10 Alberto Ribon (exhadrParticleFluenceConcentricSpheres-V11-00-00)
- Created the ConcentricSpheres variant of the ParticleFluence example.
@@ -20,6 +20,10 @@ The particle fluence is estimated by summing the track length in a
(very low density gas) material, immediately outside one of the targets -
and then dividing for the cubic volume of such scoring volume.
Complementary information on average multiplicity, average kinetic energy,
and average total energy flow (i.e. sum of kinetic energies) for the
particles produced in the three targets are also computed.
The particle fluence is evaluated for the following 11 particle types:
- all
- electron + positron
@@ -41,9 +41,9 @@
class ActionInitialization : public G4VUserActionInitialization {
public:
ActionInitialization();
virtual ~ActionInitialization();
virtual void BuildForMaster() const override;
virtual void Build() const override;
~ActionInitialization() override = default;
void BuildForMaster() const override;
void Build() const override;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -37,6 +37,7 @@
#include "G4Run.hh"
#include "G4ThreeVector.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include <array>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -45,62 +46,77 @@ class Run : public G4Run {
// This class accumulates relevant quantities related to particle fluence collected during
// the run.
// ( Note: these information are provided via calls of accessor methods of this Run class
// made by SteppingAction::UserSteppingAction. )
// At the end of a run, the printInfo method is called by the run-action to print out
// made by SteppingAction::UserSteppingAction
// and TrackingAction::PreUserTrackingAction. )
// At the end of a run, the PrintInfo method is called by the run-action to print out
// some summary information about these quantities.
// In multithreaded (MT) mode, an object of this class is filled up for each working thread,
// and then merged (automatically by the Geant4 kernel) into another object (of this class)
// owned by the master class; the printInfo method is then called only for the latter run
// owned by the master class; the PrintInfo method is then called only for the latter run
// object.
// Note that, for simplicity and brevity, we avoid histograms and print-out instead some
// statistics (compute by ourself) at the end of the run.
public:
Run();
~Run();
~Run() override = default;
virtual void RecordEvent( const G4Event* anEvent ) override;
void RecordEvent( const G4Event* anEvent ) override;
// This method is called automatically by the Geant4 kernel (not by the user!) at the end
// of each event. In the case of multithreaded mode, it is called only for the working thread
// that handled that event.
virtual void Merge( const G4Run* aRun ) override;
void Merge( const G4Run* aRun ) override;
// This method is called automatically by the Geant4 kernel (not by the user!) only in the
// case of multithreaded mode and only for working threads.
void printInfo() const;
void PrintInfo() const;
// This method is called by RunAction::EndOfRunAction : in the case of multithreaded mode,
// only the master thread calls it.
void setPrimaryParticleId( const G4int inputValue ) { fPrimaryParticleId = inputValue; }
void setPrimaryParticleEnergy( const G4double inputValue )
void SetPrimaryParticleId( const G4int inputValue ) { fPrimaryParticleId = inputValue; }
void SetPrimaryParticleEnergy( const G4double inputValue )
{ fPrimaryParticleEnergy = inputValue; }
void setPrimaryParticleDirection( const G4ThreeVector &inputValue )
void SetPrimaryParticleDirection( const G4ThreeVector &inputValue )
{ fPrimaryParticleDirection = inputValue; }
void setTrackerMaterialName( const G4String &inputValue )
void SetTrackerMaterialName( const G4String &inputValue )
{ fTrackerMaterialName = inputValue; }
void setEmCaloMaterialName( const G4String &inputValue )
void SetEmCaloMaterialName( const G4String &inputValue )
{ fEmCaloMaterialName = inputValue; }
void setHadCaloMaterialName( const G4String &inputValue )
void SetHadCaloMaterialName( const G4String &inputValue )
{ fHadCaloMaterialName = inputValue; }
void setCubicVolumeScoringTrackerShell( const G4double inputValue )
void SetCubicVolumeScoringTrackerShell( const G4double inputValue )
{ fCubicVolumeScoringTrackerShell = inputValue; }
void setCubicVolumeScoringEmCaloShell( const G4double inputValue )
void SetCubicVolumeScoringEmCaloShell( const G4double inputValue )
{ fCubicVolumeScoringEmCaloShell = inputValue; }
void setCubicVolumeScoringHadCaloShell( const G4double inputValue )
void SetCubicVolumeScoringHadCaloShell( const G4double inputValue )
{ fCubicVolumeScoringHadCaloShell = inputValue; }
G4int getPrimaryParticleId() const { return fPrimaryParticleId; }
G4double getPrimaryParticleEnergy() const { return fPrimaryParticleEnergy; }
G4ThreeVector getPrimaryParticleDirection() const { return fPrimaryParticleDirection; }
G4String getTrackerMaterialName() const { return fTrackerMaterialName; }
G4String getEmCaloMaterialName() const { return fEmCaloMaterialName; }
G4String getHadCaloMaterialName() const { return fHadCaloMaterialName; }
G4double getCubicVolumeScoringTrackerShell() const { return fCubicVolumeScoringTrackerShell; }
G4double getCubicVolumeScoringEmCaloShell() const { return fCubicVolumeScoringEmCaloShell; }
G4double getCubicVolumeScoringHadCaloShell() const { return fCubicVolumeScoringHadCaloShell; }
void setArray( const std::array< G4double, SteppingAction::numberCombinations >& inputArray );
std::array< G4double, SteppingAction::numberCombinations > getArray() const { return fArray; }
G4int GetPrimaryParticleId() const { return fPrimaryParticleId; }
G4double GetPrimaryParticleEnergy() const { return fPrimaryParticleEnergy; }
G4ThreeVector GetPrimaryParticleDirection() const { return fPrimaryParticleDirection; }
G4String GetTrackerMaterialName() const { return fTrackerMaterialName; }
G4String GetEmCaloMaterialName() const { return fEmCaloMaterialName; }
G4String GetHadCaloMaterialName() const { return fHadCaloMaterialName; }
G4double GetCubicVolumeScoringTrackerShell() const { return fCubicVolumeScoringTrackerShell; }
G4double GetCubicVolumeScoringEmCaloShell() const { return fCubicVolumeScoringEmCaloShell; }
G4double GetCubicVolumeScoringHadCaloShell() const { return fCubicVolumeScoringHadCaloShell; }
void SetSteppingArray( const std::array< G4double,
SteppingAction::fkNumberCombinations >& inputArray );
std::array< G4double, SteppingAction::fkNumberCombinations > GetSteppingArray() const
{ return fSteppingArray; }
// Accessor methods useful to transfer information collected by the stepping-action
// into this Run class
// into this Run class
void SetTrackingArray1( const std::array< G4int,
TrackingAction::fkNumberCombinations >& inputArray );
std::array< G4int, TrackingAction::fkNumberCombinations > GetTrackingArray1() const
{ return fTrackingArray1; }
void SetTrackingArray2( const std::array< G4double,
TrackingAction::fkNumberCombinations >& inputArray );
std::array< G4double, TrackingAction::fkNumberCombinations > GetTrackingArray2() const
{ return fTrackingArray2; }
// Accessor methods useful to transfer information collected by the tracking-action
// into this Run class
private:
G4int fNumEvents;
@@ -113,7 +129,9 @@ class Run : public G4Run {
G4double fCubicVolumeScoringTrackerShell;
G4double fCubicVolumeScoringEmCaloShell;
G4double fCubicVolumeScoringHadCaloShell;
std::array< G4double, SteppingAction::numberCombinations > fArray;
std::array< G4double, SteppingAction::fkNumberCombinations > fSteppingArray;
std::array< G4int, TrackingAction::fkNumberCombinations > fTrackingArray1;
std::array< G4double, TrackingAction::fkNumberCombinations > fTrackingArray2;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -38,18 +38,20 @@
class G4Run;
class SteppingAction;
class TrackingAction;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class RunAction: public G4UserRunAction {
public:
RunAction( SteppingAction* steppingAction = nullptr );
virtual ~RunAction();
virtual void BeginOfRunAction( const G4Run* aRun ) override;
virtual void EndOfRunAction( const G4Run* aRun ) override;
virtual G4Run* GenerateRun() override;
RunAction( SteppingAction* steppingAction = nullptr,
TrackingAction* trackingAction = nullptr );
void BeginOfRunAction( const G4Run* aRun ) override;
void EndOfRunAction( const G4Run* aRun ) override;
G4Run* GenerateRun() override;
private:
SteppingAction* fSteppingAction;
TrackingAction* fTrackingAction;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -46,9 +46,9 @@ class Run;
class SteppingAction : public G4UserSteppingAction {
public:
SteppingAction();
virtual ~SteppingAction();
~SteppingAction() override = default;
virtual void UserSteppingAction( const G4Step* ) override;
void UserSteppingAction( const G4Step* ) override;
// This is the main method where the step lengths of particles inside
// the scoring shell are collected, and then the corresponding fluences
// are filled up in the Run object where they are stored (and then
@@ -56,36 +56,36 @@ class SteppingAction : public G4UserSteppingAction {
// (For simplicity and brevity, we avoid histograms and compute instead
// some statistics ourself, which will be print-out at the end of the run.)
void initialize();
void Initialize();
// This method is called by RunAction::BeginOfRunAction for the
// initialization of the stepping-action at the beginning of each Run.
// This is necessary because different runs can have different primary particle
// types, kinetic energies, and detector configurations.
void setRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
void SetRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
// This method is called by RunAction::BeginOfRunAction for providing to the
// stepping-action the pointer to the run object at the beginning of each Run.
// This pointer is then used to pass the information collected by the stepping-action
// to the run object.
G4double getCubicVolumeScoringTrackerShell() const { return fCubicVolumeScoringTrackerShell; }
G4double getCubicVolumeScoringEmCaloShell() const { return fCubicVolumeScoringEmCaloShell; }
G4double getCubicVolumeScoringHadCaloShell() const { return fCubicVolumeScoringHadCaloShell; }
G4double GetCubicVolumeScoringTrackerShell() const { return fCubicVolumeScoringTrackerShell; }
G4double GetCubicVolumeScoringEmCaloShell() const { return fCubicVolumeScoringEmCaloShell; }
G4double GetCubicVolumeScoringHadCaloShell() const { return fCubicVolumeScoringHadCaloShell; }
// Needed to get the fluence from the sum of step lengths
static const G4int numberScoringShells = 3; // tracker, emCalo, hadCalo
static const G4int numberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int numberScoringPositions = 2; // forward, backward (hemisphere, with respect
// to the primary particle direction)
static const G4int numberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
// other-mesons, other-baryons
static const G4int numberCombinations =
numberScoringShells*numberKinematicRegions*numberScoringPositions*numberParticleTypes;
static const std::array< G4String, numberScoringShells > arrayScoringShellNames;
static const std::array< G4String, numberKinematicRegions > arrayKinematicRegionNames;
static const std::array< G4String, numberScoringPositions > arrayScoringPositionNames;
static const std::array< G4String, numberParticleTypes > arrayParticleTypeNames;
static G4int getIndex( const G4int iScoringShell, const G4int iKinematicRegion,
static const G4int fkNumberScoringShells = 3; // tracker, emCalo, hadCalo
static const G4int fkNumberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int fkNumberScoringPositions = 2; // forward, backward (hemisphere, w.r.t.
// the primary particle direction)
static const G4int fkNumberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
// other-mesons, other-baryons
static const G4int fkNumberCombinations = fkNumberScoringShells *
fkNumberKinematicRegions * fkNumberScoringPositions * fkNumberParticleTypes;
static const std::array< G4String, fkNumberScoringShells > fkArrayScoringShellNames;
static const std::array< G4String, fkNumberKinematicRegions > fkArrayKinematicRegionNames;
static const std::array< G4String, fkNumberScoringPositions > fkArrayScoringPositionNames;
static const std::array< G4String, fkNumberParticleTypes > fkArrayParticleTypeNames;
static G4int GetIndex( const G4int iScoringShell, const G4int iKinematicRegion,
const G4int iScoringPosition, const G4int iParticleType );
private:
@@ -107,7 +107,7 @@ class SteppingAction : public G4UserSteppingAction {
G4bool fIsFirstStepInScoringHadCaloShell;
G4double fCubicVolumeScoringHadCaloShell;
std::array< G4double, numberCombinations > fArraySumStepLengths;
std::array< G4double, fkNumberCombinations > fArraySumStepLengths;
// Array to collect the sum of step lengths in the scoring shells for the whole run,
// according to the various cases (scoring shell, kinematical region, scoring position
// and particle type).
@@ -0,0 +1,93 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file TrackingAction.hh
/// \brief Definition of the TrackingAction class
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef TrackingAction_h
#define TrackingAction_h 1
#include "globals.hh"
#include "G4UserTrackingAction.hh"
#include <array>
class Run;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class TrackingAction : public G4UserTrackingAction {
// We are using this class to monitor the average multiplicity, the average
// kinetic energy, and the average total energy flow (i.e. sum of the
// kinetic energies) of different particle types as they are produced
// inside the inner sphere (tracker), the middle spherical shell (EM calo),
// and the outmost spherical shell (HAD calo).
// The aim is then to try to correlate some changes in these (more primitive)
// quantities with the observed changes in the (more indirect and complex)
// particle fluences.
public:
TrackingAction();
~TrackingAction() override = default;
void PreUserTrackingAction( const G4Track* ) override;
void PostUserTrackingAction( const G4Track* ) override;
void Initialize();
// This method is called by RunAction::BeginOfRunAction for the
// initialization of the tracking-action at the beginning of each Run.
void SetRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
// This method is called by RunAction::BeginOfRunAction for providing to the
// tracking-action the pointer to the run object at the beginning of each Run.
// This pointer is then used to pass the information collected by the tracking-action
// to the run object.
static const G4int fkNumberScoringVolumes = 3; // tracker, emCalo, hadCalo
static const G4int fkNumberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int fkNumberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
// other-mesons, other-baryons
static const G4int fkNumberCombinations =
fkNumberScoringVolumes*fkNumberKinematicRegions*fkNumberParticleTypes;
static const std::array< G4String, fkNumberScoringVolumes > fkArrayScoringVolumeNames;
static const std::array< G4String, fkNumberKinematicRegions > fkArrayKinematicRegionNames;
static const std::array< G4String, fkNumberParticleTypes > fkArrayParticleTypeNames;
static G4int GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType );
private:
Run* fRunPtr; // Pointer to the Run object
std::array< G4int, fkNumberCombinations > fArrayMultiplicities;
std::array< G4double, fkNumberCombinations > fArraySumKineticEnergies;
// Keep record of the number of particles and their kinetic energy at production,
// according to the particle type and their kinetic energy range (below/above 20 MeV).
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif
View File
@@ -35,6 +35,7 @@
#include "PrimaryGeneratorAction.hh"
#include "RunAction.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include "Run.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -43,10 +44,6 @@ ActionInitialization::ActionInitialization() : G4VUserActionInitialization() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
ActionInitialization::~ActionInitialization() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void ActionInitialization::BuildForMaster() const {
// This is NOT called in SEQ-mode, while in the MT-mode is called only for the Master thread.
SetUserAction( new RunAction );
@@ -59,7 +56,9 @@ void ActionInitialization::Build() const {
SetUserAction( new PrimaryGeneratorAction );
SteppingAction* steppingAction = new SteppingAction;
SetUserAction( steppingAction );
SetUserAction( new RunAction( steppingAction ) );
TrackingAction* trackingAction = new TrackingAction;
SetUserAction( trackingAction );
SetUserAction( new RunAction( steppingAction, trackingAction ) );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -45,15 +45,13 @@ Run::Run() : G4Run(), fNumEvents( 0 ),
fCubicVolumeScoringTrackerShell( 1.0 ), fCubicVolumeScoringEmCaloShell( 1.0 ),
fCubicVolumeScoringHadCaloShell( 1.0 )
{
for ( G4int i = 0; i < SteppingAction::numberCombinations; ++i ) fArray[i] = 0.0;
fSteppingArray.fill( 0.0 );
fTrackingArray1.fill( 0 );
fTrackingArray2.fill( 0.0 );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Run::~Run() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::RecordEvent( const G4Event* anEvent ) {
// This method is called automatically by the Geant4 kernel (not by the user!) at the end
// of each event : in MT-mode, it is called only for the working thread that handled the event.
@@ -68,25 +66,29 @@ void Run::Merge( const G4Run* aRun ) {
// This method is called automatically by the Geant4 kernel (not by the user!) only in the case
// of multithreaded mode and only for working threads.
const Run* localRun = static_cast< const Run* >( aRun );
fPrimaryParticleId = localRun->getPrimaryParticleId();
fPrimaryParticleEnergy = localRun->getPrimaryParticleEnergy();
fPrimaryParticleDirection = localRun->getPrimaryParticleDirection();
fTrackerMaterialName = localRun->getTrackerMaterialName();
fEmCaloMaterialName = localRun->getEmCaloMaterialName();
fHadCaloMaterialName = localRun->getHadCaloMaterialName();
fCubicVolumeScoringTrackerShell = localRun->getCubicVolumeScoringTrackerShell();
fCubicVolumeScoringEmCaloShell = localRun->getCubicVolumeScoringEmCaloShell();
fCubicVolumeScoringHadCaloShell = localRun->getCubicVolumeScoringHadCaloShell();
fPrimaryParticleId = localRun->GetPrimaryParticleId();
fPrimaryParticleEnergy = localRun->GetPrimaryParticleEnergy();
fPrimaryParticleDirection = localRun->GetPrimaryParticleDirection();
fTrackerMaterialName = localRun->GetTrackerMaterialName();
fEmCaloMaterialName = localRun->GetEmCaloMaterialName();
fHadCaloMaterialName = localRun->GetHadCaloMaterialName();
fCubicVolumeScoringTrackerShell = localRun->GetCubicVolumeScoringTrackerShell();
fCubicVolumeScoringEmCaloShell = localRun->GetCubicVolumeScoringEmCaloShell();
fCubicVolumeScoringHadCaloShell = localRun->GetCubicVolumeScoringHadCaloShell();
fNumEvents += localRun->GetNumberOfEvent();
for ( G4int i = 0; i < SteppingAction::numberCombinations; ++i ) {
fArray[i] += localRun->getArray()[i];
for ( G4int i = 0; i < SteppingAction::fkNumberCombinations; ++i ) {
fSteppingArray[i] += localRun->GetSteppingArray()[i];
}
for ( G4int i = 0; i < TrackingAction::fkNumberCombinations; ++i ) {
fTrackingArray1[i] += localRun->GetTrackingArray1()[i];
fTrackingArray2[i] += localRun->GetTrackingArray2()[i];
}
G4Run::Merge( aRun );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::printInfo() const {
void Run::PrintInfo() const {
// This method is called by RunAction::EndOfRunAction.
// In MT-mode, only the master thread calls it.
const G4double floatingNumberOfEvents =
@@ -101,7 +103,7 @@ void Run::printInfo() const {
const G4double factorHadCalo =
conversionFactor / ( 0.5*fCubicVolumeScoringHadCaloShell*floatingNumberOfEvents );
G4cout << std::setprecision(6) << G4endl << G4endl
<< " =============== Run::printInfo() =============== \t RunID = " << GetRunID()
<< " =============== Run::PrintInfo() =============== \t RunID = " << GetRunID()
<< G4endl
<< " Primary particle PDG code = " << fPrimaryParticleId << G4endl
<< " Primary particle kinetic energy = " << fPrimaryParticleEnergy / CLHEP::GeV
@@ -119,36 +121,76 @@ void Run::printInfo() const {
<< " Number of events = " << floatingNumberOfEvents << G4endl
<< " Conversion factor: fluence from mm^-2 to cm^-2 = " << conversionFactor << G4endl
<< " Particle fluence in unit of cm^-2 :" << G4endl;
for ( G4int i = 0; i < SteppingAction::numberScoringShells; ++i ) {
for ( G4int i = 0; i < SteppingAction::fkNumberScoringShells; ++i ) {
G4double factor = factorTracker;
if ( i == 1 ) factor = factorEmCalo;
else if ( i == 2 ) factor = factorHadCalo;
for ( G4int j = 0; j < SteppingAction::numberKinematicRegions; ++j ) {
for ( G4int k = 0; k < SteppingAction::numberScoringPositions; ++k ) {
for ( G4int ll = 0; ll < SteppingAction::numberParticleTypes; ++ll ) {
G4int index = SteppingAction::getIndex( i, j, k, ll );
for ( G4int j = 0; j < SteppingAction::fkNumberKinematicRegions; ++j ) {
for ( G4int k = 0; k < SteppingAction::fkNumberScoringPositions; ++k ) {
for ( G4int ll = 0; ll < SteppingAction::fkNumberParticleTypes; ++ll ) {
G4int index = SteppingAction::GetIndex( i, j, k, ll );
//G4cout << "(i, j, k, ll)=(" << i << ", " << j << ", " << k << ", "
// << ll << ") ->" << index;
G4cout << " case=" << std::setw(3) << index
<< " " << std::setw(12) << SteppingAction::arrayScoringShellNames[i]
<< " " << std::setw(12) << SteppingAction::arrayKinematicRegionNames[j]
<< " " << std::setw(12) << SteppingAction::arrayScoringPositionNames[k]
<< " " << std::setw(12) << SteppingAction::arrayParticleTypeNames[ll]
<< " " << factor*fArray[index] << G4endl;
<< " " << std::setw(12) << SteppingAction::fkArrayScoringShellNames[i]
<< " " << std::setw(12) << SteppingAction::fkArrayKinematicRegionNames[j]
<< " " << std::setw(12) << SteppingAction::fkArrayScoringPositionNames[k]
<< " " << std::setw(12) << SteppingAction::fkArrayParticleTypeNames[ll]
<< " " << std::setw( 8) << factor*fSteppingArray[index] << G4endl;
}
}
}
}
G4cout << " ------------------------------------------------------------- " << G4endl
<< " Extra information: particle production \t \t <N> <E_kin> <Sum_Ekin> [MeV]"
<< G4endl;
const G4double normalization = 1.0 / floatingNumberOfEvents;
for ( G4int i = 0; i < TrackingAction::fkNumberScoringVolumes; ++i ) {
for ( G4int j = 0; j < TrackingAction::fkNumberKinematicRegions; ++j ) {
for ( G4int k = 0; k < TrackingAction::fkNumberParticleTypes; ++k ) {
G4int index = TrackingAction::GetIndex( i, j, k );
//G4cout << "(i, j, k)=(" << i << ", " << j << ", " << k << ") ->" << index;
G4cout << " case=" << std::setw(3) << index
<< " " << std::setw(12) << TrackingAction::fkArrayScoringVolumeNames[i]
<< " " << std::setw(12) << TrackingAction::fkArrayKinematicRegionNames[j]
<< " " << std::setw(12) << TrackingAction::fkArrayParticleTypeNames[k]
<< " " << std::setw( 8) << normalization * fTrackingArray1[index]
<< " " << std::setw( 8) << ( fTrackingArray1[index] > 0 ?
fTrackingArray2[index] / fTrackingArray1[index] :
0.0 )
<< " " << std::setw( 8) << normalization * fTrackingArray2[index]
<< G4endl;
}
}
}
G4cout << " ============================================================= " << G4endl << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::setArray( const std::array< G4double,
SteppingAction::numberCombinations >& inputArray ) {
for ( G4int i = 0; i < SteppingAction::numberCombinations; ++i ) {
fArray[i] = inputArray[i];
}
void Run::SetSteppingArray( const std::array< G4double,
SteppingAction::fkNumberCombinations >& inputArray ) {
for ( G4int i = 0; i < SteppingAction::fkNumberCombinations; ++i ) {
fSteppingArray[i] = inputArray[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::SetTrackingArray1( const std::array< G4int,
TrackingAction::fkNumberCombinations >& inputArray ) {
for ( G4int i = 0; i < TrackingAction::fkNumberCombinations; ++i ) {
fTrackingArray1[i] = inputArray[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::SetTrackingArray2( const std::array< G4double,
TrackingAction::fkNumberCombinations >& inputArray ) {
for ( G4int i = 0; i < TrackingAction::fkNumberCombinations; ++i ) {
fTrackingArray2[i] = inputArray[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+13 -11
View File
@@ -36,16 +36,13 @@
#include "G4Run.hh"
#include "Run.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include "G4RunManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
RunAction::RunAction( SteppingAction* steppingAction ) :
G4UserRunAction(), fSteppingAction( steppingAction ) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
RunAction::~RunAction() {}
RunAction::RunAction( SteppingAction* steppingAction, TrackingAction* trackingAction ) :
G4UserRunAction(), fSteppingAction( steppingAction ), fTrackingAction( trackingAction ) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -57,10 +54,15 @@ G4Run* RunAction::GenerateRun() {
void RunAction::BeginOfRunAction( const G4Run* aRun ) {
G4cout << "### Run " << aRun->GetRunID() << " starts." << G4endl;
if ( fSteppingAction ) {
fSteppingAction->initialize();
Run* run = const_cast< Run* >( static_cast< const Run* >( aRun ) );
if ( run != nullptr ) fSteppingAction->setRunPointer( run );
Run* run = const_cast< Run* >( static_cast< const Run* >( aRun ) );
if ( run == nullptr ) return;
if ( fSteppingAction != nullptr ) {
fSteppingAction->Initialize();
fSteppingAction->SetRunPointer( run );
}
if ( fTrackingAction != nullptr ) {
fTrackingAction->Initialize();
fTrackingAction->SetRunPointer( run );
}
}
@@ -69,7 +71,7 @@ void RunAction::BeginOfRunAction( const G4Run* aRun ) {
void RunAction::EndOfRunAction( const G4Run* aRun ) {
const Run* run = static_cast< const Run* >( aRun );
if ( run == nullptr || run->GetNumberOfEvent() == 0 ) return;
if ( IsMaster() ) run->printInfo();
if ( IsMaster() ) run->PrintInfo();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+47 -48
View File
@@ -46,33 +46,36 @@
#include "G4SystemOfUnits.hh"
#include "Run.hh"
const std::array< G4String, SteppingAction::numberScoringShells >
SteppingAction::arrayScoringShellNames = { "tracker", "emCalo", "hadCalo" };
const std::array< G4String, SteppingAction::fkNumberScoringShells >
SteppingAction::fkArrayScoringShellNames = { "tracker", "emCalo", "hadCalo" };
const std::array< G4String, SteppingAction::numberKinematicRegions >
SteppingAction::arrayKinematicRegionNames = { "", "below 20 MeV", "above 20 MeV" };
const std::array< G4String, SteppingAction::fkNumberKinematicRegions >
SteppingAction::fkArrayKinematicRegionNames = { "", "below 20 MeV", "above 20 MeV" };
const std::array< G4String, SteppingAction::numberScoringPositions >
SteppingAction::arrayScoringPositionNames = { "forward", "backward" };
const std::array< G4String, SteppingAction::fkNumberScoringPositions >
SteppingAction::fkArrayScoringPositionNames = { "forward", "backward" };
const std::array< G4String, SteppingAction::numberParticleTypes >
SteppingAction::arrayParticleTypeNames = { "all", "electron", "gamma", "muon", "neutrino",
"pion", "neutron", "proton", "ion", "otherMeson",
"otherBaryon" };
const std::array< G4String, SteppingAction::fkNumberParticleTypes >
SteppingAction::fkArrayParticleTypeNames = { "all", "electron", "gamma", "muon", "neutrino",
"pion", "neutron", "proton", "ion", "otherMeson",
"otherBaryon" };
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int SteppingAction::getIndex( const G4int iScoringShell, const G4int iKinematicRegion,
G4int SteppingAction::GetIndex( const G4int iScoringShell, const G4int iKinematicRegion,
const G4int iScoringPosition, const G4int iParticleType ) {
G4int index = -1;
if ( iScoringShell >= 0 && iScoringShell < numberScoringShells &&
iKinematicRegion >= 0 && iKinematicRegion < numberKinematicRegions &&
iScoringPosition >= 0 && iScoringPosition < numberScoringPositions &&
iParticleType >= 0 && iParticleType < numberParticleTypes ) {
index = iScoringShell * numberKinematicRegions * numberScoringPositions * numberParticleTypes +
iKinematicRegion * numberScoringPositions * numberParticleTypes +
iScoringPosition * numberParticleTypes +
iParticleType;
if ( iScoringShell >= 0 && iScoringShell < fkNumberScoringShells &&
iKinematicRegion >= 0 && iKinematicRegion < fkNumberKinematicRegions &&
iScoringPosition >= 0 && iScoringPosition < fkNumberScoringPositions &&
iParticleType >= 0 && iParticleType < fkNumberParticleTypes ) {
index = iScoringShell * fkNumberKinematicRegions * fkNumberScoringPositions *
fkNumberParticleTypes + iKinematicRegion * fkNumberScoringPositions * fkNumberParticleTypes
+ iScoringPosition * fkNumberParticleTypes + iParticleType;
}
if ( index < 0 || index >= fkNumberCombinations ) {
G4cerr << "SteppingAction::GetIndex : WRONG index=" << index << " set it to 0 !" << G4endl;
index = 0;
}
return index;
}
@@ -80,16 +83,12 @@ G4int SteppingAction::getIndex( const G4int iScoringShell, const G4int iKinemati
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
SteppingAction::SteppingAction() :G4UserSteppingAction() {
initialize();
Initialize();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
SteppingAction::~SteppingAction() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void SteppingAction::initialize() {
void SteppingAction::Initialize() {
// Initialization needed at the beginning of each Run
fPrimaryParticleId = 0;
fPrimaryParticleEnergy = 0.0;
@@ -101,17 +100,17 @@ void SteppingAction::initialize() {
fIsFirstStepInScoringHadCaloShell = true;
fCubicVolumeScoringTrackerShell = fCubicVolumeScoringEmCaloShell =
fCubicVolumeScoringHadCaloShell = 1.0;
for ( G4int i = 0; i < numberCombinations; ++i ) {
for ( G4int i = 0; i < fkNumberCombinations; ++i ) {
fArraySumStepLengths[i] = 0.0;
}
/*
for ( G4int i = 0; i < numberCombinations; ++i ) fArraySumStepLengths[i] = 999.9;
G4cout << " numberCombinations=" << numberCombinations << G4endl;
for ( G4int i = 0; i < numberScoringShells; ++i ) {
for ( G4int j = 0; j < numberKinematicRegions; ++j ) {
for ( G4int k = 0; k < numberScoringPositions; ++k ) {
for ( G4int ll = 0; ll < numberParticleTypes; ++ll ) {
G4int index = getIndex( i, j, k, ll );
for ( G4int i = 0; i < fkNumberCombinations; ++i ) fArraySumStepLengths[i] = 999.9;
G4cout << " fkNumberCombinations=" << fkNumberCombinations << G4endl;
for ( G4int i = 0; i < fkNumberScoringShells; ++i ) {
for ( G4int j = 0; j < fkNumberKinematicRegions; ++j ) {
for ( G4int k = 0; k < fkNumberScoringPositions; ++k ) {
for ( G4int ll = 0; ll < fkNumberParticleTypes; ++ll ) {
G4int index = GetIndex( i, j, k, ll );
G4cout << "(i, j, k, ll)=(" << i << ", " << j << ", " << k << ", "
<< ll << ") ->" << index;
if ( fArraySumStepLengths[ index ] < 1.0 ) G4cout << " <=== REPEATED!";
@@ -121,7 +120,7 @@ void SteppingAction::initialize() {
}
}
}
for ( G4int i = 0; i < numberCombinations; ++i ) {
for ( G4int i = 0; i < fkNumberCombinations; ++i ) {
if ( fArraySumStepLengths[i] > 999.0 ) G4cout << " i=" << i << " NOT COVERED !" << G4endl;
}
*/
@@ -137,9 +136,9 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
fPrimaryParticleEnergy = theStep->GetPreStepPoint()->GetKineticEnergy();
fPrimaryParticleDirection = theStep->GetPreStepPoint()->GetMomentumDirection();
if ( fRunPtr ) {
fRunPtr->setPrimaryParticleId( fPrimaryParticleId );
fRunPtr->setPrimaryParticleEnergy( fPrimaryParticleEnergy );
fRunPtr->setPrimaryParticleDirection( fPrimaryParticleDirection );
fRunPtr->SetPrimaryParticleId( fPrimaryParticleId );
fRunPtr->SetPrimaryParticleEnergy( fPrimaryParticleEnergy );
fRunPtr->SetPrimaryParticleDirection( fPrimaryParticleDirection );
}
fIsFirstStepOfTheEvent = false;
}
@@ -148,19 +147,19 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInTracker &&
theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "physiTrackerShell" ) {
fTrackerMaterialName = theStep->GetPreStepPoint()->GetMaterial()->GetName();
if ( fRunPtr ) fRunPtr->setTrackerMaterialName( fTrackerMaterialName );
if ( fRunPtr ) fRunPtr->SetTrackerMaterialName( fTrackerMaterialName );
fIsFirstStepInTracker = false;
}
if ( fIsFirstStepInEmCalo &&
theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "physiEmCaloShell" ) {
fEmCaloMaterialName = theStep->GetPreStepPoint()->GetMaterial()->GetName();
if ( fRunPtr ) fRunPtr->setEmCaloMaterialName( fEmCaloMaterialName );
if ( fRunPtr ) fRunPtr->SetEmCaloMaterialName( fEmCaloMaterialName );
fIsFirstStepInEmCalo = false;
}
if ( fIsFirstStepInHadCalo &&
theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "physiHadCaloShell" ) {
fHadCaloMaterialName = theStep->GetPreStepPoint()->GetMaterial()->GetName();
if ( fRunPtr ) fRunPtr->setHadCaloMaterialName( fHadCaloMaterialName );
if ( fRunPtr ) fRunPtr->SetHadCaloMaterialName( fHadCaloMaterialName );
fIsFirstStepInHadCalo = false;
}
// Get information on step lengths in the scoring shells
@@ -171,7 +170,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInScoringTrackerShell ) {
fCubicVolumeScoringTrackerShell =
theStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetSolid()->GetCubicVolume();
if ( fRunPtr ) fRunPtr->setCubicVolumeScoringTrackerShell( fCubicVolumeScoringTrackerShell );
if ( fRunPtr ) fRunPtr->SetCubicVolumeScoringTrackerShell( fCubicVolumeScoringTrackerShell );
fIsFirstStepInScoringTrackerShell = false;
}
} else if ( theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() ==
@@ -180,7 +179,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInScoringEmCaloShell ) {
fCubicVolumeScoringEmCaloShell =
theStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetSolid()->GetCubicVolume();
if ( fRunPtr ) fRunPtr->setCubicVolumeScoringEmCaloShell( fCubicVolumeScoringEmCaloShell );
if ( fRunPtr ) fRunPtr->SetCubicVolumeScoringEmCaloShell( fCubicVolumeScoringEmCaloShell );
fIsFirstStepInScoringEmCaloShell = false;
}
} else if ( theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() ==
@@ -189,7 +188,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInScoringHadCaloShell ) {
fCubicVolumeScoringHadCaloShell =
theStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetSolid()->GetCubicVolume();
if ( fRunPtr ) fRunPtr->setCubicVolumeScoringHadCaloShell( fCubicVolumeScoringHadCaloShell );
if ( fRunPtr ) fRunPtr->SetCubicVolumeScoringHadCaloShell( fCubicVolumeScoringHadCaloShell );
fIsFirstStepInScoringHadCaloShell = false;
}
}
@@ -231,21 +230,21 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
// etc.)
// Consider the specific case : scoring shell, kinematic region, scoring position, and
// particle type
G4int index = getIndex( iScoringShell, iKinematicRegion, iScoringPosition, iParticleType );
G4int index = GetIndex( iScoringShell, iKinematicRegion, iScoringPosition, iParticleType );
fArraySumStepLengths[index] += stepLength;
// Consider the "all" particle case, with the same scoring shell, kinematic region and
// scoring position
index = getIndex( iScoringShell, iKinematicRegion, iScoringPosition, 0 );
index = GetIndex( iScoringShell, iKinematicRegion, iScoringPosition, 0 );
fArraySumStepLengths[index] += stepLength;
// Consider the "any" kinematic region case, with the same scoring shell, scoring position
// and particle type
index = getIndex( iScoringShell, 0, iScoringPosition, iParticleType );
index = GetIndex( iScoringShell, 0, iScoringPosition, iParticleType );
fArraySumStepLengths[index] += stepLength;
// Consider the "any" kinematic region and "all" particle, with the same scoring shell and
// scoring position
index = getIndex( iScoringShell, 0, iScoringPosition, 0 );
index = GetIndex( iScoringShell, 0, iScoringPosition, 0 );
fArraySumStepLengths[index] += stepLength;
if ( fRunPtr ) fRunPtr->setArray( fArraySumStepLengths );
if ( fRunPtr ) fRunPtr->SetSteppingArray( fArraySumStepLengths );
}
}
@@ -0,0 +1,150 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file TrackingAction.cc
/// \brief Implementation of the TrackingAction class
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "TrackingAction.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleTypes.hh"
#include "G4IonTable.hh"
#include "G4StepPoint.hh"
#include "G4SystemOfUnits.hh"
#include "Run.hh"
const std::array< G4String, TrackingAction::fkNumberScoringVolumes >
TrackingAction::fkArrayScoringVolumeNames = { "tracker", "emCalo", "hadCalo" };
const std::array< G4String, TrackingAction::fkNumberKinematicRegions >
TrackingAction::fkArrayKinematicRegionNames = { "", "below 20 MeV", "above 20 MeV" };
const std::array< G4String, TrackingAction::fkNumberParticleTypes >
TrackingAction::fkArrayParticleTypeNames = { "all", "electron", "gamma", "muon", "neutrino",
"pion", "neutron", "proton", "ion", "otherMeson",
"otherBaryon" };
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int TrackingAction::GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType ) {
G4int index = -1;
if ( iScoringVolume >= 0 && iScoringVolume < fkNumberScoringVolumes &&
iKinematicRegion >= 0 && iKinematicRegion < fkNumberKinematicRegions &&
iParticleType >= 0 && iParticleType < fkNumberParticleTypes ) {
index = iScoringVolume * fkNumberKinematicRegions * fkNumberParticleTypes +
iKinematicRegion * fkNumberParticleTypes +
iParticleType;
}
return index;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
TrackingAction::TrackingAction() : G4UserTrackingAction() {
Initialize();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void TrackingAction::Initialize() {
// Initialization needed at the beginning of each Run
fArrayMultiplicities.fill( 0 );
fArraySumKineticEnergies.fill( 0.0 );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void TrackingAction::PreUserTrackingAction( const G4Track* aTrack ) {
// This method is called not only once when a particle is created,
// but also each time it is resumed, in the case the track gets suspended,
// as it happens in the case of neutrons with _HP Physics Lists.
// To be sure that we collect information about a track one and only once,
// we require that the current step be the first one.
if ( aTrack == nullptr ||
aTrack->GetCurrentStepNumber() != 0 ||
aTrack->GetDefinition() == nullptr ||
aTrack->GetLogicalVolumeAtVertex() == nullptr ) return;
G4int iScoringVolume = -1;
if ( aTrack->GetLogicalVolumeAtVertex()->GetName() == "logicTrackerShell" ) {
iScoringVolume = 0;
} else if ( aTrack->GetLogicalVolumeAtVertex()->GetName() == "logicEmCaloShell" ) {
iScoringVolume = 1;
} else if ( aTrack->GetLogicalVolumeAtVertex()->GetName() == "logicHadCaloShell" ) {
iScoringVolume = 2;
}
if ( iScoringVolume < 0 ) return;
// Three kinematical regions: [0] : any value ; [1] : below 20 MeV ; [2] : above 20 MeV
G4int iKinematicRegion = aTrack->GetKineticEnergy() < 20.0 ? 1 : 2;
G4int absPdg = std::abs( aTrack->GetDefinition()->GetPDGEncoding() );
G4int iParticleType = -1;
if ( absPdg == 11 ) iParticleType = 1; // electron (and positron)
else if ( absPdg == 22 ) iParticleType = 2; // gamma
else if ( absPdg == 13 ) iParticleType = 3; // muons (mu- and mu+)
else if ( absPdg == 12 || absPdg == 14 || absPdg == 16 ) iParticleType = 4;
// neutrinos (and anti-neutrinos), all flavors
else if ( absPdg == 111 || absPdg == 211 ) iParticleType = 5; // (charged) pions
else if ( absPdg == 2112 ) iParticleType = 6; // neutron (and anti-neutron)
else if ( absPdg == 2212 ) iParticleType = 7; // proton (and anti-proton)
else if ( G4IonTable::IsIon( aTrack->GetDefinition() ) ||
G4IonTable::IsAntiIon( aTrack->GetDefinition() ) ) iParticleType = 8;
// ions (and anti-ions)
else if ( absPdg < 1000 ) iParticleType = 9; // other mesons (e.g. kaons)
// (Note: this works in most cases, but not always!)
else if ( absPdg > 1000 ) iParticleType = 10; // other baryons (e.g. hyperons,
// anti-hyperons, etc.)
// Consider the specific case : scoring volume, kinematic region and particle type
G4int index = GetIndex( iScoringVolume, iKinematicRegion, iParticleType );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
// Consider the "all" particle case, with the same scoring volume and kinematic region
index = GetIndex( iScoringVolume, iKinematicRegion, 0 );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
// Consider the "any" kinematic region case, with the same scoring volume and particle type
index = GetIndex( iScoringVolume, 0, iParticleType );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
// Consider the "any" kinematic region and "all" particle, with the same scoring volume
index = GetIndex( iScoringVolume, 0, 0 );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
if ( fRunPtr ) {
fRunPtr->SetTrackingArray1( fArrayMultiplicities );
fRunPtr->SetTrackingArray2( fArraySumKineticEnergies );
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void TrackingAction::PostUserTrackingAction( const G4Track* /* aTrack */ ) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -5,6 +5,9 @@ which **must** added in reverse chronological order (newest at the top). It must
be used as a substitute for writing good git commit messages!
## 2021-06-10 Alberto Ribon (exhadrParticleFluence-V11-00-00)
## 2022-10-25 I. Hrivnacova (exhadrParticleFluence-V11-00-01)
- Fixes in Doxygen documentation (links, formatting)
## 2022-06-10 Alberto Ribon (exhadrParticleFluence-V11-00-00)
- Created this example.
@@ -1,7 +1,7 @@
///\file "hadronic/ParticleFluence/Layer/.README.txt"
///\brief Example ParticleFluence/Layer README page
/*! \page ExampeParticleFluenceLayer Example Layer
/*! \page ExampleLayer Example Layer
In this example, the particle fluence is evaluated for a simple set-up,
consisting of one target solid cylinder, with axis along the z-direction,
@@ -18,6 +18,10 @@ cases) or a thin hemisphere shell (for the "side" case) filled up with
G4_Galactic (very low density gas) material, immediately outside the
target - and then dividing for the cubic volume of such scoring volume.
Complementary information on average multiplicity, average kinetic energy,
and average total energy flow (i.e. sum of kinetic energies) for the
particles produced in the target are also computed.
The particle fluence is evaluated for the following 11 particle types:
- all
- electron + positron
@@ -47,14 +51,18 @@ physics list is used).
To build this example:
mkdir Build; cd Build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DGeant4_DIR=/path-to-geant4-libraries ../.
make
\verbatim
mkdir Build; cd Build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DGeant4_DIR=/path-to-geant4-libraries ../.
make
\endverbatim
To run it:
./Layer all_together.g4
\verbatim
./Layer all_together.g4
\endverbatim
which shoots 50 GeV pion- on different target materials, 100 events
in each run, and print out some information on the particle fluence
View File
@@ -5,6 +5,12 @@ which **must** added in reverse chronological order (newest at the top). It must
be used as a substitute for writing good git commit messages!
## 2022-09-07 Alberto Ribon (exhadrParticleFluenceLayer-V11-00-02)
- Added complementary information on particle production (multiplicity,
kinetic energy, and total energy flow) in the target.
## 2022-08-26 Alberto Ribon (exhadrParticleFluenceLayer-V11-00-01)
- SteppingAction : introduced protection on the value of the array index.
## 2021-06-10 Alberto Ribon (exhadrParticleFluenceLayer-V11-00-00)
- Created the Layer variant of the ParticleFluence example.
View File
File diff suppressed because it is too large Load Diff
@@ -13,6 +13,10 @@ cases) or a thin hemisphere shell (for the "side" case) filled up with
G4_Galactic (very low density gas) material, immediately outside the
target - and then dividing for the cubic volume of such scoring volume.
Complementary information on average multiplicity, average kinetic energy,
and average total energy flow (i.e. sum of kinetic energies) for the
particles produced in the target are also computed.
The particle fluence is evaluated for the following 11 particle types:
- all
- electron + positron
View File
View File
View File
View File
@@ -43,9 +43,9 @@ class DetectorConstruction;
class ActionInitialization : public G4VUserActionInitialization {
public:
ActionInitialization( const DetectorConstruction* inputDetectorConstruction = nullptr );
virtual ~ActionInitialization();
virtual void BuildForMaster() const override;
virtual void Build() const override;
~ActionInitialization() override = default;
void BuildForMaster() const override;
void Build() const override;
private:
const DetectorConstruction* fPtrDetectorConstruction = nullptr;
};
@@ -37,6 +37,7 @@
#include "G4Run.hh"
#include "G4ThreeVector.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include <array>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -45,54 +46,69 @@ class Run : public G4Run {
// This class accumulates relevant quantities related to particle fluence collected during
// the run.
// ( Note: these information are provided via calls of accessor methods of this Run class
// made by SteppingAction::UserSteppingAction. )
// At the end of a run, the printInfo method is called by the run-action to print out
// made by SteppingAction::UserSteppingAction
// and TrackingAction::PreUserTrackingAction . )
// At the end of a run, the PrintInfo method is called by the run-action to print out
// some summary information about these quantities.
// In multithreaded (MT) mode, an object of this class is filled up for each working thread,
// and then merged (automatically by the Geant4 kernel) into another object (of this class)
// owned by the master class; the printInfo method is then called only for the latter run
// owned by the master class; the PrintInfo method is then called only for the latter run
// object.
// Note that, for simplicity and brevity, we avoid histograms and print-out instead some
// statistics (compute by ourself) at the end of the run.
// statistics (compute by ourself) at the end of the run.
public:
Run();
~Run();
~Run() override = default;
virtual void RecordEvent( const G4Event* anEvent ) override;
void RecordEvent( const G4Event* anEvent ) override;
// This method is called automatically by the Geant4 kernel (not by the user!) at the end
// of each event. In the case of multithreaded mode, it is called only for the working thread
// that handled that event.
virtual void Merge( const G4Run* aRun ) override;
void Merge( const G4Run* aRun ) override;
// This method is called automatically by the Geant4 kernel (not by the user!) only in the
// case of multithreaded mode and only for working threads.
void printInfo() const;
void PrintInfo() const;
// This method is called by RunAction::EndOfRunAction : in the case of multithreaded mode,
// only the master thread calls it.
void setPrimaryParticleId( const G4int inputValue ) { fPrimaryParticleId = inputValue; }
void setPrimaryParticleEnergy( const G4double inputValue )
void SetPrimaryParticleId( const G4int inputValue ) { fPrimaryParticleId = inputValue; }
void SetPrimaryParticleEnergy( const G4double inputValue )
{ fPrimaryParticleEnergy = inputValue; }
void setPrimaryParticleDirection( const G4ThreeVector &inputValue )
void SetPrimaryParticleDirection( const G4ThreeVector &inputValue )
{ fPrimaryParticleDirection = inputValue; }
void setTargetMaterialName( const G4String &inputValue ) { fTargetMaterialName = inputValue; }
void setCubicVolumeScoringUpDown( const G4double inputValue )
void SetTargetMaterialName( const G4String &inputValue ) { fTargetMaterialName = inputValue; }
void SetCubicVolumeScoringUpDown( const G4double inputValue )
{ fCubicVolumeScoringUpDown = inputValue; }
void setCubicVolumeScoringSide( const G4double inputValue )
void SetCubicVolumeScoringSide( const G4double inputValue )
{ fCubicVolumeScoringSide = inputValue; }
G4int getPrimaryParticleId() const { return fPrimaryParticleId; }
G4double getPrimaryParticleEnergy() const { return fPrimaryParticleEnergy; }
G4ThreeVector getPrimaryParticleDirection() const { return fPrimaryParticleDirection; }
G4String getTargetMaterialName() const { return fTargetMaterialName; }
G4double getCubicVolumeScoringUpDown() const { return fCubicVolumeScoringUpDown; }
G4double getCubicVolumeScoringSide() const { return fCubicVolumeScoringSide; }
void setArray( const std::array< G4double, SteppingAction::numberCombinations >& inputArray );
std::array< G4double, SteppingAction::numberCombinations > getArray() const { return fArray; }
G4int GetPrimaryParticleId() const { return fPrimaryParticleId; }
G4double GetPrimaryParticleEnergy() const { return fPrimaryParticleEnergy; }
G4ThreeVector GetPrimaryParticleDirection() const { return fPrimaryParticleDirection; }
G4String GetTargetMaterialName() const { return fTargetMaterialName; }
G4double GetCubicVolumeScoringUpDown() const { return fCubicVolumeScoringUpDown; }
G4double GetCubicVolumeScoringSide() const { return fCubicVolumeScoringSide; }
void SetSteppingArray( const std::array< G4double,
SteppingAction::fkNumberCombinations >& inputArray );
std::array< G4double, SteppingAction::fkNumberCombinations > GetSteppingArray() const
{ return fSteppingArray; }
// Accessor methods useful to transfer information collected by the stepping-action
// into this Run class
// into this Run class
private:
void SetTrackingArray1( const std::array< G4int,
TrackingAction::fkNumberCombinations >& inputArray );
std::array< G4int, TrackingAction::fkNumberCombinations > GetTrackingArray1() const
{ return fTrackingArray1; }
void SetTrackingArray2( const std::array< G4double,
TrackingAction::fkNumberCombinations >& inputArray );
std::array< G4double, TrackingAction::fkNumberCombinations > GetTrackingArray2() const
{ return fTrackingArray2; }
// Accessor methods useful to transfer information collected by the tracking-action
// into this Run class
private:
G4int fNumEvents;
G4int fPrimaryParticleId;
G4double fPrimaryParticleEnergy;
@@ -100,7 +116,10 @@ class Run : public G4Run {
G4String fTargetMaterialName;
G4double fCubicVolumeScoringUpDown;
G4double fCubicVolumeScoringSide;
std::array< G4double, SteppingAction::numberCombinations > fArray;
std::array< G4double, SteppingAction::fkNumberCombinations > fSteppingArray;
std::array< G4int, TrackingAction::fkNumberCombinations > fTrackingArray1;
std::array< G4double, TrackingAction::fkNumberCombinations > fTrackingArray2;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+7 -5
View File
@@ -38,18 +38,20 @@
class G4Run;
class SteppingAction;
class TrackingAction;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class RunAction: public G4UserRunAction {
public:
RunAction( SteppingAction* steppingAction = nullptr );
virtual ~RunAction();
virtual void BeginOfRunAction( const G4Run* aRun ) override;
virtual void EndOfRunAction( const G4Run* aRun ) override;
virtual G4Run* GenerateRun() override;
RunAction( SteppingAction* steppingAction = nullptr, TrackingAction* trackingAction = nullptr );
~RunAction() override = default;
void BeginOfRunAction( const G4Run* aRun ) override;
void EndOfRunAction( const G4Run* aRun ) override;
G4Run* GenerateRun() override;
private:
SteppingAction* fSteppingAction;
TrackingAction* fTrackingAction;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+16 -16
View File
@@ -46,9 +46,9 @@ class Run;
class SteppingAction : public G4UserSteppingAction {
public:
SteppingAction();
virtual ~SteppingAction();
~SteppingAction() override = default;
virtual void UserSteppingAction( const G4Step* ) override;
void UserSteppingAction( const G4Step* ) override;
// This is the main method where the step lengths of particles inside
// the scoring volumes are collected, and then the corresponding fluences
// are filled up in the Run object where they are stored (and then
@@ -56,35 +56,35 @@ class SteppingAction : public G4UserSteppingAction {
// (For simplicity and brevity, we avoid histograms and compute instead
// some statistics ourself, which will be print-out at the end of the run.)
void initialize();
void Initialize();
// This method is called by RunAction::BeginOfRunAction for the
// initialization of the stepping-action at the beginning of each Run.
// This is necessary because different runs can have different primary particle
// types, kinetic energies, and detector configurations.
void setRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
void SetRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
// This method is called by RunAction::BeginOfRunAction for providing to the
// stepping-action the pointer to the run object at the beginning of each Run.
// This pointer is then used to pass the information collected by the stepping-action
// to the run object.
G4double getCubicVolumeScoringUpDown() const { return fCubicVolumeScoringUpDown; }
G4double getCubicVolumeScoringSide() const { return fCubicVolumeScoringSide; }
G4double GetCubicVolumeScoringUpDown() const { return fCubicVolumeScoringUpDown; }
G4double GetCubicVolumeScoringSide() const { return fCubicVolumeScoringSide; }
// The cubic-volumes of the scoring volumes are needed to get the fluence from
// the sum of step lengths in those scoring volumes.
// Notice that two of the three scoring volumes - upstream and downstream -
// have the same cubic-volume, that we call "fCubicVolumeScoringUpDown".
static const G4int numberScoringVolumes = 3; // downstream, side, upstream
static const G4int numberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int numberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
static const G4int fkNumberScoringVolumes = 3; // downstream, side, upstream
static const G4int fkNumberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int fkNumberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
// other-mesons, other-baryons
static const G4int numberCombinations =
numberScoringVolumes*numberKinematicRegions*numberParticleTypes;
static const std::array< G4String, numberScoringVolumes > arrayScoringVolumeNames;
static const std::array< G4String, numberKinematicRegions > arrayKinematicRegionNames;
static const std::array< G4String, numberParticleTypes > arrayParticleTypeNames;
static G4int getIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
static const G4int fkNumberCombinations =
fkNumberScoringVolumes*fkNumberKinematicRegions*fkNumberParticleTypes;
static const std::array< G4String, fkNumberScoringVolumes > fkArrayScoringVolumeNames;
static const std::array< G4String, fkNumberKinematicRegions > fkArrayKinematicRegionNames;
static const std::array< G4String, fkNumberParticleTypes > fkArrayParticleTypeNames;
static G4int GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType );
private:
@@ -100,7 +100,7 @@ class SteppingAction : public G4UserSteppingAction {
G4double fCubicVolumeScoringUpDown;
G4double fCubicVolumeScoringSide;
std::array< G4double, numberCombinations > fArraySumStepLengths;
std::array< G4double, fkNumberCombinations > fArraySumStepLengths;
// Array to collect the sum of step lengths in the scoring volumes for the whole run,
// according to the various cases (kinematical region and particle type).
// Note that the fluence in a scoring volume is defined as sum of step lengths
@@ -0,0 +1,92 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file TrackingAction.hh
/// \brief Definition of the TrackingAction class
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef TrackingAction_h
#define TrackingAction_h 1
#include "globals.hh"
#include "G4UserTrackingAction.hh"
#include <array>
class Run;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class TrackingAction : public G4UserTrackingAction {
// We are using this class to monitor the average multiplicity, the average
// kinetic energy, and the average total energy flow (i.e. sum of the
// kinetic energies) of different particle types as they are produced
// inside the target layer.
// The aim is then to try to correlate some changes in these (more primitive)
// quantities with the observed changes in the (more indirect and complex)
// particle fluences.
public:
TrackingAction();
~TrackingAction() override = default;
void PreUserTrackingAction( const G4Track* ) override;
void PostUserTrackingAction( const G4Track* ) override;
void Initialize();
// This method is called by RunAction::BeginOfRunAction for the
// initialization of the tracking-action at the beginning of each Run.
void SetRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
// This method is called by RunAction::BeginOfRunAction for providing to the
// tracking-action the pointer to the run object at the beginning of each Run.
// This pointer is then used to pass the information collected by the tracking-action
// to the run object.
static const G4int fkNumberScoringVolumes = 1; // only the target layer
static const G4int fkNumberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int fkNumberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
// other-mesons, other-baryons
static const G4int fkNumberCombinations =
fkNumberScoringVolumes*fkNumberKinematicRegions*fkNumberParticleTypes;
static const std::array< G4String, fkNumberScoringVolumes > fkArrayScoringVolumeNames;
static const std::array< G4String, fkNumberKinematicRegions > fkArrayKinematicRegionNames;
static const std::array< G4String, fkNumberParticleTypes > fkArrayParticleTypeNames;
static G4int GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType );
private:
Run* fRunPtr; // Pointer to the Run object
std::array< G4int, fkNumberCombinations > fArrayMultiplicities;
std::array< G4double, fkNumberCombinations > fArraySumKineticEnergies;
// Keep record of the fkNumber of particles and their kinetic energy at production,
// according to the particle type and their kinetic energy range (below/above 20 MeV).
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif
View File
View File
View File
View File
View File
@@ -35,6 +35,7 @@
#include "PrimaryGeneratorAction.hh"
#include "RunAction.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include "Run.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -45,10 +46,6 @@ ActionInitialization::ActionInitialization( const DetectorConstruction*
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
ActionInitialization::~ActionInitialization() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void ActionInitialization::BuildForMaster() const {
// This is NOT called in SEQ-mode, while in the MT-mode is called only for the Master thread.
SetUserAction( new RunAction );
@@ -61,7 +58,9 @@ void ActionInitialization::Build() const {
SetUserAction( new PrimaryGeneratorAction( fPtrDetectorConstruction ) );
SteppingAction* steppingAction = new SteppingAction;
SetUserAction( steppingAction );
SetUserAction( new RunAction( steppingAction ) );
TrackingAction* trackingAction = new TrackingAction;
SetUserAction( trackingAction );
SetUserAction( new RunAction( steppingAction, trackingAction ) );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -44,15 +44,13 @@ Run::Run() : G4Run(), fNumEvents( 0 ),
fTargetMaterialName( "" ),
fCubicVolumeScoringUpDown( 1.0 ), fCubicVolumeScoringSide( 1.0 )
{
for ( G4int i = 0; i < SteppingAction::numberCombinations; ++i ) fArray[i] = 0.0;
fSteppingArray.fill( 0.0 );
fTrackingArray1.fill( 0 );
fTrackingArray2.fill( 0.0 );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Run::~Run() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::RecordEvent( const G4Event* anEvent ) {
// This method is called automatically by the Geant4 kernel (not by the user!) at the end
// of each event : in MT-mode, it is called only for the working thread that handled the event.
@@ -67,22 +65,26 @@ void Run::Merge( const G4Run* aRun ) {
// This method is called automatically by the Geant4 kernel (not by the user!) only in the case
// of multithreaded mode and only for working threads.
const Run* localRun = static_cast< const Run* >( aRun );
fPrimaryParticleId = localRun->getPrimaryParticleId();
fPrimaryParticleEnergy = localRun->getPrimaryParticleEnergy();
fPrimaryParticleDirection = localRun->getPrimaryParticleDirection();
fTargetMaterialName = localRun->getTargetMaterialName();
fCubicVolumeScoringUpDown = localRun->getCubicVolumeScoringUpDown();
fCubicVolumeScoringSide = localRun->getCubicVolumeScoringSide();
fPrimaryParticleId = localRun->GetPrimaryParticleId();
fPrimaryParticleEnergy = localRun->GetPrimaryParticleEnergy();
fPrimaryParticleDirection = localRun->GetPrimaryParticleDirection();
fTargetMaterialName = localRun->GetTargetMaterialName();
fCubicVolumeScoringUpDown = localRun->GetCubicVolumeScoringUpDown();
fCubicVolumeScoringSide = localRun->GetCubicVolumeScoringSide();
fNumEvents += localRun->GetNumberOfEvent();
for ( G4int i = 0; i < SteppingAction::numberCombinations; ++i ) {
fArray[i] += localRun->getArray()[i];
for ( G4int i = 0; i < SteppingAction::fkNumberCombinations; ++i ) {
fSteppingArray[i] += localRun->GetSteppingArray()[i];
}
for ( G4int i = 0; i < TrackingAction::fkNumberCombinations; ++i ) {
fTrackingArray1[i] += localRun->GetTrackingArray1()[i];
fTrackingArray2[i] += localRun->GetTrackingArray2()[i];
}
G4Run::Merge( aRun );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::printInfo() const {
void Run::PrintInfo() const {
// This method is called by RunAction::EndOfRunAction. In MT-mode, only the master thread
// calls it.
const G4double floatingNumberOfEvents =
@@ -95,7 +97,7 @@ void Run::printInfo() const {
const G4double factorSide =
conversionFactor / ( fCubicVolumeScoringSide*floatingNumberOfEvents );
G4cout << std::setprecision(6) << G4endl << G4endl
<< " =============== Run::printInfo() =============== \t RunID = " << GetRunID()
<< " =============== Run::PrintInfo() =============== \t RunID = " << GetRunID()
<< G4endl
<< " Primary particle PDG code = " << fPrimaryParticleId << G4endl
<< " Primary particle kinetic energy = " << fPrimaryParticleEnergy / CLHEP::GeV
@@ -107,17 +109,39 @@ void Run::printInfo() const {
<< " Number of events = " << floatingNumberOfEvents << G4endl
<< " Conversion factor: fluence from mm^-2 to cm^-2 = " << conversionFactor << G4endl
<< " Particle fluence in unit of cm^-2 :" << G4endl;
for ( G4int i = 0; i < SteppingAction::numberScoringVolumes; ++i ) {
for ( G4int i = 0; i < SteppingAction::fkNumberScoringVolumes; ++i ) {
G4double factor = ( i == 1 ? factorSide : factorUpDown );
for ( G4int j = 0; j < SteppingAction::numberKinematicRegions; ++j ) {
for ( G4int k = 0; k < SteppingAction::numberParticleTypes; ++k ) {
G4int index = SteppingAction::getIndex( i, j, k );
for ( G4int j = 0; j < SteppingAction::fkNumberKinematicRegions; ++j ) {
for ( G4int k = 0; k < SteppingAction::fkNumberParticleTypes; ++k ) {
G4int index = SteppingAction::GetIndex( i, j, k );
//G4cout << "(i, j, k)=(" << i << ", " << j << ", " << k << ") ->" << index;
G4cout << " case=" << std::setw(3) << index
<< " " << std::setw(12) << SteppingAction::arrayScoringVolumeNames[i]
<< " " << std::setw(12) << SteppingAction::arrayKinematicRegionNames[j]
<< " " << std::setw(12) << SteppingAction::arrayParticleTypeNames[k]
<< " " << factor*fArray[index] << G4endl;
<< " " << std::setw(12) << SteppingAction::fkArrayScoringVolumeNames[i]
<< " " << std::setw(12) << SteppingAction::fkArrayKinematicRegionNames[j]
<< " " << std::setw(12) << SteppingAction::fkArrayParticleTypeNames[k]
<< " " << std::setw( 8) << factor*fSteppingArray[index] << G4endl;
}
}
}
G4cout << " ------------------------------------------------------------- " << G4endl
<< " Extra information: particle production \t \t <N> <E_kin> <Sum_Ekin> [MeV]"
<< G4endl;
const G4double normalization = 1.0 / floatingNumberOfEvents;
for ( G4int i = 0; i < TrackingAction::fkNumberScoringVolumes; ++i ) {
for ( G4int j = 0; j < TrackingAction::fkNumberKinematicRegions; ++j ) {
for ( G4int k = 0; k < TrackingAction::fkNumberParticleTypes; ++k ) {
G4int index = TrackingAction::GetIndex( i, j, k );
//G4cout << "(i, j, k)=(" << i << ", " << j << ", " << k << ") ->" << index;
G4cout << " case=" << std::setw(3) << index
<< " " << std::setw(12) << TrackingAction::fkArrayScoringVolumeNames[i]
<< " " << std::setw(12) << TrackingAction::fkArrayKinematicRegionNames[j]
<< " " << std::setw(12) << TrackingAction::fkArrayParticleTypeNames[k]
<< " " << std::setw( 8) << normalization * fTrackingArray1[index]
<< " " << std::setw( 8) << ( fTrackingArray1[index] > 0 ?
fTrackingArray2[index] / fTrackingArray1[index] :
0.0 )
<< " " << std::setw( 8) << normalization * fTrackingArray2[index]
<< G4endl;
}
}
}
@@ -126,11 +150,29 @@ void Run::printInfo() const {
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::setArray( const std::array< G4double,
SteppingAction::numberCombinations >& inputArray ) {
for ( G4int i = 0; i < SteppingAction::numberCombinations; ++i ) {
fArray[i] = inputArray[i];
}
void Run::SetSteppingArray( const std::array< G4double,
SteppingAction::fkNumberCombinations >& inputArray ) {
for ( G4int i = 0; i < SteppingAction::fkNumberCombinations; ++i ) {
fSteppingArray[i] = inputArray[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::SetTrackingArray1( const std::array< G4int,
TrackingAction::fkNumberCombinations >& inputArray ) {
for ( G4int i = 0; i < TrackingAction::fkNumberCombinations; ++i ) {
fTrackingArray1[i] = inputArray[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Run::SetTrackingArray2( const std::array< G4double,
TrackingAction::fkNumberCombinations >& inputArray ) {
for ( G4int i = 0; i < TrackingAction::fkNumberCombinations; ++i ) {
fTrackingArray2[i] = inputArray[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+13 -11
View File
@@ -36,16 +36,13 @@
#include "G4Run.hh"
#include "Run.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include "G4RunManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
RunAction::RunAction( SteppingAction* steppingAction ) :
G4UserRunAction(), fSteppingAction( steppingAction ) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
RunAction::~RunAction() {}
RunAction::RunAction( SteppingAction* steppingAction, TrackingAction* trackingAction ) :
G4UserRunAction(), fSteppingAction( steppingAction ), fTrackingAction( trackingAction ) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -57,10 +54,15 @@ G4Run* RunAction::GenerateRun() {
void RunAction::BeginOfRunAction( const G4Run* aRun ) {
G4cout << "### Run " << aRun->GetRunID() << " starts." << G4endl;
if ( fSteppingAction ) {
fSteppingAction->initialize();
Run* run = const_cast< Run* >( static_cast< const Run* >( aRun ) );
if ( run != nullptr ) fSteppingAction->setRunPointer( run );
Run* run = const_cast< Run* >( static_cast< const Run* >( aRun ) );
if ( run == nullptr ) return;
if ( fSteppingAction != nullptr ) {
fSteppingAction->Initialize();
fSteppingAction->SetRunPointer( run );
}
if ( fTrackingAction != nullptr ) {
fTrackingAction->Initialize();
fTrackingAction->SetRunPointer( run );
}
}
@@ -69,7 +71,7 @@ void RunAction::BeginOfRunAction( const G4Run* aRun ) {
void RunAction::EndOfRunAction( const G4Run* aRun ) {
const Run* run = static_cast< const Run* >( aRun );
if ( run == nullptr || run->GetNumberOfEvent() == 0 ) return;
if ( IsMaster() ) run->printInfo();
if ( IsMaster() ) run->PrintInfo();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+42 -42
View File
@@ -46,45 +46,45 @@
#include "G4SystemOfUnits.hh"
#include "Run.hh"
const std::array< G4String, SteppingAction::numberScoringVolumes >
SteppingAction::arrayScoringVolumeNames = { "downstream", "side", "upstream" };
const std::array< G4String, SteppingAction::fkNumberScoringVolumes >
SteppingAction::fkArrayScoringVolumeNames = { "downstream", "side", "upstream" };
const std::array< G4String, SteppingAction::numberKinematicRegions >
SteppingAction::arrayKinematicRegionNames = { "", "below 20 MeV", "above 20 MeV" };
const std::array< G4String, SteppingAction::fkNumberKinematicRegions >
SteppingAction::fkArrayKinematicRegionNames = { "", "below 20 MeV", "above 20 MeV" };
const std::array< G4String, SteppingAction::numberParticleTypes >
SteppingAction::arrayParticleTypeNames = { "all", "electron", "gamma", "muon", "neutrino",
"pion", "neutron", "proton", "ion", "otherMeson",
"otherBaryon" };
const std::array< G4String, SteppingAction::fkNumberParticleTypes >
SteppingAction::fkArrayParticleTypeNames = { "all", "electron", "gamma", "muon", "neutrino",
"pion", "neutron", "proton", "ion", "otherMeson",
"otherBaryon" };
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int SteppingAction::getIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
G4int SteppingAction::GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType ) {
G4int index = -1;
if ( iScoringVolume >= 0 && iScoringVolume < numberScoringVolumes &&
iKinematicRegion >= 0 && iKinematicRegion < numberKinematicRegions &&
iParticleType >= 0 && iParticleType < numberParticleTypes ) {
index = iScoringVolume * numberKinematicRegions * numberParticleTypes +
iKinematicRegion * numberParticleTypes +
iParticleType;
if ( iScoringVolume >= 0 && iScoringVolume < fkNumberScoringVolumes &&
iKinematicRegion >= 0 && iKinematicRegion < fkNumberKinematicRegions &&
iParticleType >= 0 && iParticleType < fkNumberParticleTypes ) {
index = iScoringVolume * fkNumberKinematicRegions * fkNumberParticleTypes +
iKinematicRegion * fkNumberParticleTypes +
iParticleType;
}
if ( index < 0 || index >= fkNumberCombinations ) {
G4cerr << "SteppingAction::GetIndex : WRONG index=" << index << " set it to 0 !" << G4endl;
index = 0;
}
return index;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
SteppingAction::SteppingAction() :G4UserSteppingAction() {
initialize();
SteppingAction::SteppingAction() : G4UserSteppingAction() {
Initialize();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
SteppingAction::~SteppingAction() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void SteppingAction::initialize() {
void SteppingAction::Initialize() {
// Initialization needed at the beginning of each Run
fPrimaryParticleId = 0;
fPrimaryParticleEnergy = 0.0;
@@ -96,16 +96,16 @@ void SteppingAction::initialize() {
fIsFirstStepInScoringSide = true;
fCubicVolumeScoringUpDown = 1.0;
fCubicVolumeScoringSide = 1.0;
for ( G4int i = 0; i < numberCombinations; ++i ) {
for ( G4int i = 0; i < fkNumberCombinations; ++i ) {
fArraySumStepLengths[i] = 0.0;
}
/*
for ( G4int i = 0; i < numberCombinations; ++i ) fArraySumStepLengths[i] = 999.9;
G4cout << " numberCombinations=" << numberCombinations << G4endl;
for ( G4int i = 0; i < numberScoringVolumes; ++i ) {
for ( G4int j = 0; j < numberKinematicRegions; ++j ) {
for ( G4int k = 0; k < numberParticleTypes; ++k ) {
G4int index = getIndex( i, j, k );
for ( G4int i = 0; i < fkNumberCombinations; ++i ) fArraySumStepLengths[i] = 999.9;
G4cout << " fkNumberCombinations=" << fkNumberCombinations << G4endl;
for ( G4int i = 0; i < fkNumberScoringVolumes; ++i ) {
for ( G4int j = 0; j < fkNumberKinematicRegions; ++j ) {
for ( G4int k = 0; k < fkNumberParticleTypes; ++k ) {
G4int index = GetIndex( i, j, k );
G4cout << "(i, j, k)=(" << i << ", " << j << ", " << k << ") ->" << index;
if ( fArraySumStepLengths[ index ] < 1.0 ) G4cout << " <=== REPEATED!";
else fArraySumStepLengths[ index ] = 0.0;
@@ -113,7 +113,7 @@ void SteppingAction::initialize() {
}
}
}
for ( G4int i = 0; i < numberCombinations; ++i ) {
for ( G4int i = 0; i < fkNumberCombinations; ++i ) {
if ( fArraySumStepLengths[i] > 999.0 ) G4cout << " i=" << i << " NOT COVERED !" << G4endl;
}
*/
@@ -129,9 +129,9 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
fPrimaryParticleEnergy = theStep->GetPreStepPoint()->GetKineticEnergy();
fPrimaryParticleDirection = theStep->GetPreStepPoint()->GetMomentumDirection();
if ( fRunPtr ) {
fRunPtr->setPrimaryParticleId( fPrimaryParticleId );
fRunPtr->setPrimaryParticleEnergy( fPrimaryParticleEnergy );
fRunPtr->setPrimaryParticleDirection( fPrimaryParticleDirection );
fRunPtr->SetPrimaryParticleId( fPrimaryParticleId );
fRunPtr->SetPrimaryParticleEnergy( fPrimaryParticleEnergy );
fRunPtr->SetPrimaryParticleDirection( fPrimaryParticleDirection );
}
fIsFirstStepOfTheEvent = false;
}
@@ -140,7 +140,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInTarget &&
theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "physiLayer" ) {
fTargetMaterialName = theStep->GetPreStepPoint()->GetMaterial()->GetName();
if ( fRunPtr ) fRunPtr->setTargetMaterialName( fTargetMaterialName );
if ( fRunPtr ) fRunPtr->SetTargetMaterialName( fTargetMaterialName );
fIsFirstStepInTarget = false;
}
// Get information on step lengths in the scoring volumes
@@ -150,7 +150,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInScoringUpDown ) {
fCubicVolumeScoringUpDown =
theStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetSolid()->GetCubicVolume();
if ( fRunPtr ) fRunPtr->setCubicVolumeScoringUpDown( fCubicVolumeScoringUpDown );
if ( fRunPtr ) fRunPtr->SetCubicVolumeScoringUpDown( fCubicVolumeScoringUpDown );
fIsFirstStepInScoringUpDown = false;
}
} else if ( theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() == "physiScoringSide" ) {
@@ -158,7 +158,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInScoringSide ) {
fCubicVolumeScoringSide =
theStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetSolid()->GetCubicVolume();
if ( fRunPtr ) fRunPtr->setCubicVolumeScoringSide( fCubicVolumeScoringSide );
if ( fRunPtr ) fRunPtr->SetCubicVolumeScoringSide( fCubicVolumeScoringSide );
fIsFirstStepInScoringSide = false;
}
} else if ( theStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() ==
@@ -167,7 +167,7 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
if ( fIsFirstStepInScoringUpDown ) {
fCubicVolumeScoringUpDown =
theStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetSolid()->GetCubicVolume();
if ( fRunPtr ) fRunPtr->setCubicVolumeScoringUpDown( fCubicVolumeScoringUpDown );
if ( fRunPtr ) fRunPtr->SetCubicVolumeScoringUpDown( fCubicVolumeScoringUpDown );
fIsFirstStepInScoringUpDown = false;
}
}
@@ -214,18 +214,18 @@ void SteppingAction::UserSteppingAction( const G4Step* theStep ) {
else if ( absPdg > 1000 ) iParticleType = 10; // other baryons (e.g. hyperons, anti-hyperons,
// etc.)
// Consider the specific case : scoring volume, kinematic region and particle type
G4int index = getIndex( iScoringVolume, iKinematicRegion, iParticleType );
G4int index = GetIndex( iScoringVolume, iKinematicRegion, iParticleType );
fArraySumStepLengths[index] += stepLength;
// Consider the "all" particle case, with the same scoring volume and kinematic region
index = getIndex( iScoringVolume, iKinematicRegion, 0 );
index = GetIndex( iScoringVolume, iKinematicRegion, 0 );
fArraySumStepLengths[index] += stepLength;
// Consider the "any" kinematic region case, with the same scoring volume and particle type
index = getIndex( iScoringVolume, 0, iParticleType );
index = GetIndex( iScoringVolume, 0, iParticleType );
fArraySumStepLengths[index] += stepLength;
// Consider the "any" kinematic region and "all" particle, with the same scoring volume
index = getIndex( iScoringVolume, 0, 0 );
index = GetIndex( iScoringVolume, 0, 0 );
fArraySumStepLengths[index] += stepLength;
if ( fRunPtr ) fRunPtr->setArray( fArraySumStepLengths );
if ( fRunPtr ) fRunPtr->SetSteppingArray( fArraySumStepLengths );
}
}
@@ -0,0 +1,143 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file TrackingAction.cc
/// \brief Implementation of the TrackingAction class
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "TrackingAction.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleTypes.hh"
#include "G4IonTable.hh"
#include "G4StepPoint.hh"
#include "G4SystemOfUnits.hh"
#include "Run.hh"
const std::array< G4String, TrackingAction::fkNumberScoringVolumes >
TrackingAction::fkArrayScoringVolumeNames = { "layer" };
const std::array< G4String, TrackingAction::fkNumberKinematicRegions >
TrackingAction::fkArrayKinematicRegionNames = { "", "below 20 MeV", "above 20 MeV" };
const std::array< G4String, TrackingAction::fkNumberParticleTypes >
TrackingAction::fkArrayParticleTypeNames = { "all", "electron", "gamma", "muon", "neutrino",
"pion", "neutron", "proton", "ion", "otherMeson",
"otherBaryon" };
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int TrackingAction::GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType ) {
G4int index = -1;
if ( iScoringVolume >= 0 && iScoringVolume < fkNumberScoringVolumes &&
iKinematicRegion >= 0 && iKinematicRegion < fkNumberKinematicRegions &&
iParticleType >= 0 && iParticleType < fkNumberParticleTypes ) {
index = iScoringVolume * fkNumberKinematicRegions * fkNumberParticleTypes +
iKinematicRegion * fkNumberParticleTypes +
iParticleType;
}
return index;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
TrackingAction::TrackingAction() : G4UserTrackingAction() {
Initialize();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void TrackingAction::Initialize() {
// Initialization needed at the beginning of each Run
fArrayMultiplicities.fill( 0 );
fArraySumKineticEnergies.fill( 0.0 );
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void TrackingAction::PreUserTrackingAction( const G4Track* aTrack ) {
// This method is called not only once when a particle is created,
// but also each time it is resumed, in the case the track gets suspended,
// as it happens in the case of neutrons with _HP Physics Lists.
// To be sure that we collect information about a track one and only once,
// we require that the current step be the first one.
if ( aTrack == nullptr ||
aTrack->GetCurrentStepNumber() != 0 ||
aTrack->GetDefinition() == nullptr ||
aTrack->GetLogicalVolumeAtVertex() == nullptr ||
aTrack->GetLogicalVolumeAtVertex()->GetName() != "logicLayer" ) return;
G4int iScoringVolume = 0;
// Three kinematical regions: [0] : any value ; [1] : below 20 MeV ; [2] : above 20 MeV
G4int iKinematicRegion = aTrack->GetKineticEnergy() < 20.0 ? 1 : 2;
G4int absPdg = std::abs( aTrack->GetDefinition()->GetPDGEncoding() );
G4int iParticleType = -1;
if ( absPdg == 11 ) iParticleType = 1; // electron (and positron)
else if ( absPdg == 22 ) iParticleType = 2; // gamma
else if ( absPdg == 13 ) iParticleType = 3; // muons (mu- and mu+)
else if ( absPdg == 12 || absPdg == 14 || absPdg == 16 ) iParticleType = 4;
// neutrinos (and anti-neutrinos), all flavors
else if ( absPdg == 111 || absPdg == 211 ) iParticleType = 5; // (charged) pions
else if ( absPdg == 2112 ) iParticleType = 6; // neutron (and anti-neutron)
else if ( absPdg == 2212 ) iParticleType = 7; // proton (and anti-proton)
else if ( G4IonTable::IsIon( aTrack->GetDefinition() ) ||
G4IonTable::IsAntiIon( aTrack->GetDefinition() ) ) iParticleType = 8;
// ions (and anti-ions)
else if ( absPdg < 1000 ) iParticleType = 9; // other mesons (e.g. kaons)
// (Note: this works in most cases, but not always!)
else if ( absPdg > 1000 ) iParticleType = 10; // other baryons (e.g. hyperons,
// anti-hyperons, etc.)
// Consider the specific case : scoring volume, kinematic region and particle type
G4int index = GetIndex( iScoringVolume, iKinematicRegion, iParticleType );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
// Consider the "all" particle case, with the same scoring volume and kinematic region
index = GetIndex( iScoringVolume, iKinematicRegion, 0 );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
// Consider the "any" kinematic region case, with the same scoring volume and particle type
index = GetIndex( iScoringVolume, 0, iParticleType );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
// Consider the "any" kinematic region and "all" particle, with the same scoring volume
index = GetIndex( iScoringVolume, 0, 0 );
++fArrayMultiplicities[index];
fArraySumKineticEnergies[index] += aTrack->GetKineticEnergy();
if ( fRunPtr ) {
fRunPtr->SetTrackingArray1( fArrayMultiplicities );
fRunPtr->SetTrackingArray2( fArraySumKineticEnergies );
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void TrackingAction::PostUserTrackingAction( const G4Track* /* aTrack */ ) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
View File
@@ -1,7 +1,7 @@
///\file "hadronic/ParticleFluence/Sphere/.README.txt"
///\brief Example ParticleFluence/Sphere README page
/*! \page ExampeParticleFluenceSphere Example Sphere
/*! \page ExampleSphere Example Sphere
In this example, the particle fluence is evaluated for a very simple
set-up, consisting of one target solid sphere, at the center of which
@@ -16,6 +16,10 @@ The particle fluence is estimated by summing the track length in a
(very low density gas) material, immediately outside the target sphere -
and then dividing for the cubic volume of such scoring volume.
Complementary information on average multiplicity, average kinetic energy,
and average total energy flow (i.e. sum of kinetic energies) for the
particles produced in the target are also computed.
The particle fluence is evaluated for the following 11 particle types:
- all
- electron + positron
@@ -45,14 +49,18 @@ physics list is used).
To build this example:
mkdir Build; cd Build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DGeant4_DIR=/path-to-geant4-libraries ../.
make
\verbatim
mkdir Build; cd Build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DGeant4_DIR=/path-to-geant4-libraries ../.
make
\endverbatim
To run it:
./Sphere all_together.g4
\verbatim
./Sphere all_together.g4
\endverbatim
which shoots 50 GeV pion- on different target materials, 100 events
in each run, and print out some information on the particle fluence
View File
@@ -5,6 +5,12 @@ which **must** added in reverse chronological order (newest at the top). It must
be used as a substitute for writing good git commit messages!
## 2022-09-07 Alberto Ribon (exhadrParticleFluenceSphere-V11-00-02)
- Added complementary information on particle production (multiplicity,
kinetic energy, and total energy flow) in the target.
## 2022-08-26 Alberto Ribon (exhadrParticleFluenceSphere-V11-00-01)
- SteppingAction : introduced protection on the value of the array index.
## 2021-06-10 Alberto Ribon (exhadrParticleFluenceSphere-V11-00-00)
- Created the Sphere variant of the ParticleFluence example.
@@ -11,6 +11,10 @@ The particle fluence is estimated by summing the track length in a
(very low density gas) material, immediately outside the target sphere -
and then dividing for the cubic volume of such scoring volume.
Complementary information on average multiplicity, average kinetic energy,
and average total energy flow (i.e. sum of kinetic energies) for the
particles produced in the target are also computed.
The particle fluence is evaluated for the following 11 particle types:
- all
- electron + positron
View File
File diff suppressed because it is too large Load Diff
View File
View File
View File
View File
@@ -41,9 +41,9 @@
class ActionInitialization : public G4VUserActionInitialization {
public:
ActionInitialization();
virtual ~ActionInitialization();
virtual void BuildForMaster() const override;
virtual void Build() const override;
~ActionInitialization() override = default;
void BuildForMaster() const override;
void Build() const override;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -37,6 +37,7 @@
#include "G4Run.hh"
#include "G4ThreeVector.hh"
#include "SteppingAction.hh"
#include "TrackingAction.hh"
#include <array>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -45,49 +46,64 @@ class Run : public G4Run {
// This class accumulates relevant quantities related to particle fluence collected during
// the run.
// ( Note: these information are provided via calls of accessor methods of this Run class
// made by SteppingAction::UserSteppingAction. )
// At the end of a run, the printInfo method is called by the run-action to print out
// made by SteppingAction::UserSteppingAction
// and TrackingAction::PreUserTrackingAction. )
// At the end of a run, the PrintInfo method is called by the run-action to print out
// some summary information about these quantities.
// In multithreaded (MT) mode, an object of this class is filled up for each working thread,
// and then merged (automatically by the Geant4 kernel) into another object (of this class)
// owned by the master class; the printInfo method is then called only for the latter run
// owned by the master class; the PrintInfo method is then called only for the latter run
// object.
// Note that, for simplicity and brevity, we avoid histograms and print-out instead some
// statistics (compute by ourself) at the end of the run.
public:
Run();
~Run();
~Run() override = default;
virtual void RecordEvent( const G4Event* anEvent ) override;
void RecordEvent( const G4Event* anEvent ) override;
// This method is called automatically by the Geant4 kernel (not by the user!) at the end
// of each event. In the case of multithreaded mode, it is called only for the working thread
// that handled that event.
virtual void Merge( const G4Run* aRun ) override;
void Merge( const G4Run* aRun ) override;
// This method is called automatically by the Geant4 kernel (not by the user!) only in the
// case of multithreaded mode and only for working threads.
void printInfo() const;
void PrintInfo() const;
// This method is called by RunAction::EndOfRunAction : in the case of multithreaded mode,
// only the master thread calls it.
void setPrimaryParticleId( const G4int inputValue ) { fPrimaryParticleId = inputValue; }
void setPrimaryParticleEnergy( const G4double inputValue )
void SetPrimaryParticleId( const G4int inputValue ) { fPrimaryParticleId = inputValue; }
void SetPrimaryParticleEnergy( const G4double inputValue )
{ fPrimaryParticleEnergy = inputValue; }
void setPrimaryParticleDirection( const G4ThreeVector &inputValue )
void SetPrimaryParticleDirection( const G4ThreeVector &inputValue )
{ fPrimaryParticleDirection = inputValue; }
void setTargetMaterialName( const G4String &inputValue ) { fTargetMaterialName = inputValue; }
void setCubicVolumeScoringShell( const G4double inputValue )
void SetTargetMaterialName( const G4String &inputValue ) { fTargetMaterialName = inputValue; }
void SetCubicVolumeScoringShell( const G4double inputValue )
{ fCubicVolumeScoringShell = inputValue; }
G4int getPrimaryParticleId() const { return fPrimaryParticleId; }
G4double getPrimaryParticleEnergy() const { return fPrimaryParticleEnergy; }
G4ThreeVector getPrimaryParticleDirection() const { return fPrimaryParticleDirection; }
G4String getTargetMaterialName() const { return fTargetMaterialName; }
G4double getCubicVolumeScoringShell() const { return fCubicVolumeScoringShell; }
void setArray( const std::array< G4double, SteppingAction::numberCombinations >& inputArray );
std::array< G4double, SteppingAction::numberCombinations > getArray() const { return fArray; }
G4int GetPrimaryParticleId() const { return fPrimaryParticleId; }
G4double GetPrimaryParticleEnergy() const { return fPrimaryParticleEnergy; }
G4ThreeVector GetPrimaryParticleDirection() const { return fPrimaryParticleDirection; }
G4String GetTargetMaterialName() const { return fTargetMaterialName; }
G4double GetCubicVolumeScoringShell() const { return fCubicVolumeScoringShell; }
void SetSteppingArray( const std::array< G4double,
SteppingAction::fkNumberCombinations >& inputArray );
std::array< G4double, SteppingAction::fkNumberCombinations > GetSteppingArray() const
{ return fSteppingArray; }
// Accessor methods useful to transfer information collected by the stepping-action
// into this Run class
// into this Run class
void SetTrackingArray1( const std::array< G4int,
TrackingAction::fkNumberCombinations >& inputArray );
std::array< G4int, TrackingAction::fkNumberCombinations > GetTrackingArray1() const
{ return fTrackingArray1; }
void SetTrackingArray2( const std::array< G4double,
TrackingAction::fkNumberCombinations >& inputArray );
std::array< G4double, TrackingAction::fkNumberCombinations > GetTrackingArray2() const
{ return fTrackingArray2; }
// Accessor methods useful to transfer information collected by the tracking-action
// into this Run class
private:
G4int fNumEvents;
@@ -96,7 +112,9 @@ class Run : public G4Run {
G4ThreeVector fPrimaryParticleDirection;
G4String fTargetMaterialName;
G4double fCubicVolumeScoringShell;
std::array< G4double, SteppingAction::numberCombinations > fArray;
std::array< G4double, SteppingAction::fkNumberCombinations > fSteppingArray;
std::array< G4int, TrackingAction::fkNumberCombinations > fTrackingArray1;
std::array< G4double, TrackingAction::fkNumberCombinations > fTrackingArray2;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+8 -5
View File
@@ -38,18 +38,21 @@
class G4Run;
class SteppingAction;
class TrackingAction;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class RunAction: public G4UserRunAction {
public:
RunAction( SteppingAction* steppingAction = nullptr );
virtual ~RunAction();
virtual void BeginOfRunAction( const G4Run* aRun ) override;
virtual void EndOfRunAction( const G4Run* aRun ) override;
virtual G4Run* GenerateRun() override;
RunAction( SteppingAction* steppingAction = nullptr,
TrackingAction* trackingAction = nullptr );
~RunAction() override = default;
void BeginOfRunAction( const G4Run* aRun ) override;
void EndOfRunAction( const G4Run* aRun ) override;
G4Run* GenerateRun() override;
private:
SteppingAction* fSteppingAction;
TrackingAction* fTrackingAction;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+15 -15
View File
@@ -46,9 +46,9 @@ class Run;
class SteppingAction : public G4UserSteppingAction {
public:
SteppingAction();
virtual ~SteppingAction();
~SteppingAction() override = default;
virtual void UserSteppingAction( const G4Step* ) override;
void UserSteppingAction( const G4Step* ) override;
// This is the main method where the step lengths of particles inside
// the scoring shell are collected, and then the corresponding fluences
// are filled up in the Run object where they are stored (and then
@@ -56,33 +56,33 @@ class SteppingAction : public G4UserSteppingAction {
// (For simplicity and brevity, we avoid histograms and compute instead
// some statistics ourself, which will be print-out at the end of the run.)
void initialize();
void Initialize();
// This method is called by RunAction::BeginOfRunAction for the
// initialization of the stepping-action at the beginning of each Run.
// This is necessary because different runs can have different primary particle
// types, kinetic energies, and detector configurations.
void setRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
void SetRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
// This method is called by RunAction::BeginOfRunAction for providing to the
// stepping-action the pointer to the run object at the beginning of each Run.
// This pointer is then used to pass the information collected by the stepping-action
// to the run object.
G4double getCubicVolumeScoringShell() const { return fCubicVolumeScoringShell; }
G4double GetCubicVolumeScoringShell() const { return fCubicVolumeScoringShell; }
// The cubic-volume of the scoring shell is needed to get the fluence from the
// sum of step lengths inside that scoring shell.
static const G4int numberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int numberScoringPositions = 2; // forward, backward (hemisphere with
static const G4int fkNumberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int fkNumberScoringPositions = 2; // forward, backward (hemisphere with
// respect to the primary particle direction)
static const G4int numberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
static const G4int fkNumberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
// other-mesons, other-baryons
static const G4int numberCombinations =
numberKinematicRegions*numberScoringPositions*numberParticleTypes;
static const std::array< G4String, numberKinematicRegions > arrayKinematicRegionNames;
static const std::array< G4String, numberScoringPositions > arrayScoringPositionNames;
static const std::array< G4String, numberParticleTypes > arrayParticleTypeNames;
static G4int getIndex( const G4int iKinematicRegion, const G4int iScoringPosition,
static const G4int fkNumberCombinations =
fkNumberKinematicRegions*fkNumberScoringPositions*fkNumberParticleTypes;
static const std::array< G4String, fkNumberKinematicRegions > fkArrayKinematicRegionNames;
static const std::array< G4String, fkNumberScoringPositions > fkArrayScoringPositionNames;
static const std::array< G4String, fkNumberParticleTypes > fkArrayParticleTypeNames;
static G4int GetIndex( const G4int iKinematicRegion, const G4int iScoringPosition,
const G4int iParticleType );
private:
@@ -96,7 +96,7 @@ class SteppingAction : public G4UserSteppingAction {
G4bool fIsFirstStepInScoringShell;
G4double fCubicVolumeScoringShell;
std::array< G4double, numberCombinations > fArraySumStepLengths;
std::array< G4double, fkNumberCombinations > fArraySumStepLengths;
// Array to collect the sum of step lengths in the scoring shell for the whole run,
// according to the various cases (kinematical region, scoring position and particle type).
// Note that the fluence in a scoring volume is defined as sum of step lengths
@@ -0,0 +1,92 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/// \file TrackingAction.hh
/// \brief Definition of the TrackingAction class
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef TrackingAction_h
#define TrackingAction_h 1
#include "globals.hh"
#include "G4UserTrackingAction.hh"
#include <array>
class Run;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class TrackingAction : public G4UserTrackingAction {
// We are using this class to monitor the average multiplicity, the average
// kinetic energy, and the average total energy flow (i.e. sum of the
// kinetic energies) of different particle types as they are produced
// inside the target sphere.
// The aim is then to try to correlate some changes in these (more primitive)
// quantities with the observed changes in the (more indirect and complex)
// particle fluences.
public:
TrackingAction();
~TrackingAction() override = default;
void PreUserTrackingAction( const G4Track* ) override;
void PostUserTrackingAction( const G4Track* ) override;
void Initialize();
// This method is called by RunAction::BeginOfRunAction for the
// initialization of the tracking-action at the beginning of each Run.
void SetRunPointer( Run* inputValue = nullptr ) { fRunPtr = inputValue; }
// This method is called by RunAction::BeginOfRunAction for providing to the
// tracking-action the pointer to the run object at the beginning of each Run.
// This pointer is then used to pass the information collected by the tracking-action
// to the run object.
static const G4int fkNumberScoringVolumes = 1; // only the target sphere
static const G4int fkNumberKinematicRegions = 3; // all, below 20 MeV, above 20 MeV
static const G4int fkNumberParticleTypes = 11; // all, e, gamma, mu, nu, pi, n, p, ions,
// other-mesons, other-baryons
static const G4int fkNumberCombinations =
fkNumberScoringVolumes*fkNumberKinematicRegions*fkNumberParticleTypes;
static const std::array< G4String, fkNumberScoringVolumes > fkArrayScoringVolumeNames;
static const std::array< G4String, fkNumberKinematicRegions > fkArrayKinematicRegionNames;
static const std::array< G4String, fkNumberParticleTypes > fkArrayParticleTypeNames;
static G4int GetIndex( const G4int iScoringVolume, const G4int iKinematicRegion,
const G4int iParticleType );
private:
Run* fRunPtr; // Pointer to the Run object
std::array< G4int, fkNumberCombinations > fArrayMultiplicities;
std::array< G4double, fkNumberCombinations > fArraySumKineticEnergies;
// Keep record of the number of particles and their kinetic energy at production,
// according to the particle type and their kinetic energy range (below/above 20 MeV).
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

Some files were not shown because too many files have changed in this diff Show More