Import Geant4 11.3.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2024-06-28 13:08:51 +02:00
parent f7b23877ed
commit e58e650b32
5232 changed files with 239416 additions and 244360 deletions
@@ -24,14 +24,13 @@
// ********************************************************************
//
#include "Par03ActionInitialisation.hh"
#include "Par03PrimaryGeneratorAction.hh"
#include "Par03EventAction.hh"
#include "Par03PrimaryGeneratorAction.hh"
#include "Par03RunAction.hh"
Par03ActionInitialisation::Par03ActionInitialisation(
Par03DetectorConstruction* aDetector)
: G4VUserActionInitialization()
, fDetector(aDetector)
Par03ActionInitialisation::Par03ActionInitialisation(Par03DetectorConstruction* aDetector)
: G4VUserActionInitialization(), fDetector(aDetector)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -24,36 +24,33 @@
// ********************************************************************
//
#include "Par03DetectorConstruction.hh"
#include "Par03DetectorMessenger.hh"
#include "Par03SensitiveDetector.hh"
#include "Par03EMShowerModel.hh"
#include "G4NistManager.hh"
#include "G4Material.hh"
#include "Par03DetectorMessenger.hh"
#include "Par03EMShowerModel.hh"
#include "Par03SensitiveDetector.hh"
#include "G4Box.hh"
#include "G4Tubs.hh"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
#include "G4NistManager.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"
#include "G4RunManager.hh"
#include "G4SDManager.hh"
#include "G4Tubs.hh"
#include "G4UnitsTable.hh"
#include "G4VisAttributes.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03DetectorConstruction::Par03DetectorConstruction()
: G4VUserDetectorConstruction()
Par03DetectorConstruction::Par03DetectorConstruction() : G4VUserDetectorConstruction()
{
fDetectorMessenger = new Par03DetectorMessenger(this);
G4NistManager* nistManager = G4NistManager::Instance();
fDetectorMaterial = nistManager->FindOrBuildMaterial("G4_Fe");
fDetectorMaterial = nistManager->FindOrBuildMaterial("G4_Fe");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -66,51 +63,50 @@ G4VPhysicalVolume* Par03DetectorConstruction::Construct()
{
//--------- Material definition ---------
G4NistManager* nistManager = G4NistManager::Instance();
G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR");
G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR");
//--------- Derived dimensions ---------
G4double full2Pi = 2. * CLHEP::pi * rad;
G4double full2Pi = 2. * CLHEP::pi * rad;
G4double layerThickness = fDetectorLength / fNbOfLayers;
G4double cellPhi = full2Pi / fNbOfPhiCells;
G4double cellDR = fDetectorRadius / fNbOfRhoCells;
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
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
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 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
"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");
@@ -118,88 +114,88 @@ G4VPhysicalVolume* Par03DetectorConstruction::Construct()
//--------- 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 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
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
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
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
auto fSolidRow = new G4Tubs("Row", // name
0, // inner radius
fDetectorRadius, // outer radius
layerThickness / 2., // half-width in Z
0, // start angle
cellPhi); // delta angle
0, // start angle
cellPhi); // delta angle
auto fLogicRow = new G4LogicalVolume(fSolidRow, // solid
air, // material
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
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
cellPhi); // width of single replica
else
new G4PVPlacement(0, // no rotation
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
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
auto fSolidCell = new G4Tubs("Cell", // name
0, // inner radius
cellDR, // outer radius
layerThickness / 2., // half-width in Z
0, // start angle
cellPhi); // delta angle
0, // start angle
cellPhi); // delta angle
fLogicCell = new G4LogicalVolume(fSolidCell, // solid
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
"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
cellDR); // width of single replica
else
new G4PVPlacement(0, // no rotation
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
fLogicCell, // logical volume
"Cell", // name
fLogicRow, // mother volume
false, // not used
0, // copy number
true); // check overlaps
//--------- Visualisation settings ---------
fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
@@ -218,13 +214,12 @@ G4VPhysicalVolume* Par03DetectorConstruction::Construct()
void Par03DetectorConstruction::ConstructSDandField()
{
Par03SensitiveDetector* caloSD = new Par03SensitiveDetector(
"sensitiveDetector", fNbOfLayers, fNbOfPhiCells, fNbOfRhoCells);
Par03SensitiveDetector* caloSD =
new Par03SensitiveDetector("sensitiveDetector", fNbOfLayers, fNbOfPhiCells, fNbOfRhoCells);
G4SDManager::GetSDMpointer()->AddNewDetector(caloSD);
SetSensitiveDetector(fLogicCell, caloSD);
auto detectorRegion =
G4RegionStore::GetInstance()->GetRegion("DetectorRegion");
auto detectorRegion = G4RegionStore::GetInstance()->GetRegion("DetectorRegion");
new Par03EMShowerModel("model", detectorRegion);
}
@@ -236,9 +231,8 @@ void Par03DetectorConstruction::Print() const
<< "\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;
<< "\n--- Number of layers:\t" << fNbOfLayers << "\n--- Number of R-cells:\t"
<< fNbOfRhoCells << "\n--- Number of phi-cells:\t" << fNbOfPhiCells << G4endl;
G4cout << "-----------------------------------------------------" << G4endl;
}
@@ -248,11 +242,11 @@ void Par03DetectorConstruction::SetMaterial(const G4String& aName)
{
// search material by its name
G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(aName);
if(material)
if (material)
fDetectorMaterial = material;
else
G4Exception("Par03DetectorConstruction::SetMaterial()", "InvalidSetup",
FatalException, ("Unknown material name: " + aName).c_str());
G4Exception("Par03DetectorConstruction::SetMaterial()", "InvalidSetup", FatalException,
("Unknown material name: " + aName).c_str());
G4RunManager::GetRunManager()->PhysicsHasBeenModified();
}
@@ -261,11 +255,10 @@ void Par03DetectorConstruction::SetMaterial(const G4String& aName)
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")) + ")")
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;
}
@@ -274,11 +267,10 @@ void Par03DetectorConstruction::SetRadius(G4double aRadius)
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")) + ")")
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;
}
@@ -24,20 +24,19 @@
// ********************************************************************
//
#include "Par03DetectorMessenger.hh"
#include "Par03DetectorConstruction.hh"
#include "G4UIdirectory.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UIdirectory.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03DetectorMessenger::Par03DetectorMessenger(
Par03DetectorConstruction* aDetector)
: G4UImessenger()
, fDetector(aDetector)
Par03DetectorMessenger::Par03DetectorMessenger(Par03DetectorConstruction* aDetector)
: G4UImessenger(), fDetector(aDetector)
{
fExampleDir = new G4UIdirectory("/Par03/");
fExampleDir->SetGuidance("UI commands specific to this example");
@@ -48,51 +47,43 @@ Par03DetectorMessenger::Par03DetectorMessenger(
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 = 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 = 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 = 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 = 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 = 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 = new G4UIcmdWithAnInteger("/Par03/detector/setNbOfPhiCells", this);
fNbPhiCellsCmd->SetGuidance("Set number of cells in azimuthal angle.");
fNbPhiCellsCmd->SetParameterName("NbPhiCells", false);
fNbPhiCellsCmd->SetRange("NbPhiCells>0");
@@ -117,35 +108,27 @@ Par03DetectorMessenger::~Par03DetectorMessenger()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03DetectorMessenger::SetNewValue(G4UIcommand* aCommand,
G4String aNewValue)
void Par03DetectorMessenger::SetNewValue(G4UIcommand* aCommand, G4String aNewValue)
{
if(aCommand == fPrintCmd)
{
if (aCommand == fPrintCmd) {
fDetector->Print();
}
else if(aCommand == fDetectorRadiusCmd)
{
else if (aCommand == fDetectorRadiusCmd) {
fDetector->SetRadius(fDetectorRadiusCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fDetectorLengthCmd)
{
else if (aCommand == fDetectorLengthCmd) {
fDetector->SetLength(fDetectorRadiusCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fDetectorMaterialCmd)
{
else if (aCommand == fDetectorMaterialCmd) {
fDetector->SetMaterial(aNewValue);
}
else if(aCommand == fNbLayersCmd)
{
else if (aCommand == fNbLayersCmd) {
fDetector->SetNbOfLayers(fNbLayersCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fNbRhoCellsCmd)
{
else if (aCommand == fNbRhoCellsCmd) {
fDetector->SetNbOfRhoCells(fNbRhoCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fNbPhiCellsCmd)
{
else if (aCommand == fNbPhiCellsCmd) {
fDetector->SetNbOfPhiCells(fNbPhiCellsCmd->GetNewIntValue(aNewValue));
}
}
@@ -156,28 +139,22 @@ G4String Par03DetectorMessenger::GetCurrentValue(G4UIcommand* aCommand)
{
G4String cv;
if(aCommand == fDetectorRadiusCmd)
{
if (aCommand == fDetectorRadiusCmd) {
cv = fDetectorRadiusCmd->ConvertToString(fDetector->GetRadius(), "mm");
}
else if(aCommand == fDetectorLengthCmd)
{
else if (aCommand == fDetectorLengthCmd) {
cv = fDetectorLengthCmd->ConvertToString(fDetector->GetLength(), "mm");
}
else if(aCommand == fDetectorMaterialCmd)
{
else if (aCommand == fDetectorMaterialCmd) {
cv = fDetector->GetMaterial();
}
else if(aCommand == fNbLayersCmd)
{
else if (aCommand == fNbLayersCmd) {
cv = fNbLayersCmd->ConvertToString(fDetector->GetNbOfLayers());
}
else if(aCommand == fNbPhiCellsCmd)
{
else if (aCommand == fNbPhiCellsCmd) {
cv = fNbPhiCellsCmd->ConvertToString(fDetector->GetNbOfPhiCells());
}
else if(aCommand == fNbRhoCellsCmd)
{
else if (aCommand == fNbRhoCellsCmd) {
cv = fNbRhoCellsCmd->ConvertToString(fDetector->GetNbOfRhoCells());
}
return cv;
@@ -23,38 +23,34 @@
// * 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"
#include "Par03EMShowerModel.hh"
Par03EMShowerMessenger::Par03EMShowerMessenger(Par03EMShowerModel* aModel)
: fModel(aModel)
#include "G4UIcmdWithADouble.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UIdirectory.hh"
Par03EMShowerMessenger::Par03EMShowerMessenger(Par03EMShowerModel* aModel) : fModel(aModel)
{
fDirectory = new G4UIdirectory("/Par03/fastSim/");
fDirectory->SetGuidance(
"Set mesh parameters for the example fast sim model.");
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 = 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 = 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 = new G4UIcmdWithADouble("/Par03/fastSim/longitudinalProfile/beta", this);
fBetaCmd->SetGuidance("Set beta parameter of Gamma distribution.");
fBetaCmd->SetParameterName("Beta", false);
@@ -65,10 +61,8 @@ Par03EMShowerMessenger::Par03EMShowerMessenger(Par03EMShowerModel* aModel)
"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 = 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);
}
@@ -88,31 +82,24 @@ Par03EMShowerMessenger::~Par03EMShowerMessenger()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03EMShowerMessenger::SetNewValue(G4UIcommand* aCommand,
G4String aNewValues)
void Par03EMShowerMessenger::SetNewValue(G4UIcommand* aCommand, G4String aNewValues)
{
if(aCommand == fPrintCmd)
{
if (aCommand == fPrintCmd) {
fModel->Print();
}
else if(aCommand == fSigmaCmd)
{
else if (aCommand == fSigmaCmd) {
fModel->SetSigma(fSigmaCmd->GetNewDoubleValue(aNewValues));
}
else if(aCommand == fAlphaCmd)
{
else if (aCommand == fAlphaCmd) {
fModel->SetAlpha(fAlphaCmd->GetNewDoubleValue(aNewValues));
}
else if(aCommand == fBetaCmd)
{
else if (aCommand == fBetaCmd) {
fModel->SetBeta(fBetaCmd->GetNewDoubleValue(aNewValues));
}
else if(aCommand == fNbOfHitsCmd)
{
else if (aCommand == fNbOfHitsCmd) {
fModel->SetNbOfHits(fNbOfHitsCmd->GetNewIntValue(aNewValues));
}
else if(aCommand == fLongMaxDepthCmd)
{
else if (aCommand == fLongMaxDepthCmd) {
fModel->SetLongMaxDepth(fLongMaxDepthCmd->GetNewDoubleValue(aNewValues));
}
}
@@ -123,24 +110,19 @@ G4String Par03EMShowerMessenger::GetCurrentValue(G4UIcommand* aCommand)
{
G4String cv;
if(aCommand == fSigmaCmd)
{
if (aCommand == fSigmaCmd) {
cv = fSigmaCmd->ConvertToString(fModel->GetSigma());
}
else if(aCommand == fAlphaCmd)
{
else if (aCommand == fAlphaCmd) {
cv = fAlphaCmd->ConvertToString(fModel->GetAlpha());
}
else if(aCommand == fBetaCmd)
{
else if (aCommand == fBetaCmd) {
cv = fBetaCmd->ConvertToString(fModel->GetBeta());
}
else if(aCommand == fNbOfHitsCmd)
{
else if (aCommand == fNbOfHitsCmd) {
cv = fNbOfHitsCmd->ConvertToString(fModel->GetNbOfHits());
}
else if(aCommand == fLongMaxDepthCmd)
{
else if (aCommand == fLongMaxDepthCmd) {
cv = fLongMaxDepthCmd->ConvertToString(fModel->GetLongMaxDepth());
}
return cv;
@@ -24,29 +24,30 @@
// ********************************************************************
//
#include "Par03EMShowerModel.hh"
#include "Par03EMShowerMessenger.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4FastHit.hh"
#include "G4FastSimHitMaker.hh"
#include "G4Gamma.hh"
#include "G4Positron.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)
: 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)
: G4VFastSimulationModel(aModelName),
fMessenger(new Par03EMShowerMessenger(this)),
fHitMaker(new G4FastSimHitMaker)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -55,12 +56,11 @@ Par03EMShowerModel::~Par03EMShowerModel() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par03EMShowerModel::IsApplicable(
const G4ParticleDefinition& aParticleType)
G4bool Par03EMShowerModel::IsApplicable(const G4ParticleDefinition& aParticleType)
{
return &aParticleType == G4Electron::ElectronDefinition() ||
&aParticleType == G4Positron::PositronDefinition() ||
&aParticleType == G4Gamma::GammaDefinition();
return &aParticleType == G4Electron::ElectronDefinition()
|| &aParticleType == G4Positron::PositronDefinition()
|| &aParticleType == G4Gamma::GammaDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -68,8 +68,7 @@ G4bool Par03EMShowerModel::IsApplicable(
G4bool Par03EMShowerModel::ModelTrigger(const G4FastTrack& aFastTrack)
{
// Check energy
if(aFastTrack.GetPrimaryTrack()->GetKineticEnergy() < 1 * GeV)
{
if (aFastTrack.GetPrimaryTrack()->GetKineticEnergy() < 1 * GeV) {
return false;
}
// Check length of detector
@@ -77,14 +76,13 @@ G4bool Par03EMShowerModel::ModelTrigger(const G4FastTrack& aFastTrack)
// 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);
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)
{
if (detectorDepthInX0 < fLongMaxDepth) {
return false;
}
return true;
@@ -92,8 +90,7 @@ G4bool Par03EMShowerModel::ModelTrigger(const G4FastTrack& aFastTrack)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03EMShowerModel::DoIt(const G4FastTrack& aFastTrack,
G4FastStep& aFastStep)
void Par03EMShowerModel::DoIt(const G4FastTrack& aFastTrack, G4FastStep& aFastStep)
{
// Remove particle from further processing by G4
aFastStep.KillPrimaryTrack();
@@ -102,42 +99,37 @@ void Par03EMShowerModel::DoIt(const G4FastTrack& aFastTrack,
// No need to create any deposit, it will be handled by this model (and
// G4FastSimHitMaker that will call the sensitive detector)
aFastStep.ProposeTotalEnergyDeposited(0);
auto particlePosition = aFastTrack.GetPrimaryTrackLocalPosition();
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();
auto material = aFastTrack.GetPrimaryTrack()->GetMaterial();
G4double materialX0 = material->GetRadlen();
G4double materialZ = material->GetZ();
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;
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)
{
if (fAlpha < 0) {
// from PDG Eq. (33.36)
G4double particleTmax = std::log(particleY);
if(aFastTrack.GetPrimaryTrack()->GetParticleDefinition() ==
G4Gamma::GammaDefinition())
{
if (aFastTrack.GetPrimaryTrack()->GetParticleDefinition() == G4Gamma::GammaDefinition()) {
particleTmax += 0.5;
}
else
{
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)
{
if (fSigma < 0) {
// 90% of shower is contained within 1 * R_M
// 1.645 * std dev of Gaussian contains 90%
fSigma = materialRM / 1.645;
@@ -146,13 +138,12 @@ void Par03EMShowerModel::DoIt(const G4FastTrack& aFastTrack,
// 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;
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))
if (!(std::fabs(particleDirection.x()) < epsilon && std::fabs(particleDirection.y()) < epsilon))
rotMatrix.rotateZ(particlePhi);
// Create hits
@@ -160,21 +151,19 @@ void Par03EMShowerModel::DoIt(const G4FastTrack& aFastTrack,
// 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);
G4double gammaMax = Gamma((fAlpha - 1) / fBeta, fAlpha, fBeta);
G4int generatedHits = 0;
while(generatedHits < fNbOfHits)
{
while (generatedHits < fNbOfHits) {
G4double random1 = G4UniformRand() * fLongMaxDepth;
G4double random2 = G4UniformRand() * gammaMax;
if(Gamma(random1, fAlpha, fBeta) >= random2)
{
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);
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);
@@ -190,17 +179,16 @@ void Par03EMShowerModel::Print() const
G4cout << "Par03EMShowerModel: " << G4endl;
G4cout << "Gaussian distribution (transverse plane): \tmu = 0, sigma = "
<< G4BestUnit(fSigma, "Length") << G4endl;
if(fSigma < 0)
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 << "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 = "
@@ -24,20 +24,18 @@
// ********************************************************************
//
#include "Par03EventAction.hh"
#include "Par03Hit.hh"
#include "Par03DetectorConstruction.hh"
#include "Par03Hit.hh"
#include "G4AnalysisManager.hh"
#include "G4SDManager.hh"
#include "G4HCofThisEvent.hh"
#include "G4Event.hh"
#include "G4EventManager.hh"
#include "G4HCofThisEvent.hh"
#include "G4SDManager.hh"
Par03EventAction::Par03EventAction(Par03DetectorConstruction* aDetector)
: G4UserEventAction()
, fHitCollectionID(-1)
, fTimer()
, fDetector(aDetector)
: G4UserEventAction(), fHitCollectionID(-1), fTimer(), fDetector(aDetector)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -46,7 +44,10 @@ Par03EventAction::~Par03EventAction() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par03EventAction::BeginOfEventAction(const G4Event*) { fTimer.Start(); }
void Par03EventAction::BeginOfEventAction(const G4Event*)
{
fTimer.Start();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -54,71 +55,62 @@ void Par03EventAction::EndOfEventAction(const G4Event* aEvent)
{
fTimer.Stop();
// Get hits collection ID (only once)
if(fHitCollectionID == -1)
{
if (fHitCollectionID == -1) {
fHitCollectionID = G4SDManager::GetSDMpointer()->GetCollectionID("hits");
}
// Get hits collection
auto hitsCollection = static_cast<Par03HitsCollection*>(
aEvent->GetHCofThisEvent()->GetHC(fHitCollectionID));
auto hitsCollection =
static_cast<Par03HitsCollection*>(aEvent->GetHCofThisEvent()->GetHC(fHitCollectionID));
if(hitsCollection == nullptr)
{
if (hitsCollection == nullptr) {
G4ExceptionDescription msg;
msg << "Cannot access hitsCollection ID " << fHitCollectionID;
G4Exception("Par03EventAction::GetHitsCollection()", "MyCode0001",
FatalException, msg);
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();
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);
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;
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;
Par03Hit* hit = nullptr;
G4double hitEn = 0;
G4double totalEnergy = 0;
G4int hitZ = -1;
G4int hitRho = -1;
G4int hitType = -1;
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();
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)
{
if (hitEn > 0) {
totalEnergy += hitEn;
tDistance =
hitZ * fCellSizeZ * cosDirection +
(hitRho * fCellSizeRho - primaryEntrance.perp()) * sinDirection;
rDistance =
hitZ * fCellSizeZ * (-sinDirection) +
(hitRho * fCellSizeRho - primaryEntrance.perp()) * cosDirection;
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);
@@ -136,18 +128,16 @@ void Par03EventAction::EndOfEventAction(const G4Event* aEvent)
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();
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;
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);
}
@@ -25,22 +25,20 @@
//
#include "Par03Hit.hh"
#include "G4VisAttributes.hh"
#include "G4Tubs.hh"
#include "G4Colour.hh"
#include "G4AttDefStore.hh"
#include "G4AttDef.hh"
#include "G4AttDefStore.hh"
#include "G4AttValue.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"
#include "G4VVisManager.hh"
#include "G4Colour.hh"
#include "G4LogicalVolume.hh"
#include "G4SystemOfUnits.hh"
#include "G4Tubs.hh"
#include "G4UnitsTable.hh"
#include "G4VVisManager.hh"
#include "G4VisAttributes.hh"
G4ThreadLocal G4Allocator<Par03Hit>* Par03HitAllocator;
Par03Hit::Par03Hit()
: G4VHit()
{}
Par03Hit::Par03Hit() : G4VHit() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -48,17 +46,16 @@ Par03Hit::~Par03Hit() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03Hit::Par03Hit(const Par03Hit& aRight)
: G4VHit()
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;
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;
}
@@ -66,14 +63,14 @@ Par03Hit::Par03Hit(const Par03Hit& aRight)
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;
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;
}
@@ -82,8 +79,7 @@ const Par03Hit& Par03Hit::operator=(const Par03Hit& aRight)
int Par03Hit::operator==(const Par03Hit& aRight) const
{
return (fRhoId == aRight.fRhoId && fPhiId == aRight.fPhiId &&
fZId == aRight.fZId);
return (fRhoId == aRight.fRhoId && fPhiId == aRight.fPhiId && fZId == aRight.fZId);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -92,25 +88,20 @@ void Par03Hit::Draw()
{
G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
// Hits can be filtered out in visualisation
if(!pVVisManager->FilterHit(*this))
return;
if (!pVVisManager->FilterHit(*this)) return;
// Do not draw empty hits
if(fEdep < 0)
return;
if(pVVisManager)
{
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)
{
if (fLogVol) {
const G4VisAttributes* pVA = fLogVol->GetVisAttributes();
if(pVA)
attribs = *pVA;
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());
solid = *dynamic_cast<G4Tubs*>(fLogVol->GetSolid());
double dR = solid.GetOuterRadius() - solid.GetInnerRadius();
solid.SetInnerRadius(solid.GetInnerRadius() + fRhoId * dR);
solid.SetOuterRadius(solid.GetOuterRadius() + fRhoId * dR);
@@ -131,18 +122,13 @@ void Par03Hit::Draw()
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");
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;
}
@@ -163,7 +149,6 @@ std::vector<G4AttValue>* Par03Hit::CreateAttValues() const
void Par03Hit::Print()
{
std::cout << "\tHit " << fEdep / MeV << " MeV at " << fPos / cm
<< " cm (R,phi,z)= (" << fRhoId << ", " << fPhiId << ", " << fZId
<< "), " << fTime << " ns" << std::endl;
std::cout << "\tHit " << fEdep / MeV << " MeV at " << fPos / cm << " cm (R,phi,z)= (" << fRhoId
<< ", " << fPhiId << ", " << fZId << "), " << fTime << " ns" << std::endl;
}
@@ -30,16 +30,14 @@
#include "G4SystemOfUnits.hh"
Par03PrimaryGeneratorAction::Par03PrimaryGeneratorAction()
: G4VUserPrimaryGeneratorAction()
, fParticleGun(nullptr)
: G4VUserPrimaryGeneratorAction(), fParticleGun(nullptr)
{
G4int n_particle = 1;
fParticleGun = new G4ParticleGun(n_particle);
fParticleGun = new G4ParticleGun(n_particle);
// Default particle properties
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
G4String particleName;
G4ParticleDefinition* particle =
particleTable->FindParticle(particleName = "e-");
G4ParticleDefinition* particle = particleTable->FindParticle(particleName = "e-");
fParticleGun->SetParticleDefinition(particle);
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0., 0., 1.));
fParticleGun->SetParticleEnergy(10. * GeV);
@@ -48,7 +46,10 @@ Par03PrimaryGeneratorAction::Par03PrimaryGeneratorAction()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03PrimaryGeneratorAction::~Par03PrimaryGeneratorAction() { delete fParticleGun; }
Par03PrimaryGeneratorAction::~Par03PrimaryGeneratorAction()
{
delete fParticleGun;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -24,13 +24,13 @@
// ********************************************************************
//
#include "Par03RunAction.hh"
#include "Par03DetectorConstruction.hh"
#include "G4AnalysisManager.hh"
Par03RunAction::Par03RunAction(Par03DetectorConstruction* aDetector)
: G4UserRunAction()
, fDetector(aDetector)
: G4UserRunAction(), fDetector(aDetector)
{
// Create analysis manager
G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
@@ -49,9 +49,9 @@ Par03RunAction::~Par03RunAction() = default;
void Par03RunAction::BeginOfRunAction(const G4Run*)
{
// Get detector dimensions
G4int cellNumZ = fDetector->GetNbOfLayers();
G4int cellNumRho = fDetector->GetNbOfRhoCells();
G4double cellSizeZ = fDetector->GetLength() / cellNumZ;
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;
@@ -60,50 +60,36 @@ void Par03RunAction::BeginOfRunAction(const G4Run*)
auto analysisManager = G4AnalysisManager::Instance();
// Creating control histograms
analysisManager->CreateH1("energyParticle",
"Primary energy;E_{MC} (GeV);Entries", 256, 0,
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,
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
"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
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
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);
"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();
@@ -24,27 +24,24 @@
// ********************************************************************
//
#include "Par03SensitiveDetector.hh"
#include "Par03Hit.hh"
#include "G4HCofThisEvent.hh"
#include "G4SDManager.hh"
#include "G4Step.hh"
#include "G4TouchableHistory.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4SDManager.hh"
Par03SensitiveDetector::Par03SensitiveDetector(G4String aName)
: G4VSensitiveDetector(aName)
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)
Par03SensitiveDetector::Par03SensitiveDetector(G4String aName, G4int aNumLayers, G4int aNumRho,
G4int aNumPhi)
: G4VSensitiveDetector(aName), fCellNoZ(aNumLayers), fCellNoRho(aNumRho), fCellNoPhi(aNumPhi)
{
collectionName.insert("hits");
}
@@ -57,21 +54,17 @@ Par03SensitiveDetector::~Par03SensitiveDetector() = default;
void Par03SensitiveDetector::Initialize(G4HCofThisEvent* aHCE)
{
fHitsCollection =
new Par03HitsCollection(SensitiveDetectorName, collectionName[0]);
if(fHitCollectionID < 0)
{
fHitCollectionID =
G4SDManager::GetSDMpointer()->GetCollectionID(fHitsCollection);
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++)
{
auto hit = new Par03Hit();
for (G4int iphi = 0; iphi < fCellNoPhi; iphi++)
for (G4int irho = 0; irho < fCellNoRho; irho++)
for (G4int iz = 0; iz < fCellNoZ; iz++) {
auto hit = new Par03Hit();
fHitsCollection->insert(hit);
}
}
@@ -81,11 +74,9 @@ void Par03SensitiveDetector::Initialize(G4HCofThisEvent* aHCE)
G4bool Par03SensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*)
{
G4double edep = aStep->GetTotalEnergyDeposit();
if(edep == 0.)
return true;
if (edep == 0.) return true;
auto aTouchable =
(G4TouchableHistory*) (aStep->GetPreStepPoint()->GetTouchable());
auto aTouchable = (G4TouchableHistory*)(aStep->GetPreStepPoint()->GetTouchable());
auto hit = RetrieveAndSetupHit(aTouchable);
@@ -94,27 +85,23 @@ G4bool Par03SensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*)
// 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())
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);
if (hit->GetType() != 1) hit->SetType(0);
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par03SensitiveDetector::ProcessHits(const G4FastHit* aHit,
const G4FastTrack* aTrack,
G4bool Par03SensitiveDetector::ProcessHits(const G4FastHit* aHit, const G4FastTrack* aTrack,
G4TouchableHistory* aTouchable)
{
G4double edep = aHit->GetEnergy();
if(edep == 0.)
return true;
if (edep == 0.) return true;
auto hit = RetrieveAndSetupHit(aTouchable);
@@ -123,9 +110,7 @@ G4bool Par03SensitiveDetector::ProcessHits(const G4FastHit* aHit,
// 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())
{
if (hit->GetTime() == -1 || hit->GetTime() > aTrack->GetPrimaryTrack()->GetGlobalTime()) {
hit->SetTime(aTrack->GetPrimaryTrack()->GetGlobalTime());
}
@@ -138,27 +123,22 @@ G4bool Par03SensitiveDetector::ProcessHits(const G4FastHit* aHit,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par03Hit* Par03SensitiveDetector::RetrieveAndSetupHit(
G4TouchableHistory* aTouchable)
Par03Hit* Par03SensitiveDetector::RetrieveAndSetupHit(G4TouchableHistory* aTouchable)
{
G4int rhoNo = aTouchable->GetCopyNumber(0); // cell
G4int phiNo = aTouchable->GetCopyNumber(1); // segment
G4int zNo = aTouchable->GetCopyNumber(2); // layer
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!");
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)
{
if (hit->GetRhoId() < 0) {
hit->SetRhoId(rhoNo);
hit->SetPhiId(phiNo);
hit->SetZid(zNo);