Import Geant4 11.2.0 source tree

This commit is contained in:
Gabriele Cosmo
2023-12-08 10:43:34 +01:00
parent dd1f179cda
commit 860a2b92bf
3962 changed files with 139318 additions and 164259 deletions
@@ -31,20 +31,22 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ActionInitialisation::Par04ActionInitialisation(Par04DetectorConstruction* aDetector)
Par04ActionInitialisation::Par04ActionInitialisation(Par04DetectorConstruction* aDetector,
Par04ParallelFullWorld* aParallel)
: G4VUserActionInitialization()
, fDetector(aDetector)
, fParallel(aParallel)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ActionInitialisation::~Par04ActionInitialisation() {}
Par04ActionInitialisation::~Par04ActionInitialisation() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ActionInitialisation::BuildForMaster() const
{
auto eventAction = new Par04EventAction(fDetector);
auto eventAction = new Par04EventAction(fDetector, fParallel);
SetUserAction(new Par04RunAction(fDetector, eventAction));
}
@@ -53,7 +55,7 @@ void Par04ActionInitialisation::BuildForMaster() const
void Par04ActionInitialisation::Build() const
{
SetUserAction(new Par04PrimaryGeneratorAction());
auto eventAction = new Par04EventAction(fDetector);
auto eventAction = new Par04EventAction(fDetector, fParallel);
SetUserAction(eventAction);
SetUserAction(new Par04RunAction(fDetector, eventAction));
}
@@ -49,7 +49,7 @@ Par04DefineMeshModel::Par04DefineMeshModel(G4String aModelName)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04DefineMeshModel::~Par04DefineMeshModel() {}
Par04DefineMeshModel::~Par04DefineMeshModel() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -62,7 +62,7 @@ G4bool Par04DefineMeshModel::IsApplicable(const G4ParticleDefinition&)
G4bool Par04DefineMeshModel::ModelTrigger(const G4FastTrack&)
{
Par04EventInformation* info = dynamic_cast<Par04EventInformation*>(
auto info = dynamic_cast<Par04EventInformation*>(
G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
// check if particle direction and position were already set for this event
if(info != nullptr)
@@ -75,7 +75,7 @@ G4bool Par04DefineMeshModel::ModelTrigger(const G4FastTrack&)
void Par04DefineMeshModel::DoIt(const G4FastTrack& aFastTrack, G4FastStep&)
{
Par04EventInformation* info = dynamic_cast<Par04EventInformation*>(
auto info = dynamic_cast<Par04EventInformation*>(
G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
if(info == nullptr)
{
@@ -67,7 +67,7 @@ Par04DetectorConstruction::Par04DetectorConstruction()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04DetectorConstruction::~Par04DetectorConstruction() {}
Par04DetectorConstruction::~Par04DetectorConstruction() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -106,8 +106,8 @@ G4VPhysicalVolume* Par04DetectorConstruction::Construct()
"World", // name
0, // mother volume
false, // not used
999, // copy number
true); // copy number
99999, // copy number
false); // check overlaps
fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
//--------- Detector envelope ---------
@@ -126,8 +126,8 @@ G4VPhysicalVolume* Par04DetectorConstruction::Construct()
"Detector", // name
fLogicWorld, // mother volume
false, // not used
99, // copy number
true); // check overlaps
999, // copy number
false); // check overlaps
// Region for fast simulation
auto detectorRegion = new G4Region("DetectorRegion");
@@ -145,12 +145,12 @@ G4VPhysicalVolume* Par04DetectorConstruction::Construct()
{
for(G4int iMaterial = 0; iMaterial < nbOfMaterials; iMaterial++)
{
auto fSolidLayer = new G4Tubs("Layer", // name
innerRadius, // inner radius
innerRadius + fAbsorberThickness[iMaterial], // outer radius
fDetectorLength / 2., // half-width in Z
0, // start angle
full2Pi); // delta angle
auto fSolidLayer = new G4Tubs("Layer", // name
innerRadius, // inner radius
innerRadius + fAbsorberThickness[iMaterial], // outer radius
fDetectorLength / 2., // half-width in Z
0, // start angle
full2Pi); // delta angle
G4LogicalVolume* logical = new G4LogicalVolume(fSolidLayer, // solid
fAbsorberMaterial[iMaterial], // material
"Layer"); // name
@@ -161,7 +161,7 @@ G4VPhysicalVolume* Par04DetectorConstruction::Construct()
fLogicDetector, // mother volume
false, // not used
iLayer * nbOfMaterials + iMaterial, // copy number
true); // check overlaps
false); // check overlaps
logical->SetVisAttributes(attribs[iMaterial]);
innerRadius += fAbsorberThickness[iMaterial];
if(fAbsorberSensitivity[iMaterial])
@@ -229,7 +229,8 @@ void Par04DetectorConstruction::SetAbsorberMaterial(const std::size_t aLayer, co
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorConstruction::SetAbsorberThickness(const std::size_t aLayer, const G4double aThickness)
void Par04DetectorConstruction::SetAbsorberThickness(const std::size_t aLayer,
const G4double aThickness)
{
if(aLayer < fAbsorberThickness.size())
fAbsorberThickness[aLayer] = aThickness;
@@ -244,14 +245,15 @@ void Par04DetectorConstruction::SetAbsorberThickness(const std::size_t aLayer, c
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorConstruction::SetAbsorberSensitivity(const std::size_t aLayer, const G4bool aSensitivity)
void Par04DetectorConstruction::SetAbsorberSensitivity(const std::size_t aLayer,
const G4bool aSensitivity)
{
if(aLayer < fAbsorberSensitivity.size())
fAbsorberSensitivity[aLayer] = aSensitivity;
else
G4Exception(
"Par04DetectorConstruction::SetAbsorberSensitivity()", "InvalidSetup", FatalException,
("Requested layer " + std::to_string(aLayer) + " is larger than number of available layers (" +
("Requested layer " + std::to_string(aLayer) + " is larger than number of available layers ("+
std::to_string(fAbsorberSensitivity.size()) + ").")
.c_str());
G4RunManager::GetRunManager()->PhysicsHasBeenModified();
@@ -84,23 +84,23 @@ Par04DetectorMessenger::Par04DetectorMessenger(Par04DetectorConstruction* aDetec
fAbsorCmd->SetGuidance(" material name");
fAbsorCmd->SetGuidance(" thickness (with unit) : t>0");
fAbsorCmd->SetGuidance(" if sensitive : true/false.");
G4UIparameter* absNbPrm = new G4UIparameter("AbsorNb", 'i', false);
auto absNbPrm = new G4UIparameter("AbsorNb", 'i', false);
absNbPrm->SetGuidance("absor number : from 0 to 1");
absNbPrm->SetParameterRange("AbsorNb>-1&AbsoNb<2");
fAbsorCmd->SetParameter(absNbPrm);
G4UIparameter* matPrm = new G4UIparameter("material", 's', false);
auto matPrm = new G4UIparameter("material", 's', false);
matPrm->SetGuidance("material name");
fAbsorCmd->SetParameter(matPrm);
G4UIparameter* thickPrm = new G4UIparameter("thickness", 'd', false);
auto thickPrm = new G4UIparameter("thickness", 'd', false);
thickPrm->SetGuidance("thickness of absorber");
thickPrm->SetParameterRange("thickness>0.");
fAbsorCmd->SetParameter(thickPrm);
G4UIparameter* unitPrm = new G4UIparameter("unit", 's', false);
auto unitPrm = new G4UIparameter("unit", 's', false);
unitPrm->SetGuidance("unit of thickness");
G4String unitList = G4UIcommand::UnitsList(G4UIcommand::CategoryOf("mm"));
unitPrm->SetParameterCandidates(unitList);
fAbsorCmd->SetParameter(unitPrm);
G4UIparameter* sensitivePrm = new G4UIparameter("sensitive", 'b', false);
auto sensitivePrm = new G4UIparameter("sensitive", 'b', false);
sensitivePrm->SetGuidance("if absorber is sensitive (registers energy deposits)");
fAbsorCmd->SetParameter(sensitivePrm);
@@ -24,37 +24,45 @@
// ********************************************************************
//
#include "Par04EventAction.hh"
#include <CLHEP/Units/SystemOfUnits.h> // for GeV
#include <CLHEP/Vector/ThreeVector.h> // for Hep3Vector
#include <stddef.h> // for size_t
#include <G4Exception.hh> // for G4Exception, G4ExceptionDesc...
#include <G4ExceptionSeverity.hh> // for FatalException
#include <G4GenericAnalysisManager.hh> // for G4GenericAnalysisManager
#include <G4PrimaryParticle.hh> // for G4PrimaryParticle
#include <G4PrimaryVertex.hh> // for G4PrimaryVertex
#include <G4SystemOfUnits.hh> // for GeV
#include <G4THitsCollection.hh> // for G4THitsCollection
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4Timer.hh> // for G4Timer
#include <G4UserEventAction.hh> // for G4UserEventAction
#include <algorithm> // for max
#include <ostream> // for basic_ostream::operator<<
#include "Par04DetectorConstruction.hh" // for Par04DetectorConstruction
#include "Par04Hit.hh" // for Par04Hit, Par04HitsCollection
#include "Par04ParallelFullWorld.hh"
#include "G4AnalysisManager.hh" // for G4AnalysisManager
#include "G4Event.hh" // for G4Event
#include "G4EventManager.hh" // for G4EventManager
#include "G4HCofThisEvent.hh" // for G4HCofThisEvent
#include "G4SDManager.hh" // for G4SDManager
#include "Par04DetectorConstruction.hh" // for Par04DetectorConstruction
#include "Par04Hit.hh" // for Par04Hit, Par04HitsCollection
#include <CLHEP/Units/SystemOfUnits.h> // for GeV
#include <CLHEP/Vector/ThreeVector.h> // for Hep3Vector
#include "G4Exception.hh" // for G4Exception, G4ExceptionDesc...
#include "G4ExceptionSeverity.hh" // for FatalException
#include "G4GenericAnalysisManager.hh" // for G4GenericAnalysisManager
#include "G4PrimaryParticle.hh" // for G4PrimaryParticle
#include "G4PrimaryVertex.hh" // for G4PrimaryVertex
#include "G4SystemOfUnits.hh" // for GeV
#include "G4THitsCollection.hh" // for G4THitsCollection
#include "G4ThreeVector.hh" // for G4ThreeVector
#include "G4Timer.hh" // for G4Timer
#include "G4UserEventAction.hh" // for G4UserEventAction
#include <algorithm> // for max
#include <cmath> // for log10
#include <cstddef> // for size_t
#include <ostream> // for basic_ostream::operator<<
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04EventAction::Par04EventAction(Par04DetectorConstruction* aDetector)
Par04EventAction::Par04EventAction(Par04DetectorConstruction* aDetector,
Par04ParallelFullWorld* aParallel)
: G4UserEventAction()
, fHitCollectionID(-1)
, fPhysicalFullHitCollectionID(-1)
, fPhysicalFastHitCollectionID(-1)
, fTimer()
, fDetector(aDetector)
, fParallel(aParallel)
{
fCellNbRho = aDetector->GetMeshNbOfCells().x();
fCellNbPhi = aDetector->GetMeshNbOfCells().y();
@@ -63,30 +71,65 @@ Par04EventAction::Par04EventAction(Par04DetectorConstruction* aDetector)
fCalRho.reserve(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalPhi.reserve(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalZ.reserve(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalPhysicalEdep.reserve(fPhysicalNbLayers * fPhysicalNbRows * fPhysicalNbSlices);
fCalPhysicalLayer.reserve(fPhysicalNbLayers * fPhysicalNbRows * fPhysicalNbSlices);
fCalPhysicalSlice.reserve(fPhysicalNbLayers * fPhysicalNbRows * fPhysicalNbSlices);
fCalPhysicalRow.reserve(fPhysicalNbLayers * fPhysicalNbRows * fPhysicalNbSlices);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04EventAction::~Par04EventAction() {}
Par04EventAction::~Par04EventAction() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04EventAction::BeginOfEventAction(const G4Event*) { fTimer.Start(); }
void Par04EventAction::BeginOfEventAction(const G4Event*) {
StartTimer();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04EventAction::StartTimer() {
fTimer.Start();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04EventAction::StopTimer() {
fTimer.Stop();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04EventAction::EndOfEventAction(const G4Event* aEvent)
{
fTimer.Stop();
G4SDManager::GetSDMpointer()->GetHCtable();
StopTimer();
// Get hits collection ID (only once)
if(fHitCollectionID == -1)
{
fHitCollectionID = G4SDManager::GetSDMpointer()->GetCollectionID("hits");
}
if(fPhysicalFullHitCollectionID == -1)
{
fPhysicalFullHitCollectionID =
G4SDManager::GetSDMpointer()->GetCollectionID("physicalCellsFullSim");
}
if(fPhysicalFastHitCollectionID == -1)
{
fPhysicalFastHitCollectionID =
G4SDManager::GetSDMpointer()->GetCollectionID("physicalCellsFastSim");
}
// Get hits collection
auto hitsCollection =
static_cast<Par04HitsCollection*>(aEvent->GetHCofThisEvent()->GetHC(fHitCollectionID));
auto physicalFullHitsCollection =
static_cast<Par04HitsCollection*>(aEvent->GetHCofThisEvent()
->GetHC(fPhysicalFullHitCollectionID));
auto physicalFastHitsCollection =
static_cast<Par04HitsCollection*>(aEvent->GetHCofThisEvent()
->GetHC(fPhysicalFastHitCollectionID));
if(hitsCollection == nullptr)
{
@@ -94,7 +137,18 @@ void Par04EventAction::EndOfEventAction(const G4Event* aEvent)
msg << "Cannot access hitsCollection ID " << fHitCollectionID;
G4Exception("Par04EventAction::GetHitsCollection()", "MyCode0001", FatalException, msg);
}
if(physicalFullHitsCollection == nullptr)
{
G4ExceptionDescription msg;
msg << "Cannot access physical full sim hitsCollection ID " << fPhysicalFullHitCollectionID;
G4Exception("Par04EventAction::GetHitsCollection()", "MyCode0001", FatalException, msg);
}
if(physicalFastHitsCollection == nullptr)
{
G4ExceptionDescription msg;
msg << "Cannot access physical fast sim hitsCollection ID " << fPhysicalFastHitCollectionID;
G4Exception("Par04EventAction::GetHitsCollection()", "MyCode0001", FatalException, msg);
}
// Get analysis manager
auto analysisManager = G4AnalysisManager::Instance();
// Retrieve only once detector dimensions
@@ -107,6 +161,12 @@ void Par04EventAction::EndOfEventAction(const G4Event* aEvent)
fCellNbPhi = fDetector->GetMeshNbOfCells().y();
fCellNbZ = fDetector->GetMeshNbOfCells().z();
}
if(fPhysicalNbLayers == 0)
{
fPhysicalNbLayers = fParallel->GetNbOfLayers();
fPhysicalNbSlices = fParallel->GetNbOfSlices();
fPhysicalNbRows = fParallel->GetNbOfRows();
}
// Retrieve information from primary vertex and primary particle
// To calculate shower axis and entry point to the detector
@@ -121,15 +181,21 @@ void Par04EventAction::EndOfEventAction(const G4Event* aEvent)
primaryVertex->GetPosition() - primaryVertex->GetPosition().z() * primaryDirection;
// Resize back to initial mesh size
fCalEdep.resize(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalRho.resize(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalPhi.resize(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalZ.resize(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalEdep.resize(fCellNbRho * fCellNbPhi * fCellNbZ,0);
fCalRho.resize(fCellNbRho * fCellNbPhi * fCellNbZ,0);
fCalPhi.resize(fCellNbRho * fCellNbPhi * fCellNbZ,0);
fCalZ.resize(fCellNbRho * fCellNbPhi * fCellNbZ,0);
fCalPhysicalEdep.resize(fPhysicalNbLayers * fPhysicalNbRows * fPhysicalNbSlices,0);
fCalPhysicalLayer.resize(fPhysicalNbLayers * fPhysicalNbRows * fPhysicalNbSlices,0);
fCalPhysicalSlice.resize(fPhysicalNbLayers * fPhysicalNbRows * fPhysicalNbSlices,0);
fCalPhysicalRow.resize(fPhysicalNbLayers * fPhysicalNbRows * fPhysicalNbSlices,0);
// Fill histograms
Par04Hit* hit = nullptr;
G4double hitEn = 0;
G4double totalEnergy = 0;
G4int hitNum = 0;
G4int totalNum = 0;
G4int hitZ = -1;
G4int hitRho = -1;
G4int hitPhi = -1;
@@ -146,10 +212,12 @@ void Par04EventAction::EndOfEventAction(const G4Event* aEvent)
hitRho = hit->GetRhoId();
hitPhi = hit->GetPhiId();
hitEn = hit->GetEdep();
hitNum = hit->GetNdep();
hitType = hit->GetType();
if(hitEn > 0)
{
totalEnergy += hitEn;
totalNum += hitNum;
tDistance = hitZ * fCellSizeZ;
rDistance = hitRho * fCellSizeRho;
phiDistance = hitPhi * fCellSizePhi;
@@ -167,6 +235,7 @@ void Par04EventAction::EndOfEventAction(const G4Event* aEvent)
fCalZ[numNonZeroThresholdCells] = hitZ;
numNonZeroThresholdCells++;
analysisManager->FillH1(13, std::log10(hitEn));
analysisManager->FillH1(15, hitNum);
}
}
}
@@ -180,14 +249,14 @@ void Par04EventAction::EndOfEventAction(const G4Event* aEvent)
analysisManager->FillH1(6, tFirstMoment);
analysisManager->FillH1(7, rFirstMoment);
analysisManager->FillH1(12, numNonZeroThresholdCells);
analysisManager->FillH1(14, totalNum);
// Resize to store only energy hits above threshold
fCalEdep.resize(numNonZeroThresholdCells);
fCalRho.resize(numNonZeroThresholdCells);
fCalPhi.resize(numNonZeroThresholdCells);
fCalZ.resize(numNonZeroThresholdCells);
analysisManager->FillNtupleDColumn(0, primaryEnergy);
analysisManager->FillNtupleDColumn(5, fTimer.GetRealElapsed());
analysisManager->FillNtupleDColumn(0, 0, primaryEnergy);
analysisManager->FillNtupleDColumn(0, 1, fTimer.GetRealElapsed());
// Second loop over hits to calculate second moments
for(size_t iHit = 0; iHit < hitsCollection->entries(); iHit++)
{
@@ -210,5 +279,72 @@ void Par04EventAction::EndOfEventAction(const G4Event* aEvent)
rSecondMoment /= totalEnergy;
analysisManager->FillH1(8, tSecondMoment);
analysisManager->FillH1(9, rSecondMoment);
analysisManager->AddNtupleRow();
// Fill ntuple with physical readout data
G4double totalPhysicalEnergy = 0;
totalNum = 0;
hitEn = 0;
hitNum = 0;
G4int hitLayer = -1;
G4int hitRow = -1;
G4int hitSlice = -1;
numNonZeroThresholdCells = 0;
for(size_t iHit = 0; iHit < physicalFullHitsCollection->entries(); iHit++)
{
hit = static_cast<Par04Hit*>(physicalFullHitsCollection->GetHit(iHit));
hitLayer = hit->GetRhoId();
hitRow = hit->GetZid();
hitSlice = hit->GetPhiId();
hitEn = hit->GetEdep();
hitNum = hit->GetNdep();
if(hitEn > 0)
{
totalPhysicalEnergy += hitEn;
totalNum += hitNum;
if(hitEn > 0.0005)
{ // e > 0.5 keV
fCalPhysicalEdep[numNonZeroThresholdCells] = hitEn;
fCalPhysicalLayer[numNonZeroThresholdCells] = hitLayer;
fCalPhysicalRow[numNonZeroThresholdCells] = hitRow;
fCalPhysicalSlice[numNonZeroThresholdCells] = hitSlice;
numNonZeroThresholdCells++;
analysisManager->FillH1(19, std::log10(hitEn));
analysisManager->FillH1(21, hitNum);
}
}
}for(size_t iHit = 0; iHit < physicalFastHitsCollection->entries(); iHit++)
{
hit = static_cast<Par04Hit*>(physicalFastHitsCollection->GetHit(iHit));
hitLayer = hit->GetRhoId();
hitRow = hit->GetZid();
hitSlice = hit->GetPhiId();
hitEn = hit->GetEdep();
hitNum = hit->GetNdep();
if(hitEn > 0)
{
totalPhysicalEnergy += hitEn;
totalNum += hitNum;
if(hitEn > 0.0005)
{ // e > 0.5 keV
fCalPhysicalEdep[numNonZeroThresholdCells] = hitEn;
fCalPhysicalLayer[numNonZeroThresholdCells] = hitLayer;
fCalPhysicalRow[numNonZeroThresholdCells] = hitRow;
fCalPhysicalSlice[numNonZeroThresholdCells] = hitSlice;
numNonZeroThresholdCells++;
analysisManager->FillH1(19, std::log10(hitEn));
analysisManager->FillH1(21, hitNum);
}
}
}
analysisManager->FillH1(16, totalPhysicalEnergy / GeV);
analysisManager->FillH1(17, totalPhysicalEnergy / primaryEnergy);
analysisManager->FillH1(18, numNonZeroThresholdCells);
analysisManager->FillH1(20, totalNum);
fCalPhysicalEdep.resize(numNonZeroThresholdCells);
fCalPhysicalLayer.resize(numNonZeroThresholdCells);
fCalPhysicalSlice.resize(numNonZeroThresholdCells);
fCalPhysicalRow.resize(numNonZeroThresholdCells);
analysisManager->AddNtupleRow(0);
analysisManager->AddNtupleRow(1);
analysisManager->AddNtupleRow(2);
}
@@ -39,7 +39,7 @@ Par04EventInformation::Par04EventInformation()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04EventInformation::~Par04EventInformation() {}
Par04EventInformation::~Par04EventInformation() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -56,7 +56,7 @@ Par04Hit::Par04Hit()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04Hit::~Par04Hit() {}
Par04Hit::~Par04Hit() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -64,6 +64,7 @@ Par04Hit::Par04Hit(const Par04Hit& aRight)
: G4VHit()
{
fEdep = aRight.fEdep;
fNdep = aRight.fNdep;
fZId = aRight.fZId;
fRhoId = aRight.fRhoId;
fPhiId = aRight.fPhiId;
@@ -79,6 +80,7 @@ Par04Hit::Par04Hit(const Par04Hit& aRight)
const Par04Hit& Par04Hit::operator=(const Par04Hit& aRight)
{
fEdep = aRight.fEdep;
fNdep = aRight.fNdep;
fZId = aRight.fZId;
fRhoId = aRight.fRhoId;
fPhiId = aRight.fPhiId;
@@ -108,6 +110,9 @@ void Par04Hit::Draw()
// Hits can be filtered out in visualisation
if(!pVVisManager->FilterHit(*this))
return;
// Do not plot hits from parallel world
if(fType >= 2)
return;
// Do not draw empty hits
if(fEdep <= 0)
return;
@@ -127,7 +132,6 @@ void Par04Hit::Draw()
// Set transparency depending on the energy
// Arbitrary formula
G4double alpha = 2 * std::log10(fEdep + 1);
G4cout << "alpha = " << alpha << G4endl;
G4Colour colour(colR, colG, colB, alpha);
attribs.SetColour(colour);
attribs.SetForceSolid(true);
@@ -168,7 +172,7 @@ std::vector<G4AttValue>* Par04Hit::CreateAttValues() const
void Par04Hit::Print()
{
std::cout << "\tHit " << fEdep / MeV << " MeV at " << fPos / cm << " cm rotation " << fRot
<< " (R,phi,z)= (" << fRhoId << ", " << fPhiId << ", " << fZId << "), " << fTime << " ns"
<< std::endl;
std::cout << "\tHit " << fEdep / MeV << " MeV from " << fNdep << " deposits at " << fPos / cm
<< " cm rotation " << fRot << " (R,phi,z)= (" << fRhoId << ", " << fPhiId
<< ", " << fZId << "), " << fTime << " ns" << std::endl;
}
@@ -24,38 +24,39 @@
// ********************************************************************
//
#ifdef USE_INFERENCE
#include "G4UIcmdWithADoubleAndUnit.hh" // for G4UIcmdWithADoubleAndUnit
#include "G4UIcmdWithAString.hh" // for G4UIcmdWithAString
#include "G4UIcmdWithAnInteger.hh" // for G4UIcmdWithAnInteger
#include "G4UIdirectory.hh" // for G4UIdirectory
#include "Par04InferenceMessenger.hh"
#include <CLHEP/Units/SystemOfUnits.h> // for pi
#include <G4ApplicationState.hh> // for G4State_Idle
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4UImessenger.hh> // for G4UImessenger
#include <string> // for stoi
#include "G4UIcmdWithADoubleAndUnit.hh" // for G4UIcmdWithADoubleAndUnit
#include "G4UIcmdWithAString.hh" // for G4UIcmdWithAString
#include "G4UIcmdWithAnInteger.hh" // for G4UIcmdWithAnInteger
#include "G4UIdirectory.hh" // for G4UIdirectory
#include "Par04InferenceSetup.hh" // for Par04InferenceSetup
#include "Par04InferenceSetup.hh" // for Par04InferenceSetup
#include <CLHEP/Units/SystemOfUnits.h> // for pi
#include <G4ApplicationState.hh> // for G4State_Idle
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4UImessenger.hh> // for G4UImessenger
#include <string> // for stoi
class G4UIcommand;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04InferenceMessenger::Par04InferenceMessenger(Par04InferenceSetup* aInference)
: G4UImessenger()
, fInference(aInference)
{
Par04InferenceMessenger::Par04InferenceMessenger(
Par04InferenceSetup *aInference)
: G4UImessenger(), fInference(aInference) {
fExampleDir = new G4UIdirectory("/Par04/");
fExampleDir->SetGuidance("UI commands specific to this example");
fInferenceDir = new G4UIdirectory("/Par04/inference/");
fInferenceDir->SetGuidance("Inference construction UI commands");
fInferenceLibraryCmd = new G4UIcmdWithAString("/Par04/inference/setInferenceLibrary", this);
fInferenceLibraryCmd =
new G4UIcmdWithAString("/Par04/inference/setInferenceLibrary", this);
fInferenceLibraryCmd->SetGuidance("Inference library.");
fInferenceLibraryCmd->SetParameterName("InferenceLibrary", false);
fInferenceLibraryCmd->AvailableForStates(G4State_Idle);
fInferenceLibraryCmd->SetToBeBroadcasted(true);
fSizeLatentVectorCmd = new G4UIcmdWithAnInteger("/Par04/inference/setSizeLatentVector", this);
fSizeLatentVectorCmd =
new G4UIcmdWithAnInteger("/Par04/inference/setSizeLatentVector", this);
fSizeLatentVectorCmd->SetGuidance("Set size of the latent space vector.");
fSizeLatentVectorCmd->SetParameterName("SizeLatentVector", false);
fSizeLatentVectorCmd->SetRange("SizeLatentVector>0");
@@ -63,75 +64,155 @@ Par04InferenceMessenger::Par04InferenceMessenger(Par04InferenceSetup* aInference
fSizeLatentVectorCmd->SetToBeBroadcasted(true);
fSizeConditionVectorCmd =
new G4UIcmdWithAnInteger("/Par04/inference/setSizeConditionVector", this);
new G4UIcmdWithAnInteger("/Par04/inference/setSizeConditionVector", this);
fSizeConditionVectorCmd->SetGuidance("Set size of the condition vector.");
fSizeConditionVectorCmd->SetParameterName("SizeConditionVector", false);
fSizeConditionVectorCmd->SetRange("SizeConditionVector>0");
fSizeConditionVectorCmd->AvailableForStates(G4State_Idle);
fSizeConditionVectorCmd->SetToBeBroadcasted(true);
fModelPathNameCmd = new G4UIcmdWithAString("/Par04/inference/setModelPathName", this);
fModelPathNameCmd =
new G4UIcmdWithAString("/Par04/inference/setModelPathName", this);
fModelPathNameCmd->SetGuidance("Model path and name.");
fModelPathNameCmd->SetParameterName("Name", false);
fModelPathNameCmd->AvailableForStates(G4State_Idle);
fModelPathNameCmd->SetToBeBroadcasted(true);
fProfileFlagCmd = new G4UIcmdWithAnInteger("/Par04/inference/setProfileFlag", this);
fProfileFlagCmd->SetGuidance("Flag to save a json file for model execution profiling.");
fProfileFlagCmd =
new G4UIcmdWithAnInteger("/Par04/inference/setProfileFlag", this);
fProfileFlagCmd->SetGuidance(
"Flag to save a json file for model execution profiling.");
fProfileFlagCmd->SetParameterName("ProfileFlag", false);
fProfileFlagCmd->SetRange("ProfileFlag>-1");
fProfileFlagCmd->AvailableForStates(G4State_Idle);
fProfileFlagCmd->SetToBeBroadcasted(true);
fOptimizationFlagCmd = new G4UIcmdWithAnInteger("/Par04/inference/setOptimizationFlag", this);
fOptimizationFlagCmd =
new G4UIcmdWithAnInteger("/Par04/inference/setOptimizationFlag", this);
fOptimizationFlagCmd->SetGuidance("Set optimization flag");
fOptimizationFlagCmd->SetParameterName("OptimizationFlag", false);
fOptimizationFlagCmd->SetRange("OptimizationFlag>-1");
fOptimizationFlagCmd->AvailableForStates(G4State_Idle);
fOptimizationFlagCmd->SetToBeBroadcasted(true);
fMeshNbRhoCellsCmd = new G4UIcmdWithAnInteger("/Par04/inference/setNbOfRhoCells", this);
fMeshNbRhoCellsCmd->SetGuidance("Set number of rho cells in the cylindrical mesh readout.");
fMeshNbRhoCellsCmd =
new G4UIcmdWithAnInteger("/Par04/inference/setNbOfRhoCells", this);
fMeshNbRhoCellsCmd->SetGuidance(
"Set number of rho cells in the cylindrical mesh readout.");
fMeshNbRhoCellsCmd->SetParameterName("NbRhoCells", false);
fMeshNbRhoCellsCmd->SetRange("NbRhoCells>0");
fMeshNbRhoCellsCmd->AvailableForStates(G4State_Idle);
fMeshNbRhoCellsCmd->SetToBeBroadcasted(true);
fMeshNbPhiCellsCmd = new G4UIcmdWithAnInteger("/Par04/inference/setNbOfPhiCells", this);
fMeshNbPhiCellsCmd->SetGuidance("Set number of phi cells in the cylindrical mesh readout.");
fMeshNbPhiCellsCmd =
new G4UIcmdWithAnInteger("/Par04/inference/setNbOfPhiCells", this);
fMeshNbPhiCellsCmd->SetGuidance(
"Set number of phi cells in the cylindrical mesh readout.");
fMeshNbPhiCellsCmd->SetParameterName("NbPhiCells", false);
fMeshNbPhiCellsCmd->SetRange("NbPhiCells>0");
fMeshNbPhiCellsCmd->AvailableForStates(G4State_Idle);
fMeshNbPhiCellsCmd->SetToBeBroadcasted(true);
fMeshNbZCellsCmd = new G4UIcmdWithAnInteger("/Par04/inference/setNbOfZCells", this);
fMeshNbZCellsCmd->SetGuidance("Set number of z cells in the cylindrical mesh readout.");
fMeshNbZCellsCmd =
new G4UIcmdWithAnInteger("/Par04/inference/setNbOfZCells", this);
fMeshNbZCellsCmd->SetGuidance(
"Set number of z cells in the cylindrical mesh readout.");
fMeshNbZCellsCmd->SetParameterName("NbZCells", false);
fMeshNbZCellsCmd->SetRange("NbZCells>0");
fMeshNbZCellsCmd->AvailableForStates(G4State_Idle);
fMeshNbZCellsCmd->SetToBeBroadcasted(true);
fMeshSizeRhoCellsCmd = new G4UIcmdWithADoubleAndUnit("/Par04/inference/setSizeOfRhoCells", this);
fMeshSizeRhoCellsCmd->SetGuidance("Set size of rho cells in the cylindrical readout mesh");
fMeshSizeRhoCellsCmd =
new G4UIcmdWithADoubleAndUnit("/Par04/inference/setSizeOfRhoCells", this);
fMeshSizeRhoCellsCmd->SetGuidance(
"Set size of rho cells in the cylindrical readout mesh");
fMeshSizeRhoCellsCmd->SetParameterName("Size", false);
fMeshSizeRhoCellsCmd->SetRange("Size>0.");
fMeshSizeRhoCellsCmd->SetUnitCategory("Length");
fMeshSizeRhoCellsCmd->AvailableForStates(G4State_Idle);
fMeshSizeRhoCellsCmd->SetToBeBroadcasted(true);
fMeshSizeZCellsCmd = new G4UIcmdWithADoubleAndUnit("/Par04/inference/setSizeOfZCells", this);
fMeshSizeZCellsCmd->SetGuidance("Set size of z cells in the cylindrical readout mesh");
fMeshSizeZCellsCmd =
new G4UIcmdWithADoubleAndUnit("/Par04/inference/setSizeOfZCells", this);
fMeshSizeZCellsCmd->SetGuidance(
"Set size of z cells in the cylindrical readout mesh");
fMeshSizeZCellsCmd->SetParameterName("Size", false);
fMeshSizeZCellsCmd->SetRange("Size>0.");
fMeshSizeZCellsCmd->SetUnitCategory("Length");
fMeshSizeZCellsCmd->AvailableForStates(G4State_Idle);
fMeshSizeZCellsCmd->SetToBeBroadcasted(true);
// Onnx Runtime Execution Provider flag commands
fCudaFlagCmd = new G4UIcmdWithAnInteger("/Par04/inference/setCudaFlag", this);
G4cout << "f CudaFlagCmd " << fCudaFlagCmd << G4endl;
fCudaFlagCmd->SetGuidance(
"Whether to use CUDA Execution Provider for Onnx Runtime or not");
fCudaFlagCmd->SetParameterName("CudaFlag", false);
fCudaFlagCmd->SetRange("CudaFlag>-1");
fCudaFlagCmd->AvailableForStates(G4State_Idle);
fCudaFlagCmd->SetToBeBroadcasted(true);
/// OnnxRuntime Execution Provider Options
/// Cuda
fCudaOptionsDir = new G4UIdirectory("/Par04/inference/cuda/");
fCudaOptionsDir->SetGuidance(
"Commands for setting options for Cuda execution provider");
fCudaDeviceIdCmd =
new G4UIcmdWithAString("/Par04/inference/cuda/setDeviceId", this);
fCudaDeviceIdCmd->SetGuidance(
"Device ID of Device on which to run CUDA code");
fCudaDeviceIdCmd->SetParameterName("CudaDeviceId", false);
fCudaDeviceIdCmd->AvailableForStates(G4State_Idle);
fCudaDeviceIdCmd->SetToBeBroadcasted(true);
fCudaGpuMemLimitCmd =
new G4UIcmdWithAString("/Par04/inference/cuda/setGpuMemLimit", this);
fCudaGpuMemLimitCmd->SetGuidance("GPU Memory limit for CUDA");
fCudaGpuMemLimitCmd->SetParameterName("CudaGpuMemLimit", false);
fCudaGpuMemLimitCmd->AvailableForStates(G4State_Idle);
fCudaGpuMemLimitCmd->SetToBeBroadcasted(true);
fCudaArenaExtendedStrategyCmd = new G4UIcmdWithAString(
"/Par04/inference/cuda/setArenaExtendedStrategy", this);
fCudaArenaExtendedStrategyCmd->SetGuidance(
"Strategy for extending the device memory arena for CUDA");
fCudaArenaExtendedStrategyCmd->SetParameterName("CudaArenaExtendedStrategy",
false);
fCudaArenaExtendedStrategyCmd->AvailableForStates(G4State_Idle);
fCudaArenaExtendedStrategyCmd->SetToBeBroadcasted(true);
fCudaCudnnConvAlgoSearchCmd = new G4UIcmdWithAString(
"/Par04/inference/cuda/setCudnnConvAlgoSearch", this);
fCudaCudnnConvAlgoSearchCmd->SetGuidance(
"Set which cuDNN Convolution Operation to use");
fCudaCudnnConvAlgoSearchCmd->SetParameterName("CudaCudnnConvAlgoSearch",
false);
fCudaCudnnConvAlgoSearchCmd->AvailableForStates(G4State_Idle);
fCudaCudnnConvAlgoSearchCmd->SetToBeBroadcasted(true);
fCudaDoCopyInDefaultStreamCmd = new G4UIcmdWithAString(
"/Par04/inference/cuda/setDoCopyInDefaultStream", this);
fCudaDoCopyInDefaultStreamCmd->SetGuidance(
"Whether to use same stream for copying");
fCudaDoCopyInDefaultStreamCmd->SetParameterName("CudaDoCopyInDefaultStream",
false);
fCudaDoCopyInDefaultStreamCmd->AvailableForStates(G4State_Idle);
fCudaDoCopyInDefaultStreamCmd->SetToBeBroadcasted(true);
fCudaCudnnConvUseMaxWorkspaceCmd = new G4UIcmdWithAString(
"/Par04/inference/cuda/setCudnnConvUseMaxWorkspace", this);
fCudaCudnnConvUseMaxWorkspaceCmd->SetGuidance(
"Memory Limit for cuDNN convolution operations");
fCudaCudnnConvUseMaxWorkspaceCmd->SetParameterName(
"CudaCudnnConvUseMaxWorkspace", false);
fCudaCudnnConvUseMaxWorkspaceCmd->AvailableForStates(G4State_Idle);
fCudaCudnnConvUseMaxWorkspaceCmd->SetToBeBroadcasted(true);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04InferenceMessenger::~Par04InferenceMessenger()
{
Par04InferenceMessenger::~Par04InferenceMessenger() {
delete fInferenceLibraryCmd;
delete fSizeLatentVectorCmd;
delete fSizeConditionVectorCmd;
@@ -147,105 +228,120 @@ Par04InferenceMessenger::~Par04InferenceMessenger()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04InferenceMessenger::SetNewValue(G4UIcommand* aCommand, G4String aNewValue)
{
if(aCommand == fInferenceLibraryCmd)
{
void Par04InferenceMessenger::SetNewValue(G4UIcommand *aCommand,
G4String aNewValue) {
if (aCommand == fInferenceLibraryCmd) {
fInference->SetInferenceLibrary(aNewValue);
}
if(aCommand == fSizeLatentVectorCmd)
{
if (aCommand == fSizeLatentVectorCmd) {
fInference->SetSizeLatentVector(std::stoi(aNewValue));
}
if(aCommand == fSizeConditionVectorCmd)
{
if (aCommand == fSizeConditionVectorCmd) {
fInference->SetSizeConditionVector(std::stoi(aNewValue));
}
if(aCommand == fModelPathNameCmd)
{
if (aCommand == fModelPathNameCmd) {
fInference->SetModelPathName(aNewValue);
}
if(aCommand == fProfileFlagCmd)
{
if (aCommand == fProfileFlagCmd) {
fInference->SetProfileFlag(std::stoi(aNewValue));
}
if(aCommand == fOptimizationFlagCmd)
{
if (aCommand == fOptimizationFlagCmd) {
fInference->SetOptimizationFlag(std::stoi(aNewValue));
} else if (aCommand == fMeshNbRhoCellsCmd) {
fInference->SetMeshNbOfCells(0,
fMeshNbRhoCellsCmd->GetNewIntValue(aNewValue));
} else if (aCommand == fMeshNbPhiCellsCmd) {
fInference->SetMeshNbOfCells(1,
fMeshNbPhiCellsCmd->GetNewIntValue(aNewValue));
fInference->SetMeshSizeOfCells(
1, 2. * CLHEP::pi / fMeshNbPhiCellsCmd->GetNewIntValue(aNewValue));
} else if (aCommand == fMeshNbZCellsCmd) {
fInference->SetMeshNbOfCells(2,
fMeshNbZCellsCmd->GetNewIntValue(aNewValue));
} else if (aCommand == fMeshSizeRhoCellsCmd) {
fInference->SetMeshSizeOfCells(
0, fMeshSizeRhoCellsCmd->GetNewDoubleValue(aNewValue));
} else if (aCommand == fMeshSizeZCellsCmd) {
fInference->SetMeshSizeOfCells(
2, fMeshSizeZCellsCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fMeshNbRhoCellsCmd)
{
fInference->SetMeshNbOfCells(0, fMeshNbRhoCellsCmd->GetNewIntValue(aNewValue));
/// Onnx Runtime Execution Provider Flags
/// Cuda
if (aCommand == fCudaFlagCmd) {
fInference->SetCudaFlag(std::stoi(aNewValue));
}
else if(aCommand == fMeshNbPhiCellsCmd)
{
fInference->SetMeshNbOfCells(1, fMeshNbPhiCellsCmd->GetNewIntValue(aNewValue));
fInference->SetMeshSizeOfCells(1,
2. * CLHEP::pi / fMeshNbPhiCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fMeshNbZCellsCmd)
{
fInference->SetMeshNbOfCells(2, fMeshNbZCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fMeshSizeRhoCellsCmd)
{
fInference->SetMeshSizeOfCells(0, fMeshSizeRhoCellsCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fMeshSizeZCellsCmd)
{
fInference->SetMeshSizeOfCells(2, fMeshSizeZCellsCmd->GetNewDoubleValue(aNewValue));
if (aCommand == fCudaDeviceIdCmd) {
fInference->SetCudaDeviceId(aNewValue);
} else if (aCommand == fCudaGpuMemLimitCmd) {
fInference->SetCudaGpuMemLimit(aNewValue);
} else if (aCommand == fCudaArenaExtendedStrategyCmd) {
fInference->SetCudaArenaExtendedStrategy(aNewValue);
} else if (aCommand == fCudaCudnnConvAlgoSearchCmd) {
fInference->SetCudaCudnnConvAlgoSearch(aNewValue);
} else if (aCommand == fCudaDoCopyInDefaultStreamCmd) {
fInference->SetCudaDoCopyInDefaultStream(aNewValue);
} else if (aCommand == fCudaCudnnConvUseMaxWorkspaceCmd) {
fInference->SetCudaCudnnConvUseMaxWorkspace(aNewValue);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4String Par04InferenceMessenger::GetCurrentValue(G4UIcommand* aCommand)
{
G4String Par04InferenceMessenger::GetCurrentValue(G4UIcommand *aCommand) {
G4String cv;
if(aCommand == fInferenceLibraryCmd)
{
cv = fInferenceLibraryCmd->ConvertToString(fInference->GetInferenceLibrary());
if (aCommand == fInferenceLibraryCmd) {
cv = fInferenceLibraryCmd->ConvertToString(
fInference->GetInferenceLibrary());
}
if(aCommand == fSizeLatentVectorCmd)
{
cv = fSizeLatentVectorCmd->ConvertToString(fInference->GetSizeLatentVector());
if (aCommand == fSizeLatentVectorCmd) {
cv = fSizeLatentVectorCmd->ConvertToString(
fInference->GetSizeLatentVector());
}
if(aCommand == fSizeConditionVectorCmd)
{
cv = fSizeConditionVectorCmd->ConvertToString(fInference->GetSizeConditionVector());
if (aCommand == fSizeConditionVectorCmd) {
cv = fSizeConditionVectorCmd->ConvertToString(
fInference->GetSizeConditionVector());
}
if(aCommand == fModelPathNameCmd)
{
if (aCommand == fModelPathNameCmd) {
cv = fModelPathNameCmd->ConvertToString(fInference->GetModelPathName());
}
if(aCommand == fProfileFlagCmd)
{
if (aCommand == fProfileFlagCmd) {
cv = fSizeLatentVectorCmd->ConvertToString(fInference->GetProfileFlag());
}
if(aCommand == fOptimizationFlagCmd)
{
cv = fSizeLatentVectorCmd->ConvertToString(fInference->GetOptimizationFlag());
}
else if(aCommand == fMeshNbRhoCellsCmd)
{
if (aCommand == fOptimizationFlagCmd) {
cv = fSizeLatentVectorCmd->ConvertToString(
fInference->GetOptimizationFlag());
} else if (aCommand == fMeshNbRhoCellsCmd) {
cv = fMeshNbRhoCellsCmd->ConvertToString(fInference->GetMeshNbOfCells()[0]);
}
else if(aCommand == fMeshNbPhiCellsCmd)
{
} else if (aCommand == fMeshNbPhiCellsCmd) {
cv = fMeshNbPhiCellsCmd->ConvertToString(fInference->GetMeshNbOfCells()[1]);
}
else if(aCommand == fMeshNbZCellsCmd)
{
} else if (aCommand == fMeshNbZCellsCmd) {
cv = fMeshNbZCellsCmd->ConvertToString(fInference->GetMeshNbOfCells()[2]);
} else if (aCommand == fMeshSizeRhoCellsCmd) {
cv = fMeshSizeRhoCellsCmd->ConvertToString(
fInference->GetMeshSizeOfCells()[0]);
} else if (aCommand == fMeshSizeZCellsCmd) {
cv = fMeshSizeZCellsCmd->ConvertToString(
fInference->GetMeshSizeOfCells()[2]);
}
else if(aCommand == fMeshSizeRhoCellsCmd)
{
cv = fMeshSizeRhoCellsCmd->ConvertToString(fInference->GetMeshSizeOfCells()[0]);
}
else if(aCommand == fMeshSizeZCellsCmd)
{
cv = fMeshSizeZCellsCmd->ConvertToString(fInference->GetMeshSizeOfCells()[2]);
/// Onnx Runtime Execution Provider Flags
/// Cuda
if (aCommand == fCudaDeviceIdCmd) {
cv = fCudaDeviceIdCmd->ConvertToString(fInference->GetCudaDeviceId());
} else if (aCommand == fCudaGpuMemLimitCmd) {
cv = fCudaGpuMemLimitCmd->ConvertToString(fInference->GetCudaGpuMemLimit());
} else if (aCommand == fCudaArenaExtendedStrategyCmd) {
cv = fCudaArenaExtendedStrategyCmd->ConvertToString(
fInference->GetCudaArenaExtendedStrategy());
} else if (aCommand == fCudaCudnnConvAlgoSearchCmd) {
cv = fCudaCudnnConvAlgoSearchCmd->ConvertToString(
fInference->GetCudaCudnnConvAlgoSearch());
} else if (aCommand == fCudaDoCopyInDefaultStreamCmd) {
cv = fCudaDoCopyInDefaultStreamCmd->ConvertToString(
fInference->GetCudaDoCopyInDefaultStream());
} else if (aCommand == fCudaCudnnConvUseMaxWorkspaceCmd) {
cv = fCudaCudnnConvUseMaxWorkspaceCmd->ConvertToString(
fInference->GetCudaCudnnConvUseMaxWorkspace());
}
return cv;
@@ -24,36 +24,35 @@
// ********************************************************************
//
#ifdef USE_INFERENCE
#include "Par04InferenceInterface.hh" // for Par04InferenceInterface
#include "Par04InferenceMessenger.hh" // for Par04InferenceMessenger
#include "Par04InferenceSetup.hh"
#include "Par04InferenceInterface.hh" // for Par04InferenceInterface
#include "Par04InferenceMessenger.hh" // for Par04InferenceMessenger
#ifdef USE_INFERENCE_ONNX
#include "Par04OnnxInference.hh" // for Par04OnnxInference
#include "Par04OnnxInference.hh" // for Par04OnnxInference
#endif
#ifdef USE_INFERENCE_LWTNN
#include "Par04LwtnnInference.hh" // for Par04LwtnnInference
#include "Par04LwtnnInference.hh" // for Par04LwtnnInference
#endif
#ifdef USE_INFERENCE_TORCH
#include "Par04TorchInference.hh" // for Par04TorchInference
#include "Par04TorchInference.hh" // for Par04TorchInference
#endif
#include <CLHEP/Units/SystemOfUnits.h> // for pi, GeV, deg
#include <CLHEP/Vector/Rotation.h> // for HepRotation
#include <CLHEP/Vector/ThreeVector.h> // for Hep3Vector
#include <G4Exception.hh> // for G4Exception
#include <G4ExceptionSeverity.hh> // for FatalException
#include <G4ThreeVector.hh> // for G4ThreeVector
#include "CLHEP/Random/RandGauss.h" // for RandGauss
#include "G4RotationMatrix.hh" // for G4RotationMatrix
#include <algorithm> // for max, copy
#include <string> // for char_traits, basic_string
#include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <cmath> // for cos, sin
#include "CLHEP/Random/RandGauss.h" // for RandGauss
#include "G4RotationMatrix.hh" // for G4RotationMatrix
#include <CLHEP/Units/SystemOfUnits.h> // for pi, GeV, deg
#include <CLHEP/Vector/Rotation.h> // for HepRotation
#include <CLHEP/Vector/ThreeVector.h> // for Hep3Vector
#include <G4Exception.hh> // for G4Exception
#include <G4ExceptionSeverity.hh> // for FatalException
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <algorithm> // for max, copy
#include <cmath> // for cos, sin
#include <ext/alloc_traits.h> // for __alloc_traits<>::value_type
#include <string> // for char_traits, basic_string
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04InferenceSetup::Par04InferenceSetup()
: fInferenceMessenger(new Par04InferenceMessenger(this))
{}
: fInferenceMessenger(new Par04InferenceMessenger(this)) {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -64,7 +63,7 @@ Par04InferenceSetup::~Par04InferenceSetup() {}
G4bool Par04InferenceSetup::IfTrigger(G4double aEnergy)
{
/// Energy of electrons used in training dataset
if(aEnergy > 1 * CLHEP::GeV || aEnergy < 1024 * CLHEP::GeV)
if (aEnergy > 1 * CLHEP::GeV || aEnergy < 1024 * CLHEP::GeV)
return true;
return false;
}
@@ -76,19 +75,22 @@ void Par04InferenceSetup::SetInferenceLibrary(G4String aName)
fInferenceLibrary = aName;
#ifdef USE_INFERENCE_ONNX
if(fInferenceLibrary == "ONNX")
fInferenceInterface = std::unique_ptr<Par04InferenceInterface>(
new Par04OnnxInference(fModelPathName, fProfileFlag, fOptimizationFlag, fIntraOpNumThreads));
if (fInferenceLibrary == "ONNX")
fInferenceInterface =
std::unique_ptr<Par04InferenceInterface>(new Par04OnnxInference(
fModelPathName, fProfileFlag, fOptimizationFlag, fIntraOpNumThreads,
fCudaFlag, cuda_keys, cuda_values, fModelSavePath,
fProfilingOutputSavePath));
#endif
#ifdef USE_INFERENCE_LWTNN
if(fInferenceLibrary == "LWTNN")
fInferenceInterface =
std::unique_ptr<Par04InferenceInterface>(new Par04LwtnnInference(fModelPathName));
if (fInferenceLibrary == "LWTNN")
fInferenceInterface = std::unique_ptr<Par04InferenceInterface>(
new Par04LwtnnInference(fModelPathName));
#endif
#ifdef USE_INFERENCE_TORCH
if(fInferenceLibrary == "TORCH")
fInferenceInterface =
std::unique_ptr<Par04InferenceInterface>(new Par04TorchInference(fModelPathName));
if (fInferenceLibrary == "TORCH")
fInferenceInterface = std::unique_ptr<Par04InferenceInterface>(
new Par04TorchInference(fModelPathName));
#endif
CheckInferenceLibrary();
@@ -108,14 +110,16 @@ void Par04InferenceSetup::CheckInferenceLibrary()
#ifdef USE_INFERENCE_TORCH
msg += "TORCH";
#endif
if(fInferenceInterface == nullptr)
G4Exception("Par04InferenceSetup::CheckInferenceLibrary()", "InvalidSetup", FatalException,
if (fInferenceInterface == nullptr)
G4Exception("Par04InferenceSetup::CheckInferenceLibrary()", "InvalidSetup",
FatalException,
(msg + "). Current name: " + fInferenceLibrary).c_str());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04InferenceSetup::GetEnergies(std::vector<G4double>& aEnergies, G4double aInitialEnergy,
void Par04InferenceSetup::GetEnergies(std::vector<G4double> &aEnergies,
G4double aInitialEnergy,
G4float aInitialAngle)
{
// First check if inference library was set correctly
@@ -125,26 +129,25 @@ void Par04InferenceSetup::GetEnergies(std::vector<G4double>& aEnergies, G4double
// randomly sample from a gaussian distribution in the latent space
std::vector<G4float> genVector(fSizeLatentVector + fSizeConditionVector, 0);
for(int i = 0; i < fSizeLatentVector; ++i)
for (int i = 0; i < fSizeLatentVector; ++i)
{
genVector[i] = CLHEP::RandGauss::shoot(0., 1.);
}
// Vector of condition
// this is application specific it depdens on what the model was condition on
// and it depends on how the condition values were encoded at the training time
// in this example the energy of each particle is normlaized to the highest
// energy in the considered range (1GeV-500GeV)
// the angle is also is normlaized to the highest angle in the considered range
// (0-90 in dergrees)
// and it depends on how the condition values were encoded at the training
// time in this example the energy of each particle is normlaized to the
// highest energy in the considered range (1GeV-500GeV) the angle is also is
// normlaized to the highest angle in the considered range (0-90 in dergrees)
// the model in this example was trained on two detector geometries PBW04
// and SiW a one hot encoding vector is used to represent the geometry with
// [0,1] for PBW04 and [1,0] for SiW
// 1.energy
// 1. energy
genVector[fSizeLatentVector] = aInitialEnergy / fMaxEnergy;
// 2. angle
genVector[fSizeLatentVector + 1] = (aInitialAngle / (CLHEP::deg)) / fMaxAngle;
// 3.geometry
// 3. geometry
genVector[fSizeLatentVector + 2] = 0;
genVector[fSizeLatentVector + 3] = 1;
@@ -153,7 +156,7 @@ void Par04InferenceSetup::GetEnergies(std::vector<G4double>& aEnergies, G4double
// After the inference rescale back to the initial energy (in this example the
// energies of cells were normalized to the energy of the particle)
for(int i = 0; i < size; ++i)
for (int i = 0; i < size; ++i)
{
aEnergies[i] = aEnergies[i] * aInitialEnergy;
}
@@ -161,7 +164,8 @@ void Par04InferenceSetup::GetEnergies(std::vector<G4double>& aEnergies, G4double
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04InferenceSetup::GetPositions(std::vector<G4ThreeVector>& aPositions, G4ThreeVector pos0,
void Par04InferenceSetup::GetPositions(std::vector<G4ThreeVector> &aPositions,
G4ThreeVector pos0,
G4ThreeVector direction)
{
aPositions.resize(fMeshNumber.x() * fMeshNumber.y() * fMeshNumber.z());
@@ -169,27 +173,31 @@ void Par04InferenceSetup::GetPositions(std::vector<G4ThreeVector>& aPositions, G
// 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 = direction.theta();
double particlePhi = direction.phi();
double particleTheta = direction.theta();
double particlePhi = direction.phi();
rotMatrix.rotateZ(-particlePhi);
rotMatrix.rotateY(-particleTheta);
G4RotationMatrix rotMatrixInv = CLHEP::inverseOf(rotMatrix);
int cpt = 0;
for(G4int iCellR = 0; iCellR < fMeshNumber.x(); iCellR++)
for (G4int iCellR = 0; iCellR < fMeshNumber.x(); iCellR++)
{
for(G4int iCellPhi = 0; iCellPhi < fMeshNumber.y(); iCellPhi++)
for (G4int iCellPhi = 0; iCellPhi < fMeshNumber.y(); iCellPhi++)
{
for(G4int iCellZ = 0; iCellZ < fMeshNumber.z(); iCellZ++)
for (G4int iCellZ = 0; iCellZ < fMeshNumber.z(); iCellZ++)
{
aPositions[cpt] =
pos0 +
rotMatrixInv *
G4ThreeVector((iCellR + 0.5) * fMeshSize.x() *
std::cos((iCellPhi + 0.5) * 2 * CLHEP::pi / fMeshNumber.y() - CLHEP::pi),
(iCellR + 0.5) * fMeshSize.x() *
std::sin((iCellPhi + 0.5) * 2 * CLHEP::pi / fMeshNumber.y() - CLHEP::pi),
(iCellZ + 0.5) * fMeshSize.z());
pos0 +
rotMatrixInv *
G4ThreeVector((iCellR + 0.5) * fMeshSize.x() *
std::cos((iCellPhi + 0.5) * 2 * CLHEP::pi /
fMeshNumber.y() -
CLHEP::pi),
(iCellR + 0.5) * fMeshSize.x() *
std::sin((iCellPhi + 0.5) * 2 * CLHEP::pi /
fMeshNumber.y() -
CLHEP::pi),
(iCellZ + 0.5) * fMeshSize.z());
cpt++;
}
}
@@ -43,7 +43,8 @@ Par04LwtnnInference::Par04LwtnnInference(G4String modelPath)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04LwtnnInference::RunInference(std::vector<float> aGenVector, std::vector<G4double>& aEnergies,
void Par04LwtnnInference::RunInference(std::vector<float> aGenVector,
std::vector<G4double>& aEnergies,
int aSize)
{
// generation vector
@@ -45,7 +45,9 @@ Par04MLFastSimModel::Par04MLFastSimModel(G4String aModelName, G4Region* aEnvelop
: G4VFastSimulationModel(aModelName, aEnvelope)
, fInference(new Par04InferenceSetup)
, fHitMaker(new G4FastSimHitMaker)
{}
, fParallelHitMaker(new G4FastSimHitMaker) {
fParallelHitMaker->SetNameOfWorldWithSD("parallelWorldFastSim");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -53,7 +55,10 @@ Par04MLFastSimModel::Par04MLFastSimModel(G4String aModelName)
: G4VFastSimulationModel(aModelName)
, fInference(new Par04InferenceSetup)
, fHitMaker(new G4FastSimHitMaker)
{}
, fParallelHitMaker(new G4FastSimHitMaker) {
fParallelHitMaker->SetNameOfWorldWithSD("parallelWorldFastSim");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04MLFastSimModel::~Par04MLFastSimModel() {}
@@ -98,7 +103,12 @@ void Par04MLFastSimModel::DoIt(const G4FastTrack& aFastTrack, G4FastStep& aFastS
// and positions
for(size_t iHit = 0; iHit < fPositions.size(); iHit++)
{
fHitMaker->make(G4FastHit(fPositions[iHit], fEnergies[iHit]), aFastTrack);
if (fEnergies[iHit] > 0.0005) {
// Place hit in the physical readout of the detector
fParallelHitMaker->make(G4FastHit(fPositions[iHit], fEnergies[iHit]), aFastTrack);
// Place hit in the virtual grid, for validation purposes
fHitMaker->make(G4FastHit(fPositions[iHit], fEnergies[iHit]), aFastTrack);
}
}
}
#endif
@@ -24,103 +24,143 @@
// ********************************************************************
//
#ifdef USE_INFERENCE_ONNX
#include "Par04InferenceInterface.hh" // for Par04InferenceInterface
#include "Par04OnnxInference.hh"
#include <core/session/onnxruntime_cxx_api.h> // for Value, Session, Env
#include <algorithm> // for copy, max
#include <cassert> // for assert
#include <cstddef> // for size_t
#include <cstdint> // for int64_t
#include <utility> // for move
#include "Par04InferenceInterface.hh" // for Par04InferenceInterface
#include <algorithm> // for copy, max
#include <cassert> // for assert
#include <core/session/onnxruntime_cxx_api.h> // for Value, Session, Env
#include <cstddef> // for size_t
#include <cstdint> // for int64_t
#include <utility> // for move
#ifdef USE_CUDA
#include "cuda_runtime_api.h"
#endif
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04OnnxInference::Par04OnnxInference(G4String modelPath, G4int profileFlag, G4int optimizeFlag,
G4int intraOpNumThreads)
: Par04InferenceInterface()
{
Par04OnnxInference::Par04OnnxInference(G4String modelPath, G4int profileFlag,
G4int optimizeFlag,
G4int intraOpNumThreads, G4int cudaFlag,
std::vector<const char *> &cuda_keys,
std::vector<const char *> &cuda_values,
G4String ModelSavePath,
G4String profilingOutputSavePath)
: Par04InferenceInterface() {
// initialization of the enviroment and inference session
auto envLocal = std::make_unique<Ort::Env>(ORT_LOGGING_LEVEL_WARNING, "ENV");
fEnv = std::move(envLocal);
fEnv = std::move(envLocal);
// Creating a OrtApi Class variable for getting access to C api, necessary for
// CUDA
const auto &ortApi = Ort::GetApi();
fSessionOptions.SetIntraOpNumThreads(intraOpNumThreads);
// graph optimizations of the model
// if the flag is not set to true none of the optimizations will be applied
// if it is set to true all the optimizations will be applied
if(optimizeFlag)
{
if (optimizeFlag) {
fSessionOptions.SetOptimizedModelFilePath("opt-graph");
fSessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_ALL);
// ORT_ENABLE_BASIC #### ORT_ENABLE_EXTENDED
}
else
} else
fSessionOptions.SetGraphOptimizationLevel(ORT_DISABLE_ALL);
#ifdef USE_CUDA
if (cudaFlag) {
OrtCUDAProviderOptionsV2 *fCudaOptions = nullptr;
// Initialize the CUDA provider options, fCudaOptions should now point to a
// valid CUDA configuration.
(void)ortApi.CreateCUDAProviderOptions(&fCudaOptions);
// Update the CUDA provider options
(void)ortApi.UpdateCUDAProviderOptions(
fCudaOptions, cuda_keys.data(), cuda_values.data(), cuda_keys.size());
// Append the CUDA execution provider to the session options, indicating to
// use CUDA for execution
(void)ortApi.SessionOptionsAppendExecutionProvider_CUDA_V2(fSessionOptions,
fCudaOptions);
}
#endif
// save json file for model execution profiling
if(profileFlag)
if (profileFlag)
fSessionOptions.EnableProfiling("opt.json");
auto sessionLocal = std::make_unique<Ort::Session>(*fEnv, modelPath, fSessionOptions);
fSession = std::move(sessionLocal);
fInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemTypeDefault);
auto sessionLocal =
std::make_unique<Ort::Session>(*fEnv, modelPath, fSessionOptions);
fSession = std::move(sessionLocal);
fInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator,
OrtMemTypeDefault);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04OnnxInference::RunInference(std::vector<float> aGenVector, std::vector<G4double>& aEnergies,
int aSize)
{
void Par04OnnxInference::RunInference(std::vector<float> aGenVector,
std::vector<G4double> &aEnergies,
int aSize) {
// input nodes
Ort::AllocatorWithDefaultOptions allocator;
#if ORT_API_VERSION < 13
// Before 1.13 we have to roll our own unique_ptr wrapper here
auto allocDeleter = [&allocator](char *p) { allocator.Free(p); };
using AllocatedStringPtr = std::unique_ptr<char, decltype(allocDeleter)>;
#endif
std::vector<int64_t> input_node_dims;
size_t num_input_nodes = fSession->GetInputCount();
std::vector<const char*> input_node_names(num_input_nodes);
for(std::size_t i = 0; i < num_input_nodes; i++)
{
char* input_name = fSession->GetInputName(i, allocator);
fInames = { input_name };
input_node_names[i] = input_name;
Ort::TypeInfo type_info = fSession->GetInputTypeInfo(i);
auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
input_node_dims = tensor_info.GetShape();
for(std::size_t j = 0; j < input_node_dims.size(); j++)
{
if(input_node_dims[j] < 0)
std::vector<const char *> input_node_names(num_input_nodes);
for (std::size_t i = 0; i < num_input_nodes; i++) {
#if ORT_API_VERSION < 13
const auto input_name =
AllocatedStringPtr(fSession->GetInputName(i, allocator), allocDeleter)
.release();
#else
const auto input_name =
fSession->GetInputNameAllocated(i, allocator).release();
#endif
fInames = {input_name};
input_node_names[i] = input_name;
Ort::TypeInfo type_info = fSession->GetInputTypeInfo(i);
auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
input_node_dims = tensor_info.GetShape();
for (std::size_t j = 0; j < input_node_dims.size(); j++) {
if (input_node_dims[j] < 0)
input_node_dims[j] = 1;
}
}
// output nodes
std::vector<int64_t> output_node_dims;
size_t num_output_nodes = fSession->GetOutputCount();
std::vector<const char*> output_node_names(num_output_nodes);
for(std::size_t i = 0; i < num_output_nodes; i++)
{
char* output_name = fSession->GetOutputName(i, allocator);
output_node_names[i] = output_name;
Ort::TypeInfo type_info = fSession->GetOutputTypeInfo(i);
auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
output_node_dims = tensor_info.GetShape();
for(std::size_t j = 0; j < output_node_dims.size(); j++)
{
if(output_node_dims[j] < 0)
std::vector<const char *> output_node_names(num_output_nodes);
for (std::size_t i = 0; i < num_output_nodes; i++) {
#if ORT_API_VERSION < 13
const auto output_name =
AllocatedStringPtr(fSession->GetOutputName(i, allocator), allocDeleter)
.release();
#else
const auto output_name =
fSession->GetOutputNameAllocated(i, allocator).release();
#endif
output_node_names[i] = output_name;
Ort::TypeInfo type_info = fSession->GetOutputTypeInfo(i);
auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
output_node_dims = tensor_info.GetShape();
for (std::size_t j = 0; j < output_node_dims.size(); j++) {
if (output_node_dims[j] < 0)
output_node_dims[j] = 1;
}
}
// create input tensor object from data values
std::vector<int64_t> dims = { 1, (unsigned) (aGenVector.size()) };
Ort::Value Input_noise_tensor =
Ort::Value::CreateTensor<float>(fInfo, aGenVector.data(), aGenVector.size(), dims.data(), dims.size());
std::vector<int64_t> dims = {1, (unsigned)(aGenVector.size())};
Ort::Value Input_noise_tensor = Ort::Value::CreateTensor<float>(
fInfo, aGenVector.data(), aGenVector.size(), dims.data(), dims.size());
assert(Input_noise_tensor.IsTensor());
std::vector<Ort::Value> ort_inputs;
ort_inputs.push_back(std::move(Input_noise_tensor));
// run the inference session
std::vector<Ort::Value> ort_outputs =
fSession->Run(Ort::RunOptions{ nullptr }, fInames.data(), ort_inputs.data(), ort_inputs.size(),
output_node_names.data(), output_node_names.size());
std::vector<Ort::Value> ort_outputs = fSession->Run(
Ort::RunOptions{nullptr}, fInames.data(), ort_inputs.data(),
ort_inputs.size(), output_node_names.data(), output_node_names.size());
// get pointer to output tensor float values
float* floatarr = ort_outputs.front().GetTensorMutableData<float>();
float *floatarr = ort_outputs.front().GetTensorMutableData<float>();
aEnergies.assign(aSize, 0);
for(int i = 0; i < aSize; ++i)
for (int i = 0; i < aSize; ++i)
aEnergies[i] = floatarr[i];
}
@@ -0,0 +1,144 @@
//
// ********************************************************************
// * 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 "Par04ParallelFastSensitiveDetector.hh"
#include <CLHEP/Vector/Rotation.h> // for HepRotation
#include <CLHEP/Vector/ThreeVector.h> // for Hep3Vector
#include <cmath> // for floor
#include <G4CollectionNameVector.hh> // for G4CollectionNameVector
#include <G4FastHit.hh> // for G4FastHit
#include <G4FastTrack.hh> // for G4FastTrack
#include <G4RotationMatrix.hh> // for G4RotationMatrix
#include <G4StepPoint.hh> // for G4StepPoint
#include <G4THitsCollection.hh> // for G4THitsCollection
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4VSensitiveDetector.hh> // for G4VSensitiveDetector
#include <G4VUserEventInformation.hh> // for G4VUserEventInformation
#include <cstddef> // for size_t
#include <vector> // for vector
#include "G4Event.hh" // for G4Event
#include "G4EventManager.hh" // for G4EventManager
#include "G4HCofThisEvent.hh" // for G4HCofThisEvent
#include "G4SDManager.hh" // for G4SDManager
#include "G4Step.hh" // for G4Step
#include "G4Track.hh" // for G4Track
#include "Par04EventInformation.hh" // for Par04EventInformation
#include "Par04Hit.hh" // for Par04Hit, Par04HitsCollection
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFastSensitiveDetector::Par04ParallelFastSensitiveDetector(G4String aName)
: G4VSensitiveDetector(aName)
{
collectionName.insert("physicalCellsFastSim");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFastSensitiveDetector::Par04ParallelFastSensitiveDetector(G4String aName,
G4int aNbOfLayers,
G4int aNbOfSlices)
: G4VSensitiveDetector(aName)
, fNbOfLayers(aNbOfLayers)
, fNbOfSlices(aNbOfSlices)
{
collectionName.insert("physicalCellsFastSim");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFastSensitiveDetector::~Par04ParallelFastSensitiveDetector() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFastSensitiveDetector::Initialize(G4HCofThisEvent* aHCE)
{
fHitsCollection = new Par04HitsCollection(SensitiveDetectorName, collectionName[0]);
if(fHitCollectionID < 0)
{
fHitCollectionID = G4SDManager::GetSDMpointer()->GetCollectionID(fHitsCollection);
}
aHCE->AddHitsCollection(fHitCollectionID, fHitsCollection);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04ParallelFastSensitiveDetector::ProcessHits(G4Step*, G4TouchableHistory* )
{
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04ParallelFastSensitiveDetector::ProcessHits(const G4FastHit* aHit,
const G4FastTrack*,
G4TouchableHistory* aTouchable)
{
G4double edep = aHit->GetEnergy();
if(edep == 0.)
return true;
G4int layerNo = aTouchable->GetCopyNumber(0);
G4int sliceNo = aTouchable->GetCopyNumber(1);
G4int rowNo = aTouchable->GetCopyNumber(2);
G4int hitID = fNbOfLayers*fNbOfSlices*rowNo+fNbOfLayers*sliceNo+layerNo;
auto hit = fHitsMap[hitID].get();
if (hit==nullptr) {
fHitsMap[hitID] = std::unique_ptr<Par04Hit>(new Par04Hit());
hit = fHitsMap[hitID].get();
hit->SetPhiId(sliceNo);
hit->SetRhoId(layerNo);
hit->SetZid(rowNo);
}
if (layerNo != hit->GetRhoId()) {
G4cout << "ERROR, problem with Layer IDs: " << layerNo << " != " << hit->GetRhoId() << G4endl;
return false;
}
if (sliceNo != hit->GetPhiId()) {
G4cout << "ERROR, problem with Slice IDs: " << sliceNo << " != " << hit->GetPhiId() << G4endl;
return false;
}
if (rowNo != hit->GetZid()) {
G4cout << "ERROR, problem with Row IDs: " << rowNo << " != " << hit->GetZid() << G4endl;
return false;
}
// Add energy deposit from G4Step
hit->AddEdep(edep);
// Increment the counter
hit->AddNdep(1);
// Set hit type to parallel world fast simulation (even if hit was already marked as full
// sim, overwrite it)
hit->SetType(3);
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFastSensitiveDetector::EndOfEvent(G4HCofThisEvent*)
{
for(const auto& hits: fHitsMap){
fHitsCollection->insert(new Par04Hit(*hits.second.get()));
}
fHitsMap.clear();
}
@@ -0,0 +1,213 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// User Classes
#include "Par04ParallelFastWorld.hh"
#include "Par04ParallelFullWorld.hh"
#include "Par04ParallelFastSensitiveDetector.hh"
// G4 Classes
#include "G4NistManager.hh"
#include "G4Material.hh"
#include "G4ThreeVector.hh"
#include "G4PVPlacement.hh"
#include "G4PVReplica.hh"
#include "G4VPhysicalVolume.hh"
#include "G4LogicalVolume.hh"
#include "G4Tubs.hh"
#include "G4SDManager.hh"
#include "G4VisAttributes.hh"
#include "G4Colour.hh"
#include "G4SystemOfUnits.hh"
#include "G4AutoDelete.hh"
#include "globals.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFastWorld::Par04ParallelFastWorld(G4String aWorldName,
const Par04DetectorConstruction* aMassDetector,
const Par04ParallelFullWorld* aParallelFull)
:G4VUserParallelWorld(aWorldName), fMassDetector(aMassDetector), fParallelFull(aParallelFull) {
fNbOfLayers = fMassDetector->GetNbOfLayers();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFastWorld::~Par04ParallelFastWorld() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFastWorld::Construct()
{
// In parallel world material does not matter
G4Material* dummy = nullptr;
// Build parallel geometry:
auto parallelLogicalVolume = GetWorld()->GetLogicalVolume();
G4double detectorInnerRadius = fMassDetector->GetInnerRadius();
G4double detectorLength = fMassDetector->GetLength();
G4double fullLayerThickness = fMassDetector->GetAbsorberThickness(0)
+ fMassDetector->GetAbsorberThickness(1);
fLayerThickness = fullLayerThickness;
// Get an updated value
fNbOfLayers = fMassDetector->GetNbOfLayers();
fNbOfSlices = fParallelFull->GetNbOfSlices();
fNbOfRows = fParallelFull->GetNbOfRows();
G4double detectorRadius = fNbOfLayers * fullLayerThickness;
G4double detectorOuterRadius = detectorInnerRadius + detectorRadius;
G4double rowThickness = detectorLength / fNbOfRows;
G4double full2Pi = 2.* CLHEP::pi * rad;
Print();
// Insert cells to create a readout structure that contains both passive and active materials
// Mostly a copy from the detector construction
auto solidDetector = new G4Tubs("Detector", // name
detectorInnerRadius, // inner radius
detectorOuterRadius, // outer radius
detectorLength / 2., // half-width in Z
0, // start angle
full2Pi); // delta angle
auto logicDetector = new G4LogicalVolume(solidDetector, // solid
dummy, // material
"Detector"); // name
new G4PVPlacement(0, // no rotation
G4ThreeVector(0, 0, 0), // detector centre at (0,0,0)
logicDetector, // logical volume
"Detector", // name
parallelLogicalVolume, // mother volume
false, // not used
9999, // copy number
true); // check overlaps
//--------- Detector cylinder (division along z axis) ---------
auto solidRow = new G4Tubs("Row", detectorInnerRadius, detectorOuterRadius, rowThickness / 2.,
0, full2Pi);
auto logicRow = new G4LogicalVolume(solidRow, dummy, "Row");
if (fNbOfRows > 1)
new G4PVReplica("Row",
logicRow,
logicDetector,
kZAxis,
fNbOfRows,
rowThickness);
else
new G4PVPlacement(0,
G4ThreeVector(),
logicRow,
"Row",
logicDetector,
false,
0);
//--------- Detector slices (division in azimuthal angle) ---------
G4double cellPhi = full2Pi / fNbOfSlices;
auto solidSlice = new G4Tubs("Slice", detectorInnerRadius, detectorOuterRadius, rowThickness/2,
0, cellPhi);
auto logicSlice = new G4LogicalVolume(solidSlice,
dummy,
"Slice");
if(fNbOfSlices>1) {
new G4PVReplica("Slice",
logicSlice,
logicRow,
kPhi,
fNbOfSlices,
cellPhi,
-cellPhi);
} else {
new G4PVPlacement(0,
G4ThreeVector(),
logicSlice,
"Slice",
logicRow,
false,
0);
}
//--------- Detector cells (division along radial axis) ---------
G4VisAttributes attribs;
attribs.SetColour(G4Colour(0, 1, 0, 0.1));
attribs.SetForceSolid(true);
if(fNbOfLayers>1) {
auto solidCell = new G4Tubs("Cell", detectorInnerRadius,
detectorInnerRadius + fLayerThickness,
rowThickness/2, 0, cellPhi);
fLogicalCell.push_back(new G4LogicalVolume(solidCell, dummy, "Cell_0"));
new G4PVReplica("Cell",
fLogicalCell.back(),
logicSlice,
kRho,
fNbOfLayers,
fLayerThickness,
detectorInnerRadius);
} else {
auto solidCell = new G4Tubs("Cell", detectorInnerRadius,
detectorInnerRadius + fLayerThickness,
rowThickness/2, 0, cellPhi);
fLogicalCell.push_back(new G4LogicalVolume(solidCell, dummy, "Cell"));
fLogicalCell.back()->SetVisAttributes(attribs);
new G4PVPlacement(0,
G4ThreeVector(),
fLogicalCell.back(),
"Cell",
logicSlice,
false,
0);
}
Print();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFastWorld::ConstructSD()
{
// -- sensitive detectors:
G4SDManager* SDman = G4SDManager::GetSDMpointer();
Par04ParallelFastSensitiveDetector* caloSD =
new Par04ParallelFastSensitiveDetector("parallelFastSD", fNbOfLayers, fNbOfSlices);
SDman->AddNewDetector(caloSD);
for(const auto& logicalCell: fLogicalCell)
logicalCell->SetSensitiveDetector(caloSD);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFastWorld::Print() {
G4cout << "\n------------------------------------------------------"
<< "\n Readout geometry with physics layout is set in parallel geometry:\t"
<< "\n Cylindrical detector is divided along radius (layers), phi (slices), and z (rows)."
<< "\n Number of layers is determined by number of layers set in detector construction. "
<< "\n- Number of layers: " << fNbOfLayers << "\n------- Number of slices: " << fNbOfSlices
<< "\n- Number of rows: " << fNbOfRows;
G4cout << "\n Readout will collect energy from fast simulation.\n------- Thickness is "
<< "a sum of all absorbers" << " = " << G4BestUnit(fLayerThickness, "Length")
<< "\n-----------------------------------------------------" << G4endl;
}
@@ -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 "Par04ParallelFullSensitiveDetector.hh"
#include <CLHEP/Vector/Rotation.h> // for HepRotation
#include <CLHEP/Vector/ThreeVector.h> // for Hep3Vector
#include <cmath> // for floor
#include <G4CollectionNameVector.hh> // for G4CollectionNameVector
#include <G4FastHit.hh> // for G4FastHit
#include <G4FastTrack.hh> // for G4FastTrack
#include <G4RotationMatrix.hh> // for G4RotationMatrix
#include <G4StepPoint.hh> // for G4StepPoint
#include <G4THitsCollection.hh> // for G4THitsCollection
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4VSensitiveDetector.hh> // for G4VSensitiveDetector
#include <G4VUserEventInformation.hh> // for G4VUserEventInformation
#include <cstddef> // for size_t
#include <vector> // for vector
#include "G4Event.hh" // for G4Event
#include "G4EventManager.hh" // for G4EventManager
#include "G4HCofThisEvent.hh" // for G4HCofThisEvent
#include "G4SDManager.hh" // for G4SDManager
#include "G4Step.hh" // for G4Step
#include "G4Track.hh" // for G4Track
#include "Par04EventInformation.hh" // for Par04EventInformation
#include "Par04Hit.hh" // for Par04Hit, Par04HitsCollection
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFullSensitiveDetector::Par04ParallelFullSensitiveDetector(G4String aName)
: G4VSensitiveDetector(aName)
{
collectionName.insert("physicalCellsFullSim");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFullSensitiveDetector::Par04ParallelFullSensitiveDetector(G4String aName,
G4int aNbOfLayers,
G4int aNbOfSlices,
G4int aNbOfRows)
: G4VSensitiveDetector(aName)
, fNbOfLayers(aNbOfLayers)
, fNbOfSlices(aNbOfSlices)
, fNbOfRows(aNbOfRows)
{
collectionName.insert("physicalCellsFullSim");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFullSensitiveDetector::~Par04ParallelFullSensitiveDetector() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFullSensitiveDetector::Initialize(G4HCofThisEvent* aHCE)
{
fHitsCollection = new Par04HitsCollection(SensitiveDetectorName, collectionName[0]);
if(fHitCollectionID < 0)
{
fHitCollectionID = G4SDManager::GetSDMpointer()->GetCollectionID(fHitsCollection);
}
aHCE->AddHitsCollection(fHitCollectionID, fHitsCollection);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04ParallelFullSensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*)
{
G4double edep = aStep->GetTotalEnergyDeposit();
if(edep == 0.)
return true;
auto touchable = (G4TouchableHistory*)(aStep->GetPreStepPoint()->GetTouchable());
G4int layerNo = touchable->GetCopyNumber(0);
G4int sliceNo = touchable->GetCopyNumber(1);
G4int rowNo = touchable->GetCopyNumber(2);
G4int hitID = fNbOfLayers*fNbOfSlices*rowNo+fNbOfLayers*sliceNo+layerNo;
if (layerNo >= fNbOfLayers) {
G4cout << "ERROR, problem with Layer IDs: " << layerNo << " > " << fNbOfLayers << G4endl;
return false;
}
if (sliceNo >= fNbOfSlices) {
G4cout << "ERROR, problem with Slice IDs: " << sliceNo << " >= " << fNbOfSlices << G4endl;
return false;
}
if (rowNo >= fNbOfRows) {
G4cout << "ERROR, problem with Row IDs: " << rowNo << " >= " << fNbOfRows << G4endl;
return false;
}
auto hit = fHitsMap[hitID].get();
if (hit==nullptr) {
fHitsMap[hitID] = std::unique_ptr<Par04Hit>(new Par04Hit());
hit = fHitsMap[hitID].get();
hit->SetPhiId(sliceNo);
hit->SetRhoId(layerNo);
hit->SetZid(rowNo);
}
// Add energy deposit from G4Step
hit->AddEdep(edep);
// Increment the counter
hit->AddNdep(1);
// 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 type to parallel world full hit
hit->SetType(2);
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFullSensitiveDetector::EndOfEvent(G4HCofThisEvent*)
{
for(const auto& hits: fHitsMap){
fHitsCollection->insert(new Par04Hit(*hits.second.get()));
}
fHitsMap.clear();
}
@@ -0,0 +1,228 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// User Classes
#include "Par04ParallelFullWorld.hh"
#include "Par04ParallelMessenger.hh"
#include "Par04ParallelFullSensitiveDetector.hh"
// G4 Classes
#include "G4NistManager.hh"
#include "G4Material.hh"
#include "G4ThreeVector.hh"
#include "G4PVPlacement.hh"
#include "G4PVReplica.hh"
#include "G4VPhysicalVolume.hh"
#include "G4LogicalVolume.hh"
#include "G4Tubs.hh"
#include "G4SDManager.hh"
#include "G4VisAttributes.hh"
#include "G4Colour.hh"
#include "G4SystemOfUnits.hh"
#include "G4AutoDelete.hh"
#include "globals.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFullWorld::Par04ParallelFullWorld(G4String aWorldName,
const Par04DetectorConstruction* aMassDetector)
:G4VUserParallelWorld(aWorldName), fMassDetector(aMassDetector) {
fParallelMessenger = new Par04ParallelMessenger(this);
fNbOfLayers = fMassDetector->GetNbOfLayers();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelFullWorld::~Par04ParallelFullWorld() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFullWorld::Construct()
{
// In parallel world material does not matter
G4Material* dummy = nullptr;
// Build parallel geometry:
auto parallelLogicalVolume = GetWorld()->GetLogicalVolume();
G4double detectorInnerRadius = fMassDetector->GetInnerRadius();
G4double detectorLength = fMassDetector->GetLength();
G4double fullLayerThickness = fMassDetector->GetAbsorberThickness(0)
+ fMassDetector->GetAbsorberThickness(1);
G4double sensitiveLayerOffset = 0;
if(fMassDetector->GetAbsorberSensitivity(0))
fLayerThickness = fMassDetector->GetAbsorberThickness(0);
else
sensitiveLayerOffset = fMassDetector->GetAbsorberThickness(0);
if(fMassDetector->GetAbsorberSensitivity(1))
fLayerThickness += fMassDetector->GetAbsorberThickness(1);
fNbOfLayers = fMassDetector->GetNbOfLayers(); // Get an updated value
G4double detectorRadius = fNbOfLayers * fullLayerThickness;
G4double detectorOuterRadius = detectorInnerRadius + detectorRadius;
G4double rowThickness = detectorLength / fNbOfRows;
G4double full2Pi = 2.* CLHEP::pi * rad;
Print();
// Insert cells to create a readout structure that contains both passive and active materials
// Mostly a copy from the detector construction
auto solidDetector = new G4Tubs("Detector", // name
detectorInnerRadius, // inner radius
detectorOuterRadius, // outer radius
detectorLength / 2., // half-width in Z
0, // start angle
full2Pi); // delta angle
auto logicDetector = new G4LogicalVolume(solidDetector, // solid
dummy, // material
"Detector"); // name
new G4PVPlacement(0, // no rotation
G4ThreeVector(0, 0, 0), // detector centre at (0,0,0)
logicDetector, // logical volume
"Detector", // name
parallelLogicalVolume, // mother volume
false, // not used
9999, // copy number
true); // check overlaps
//--------- Detector cylinder (division along z axis) ---------
auto solidRow = new G4Tubs("Row", detectorInnerRadius, detectorOuterRadius, rowThickness / 2.,
0, full2Pi);
auto logicRow = new G4LogicalVolume(solidRow, dummy, "Row");
if (fNbOfRows > 1)
new G4PVReplica("Row",
logicRow,
logicDetector,
kZAxis,
fNbOfRows,
rowThickness);
else
new G4PVPlacement(0,
G4ThreeVector(),
logicRow,
"Row",
logicDetector,
false,
0);
//--------- Detector slices (division in azimuthal angle) ---------
G4double cellPhi = full2Pi / fNbOfSlices;
auto solidSlice = new G4Tubs("Slice", detectorInnerRadius, detectorOuterRadius, rowThickness/2,
0, cellPhi);
auto logicSlice = new G4LogicalVolume(solidSlice,
dummy,
"Slice");
if(fNbOfLayers>1 && fullLayerThickness == fLayerThickness) {
new G4PVReplica("Slice",
logicSlice,
logicRow,
kPhi,
fNbOfSlices,
cellPhi,
-cellPhi);
} else {
// full simulation readout, cannot use replica because of gaps between absorbers
for (int iSlice = 0; iSlice<fNbOfSlices; iSlice++) {
auto rotation = new G4RotationMatrix();
rotation->setPhi((iSlice+0.5)*cellPhi);
new G4PVPlacement(rotation,
G4ThreeVector(),
logicSlice,
"Slice_"+std::to_string(iSlice),
logicRow,
false,
iSlice);
}
}
//--------- Detector cells (division along radial axis) ---------
G4VisAttributes attribs;
attribs.SetColour(G4Colour(0, 1, 0, 0.1));
attribs.SetForceSolid(true);
if(fNbOfLayers>1 && fullLayerThickness == fLayerThickness) {
auto solidCell = new G4Tubs("Cell", detectorInnerRadius + sensitiveLayerOffset,
detectorInnerRadius + sensitiveLayerOffset + fLayerThickness,
rowThickness/2, 0, cellPhi);
fLogicalCell.push_back(new G4LogicalVolume(solidCell, dummy, "Cell_0"));
new G4PVReplica("Cell",
fLogicalCell.back(),
logicSlice,
kRho,
fNbOfLayers,
fLayerThickness,
detectorInnerRadius);
} else {
// full simulation readout, cannot use replica because of gaps between absorbers
for (int iLayer = 0; iLayer<fNbOfLayers; iLayer++) {
auto solidCell = new G4Tubs("Cell_"+std::to_string(iLayer),
detectorInnerRadius + iLayer * fullLayerThickness
+ sensitiveLayerOffset,
detectorInnerRadius + iLayer * fullLayerThickness
+ sensitiveLayerOffset + fLayerThickness,
rowThickness/2, 0, cellPhi);
fLogicalCell.push_back(new G4LogicalVolume(solidCell, dummy, "Cell_"+std::to_string(iLayer)));
fLogicalCell.back()->SetVisAttributes(attribs);
new G4PVPlacement(0,
G4ThreeVector(),
fLogicalCell.back(),
"Cell_"+std::to_string(iLayer),
logicSlice,
false,
iLayer);
}
}
Print();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFullWorld::ConstructSD()
{
// -- sensitive detectors:
G4SDManager* SDman = G4SDManager::GetSDMpointer();
Par04ParallelFullSensitiveDetector* caloSD =
new Par04ParallelFullSensitiveDetector("parallelFullSD", fNbOfLayers, fNbOfSlices, fNbOfRows);
SDman->AddNewDetector(caloSD);
for(const auto& logicalCell: fLogicalCell)
logicalCell->SetSensitiveDetector(caloSD);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelFullWorld::Print() {
G4cout << "\n------------------------------------------------------"
<< "\n Readout geometry with physics layout is set in parallel geometry:\t"
<< "\n Cylindrical detector is divided along radius (layers), phi (slices), and z (rows)."
<< "\n Number of layers is determined by number of layers set in detector construction. "
<< "\n- Number of layers: " << fNbOfLayers << "\n------- Number of slices: " << fNbOfSlices
<< "\n- Number of rows: " << fNbOfRows;
G4cout << "\n Readout will collect energy for full simulation.\n------- Therefore thickness is "
<< "only a thickness of sensitive absorbers = " << G4BestUnit(fLayerThickness, "Length")
<< "\n-----------------------------------------------------" << G4endl;
}
@@ -0,0 +1,116 @@
//
// ********************************************************************
// * 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 "Par04ParallelMessenger.hh"
#include <CLHEP/Units/SystemOfUnits.h> // for pi
#include <G4ApplicationState.hh> // for G4State_PreInit, G4State_Idle
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4Types.hh> // for G4bool, G4double, G4int
#include <G4UIcommand.hh> // for G4UIcommand
#include <G4UImessenger.hh> // for G4UImessenger
#include <G4UIparameter.hh> // for G4UIparameter
#include <istream> // for basic_istream, basic_istream...
#include <string> // for operator>>
#include "G4UIcmdWithAnInteger.hh" // for G4UIcmdWithAnInteger
#include "G4UIcmdWithoutParameter.hh" // for G4UIcmdWithoutParameter
#include "G4UIcmdWithABool.hh" // for G4UIcmdWithABool
#include "G4UIdirectory.hh" // for G4UIdirectory
#include "Par04ParallelFullWorld.hh" // for Par04ParallelFullWorld
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelMessenger::Par04ParallelMessenger(Par04ParallelFullWorld* aParallel)
: G4UImessenger()
, fParallel(aParallel)
{
fExampleDir = new G4UIdirectory("/Par04/");
fExampleDir->SetGuidance("UI commands specific to this example");
fParallelDir = new G4UIdirectory("/Par04/parallel/");
fParallelDir->SetGuidance("Parallel construction UI commands");
fPrintCmd = new G4UIcmdWithoutParameter("/Par04/parallel/print", this);
fPrintCmd->SetGuidance("Print current settings.");
fNbSlicesCmd = new G4UIcmdWithAnInteger("/Par04/parallel/setNbOfSlices", this);
fNbSlicesCmd->SetGuidance("Set number of slices.");
fNbSlicesCmd->SetParameterName("NbSlices", false);
fNbSlicesCmd->SetRange("NbSlices>0");
fNbSlicesCmd->AvailableForStates(G4State_PreInit);
fNbSlicesCmd->SetToBeBroadcasted(false);
fNbRowsCmd = new G4UIcmdWithAnInteger("/Par04/parallel/setNbOfRows", this);
fNbRowsCmd->SetGuidance("Set number of rows.");
fNbRowsCmd->SetParameterName("NbRows", false);
fNbRowsCmd->SetRange("NbRows>0");
fNbRowsCmd->AvailableForStates(G4State_PreInit);
fNbRowsCmd->SetToBeBroadcasted(false);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ParallelMessenger::~Par04ParallelMessenger()
{
delete fPrintCmd;
delete fNbSlicesCmd;
delete fNbRowsCmd;
delete fParallelDir;
delete fExampleDir;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ParallelMessenger::SetNewValue(G4UIcommand* aCommand, G4String aNewValue)
{
if(aCommand == fPrintCmd)
{
fParallel->Print();
}
else if(aCommand == fNbSlicesCmd)
{
fParallel->SetNbOfSlices(fNbSlicesCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fNbRowsCmd)
{
fParallel->SetNbOfRows(fNbRowsCmd->GetNewIntValue(aNewValue));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4String Par04ParallelMessenger::GetCurrentValue(G4UIcommand* aCommand)
{
G4String cv;
if(aCommand == fNbSlicesCmd)
{
cv = fNbSlicesCmd->ConvertToString(fParallel->GetNbOfSlices());
}
else if(aCommand == fNbRowsCmd)
{
cv = fNbRowsCmd->ConvertToString(fParallel->GetNbOfRows());
}
return cv;
}
@@ -49,7 +49,7 @@ Par04RunAction::Par04RunAction(Par04DetectorConstruction* aDetector, Par04EventA
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04RunAction::~Par04RunAction() {}
Par04RunAction::~Par04RunAction() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -75,10 +75,11 @@ void Par04RunAction::BeginOfRunAction(const G4Run*)
// Creating control histograms
analysisManager->CreateH1("energyParticle", "Primary energy;E_{MC} (GeV);Entries", 1024, 0,
1.1 * maxEnergy);
analysisManager->CreateH1("energyDeposited", "Deposited energy;E_{MC} (GeV);Entries", 1024, 0,
1.1 * maxEnergy);
analysisManager->CreateH1("energyDepositedInVirtual", "Deposited energy;E_{MC} (GeV);Entries",
1024, 0, 1.1 * maxEnergy);
analysisManager->CreateH1(
"energyRatio", "Ratio of energy deposited to primary;E_{dep} / E_{MC};Entries", 1024, 0, 1);
"energyRatioInVirtual", "Ratio of energy deposited to primary;E_{dep} / E_{MC};Entries",
1024, 0, 1);
analysisManager->CreateH1("time", "Simulation time; time (s);Entries", 2048, 0, 100);
analysisManager->CreateH1("longProfile", "Longitudinal profile;t (mm);#LTE#GT (MeV)", cellNumZ,
-0.5 * cellSizeZ, (cellNumZ - 0.5) * cellSizeZ);
@@ -103,19 +104,51 @@ void Par04RunAction::BeginOfRunAction(const G4Run*)
"transSecondMoment", "Second moment of transverse distribution;#LTr^{2}#GT (mm^{2});Entries",
1024, 0, std::pow(cellNumRho * cellSizeRho, 2) / 5); // arbitrary scaling of max value on axis
analysisManager->CreateH1("hitType", "hit type;type (0=full, 1= fast);Entries", 2, -0.5, 1.5);
analysisManager->CreateH1("phiProfile", "Azimuthal angle profile, centred at mean;phi;#LTE#GT (MeV)", cellNumPhi,
- (cellNumPhi - 0.5) * cellSizePhi, (cellNumPhi - 0.5) * cellSizePhi);
analysisManager->CreateH1("numHits", "Number of hits above 0.5 keV", 4048, 0, 40500);
analysisManager->CreateH1("cellEnergy", "Cell energy distribution;log10(E/MeV);Entries", 1024, -4, 2);
analysisManager->CreateH1("phiProfile",
"Azimuthal angle profile, centred at mean;phi;#LTE#GT (MeV)",
cellNumPhi, - (cellNumPhi - 0.5) * cellSizePhi,
(cellNumPhi - 0.5) * cellSizePhi);
analysisManager->CreateH1("numHitsInVirtual", "Number of hits above 0.5 keV", 4048, 0, 20000);
analysisManager->CreateH1("cellEnergy", "Cell energy distribution;log10(E/MeV);Entries",
1024, -4, 2);
analysisManager->CreateH1("numDepositsInVirtual", "Number of deposits in all cells per event",
4048, 0, 40000);
analysisManager->CreateH1("cellDepositsInVirtual",
"Distribution of number of deposits per cell per event", 4048, 0, 1024);
analysisManager->CreateH1("energyDepositedInPhysical",
"Deposited energy in physical detector readout;E_{MC} (GeV);Entries",
1024, 0, 1.1 * maxEnergy);
analysisManager->CreateH1("energyRatioInPhysical",
"Ratio of energy deposited in physical readout to primary; E_{dep} / E_{MC};Entries",
1024, 0, 1);
analysisManager->CreateH1("numHitsInPhysical", "Number of hits in physical readout above 0.5 keV",
4048, 0, 5000);
analysisManager->CreateH1("cellEnergyInPhysical",
"Physical cell energy distribution;log10(E/MeV);Entries", 1024, -4, 2);
analysisManager->CreateH1("numDepositsInPhysical",
"Number of deposits in all physical cells per event", 4048, 0, 40000);
analysisManager->CreateH1("cellDepositsInPhysical",
"Distribution of number of deposits per physical cell per event",
4048, 0, 1024);
// Creating ntuple
analysisManager->CreateNtuple("events", "per event data");
analysisManager->CreateNtuple("global", "Event data");
analysisManager->CreateNtupleDColumn("EnergyMC");
analysisManager->CreateNtupleDColumn("SimTime");
analysisManager->FinishNtuple();
analysisManager->CreateNtuple("virtualReadout", "Cylindrical mesh readout");
analysisManager->CreateNtupleDColumn("EnergyCell", fEventAction->GetCalEdep());
analysisManager->CreateNtupleIColumn("rhoCell", fEventAction->GetCalRho());
analysisManager->CreateNtupleIColumn("phiCell", fEventAction->GetCalPhi());
analysisManager->CreateNtupleIColumn("zCell", fEventAction->GetCalZ());
analysisManager->CreateNtupleDColumn("SimTime");
analysisManager->FinishNtuple();
analysisManager->CreateNtuple("physicalReadout", "Detector physical readout");
analysisManager->CreateNtupleDColumn("EnergyCell", fEventAction->GetPhysicalCalEdep());
analysisManager->CreateNtupleIColumn("layerCell", fEventAction->GetPhysicalCalLayer());
analysisManager->CreateNtupleIColumn("rowCell", fEventAction->GetPhysicalCalRow());
analysisManager->CreateNtupleIColumn("sliceCell", fEventAction->GetPhysicalCalSlice());
analysisManager->FinishNtuple();
analysisManager->OpenFile();
@@ -67,7 +67,7 @@ Par04SensitiveDetector::Par04SensitiveDetector(G4String aName, G4ThreeVector aNb
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04SensitiveDetector::~Par04SensitiveDetector() {}
Par04SensitiveDetector::~Par04SensitiveDetector() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -80,14 +80,6 @@ void Par04SensitiveDetector::Initialize(G4HCofThisEvent* aHCE)
}
aHCE->AddHitsCollection(fHitCollectionID, fHitsCollection);
// fill calorimeter hits with zero energy deposition
for(G4int iphi = 0; iphi < fMeshNbOfCells.y(); iphi++)
for(G4int irho = 0; irho < fMeshNbOfCells.x(); irho++)
for(G4int iz = 0; iz < fMeshNbOfCells.z(); iz++)
{
Par04Hit* hit = new Par04Hit();
fHitsCollection->insert(hit);
}
// reset entrance position
fEntrancePosition.set(-1, -1, -1);
fEntranceDirection.set(-1, -1, -1);
@@ -107,6 +99,8 @@ G4bool Par04SensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*)
// Add energy deposit from G4Step
hit->AddEdep(edep);
// Increment the counter
hit->AddNdep(1);
// Fill time information from G4Step
// If it's already filled, choose hit with earliest global time
@@ -136,6 +130,8 @@ G4bool Par04SensitiveDetector::ProcessHits(const G4FastHit* aHit, const G4FastTr
// Add energy deposit from G4FastHit
hit->AddEdep(edep);
// Increment the counter
hit->AddNdep(1);
// Fill time information from G4FastTrack
// If it's already filled, choose hit with earliest global time
@@ -157,7 +153,7 @@ Par04Hit* Par04SensitiveDetector::RetrieveAndSetupHit(G4ThreeVector aGlobalPosit
{
if(fEntrancePosition.x() == -1)
{
Par04EventInformation* info = dynamic_cast<Par04EventInformation*>(
auto info = dynamic_cast<Par04EventInformation*>(
G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
if(info == nullptr)
return nullptr;
@@ -184,23 +180,33 @@ Par04Hit* Par04SensitiveDetector::RetrieveAndSetupHit(G4ThreeVector aGlobalPosit
std::size_t hitID =
fMeshNbOfCells.x() * fMeshNbOfCells.z() * phiNo + fMeshNbOfCells.z() * rhoNo + zNo;
if(hitID >= fHitsCollection->entries() || zNo >= fMeshNbOfCells.z() ||
rhoNo >= fMeshNbOfCells.x() || zNo < 0)
if(zNo >= fMeshNbOfCells.z() || rhoNo >= fMeshNbOfCells.x() || zNo < 0)
{
return nullptr;
}
Par04Hit* hit = (*fHitsCollection)[hitID];
if(hit->GetRhoId() < 0)
{
hit->SetRhoId(rhoNo);
auto hit = fHitsMap[hitID].get();
if (hit==nullptr) {
fHitsMap[hitID] = std::unique_ptr<Par04Hit>(new Par04Hit());
hit = fHitsMap[hitID].get();
hit->SetPhiId(phiNo);
hit->SetRhoId(rhoNo);
hit->SetZid(zNo);
hit->SetRot(rotMatrixInv);
hit->SetPos(fEntrancePosition +
rotMatrixInv * G4ThreeVector(0, 0, (zNo + 0.5) * fMeshSizeOfCells.z()));
}
return hit;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04SensitiveDetector::EndOfEvent(G4HCofThisEvent*)
{
for(const auto& hits: fHitsMap){
fHitsCollection->insert(new Par04Hit(*hits.second.get()));
}
fHitsMap.clear();
}
@@ -44,8 +44,9 @@ Par04TorchInference::Par04TorchInference(G4String modelPath)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04TorchInference::RunInference(std::vector<float> aGenVector, std::vector<G4double>& aEnergies,
int aSize)
void Par04TorchInference::RunInference(std::vector<float> aGenVector,
std::vector<G4double>& aEnergies,
int aSize)
{
// latentSize : size of the latent space
// 4 is the size of the condition vector
@@ -79,7 +80,8 @@ void Par04TorchInference::RunInference(std::vector<float> aGenVector, std::vecto
at::Tensor outTensor = fModule.forward( genInput).toTensor().contiguous();
std::vector<G4double> output( outTensor.data_ptr<float>(), outTensor.data_ptr<float>() + outTensor.numel() );
std::vector<G4double> output( outTensor.data_ptr<float>(),
outTensor.data_ptr<float>() + outTensor.numel() );
aEnergies.assign(aSize, 0);
for(int i = 0; i < aSize; i++) {