Import Geant4 10.7.0 source tree

This commit is contained in:
Gabriele Cosmo
2020-12-04 12:30:43 +01:00
parent 67ba86d073
commit dab42d2018
3770 changed files with 226369 additions and 286486 deletions
@@ -0,0 +1,55 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03ActionInitialisation.hh"
#include "Par03PrimaryGeneratorAction.hh"
#include "Par03EventAction.hh"
#include "Par03RunAction.hh"
Par03ActionInitialisation::Par03ActionInitialisation(
Par03DetectorConstruction* aDetector)
: G4VUserActionInitialization()
, fDetector(aDetector)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03ActionInitialisation::~Par03ActionInitialisation() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03ActionInitialisation::BuildForMaster() const
{
SetUserAction(new Par03RunAction(fDetector));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03ActionInitialisation::Build() const
{
SetUserAction(new Par03PrimaryGeneratorAction());
SetUserAction(new Par03EventAction(fDetector));
SetUserAction(new Par03RunAction(fDetector));
}
@@ -0,0 +1,284 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03DetectorConstruction.hh"
#include "Par03DetectorMessenger.hh"
#include "Par03SensitiveDetector.hh"
#include "Par03EMShowerModel.hh"
#include "G4NistManager.hh"
#include "G4Material.hh"
#include "G4Box.hh"
#include "G4Tubs.hh"
#include "G4LogicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4PVReplica.hh"
#include "G4VisAttributes.hh"
#include "G4RunManager.hh"
#include "G4SDManager.hh"
#include "G4UnitsTable.hh"
#include "G4Region.hh"
#include "G4RegionStore.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03DetectorConstruction::Par03DetectorConstruction()
: G4VUserDetectorConstruction()
{
fDetectorMessenger = new Par03DetectorMessenger(this);
G4NistManager* nistManager = G4NistManager::Instance();
fDetectorMaterial = nistManager->FindOrBuildMaterial("G4_Fe");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03DetectorConstruction::~Par03DetectorConstruction() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VPhysicalVolume* Par03DetectorConstruction::Construct()
{
//--------- Material definition ---------
G4NistManager* nistManager = G4NistManager::Instance();
G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR");
//--------- Derived dimensions ---------
G4double full2Pi = 2. * CLHEP::pi * rad;
G4double layerThickness = fDetectorLength / fNbOfLayers;
G4double cellPhi = full2Pi / fNbOfPhiCells;
G4double cellDR = fDetectorRadius / fNbOfRhoCells;
//--------- World ---------
auto fSolidWorld = new G4Box("World", // name
fWorldSize / 2., // half-width in X
fWorldSize / 2., // half-width in Y
fWorldSize / 2.); // half-width in Z
auto fLogicWorld = new G4LogicalVolume(fSolidWorld, // solid
air, // material
"World"); // name
auto fPhysicWorld = new G4PVPlacement(0, // no rotation
G4ThreeVector(), // at (0,0,0)
fLogicWorld, // logical volume
"World", // name
0, // mother volume
false, // not used
999, // copy number
true); // copy number
//--------- Detector envelope ---------
auto fSolidDetector = new G4Tubs("Detector", // name
0, // inner radius
fDetectorRadius, // outer radius
fDetectorLength / 2., // half-width in Z
0, // start angle
full2Pi); // delta angle
auto fLogicDetector = new G4LogicalVolume(fSolidDetector, // solid
fDetectorMaterial, // material
"Detector"); // name
new G4PVPlacement(
0, // no rotation
G4ThreeVector(0, 0,
fDetectorLength / 2), // detector face starts at (0,0,0)
fLogicDetector, // logical volume
"Detector", // name
fLogicWorld, // mother volume
false, // not used
99, // copy number
true); // check overlaps
// Region for fast simulation
auto detectorRegion = new G4Region("DetectorRegion");
detectorRegion->AddRootLogicalVolume(fLogicDetector);
//--------- Readout geometry ---------
// Layers (along z)
auto fSolidLayer = new G4Tubs("Layer", // name
0, // inner radius
fDetectorRadius, // outer radius
layerThickness / 2., // half-width in Z
0, // start angle
full2Pi); // delta angle
auto fLogicLayer = new G4LogicalVolume(fSolidLayer, // solid
air, // material
"Layer"); // name
if(fNbOfLayers > 1)
new G4PVReplica("Layer", // name
fLogicLayer, // logical volume
fLogicDetector, // mother volume
kZAxis, // axis of replication
fNbOfLayers, // number of replicas
layerThickness); // width of single replica
else
new G4PVPlacement(0, // no rotation
G4ThreeVector(), // place at centre of mother volume
fLogicLayer, // logical volume
"Layer", // name
fLogicDetector, // mother volume
false, // not used
0, // copy number
true); // check overlaps
// Layer segment (division in phi)
auto fSolidRow = new G4Tubs("Row", // name
0, // inner radius
fDetectorRadius, // outer radius
layerThickness / 2., // half-width in Z
0, // start angle
cellPhi); // delta angle
auto fLogicRow = new G4LogicalVolume(fSolidRow, // solid
air, // material
"Segment"); // name
if(fNbOfPhiCells > 1)
new G4PVReplica("Segment", // name
fLogicRow, // logical volume
fLogicLayer, // mother volume
kPhi, // axis of replication
fNbOfPhiCells, // number of replicas
cellPhi); // width of single replica
else
new G4PVPlacement(0, // no rotation
G4ThreeVector(), // place at centre of mother volume
fLogicRow, // logical volume
"Row", // name
fLogicLayer, // mother volume
false, // not used
0, // copy number
true); // check overlaps
// Final cells (segment slices in radius)
// No volume can be placed inside a radial replication
auto fSolidCell = new G4Tubs("Cell", // name
0, // inner radius
cellDR, // outer radius
layerThickness / 2., // half-width in Z
0, // start angle
cellPhi); // delta angle
fLogicCell = new G4LogicalVolume(fSolidCell, // solid
fDetectorMaterial, // material
"Cell"); // name
if(fNbOfRhoCells > 1)
new G4PVReplica("Cell", // name
fLogicCell, // logical volume
fLogicRow, // mother volume
kRho, // axis of replication
fNbOfRhoCells, // number of replicas
cellDR); // width of single replica
else
new G4PVPlacement(0, // no rotation
G4ThreeVector(), // place at centre of mother volume
fLogicCell, // logical volume
"Cell", // name
fLogicRow, // mother volume
false, // not used
0, // copy number
true); // check overlaps
//--------- Visualisation settings ---------
fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
fLogicLayer->SetVisAttributes(G4VisAttributes::GetInvisible());
fLogicRow->SetVisAttributes(G4VisAttributes::GetInvisible());
G4VisAttributes attribs;
attribs.SetColour(G4Colour(0, 0, 1, 0.3));
attribs.SetForceSolid(true);
fLogicCell->SetVisAttributes(attribs);
Print();
return fPhysicWorld;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03DetectorConstruction::ConstructSDandField()
{
Par03SensitiveDetector* caloSD = new Par03SensitiveDetector(
"sensitiveDetector", fNbOfLayers, fNbOfPhiCells, fNbOfRhoCells);
G4SDManager::GetSDMpointer()->AddNewDetector(caloSD);
SetSensitiveDetector(fLogicCell, caloSD);
auto detectorRegion =
G4RegionStore::GetInstance()->GetRegion("DetectorRegion");
new Par03EMShowerModel("model", detectorRegion);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03DetectorConstruction::Print() const
{
G4cout << "\n------------------------------------------------------"
<< "\n--- Detector material:\t" << fDetectorMaterial->GetName()
<< "\n--- Detector length:\t" << G4BestUnit(fDetectorLength, "Length")
<< "\n--- Detector radius:\t" << G4BestUnit(fDetectorRadius, "Length")
<< "\n--- Number of layers:\t" << fNbOfLayers
<< "\n--- Number of R-cells:\t" << fNbOfRhoCells
<< "\n--- Number of phi-cells:\t" << fNbOfPhiCells << G4endl;
G4cout << "-----------------------------------------------------" << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03DetectorConstruction::SetMaterial(const G4String& aName)
{
// search material by its name
G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(aName);
if(material)
fDetectorMaterial = material;
else
G4Exception("Par03DetectorConstruction::SetMaterial()", "InvalidSetup",
FatalException, ("Unknown material name: " + aName).c_str());
G4RunManager::GetRunManager()->PhysicsHasBeenModified();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03DetectorConstruction::SetRadius(G4double aRadius)
{
// check if fits within world volume
if(aRadius >= fWorldSize / 2.)
G4Exception("Par03DetectorConstruction::SetRadius()", "InvalidSetup",
FatalException,
("Detector radius cannot be larger than the world size (" +
G4String(G4BestUnit(fWorldSize / 2., "Length")) + ")")
.c_str());
fDetectorRadius = aRadius;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03DetectorConstruction::SetLength(G4double aLength)
{
// check if fits within world volume
if(aLength >= fWorldSize / 2.)
G4Exception("Par03DetectorConstruction::SetLength()", "InvalidSetup",
FatalException,
("Detector length cannot be larger than the world size (" +
G4String(G4BestUnit(fWorldSize / 2., "Length")) + ")")
.c_str());
fDetectorLength = aLength;
}
@@ -0,0 +1,184 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03DetectorMessenger.hh"
#include "Par03DetectorConstruction.hh"
#include "G4UIdirectory.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithAString.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03DetectorMessenger::Par03DetectorMessenger(
Par03DetectorConstruction* aDetector)
: G4UImessenger()
, fDetector(aDetector)
{
fExampleDir = new G4UIdirectory("/Par03/");
fExampleDir->SetGuidance("UI commands specific to this example");
fDetectorDir = new G4UIdirectory("/Par03/detector/");
fDetectorDir->SetGuidance("Detector construction UI commands");
fPrintCmd = new G4UIcmdWithoutParameter("/Par03/detector/print", this);
fPrintCmd->SetGuidance("Print current settings.");
fDetectorRadiusCmd =
new G4UIcmdWithADoubleAndUnit("/Par03/detector/setDetectorRadius", this);
fDetectorRadiusCmd->SetGuidance(
"Set tranverse size of the detector (cylinder radius)");
fDetectorRadiusCmd->SetParameterName("Size", false);
fDetectorRadiusCmd->SetRange("Size>0.");
fDetectorRadiusCmd->SetUnitCategory("Length");
fDetectorRadiusCmd->AvailableForStates(G4State_PreInit);
fDetectorRadiusCmd->SetToBeBroadcasted(false);
fDetectorLengthCmd =
new G4UIcmdWithADoubleAndUnit("/Par03/detector/setDetectorLength", this);
fDetectorLengthCmd->SetGuidance(
"Set length of the detector (cylinder length)");
fDetectorLengthCmd->SetParameterName("Size", false);
fDetectorLengthCmd->SetRange("Size>0.");
fDetectorLengthCmd->SetUnitCategory("Length");
fDetectorLengthCmd->AvailableForStates(G4State_PreInit);
fDetectorLengthCmd->SetToBeBroadcasted(false);
fDetectorMaterialCmd =
new G4UIcmdWithAString("/Par03/detector/setDetectorMaterial", this);
fDetectorMaterialCmd->SetGuidance("Material of the detector.");
fDetectorMaterialCmd->SetParameterName("Name", false);
fDetectorMaterialCmd->AvailableForStates(G4State_PreInit);
fDetectorMaterialCmd->SetToBeBroadcasted(false);
fNbLayersCmd =
new G4UIcmdWithAnInteger("/Par03/detector/setNbOfLayers", this);
fNbLayersCmd->SetGuidance("Set number of layers.");
fNbLayersCmd->SetParameterName("NbLayers", false);
fNbLayersCmd->SetRange("NbLayers>0");
fNbLayersCmd->AvailableForStates(G4State_PreInit);
fNbLayersCmd->SetToBeBroadcasted(false);
fNbRhoCellsCmd =
new G4UIcmdWithAnInteger("/Par03/detector/setNbOfRhoCells", this);
fNbRhoCellsCmd->SetGuidance("Set number of cells along radius.");
fNbRhoCellsCmd->SetParameterName("NbRhoCells", false);
fNbRhoCellsCmd->SetRange("NbRhoCells>0");
fNbRhoCellsCmd->AvailableForStates(G4State_PreInit);
fNbRhoCellsCmd->SetToBeBroadcasted(false);
fNbPhiCellsCmd =
new G4UIcmdWithAnInteger("/Par03/detector/setNbOfPhiCells", this);
fNbPhiCellsCmd->SetGuidance("Set number of cells in azimuthal angle.");
fNbPhiCellsCmd->SetParameterName("NbPhiCells", false);
fNbPhiCellsCmd->SetRange("NbPhiCells>0");
fNbPhiCellsCmd->AvailableForStates(G4State_PreInit);
fNbPhiCellsCmd->SetToBeBroadcasted(false);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03DetectorMessenger::~Par03DetectorMessenger()
{
delete fPrintCmd;
delete fDetectorRadiusCmd;
delete fDetectorLengthCmd;
delete fDetectorMaterialCmd;
delete fNbLayersCmd;
delete fNbRhoCellsCmd;
delete fNbPhiCellsCmd;
delete fDetectorDir;
delete fExampleDir;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03DetectorMessenger::SetNewValue(G4UIcommand* aCommand,
G4String aNewValue)
{
if(aCommand == fPrintCmd)
{
fDetector->Print();
}
else if(aCommand == fDetectorRadiusCmd)
{
fDetector->SetRadius(fDetectorRadiusCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fDetectorLengthCmd)
{
fDetector->SetLength(fDetectorRadiusCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fDetectorMaterialCmd)
{
fDetector->SetMaterial(aNewValue);
}
else if(aCommand == fNbLayersCmd)
{
fDetector->SetNbOfLayers(fNbLayersCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fNbRhoCellsCmd)
{
fDetector->SetNbOfRhoCells(fNbRhoCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fNbPhiCellsCmd)
{
fDetector->SetNbOfPhiCells(fNbPhiCellsCmd->GetNewIntValue(aNewValue));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4String Par03DetectorMessenger::GetCurrentValue(G4UIcommand* aCommand)
{
G4String cv;
if(aCommand == fDetectorRadiusCmd)
{
cv = fDetectorRadiusCmd->ConvertToString(fDetector->GetRadius(), "mm");
}
else if(aCommand == fDetectorLengthCmd)
{
cv = fDetectorLengthCmd->ConvertToString(fDetector->GetLength(), "mm");
}
else if(aCommand == fDetectorMaterialCmd)
{
cv = fDetector->GetMaterial();
}
else if(aCommand == fNbLayersCmd)
{
cv = fNbLayersCmd->ConvertToString(fDetector->GetNbOfLayers());
}
else if(aCommand == fNbPhiCellsCmd)
{
cv = fNbPhiCellsCmd->ConvertToString(fDetector->GetNbOfPhiCells());
}
else if(aCommand == fNbRhoCellsCmd)
{
cv = fNbRhoCellsCmd->ConvertToString(fDetector->GetNbOfRhoCells());
}
return cv;
}
@@ -0,0 +1,147 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03EMShowerModel.hh"
#include "Par03EMShowerMessenger.hh"
#include "G4UIdirectory.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithADouble.hh"
#include "G4UIcmdWithAnInteger.hh"
Par03EMShowerMessenger::Par03EMShowerMessenger(Par03EMShowerModel* aModel)
: fModel(aModel)
{
fDirectory = new G4UIdirectory("/Par03/fastSim/");
fDirectory->SetGuidance(
"Set mesh parameters for the example fast sim model.");
fPrintCmd = new G4UIcmdWithoutParameter("/Par03/fastSim/print", this);
fPrintCmd->SetGuidance("Print current settings.");
fSigmaCmd = new G4UIcmdWithADoubleAndUnit(
"/Par03/fastSim/transverseProfile/sigma", this);
fSigmaCmd->SetGuidance("Set sigma parameter of 2D Gaussian distribution.");
fSigmaCmd->SetParameterName("Sigma", false);
fSigmaCmd->SetUnitCategory("Length");
fAlphaCmd =
new G4UIcmdWithADouble("/Par03/fastSim/longitudinalProfile/alpha", this);
fAlphaCmd->SetGuidance("Set alpha parameter of Gamma distribution.");
fAlphaCmd->SetParameterName("Alpha", false);
fBetaCmd =
new G4UIcmdWithADouble("/Par03/fastSim/longitudinalProfile/beta", this);
fBetaCmd->SetGuidance("Set beta parameter of Gamma distribution.");
fBetaCmd->SetParameterName("Beta", false);
fNbOfHitsCmd = new G4UIcmdWithAnInteger("/Par03/fastSim/numberOfHits", this);
fNbOfHitsCmd->SetGuidance(
"Set number of (same energy) energy deposits created in fast simulation. "
"Those deposits will be scored in the detector according to the readout of "
"the sensitive detector.");
fNbOfHitsCmd->SetParameterName("Number", false);
fLongMaxDepthCmd =
new G4UIcmdWithADouble("/Par03/fastSim/longitudinalProfile/maxDepth", this);
fLongMaxDepthCmd->SetGuidance(
"Set maximum shower depth used in parametrisation.");
fLongMaxDepthCmd->SetGuidance("Expressed in units of radiation length.");
fLongMaxDepthCmd->SetParameterName("Depth", false);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03EMShowerMessenger::~Par03EMShowerMessenger()
{
delete fPrintCmd;
delete fSigmaCmd;
delete fAlphaCmd;
delete fBetaCmd;
delete fNbOfHitsCmd;
delete fLongMaxDepthCmd;
delete fDirectory;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03EMShowerMessenger::SetNewValue(G4UIcommand* aCommand,
G4String aNewValues)
{
if(aCommand == fPrintCmd)
{
fModel->Print();
}
else if(aCommand == fSigmaCmd)
{
fModel->SetSigma(fSigmaCmd->GetNewDoubleValue(aNewValues));
}
else if(aCommand == fAlphaCmd)
{
fModel->SetAlpha(fAlphaCmd->GetNewDoubleValue(aNewValues));
}
else if(aCommand == fBetaCmd)
{
fModel->SetBeta(fBetaCmd->GetNewDoubleValue(aNewValues));
}
else if(aCommand == fNbOfHitsCmd)
{
fModel->SetNbOfHits(fNbOfHitsCmd->GetNewIntValue(aNewValues));
}
else if(aCommand == fLongMaxDepthCmd)
{
fModel->SetLongMaxDepth(fLongMaxDepthCmd->GetNewDoubleValue(aNewValues));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4String Par03EMShowerMessenger::GetCurrentValue(G4UIcommand* aCommand)
{
G4String cv;
if(aCommand == fSigmaCmd)
{
cv = fSigmaCmd->ConvertToString(fModel->GetSigma());
}
else if(aCommand == fAlphaCmd)
{
cv = fAlphaCmd->ConvertToString(fModel->GetAlpha());
}
else if(aCommand == fBetaCmd)
{
cv = fBetaCmd->ConvertToString(fModel->GetBeta());
}
else if(aCommand == fNbOfHitsCmd)
{
cv = fNbOfHitsCmd->ConvertToString(fModel->GetNbOfHits());
}
else if(aCommand == fLongMaxDepthCmd)
{
cv = fLongMaxDepthCmd->ConvertToString(fModel->GetLongMaxDepth());
}
return cv;
}
@@ -0,0 +1,212 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03EMShowerModel.hh"
#include "Par03EMShowerMessenger.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4Gamma.hh"
#include "G4SystemOfUnits.hh"
#include "G4UnitsTable.hh"
#include "G4FastHit.hh"
#include "Randomize.hh"
#include "G4FastSimHitMaker.hh"
Par03EMShowerModel::Par03EMShowerModel(G4String aModelName, G4Region* aEnvelope)
: G4VFastSimulationModel(aModelName, aEnvelope)
, fMessenger(new Par03EMShowerMessenger(this))
, fHitMaker(new G4FastSimHitMaker)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03EMShowerModel::Par03EMShowerModel(G4String aModelName)
: G4VFastSimulationModel(aModelName)
, fMessenger(new Par03EMShowerMessenger(this))
, fHitMaker(new G4FastSimHitMaker)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03EMShowerModel::~Par03EMShowerModel() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par03EMShowerModel::IsApplicable(
const G4ParticleDefinition& aParticleType)
{
return &aParticleType == G4Electron::ElectronDefinition() ||
&aParticleType == G4Positron::PositronDefinition() ||
&aParticleType == G4Gamma::GammaDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par03EMShowerModel::ModelTrigger(const G4FastTrack& aFastTrack)
{
// Check energy
if(aFastTrack.GetPrimaryTrack()->GetKineticEnergy() < 1 * GeV)
{
return false;
}
// Check length of detector
// Calculate depth of the detector along shower axis to verify if shower
// will fit inside. Required max shower depth is defined by fLongMaxDepth, and
// can be changed with UI command `/Par03/fastSim/longitudinalProfile/maxDepth
G4double X0 = aFastTrack.GetPrimaryTrack()->GetMaterial()->GetRadlen();
auto particleDirection = aFastTrack.GetPrimaryTrackLocalDirection();
auto particlePosition = aFastTrack.GetPrimaryTrackLocalPosition();
G4double detectorDepthInMM = aFastTrack.GetEnvelopeSolid()->DistanceToOut(
particlePosition, particleDirection);
G4double detectorDepthInX0 = detectorDepthInMM / X0;
// check if detector depth is sufficient to create showers
if(detectorDepthInX0 < fLongMaxDepth)
{
return false;
}
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03EMShowerModel::DoIt(const G4FastTrack& aFastTrack,
G4FastStep& aFastStep)
{
// Remove particle from further processing by G4
aFastStep.KillPrimaryTrack();
aFastStep.SetPrimaryTrackPathLength(0.0);
G4double energy = aFastTrack.GetPrimaryTrack()->GetKineticEnergy();
// No need to create any deposit, it will be handled by this model (and
// G4FastSimHitMaker that will call the sensitive detector)
aFastStep.SetTotalEnergyDeposited(0);
auto particlePosition = aFastTrack.GetPrimaryTrackLocalPosition();
auto particleDirection = aFastTrack.GetPrimaryTrackLocalDirection();
// Calculate how to create energy deposits
// Following PDG 33.5 chapter
// material calculation assumes homogeneous detector (true for Par03 example)
auto material = aFastTrack.GetPrimaryTrack()->GetMaterial();
G4double materialX0 = material->GetRadlen();
G4double materialZ = material->GetZ();
// EC estimation follows PDG fit to solids in Fig. 33.14 (rms 2.2%)
G4double materialEc = 610 * MeV / (materialZ + 1.24);
// RM estimation follows PDG Eq. (33.37) (rms 2.2%)
G4double materialRM = 21.2052 * MeV * materialX0 / materialEc;
G4double particleY = energy / materialEc;
// Estimate shower maximum and alpha parameter of Gamma distribution
// that describes the longitudinal profile (PDG Eq. (33.35))
// unless alpha is specified by UI command
if(fAlpha < 0)
{
// from PDG Eq. (33.36)
G4double particleTmax = std::log(particleY);
if(aFastTrack.GetPrimaryTrack()->GetParticleDefinition() ==
G4Gamma::GammaDefinition())
{
particleTmax += 0.5;
}
else
{
particleTmax -= 0.5;
}
fAlpha = particleTmax * fBeta + 1;
}
// Unless sigma of Gaussian distribution describing the transverse profile
// is specified by UI command, use value calculated from Moliere Radius
if(fSigma < 0)
{
// 90% of shower is contained within 1 * R_M
// 1.645 * std dev of Gaussian contains 90%
fSigma = materialRM / 1.645;
}
// Calculate rotation matrix along the particle momentum direction
// It will rotate the shower axes to match the incoming particle direction
G4RotationMatrix rotMatrix = G4RotationMatrix();
double particleTheta = particleDirection.theta();
double particlePhi = particleDirection.phi();
double epsilon = 1e-3;
rotMatrix.rotateY(particleTheta);
// do not use (random) phi if x==y==0
if(!(std::fabs(particleDirection.x()) < epsilon &&
std::fabs(particleDirection.y()) < epsilon))
rotMatrix.rotateZ(particlePhi);
// Create hits
// First use rejecton sampling to sample from Gamma distribution
// then get random numbers from uniform distribution for azimuthal angle, and
// from Gaussian for radius
G4ThreeVector position;
G4double gammaMax = gamma((fAlpha - 1) / fBeta, fAlpha, fBeta);
G4int generatedHits = 0;
while(generatedHits < fNbOfHits)
{
G4double random1 = G4UniformRand() * fLongMaxDepth;
G4double random2 = G4UniformRand() * gammaMax;
if(gamma(random1, fAlpha, fBeta) >= random2)
{
// Generate corresponding rho (phi) from Gaussian (flat) distribution
G4double phiPosition = G4UniformRand() * 2 * CLHEP::pi;
G4double rhoPosition = G4RandGauss::shoot(0, fSigma);
position = particlePosition +
rotMatrix * G4ThreeVector(rhoPosition * std::sin(phiPosition),
rhoPosition * std::cos(phiPosition),
random1 * materialX0);
// Create energy deposit in the detector
// This will call appropriate sensitive detector class
fHitMaker->make(G4FastHit(position, energy / fNbOfHits), aFastTrack);
generatedHits++;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03EMShowerModel::Print() const
{
G4cout << "Par03EMShowerModel: " << G4endl;
G4cout << "Gaussian distribution (transverse plane): \tmu = 0, sigma = "
<< G4BestUnit(fSigma, "Length") << G4endl;
if(fSigma < 0)
G4cout << "Negative sigma value means that it will be recalculated "
"from the value of the Moliere radius of the detector material, "
"taking into account that 90% of the area below the Gaussian "
"distribution (from mu - 1.645 sigma to mu + 1.645 sigma) "
"corresponds to area within 1 Moliere radius."
<< G4endl;
G4cout << "Gamma distribution (along shower axis): \talpha = " << fAlpha
<< ", beta = " << fBeta << ", max depth = " << fLongMaxDepth << " X0"
<< G4endl;
if(fAlpha < 0)
G4cout << "Negative alpha value means that it will be recalculated "
"from the critical energy of the detector material, particle "
"type, and beta parameter.\n alpha = beta * T_max, where T_max = "
"ln(E/E_C) + C\n where E is particle energy, E_C is critical "
"energy in the material, and constant C = -0.5 for electrons and "
"0.5 for photons (Eq. (33.36) from PDG)."
<< G4endl;
G4cout << "Number of created energy deposits: " << fNbOfHits << G4endl;
}
@@ -0,0 +1,159 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03EventAction.hh"
#include "Par03Hit.hh"
#include "Par03DetectorConstruction.hh"
#include "g4analysis.hh"
#include "G4SDManager.hh"
#include "G4HCofThisEvent.hh"
#include "G4Event.hh"
#include "G4EventManager.hh"
Par03EventAction::Par03EventAction(Par03DetectorConstruction* aDetector)
: G4UserEventAction()
, fHitCollectionID(-1)
, fTimer()
, fDetector(aDetector)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03EventAction::~Par03EventAction() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03EventAction::BeginOfEventAction(const G4Event*) { fTimer.Start(); }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03EventAction::EndOfEventAction(const G4Event* aEvent)
{
fTimer.Stop();
// Get hits collection ID (only once)
if(fHitCollectionID == -1)
{
fHitCollectionID = G4SDManager::GetSDMpointer()->GetCollectionID("hits");
}
// Get hits collection
auto hitsCollection = static_cast<Par03HitsCollection*>(
aEvent->GetHCofThisEvent()->GetHC(fHitCollectionID));
if(hitsCollection == nullptr)
{
G4ExceptionDescription msg;
msg << "Cannot access hitsCollection ID " << fHitCollectionID;
G4Exception("Par03EventAction::GetHitsCollection()", "MyCode0001",
FatalException, msg);
}
// Get analysis manager
auto analysisManager = G4AnalysisManager::Instance();
// Retrieve only once detector dimensions
if(fCellSizeZ == 0)
{
fCellSizeZ = fDetector->GetLength() / fDetector->GetNbOfLayers();
fCellSizeRho = fDetector->GetRadius() / fDetector->GetNbOfRhoCells();
}
// Retrieve information from primary vertex and primary particle
// To calculate shower axis and entry point to the detector
auto primaryVertex = G4EventManager::GetEventManager()
->GetConstCurrentEvent()
->GetPrimaryVertex();
auto primaryParticle = primaryVertex->GetPrimary(0);
G4double primaryEnergy = primaryParticle->GetTotalEnergy();
// Estimate from vertex and particle direction the entry point to the detector
// Calculate entrance point to the detector located at z = 0
auto primaryDirection = primaryParticle->GetMomentumDirection();
auto primaryEntrance = primaryVertex->GetPosition() -
primaryVertex->GetPosition().z() * primaryDirection;
G4double cosDirection = std::cos(primaryDirection.theta());
G4double sinDirection = std::sin(primaryDirection.theta());
// Fill histograms
Par03Hit* hit = nullptr;
G4double hitEn = 0;
G4double totalEnergy = 0;
G4int hitZ = -1;
G4int hitRho = -1;
G4int hitType = -1;
G4double tDistance = 0., rDistance = 0.;
G4double tFirstMoment = 0., tSecondMoment = 0.;
G4double rFirstMoment = 0., rSecondMoment = 0.;
for(size_t iHit = 0; iHit < hitsCollection->entries(); iHit++)
{
hit = static_cast<Par03Hit*>(hitsCollection->GetHit(iHit));
hitZ = hit->GetZid();
hitRho = hit->GetRhoId();
hitEn = hit->GetEdep();
hitType = hit->GetType();
if(hitEn > 0)
{
totalEnergy += hitEn;
tDistance =
hitZ * fCellSizeZ * cosDirection +
(hitRho * fCellSizeRho - primaryEntrance.perp()) * sinDirection;
rDistance =
hitZ * fCellSizeZ * (-sinDirection) +
(hitRho * fCellSizeRho - primaryEntrance.perp()) * cosDirection;
tFirstMoment += hitEn * tDistance;
rFirstMoment += hitEn * rDistance;
analysisManager->FillH1(4, tDistance, hitEn);
analysisManager->FillH1(5, rDistance, hitEn);
analysisManager->FillH1(10, hitType);
}
}
tFirstMoment /= totalEnergy;
rFirstMoment /= totalEnergy;
analysisManager->FillH1(0, primaryEnergy / GeV);
analysisManager->FillH1(1, totalEnergy / GeV);
analysisManager->FillH1(2, totalEnergy / primaryEnergy);
analysisManager->FillH1(3, fTimer.GetRealElapsed());
analysisManager->FillH1(6, tFirstMoment);
analysisManager->FillH1(7, rFirstMoment);
// Second loop over hits to calculate second moments
for(size_t iHit = 0; iHit < hitsCollection->entries(); iHit++)
{
hit = static_cast<Par03Hit*>(hitsCollection->GetHit(iHit));
hitEn = hit->GetEdep();
hitZ = hit->GetZid();
hitRho = hit->GetRhoId();
if(hitEn > 0)
{
tDistance = hitZ * fCellSizeZ * cosDirection +
(hitRho * fCellSizeRho - primaryEntrance.r()) * sinDirection;
rDistance = hitZ * fCellSizeZ * (-sinDirection) +
(hitRho * fCellSizeRho - primaryEntrance.r()) * cosDirection;
tSecondMoment += hitEn * std::pow(tDistance - tFirstMoment, 2);
rSecondMoment += hitEn * std::pow(rDistance - rFirstMoment, 2);
}
}
tSecondMoment /= totalEnergy;
rSecondMoment /= totalEnergy;
analysisManager->FillH1(8, tSecondMoment);
analysisManager->FillH1(9, rSecondMoment);
}
@@ -0,0 +1,169 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03Hit.hh"
#include "G4VisAttributes.hh"
#include "G4Tubs.hh"
#include "G4Colour.hh"
#include "G4AttDefStore.hh"
#include "G4AttDef.hh"
#include "G4AttValue.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"
#include "G4VVisManager.hh"
#include "G4LogicalVolume.hh"
G4ThreadLocal G4Allocator<Par03Hit>* Par03HitAllocator;
Par03Hit::Par03Hit()
: G4VHit()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03Hit::~Par03Hit() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03Hit::Par03Hit(const Par03Hit& aRight)
: G4VHit()
{
fEdep = aRight.fEdep;
fZId = aRight.fZId;
fRhoId = aRight.fRhoId;
fPhiId = aRight.fPhiId;
fTime = aRight.fTime;
fPos = aRight.fPos;
fRot = aRight.fRot;
fType = aRight.fType;
fLogVol = aRight.fLogVol;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
const Par03Hit& Par03Hit::operator=(const Par03Hit& aRight)
{
fEdep = aRight.fEdep;
fZId = aRight.fZId;
fRhoId = aRight.fRhoId;
fPhiId = aRight.fPhiId;
fTime = aRight.fTime;
fPos = aRight.fPos;
fRot = aRight.fRot;
fType = aRight.fType;
fLogVol = aRight.fLogVol;
return *this;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
int Par03Hit::operator==(const Par03Hit& aRight) const
{
return (fRhoId == aRight.fRhoId && fPhiId == aRight.fPhiId &&
fZId == aRight.fZId);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03Hit::Draw()
{
G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
// Hits can be filtered out in visualisation
if(!pVVisManager->FilterHit(*this))
return;
// Do not draw empty hits
if(fEdep < 0)
return;
if(pVVisManager)
{
G4Transform3D trans(fRot, fPos);
G4VisAttributes attribs;
// Create default dimensions
G4Tubs solid("draw", 0, 1 * cm, 1 * cm, 0, 0.05 * CLHEP::pi);
if(fLogVol)
{
const G4VisAttributes* pVA = fLogVol->GetVisAttributes();
if(pVA)
attribs = *pVA;
// Cannot use directly fLogVol due to rho parametrisation (change of
// solid!) Recalculation of radius is needed
solid = *dynamic_cast<G4Tubs*>(fLogVol->GetSolid());
double dR = solid.GetOuterRadius() - solid.GetInnerRadius();
solid.SetInnerRadius(solid.GetInnerRadius() + fRhoId * dR);
solid.SetOuterRadius(solid.GetOuterRadius() + fRhoId * dR);
}
// Set colours depending on type of hit (full/fast sim)
G4double colR = fType == 0 ? 0 : 1;
G4double colG = fType == 0 ? 1 : 0;
G4double colB = 0;
G4Colour colour(colR, colG, colB, 0.5);
attribs.SetColour(colour);
attribs.SetForceSolid(true);
pVVisManager->Draw(solid, attribs, trans);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
const std::map<G4String, G4AttDef>* Par03Hit::GetAttDefs() const
{
G4bool isNew;
std::map<G4String, G4AttDef>* store =
G4AttDefStore::GetInstance("Par03Hit", isNew);
if(isNew)
{
(*store)["HitType"] =
G4AttDef("HitType", "Hit Type", "Physics", "", "G4String");
(*store)["Energy"] = G4AttDef("Energy", "Energy Deposited", "Physics",
"G4BestUnit", "G4double");
(*store)["Time"] =
G4AttDef("Time", "Time", "Physics", "G4BestUnit", "G4double");
(*store)["Pos"] =
G4AttDef("Pos", "Position", "Physics", "G4BestUnit", "G4ThreeVector");
}
return store;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
std::vector<G4AttValue>* Par03Hit::CreateAttValues() const
{
std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
values->push_back(G4AttValue("HitType", "HadPar03Hit", ""));
values->push_back(G4AttValue("Energy", G4BestUnit(fEdep, "Energy"), ""));
values->push_back(G4AttValue("Time", G4BestUnit(fTime, "Time"), ""));
values->push_back(G4AttValue("Pos", G4BestUnit(fPos, "Length"), ""));
return values;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03Hit::Print()
{
std::cout << "\tHit " << fEdep / MeV << " MeV at " << fPos / cm
<< " cm (R,phi,z)= (" << fRhoId << ", " << fPhiId << ", " << fZId
<< "), " << fTime << " ns" << std::endl;
}
@@ -0,0 +1,58 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03PrimaryGeneratorAction.hh"
#include "G4ParticleGun.hh"
#include "G4ParticleTable.hh"
#include "G4SystemOfUnits.hh"
Par03PrimaryGeneratorAction::Par03PrimaryGeneratorAction()
: G4VUserPrimaryGeneratorAction()
, fParticleGun(nullptr)
{
G4int n_particle = 1;
fParticleGun = new G4ParticleGun(n_particle);
// Default particle properties
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
G4String particleName;
G4ParticleDefinition* particle =
particleTable->FindParticle(particleName = "e-");
fParticleGun->SetParticleDefinition(particle);
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0., 0., 1.));
fParticleGun->SetParticleEnergy(10. * GeV);
fParticleGun->SetParticlePosition(G4ThreeVector(0., 0., -10. * cm));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03PrimaryGeneratorAction::~Par03PrimaryGeneratorAction() { delete fParticleGun; }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03PrimaryGeneratorAction::GeneratePrimaries(G4Event* aEvent)
{
fParticleGun->GeneratePrimaryVertex(aEvent);
}
@@ -0,0 +1,117 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03RunAction.hh"
#include "Par03DetectorConstruction.hh"
#include "g4analysis.hh"
Par03RunAction::Par03RunAction(Par03DetectorConstruction* aDetector)
: G4UserRunAction()
, fDetector(aDetector)
{
// Create analysis manager
G4AnalysisManager* analysisManager = G4Analysis::ManagerInstance("root");
// Default filename, can be overriden with /analysis/setFileName
analysisManager->SetFileName("Par03Output");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03RunAction::~Par03RunAction() { delete G4AnalysisManager::Instance(); }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03RunAction::BeginOfRunAction(const G4Run*)
{
// Get detector dimensions
G4int cellNumZ = fDetector->GetNbOfLayers();
G4int cellNumRho = fDetector->GetNbOfRhoCells();
G4double cellSizeZ = fDetector->GetLength() / cellNumZ;
G4double cellSizeRho = fDetector->GetRadius() / cellNumRho;
// Default max value of energy stored in histogram (in GeV)
G4double maxEnergy = 100;
// Get analysis manager
auto analysisManager = G4AnalysisManager::Instance();
// Creating control histograms
analysisManager->CreateH1("energyParticle",
"Primary energy;E_{MC} (GeV);Entries", 256, 0,
1.1 * maxEnergy);
analysisManager->CreateH1("energyDeposited",
"Deposited energy;E_{MC} (GeV);Entries", 256, 0,
1.1 * maxEnergy);
analysisManager->CreateH1(
"energyRatio",
"Ratio of energy deposited to primary;E_{dep} / E_{MC};Entries", 1024, 0,
1);
analysisManager->CreateH1("time", "Simulation time; time (s);Entries", 2048,
0, 30);
analysisManager->CreateH1(
"longProfile", "Longitudinal profile;t (mm);#LTE#GT (MeV)", cellNumZ,
-0.5 * cellSizeZ, (cellNumZ - 0.5) * cellSizeZ);
analysisManager->CreateH1(
"transProfile", "Transverse profile;r (mm);#LTE#GT (MeV)", cellNumRho,
-0.5 * cellSizeRho, (cellNumRho - 0.5) * cellSizeRho);
analysisManager->CreateH1(
"longFirstMoment",
"First moment of longitudinal distribution;#LT#lambda#GT (mm);Entries",
1024, -0.5 * cellSizeZ,
cellNumZ * cellSizeZ / 2); // arbitrary scaling of max value on axis
analysisManager->CreateH1("transFirstMoment",
"First moment of transverse distribution;#LTr#GT "
"(mm);Entries",
1024, -0.5 * cellSizeRho,
cellNumRho * cellSizeRho /
10); // arbitrary scaling of max value on axis
analysisManager->CreateH1(
"longSecondMoment",
"Second moment of longitudinal distribution;#LT#lambda^{2}#GT "
"(mm^{2});Entries",
1024, 0,
std::pow(cellNumZ * cellSizeZ, 2) /
25); // arbitrary scaling of max value on axis
analysisManager->CreateH1(
"transSecondMoment",
"Second moment of transverse distribution;#LTr^{2}#GT (mm^{2});Entries",
1024, 0,
std::pow(cellNumRho * cellSizeRho, 2) /
25); // arbitrary scaling of max value on axis
analysisManager->CreateH1(
"hitType", "hit type;type (0=full, 1= fast);Entries", 2, -0.5, 1.5);
// Open an output file
analysisManager->OpenFile();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03RunAction::EndOfRunAction(const G4Run*)
{
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->Write();
analysisManager->CloseFile();
}
@@ -0,0 +1,172 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#include "Par03SensitiveDetector.hh"
#include "Par03Hit.hh"
#include "G4HCofThisEvent.hh"
#include "G4TouchableHistory.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4SDManager.hh"
Par03SensitiveDetector::Par03SensitiveDetector(G4String aName)
: G4VSensitiveDetector(aName)
{
collectionName.insert("hits");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03SensitiveDetector::Par03SensitiveDetector(G4String aName, G4int aNumLayers,
G4int aNumRho, G4int aNumPhi)
: G4VSensitiveDetector(aName)
, fCellNoZ(aNumLayers)
, fCellNoRho(aNumRho)
, fCellNoPhi(aNumPhi)
{
collectionName.insert("hits");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03SensitiveDetector::~Par03SensitiveDetector() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03SensitiveDetector::Initialize(G4HCofThisEvent* aHCE)
{
fHitsCollection =
new Par03HitsCollection(SensitiveDetectorName, collectionName[0]);
if(fHitCollectionID < 0)
{
fHitCollectionID =
G4SDManager::GetSDMpointer()->GetCollectionID(fHitsCollection);
}
aHCE->AddHitsCollection(fHitCollectionID, fHitsCollection);
// fill calorimeter hits with zero energy deposition
for(G4int iphi = 0; iphi < fCellNoPhi; iphi++)
for(G4int irho = 0; irho < fCellNoRho; irho++)
for(G4int iz = 0; iz < fCellNoZ; iz++)
{
Par03Hit* hit = new Par03Hit();
fHitsCollection->insert(hit);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par03SensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*)
{
G4double edep = aStep->GetTotalEnergyDeposit();
if(edep == 0.)
return true;
G4TouchableHistory* aTouchable =
(G4TouchableHistory*) (aStep->GetPreStepPoint()->GetTouchable());
auto hit = RetrieveAndSetupHit(aTouchable);
// Add energy deposit from G4Step
hit->AddEdep(edep);
// Fill time information from G4Step
// If it's already filled, choose hit with earliest global time
if(hit->GetTime() == -1 ||
hit->GetTime() > aStep->GetTrack()->GetGlobalTime())
hit->SetTime(aStep->GetTrack()->GetGlobalTime());
// Set hit type to full simulation (only if hit is not already marked as fast
// sim)
if(hit->GetType() != 1)
hit->SetType(0);
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par03SensitiveDetector::ProcessHits(const G4FastHit* aHit,
const G4FastTrack* aTrack,
G4TouchableHistory* aTouchable)
{
G4double edep = aHit->GetEnergy();
if(edep == 0.)
return true;
auto hit = RetrieveAndSetupHit(aTouchable);
// Add energy deposit from G4FastHit
hit->AddEdep(edep);
// Fill time information from G4FastTrack
// If it's already filled, choose hit with earliest global time
if(hit->GetTime() == -1 ||
hit->GetTime() > aTrack->GetPrimaryTrack()->GetGlobalTime())
{
hit->SetTime(aTrack->GetPrimaryTrack()->GetGlobalTime());
}
// Set hit type to fast simulation (even if hit was already marked as full
// sim, overwrite it)
hit->SetType(1);
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03Hit* Par03SensitiveDetector::RetrieveAndSetupHit(
G4TouchableHistory* aTouchable)
{
G4int rhoNo = aTouchable->GetCopyNumber(0); // cell
G4int phiNo = aTouchable->GetCopyNumber(1); // segment
G4int zNo = aTouchable->GetCopyNumber(2); // layer
std::size_t hitID = fCellNoRho * fCellNoZ * phiNo + fCellNoZ * rhoNo + zNo;
if(hitID >= fHitsCollection->entries())
{
G4Exception(
"Par03SensitiveDetector::RetrieveAndSetupHit()", "InvalidSetup",
FatalException,
"Size of hit collection in Par03SensitiveDetector is smaller than the "
"number of cells created in Par03DetectorConstruction!");
}
Par03Hit* hit = (*fHitsCollection)[hitID];
if(hit->GetRhoId() < 0)
{
hit->SetRhoId(rhoNo);
hit->SetPhiId(phiNo);
hit->SetZid(zNo);
hit->SetLogV(aTouchable->GetVolume(0)->GetLogicalVolume());
G4AffineTransform transform = aTouchable->GetHistory()->GetTopTransform();
hit->SetRot(transform.NetRotation());
transform.Invert();
hit->SetPos(transform.NetTranslation());
}
return hit;
}