File indexing completed on 2026-09-16 08:27:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #include "G4HCofThisEvent.hh"
0040 #include "G4Step.hh"
0041 #include "G4ThreeVector.hh"
0042 #include "G4SDManager.hh"
0043 #include "G4ios.hh"
0044 #include "G4Track.hh"
0045 #ifdef WITH_G4OPTICKS
0046 # include "G4Opticks.hh"
0047 # include "TrackInfo.hh"
0048 # include "OpticksGenstep.h"
0049 # include "OpticksFlags.hh"
0050 # include "G4OpticksHit.hh"
0051 # include "G4Cerenkov.hh"
0052 # include "G4Event.hh"
0053 # include "G4MaterialPropertiesTable.hh"
0054 # include "G4PhysicalConstants.hh"
0055 # include "G4RunManager.hh"
0056 # include "G4SteppingManager.hh"
0057 # include "G4SystemOfUnits.hh"
0058 # include "G4UnitsTable.hh"
0059 # include "G4VProcess.hh"
0060 # include "G4VRestDiscreteProcess.hh"
0061 # include "PhotonSD.hh"
0062 # include "G4Cerenkov.hh"
0063 # include "G4Scintillation.hh"
0064 # include "G4Version.hh"
0065 #endif
0066
0067 #include "lArTPCSD.hh"
0068 #include "ConfigurationManager.hh"
0069
0070
0071 lArTPCSD::lArTPCSD(G4String name)
0072 : G4VSensitiveDetector(name)
0073 {
0074 G4String HCname = name + "_HC";
0075 collectionName.insert(HCname);
0076 verbose = ConfigurationManager::getInstance()->isEnable_verbose();
0077 if(verbose)
0078 {
0079 G4cout << collectionName.size() << " lArTPCSD name: " << name
0080 << " collection Name: " << HCname << G4endl;
0081 }
0082 fHCID = -1;
0083 first = true;
0084 }
0085
0086
0087 void lArTPCSD::Initialize(G4HCofThisEvent* hce)
0088 {
0089 flArTPCHitsCollection =
0090 new lArTPCHitsCollection(SensitiveDetectorName, collectionName[0]);
0091 if(fHCID < 0)
0092 {
0093 if(verbose)
0094 {
0095 G4cout << "lArTPCSD::Initialize: " << SensitiveDetectorName << " "
0096 << collectionName[0] << G4endl;
0097 }
0098 fHCID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]);
0099 }
0100 hce->AddHitsCollection(fHCID, flArTPCHitsCollection);
0101 }
0102
0103
0104 G4bool lArTPCSD::ProcessHits(G4Step* aStep, G4TouchableHistory*)
0105 {
0106 G4double edep = aStep->GetTotalEnergyDeposit();
0107 if(edep == 0.)
0108 return false;
0109
0110 G4Track* aTrack = aStep->GetTrack();
0111 G4double charge = aTrack->GetDynamicParticle()->GetCharge();
0112 if(charge == 0)
0113 return false;
0114 G4double ds = aStep->GetStepLength();
0115 lArTPCHit* newHit = new lArTPCHit(
0116 NumElectrons(edep, ds), aStep->GetPostStepPoint()->GetPosition().getX(),
0117 aStep->GetPostStepPoint()->GetPosition().getY(),
0118 aStep->GetPostStepPoint()->GetPosition().getZ());
0119 flArTPCHitsCollection->insert(newHit);
0120 #ifdef WITH_G4OPTICKS
0121 if(ConfigurationManager::getInstance()->isEnable_opticks())
0122 {
0123 if(first)
0124 {
0125 aMaterial = aTrack->GetMaterial();
0126 materialIndex = aMaterial->GetIndex();
0127 if(verbose)
0128 {
0129 G4cout << "*******************************" << G4endl;
0130 G4cout << "RadiatorSD::ProcessHits initializing Material: "
0131 << aMaterial->GetName() << " " << G4endl;
0132 G4cout << "RadiatorSD::ProcessHits: Name "
0133 << aStep->GetPreStepPoint()
0134 ->GetPhysicalVolume()
0135 ->GetLogicalVolume()
0136 ->GetName()
0137 << G4endl;
0138 }
0139 aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable();
0140 if(verbose)
0141 {
0142 aMaterialPropertiesTable->DumpTable();
0143 }
0144
0145
0146
0147 # if(G4VERSION_NUMBER > 1072)
0148 YieldRatio =
0149 aMaterialPropertiesTable->GetConstProperty(kSCINTILLATIONYIELD1) /
0150 aMaterialPropertiesTable->GetConstProperty(
0151 kSCINTILLATIONYIELD2);
0152 FastTimeConstant = aMaterialPropertiesTable->GetConstProperty(
0153 kSCINTILLATIONTIMECONSTANT1);
0154 SlowTimeConstant = aMaterialPropertiesTable->GetConstProperty(
0155 kSCINTILLATIONTIMECONSTANT2);
0156 # else
0157 Fast_Intensity = aMaterialPropertiesTable->GetProperty(kFASTCOMPONENT);
0158 Slow_Intensity = aMaterialPropertiesTable->GetProperty(kSLOWCOMPONENT);
0159 YieldRatio = aMaterialPropertiesTable->GetConstProperty(kYIELDRATIO);
0160 # endif
0161 ScintillationType = Slow;
0162
0163
0164
0165 Rindex = aMaterialPropertiesTable->GetProperty("RINDEX");
0166 # if(G4VERSION_NUMBER > 1072)
0167 Pmin = Rindex->GetMinEnergy();
0168 Pmax = Rindex->GetMaxEnergy();
0169 # else
0170 Pmin = Rindex->GetMinLowEdgeEnergy();
0171 Pmax = Rindex->GetMaxLowEdgeEnergy();
0172 # endif
0173 dp = Pmax - Pmin;
0174 if(verbose)
0175 {
0176 G4cout << "nMax: " << nMax << "Pmin: " << Pmin << "Pmax: " << Pmax
0177 << "dp: " << dp << G4endl;
0178 Rindex->DumpValues();
0179 }
0180
0181 first = false;
0182 }
0183 G4int Sphotons = 0;
0184 G4int Cphotons = 0;
0185
0186
0187
0188 G4double maxCos = 0.0;
0189 G4double maxSin2 = 0.0;
0190 G4double beta = 0.0;
0191 G4double beta1 = 0.0;
0192 G4double beta2 = 0.0;
0193 G4double BetaInverse = 0.0;
0194 G4double MeanNumberOfPhotons1 = 0.0;
0195 G4double MeanNumberOfPhotons2 = 0.0;
0196 G4SteppingManager* fpSteppingManager = G4EventManager::GetEventManager()
0197 ->GetTrackingManager()
0198 ->GetSteppingManager();
0199 G4StepStatus stepStatus = fpSteppingManager->GetfStepStatus();
0200 if(stepStatus != fAtRestDoItProc)
0201 {
0202 G4ProcessVector* procPost = fpSteppingManager->GetfPostStepDoItVector();
0203 size_t MAXofPostStepLoops = fpSteppingManager->GetMAXofPostStepLoops();
0204 for(size_t i3 = 0; i3 < MAXofPostStepLoops; i3++)
0205 {
0206 if((*procPost)[i3]->GetProcessName() == "Cerenkov")
0207 {
0208 G4Cerenkov* proc = (G4Cerenkov*) (*procPost)[i3];
0209 thePhysicsTable = proc->GetPhysicsTable();
0210 CerenkovAngleIntegrals =
0211 (G4PhysicsOrderedFreeVector*) ((*thePhysicsTable)(materialIndex));
0212 Cphotons = proc->GetNumPhotons();
0213 if(Cphotons > 0)
0214 {
0215 beta1 = aStep->GetPreStepPoint()->GetBeta();
0216 beta2 = aStep->GetPostStepPoint()->GetBeta();
0217 beta = (beta1 + beta2) * 0.5;
0218 BetaInverse = 1. / beta;
0219 maxCos = BetaInverse / nMax;
0220 maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
0221 MeanNumberOfPhotons1 =
0222 proc->GetAverageNumberOfPhotons(charge, beta1, aMaterial, Rindex);
0223 MeanNumberOfPhotons2 =
0224 proc->GetAverageNumberOfPhotons(charge, beta2, aMaterial, Rindex);
0225 }
0226 }
0227 if((*procPost)[i3]->GetProcessName() == "Scintillation")
0228 {
0229 G4Scintillation* proc1 = (G4Scintillation*) (*procPost)[i3];
0230 Sphotons = proc1->GetNumPhotons();
0231 }
0232 }
0233 }
0234 tSphotons += Sphotons;
0235 tCphotons += Cphotons;
0236 G4ThreeVector deltaPosition = aStep->GetDeltaPosition();
0237 G4double ScintillationTime = 0. * ns;
0238 G4int scntId = 1;
0239 G4StepPoint* pPreStepPoint = aStep->GetPreStepPoint();
0240 G4ThreeVector x0 = pPreStepPoint->GetPosition();
0241 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
0242
0243
0244
0245 if(Sphotons > 0)
0246 {
0247 G4double ScintillationRiseTime = 0.0;
0248 G4Opticks::Get()->collectGenstep_G4Scintillation_1042(
0249 aTrack, aStep, Sphotons, scntId, ScintillationTime,
0250 ScintillationRiseTime);
0251 }
0252
0253
0254
0255 if(Cphotons > 0)
0256 {
0257 G4Opticks::Get()->collectGenstep_G4Cerenkov_1042(
0258 aTrack, aStep, Cphotons, BetaInverse, Pmin, Pmax, maxCos, maxSin2,
0259 MeanNumberOfPhotons1, MeanNumberOfPhotons2);
0260 }
0261 G4Opticks* g4ok = G4Opticks::Get();
0262 G4RunManager* rm = G4RunManager::GetRunManager();
0263 const G4Event* event = rm->GetCurrentEvent();
0264 G4int eventid = event->GetEventID();
0265 G4OpticksHit hit;
0266 unsigned num_photons = g4ok->getNumPhotons();
0267 if(num_photons > ConfigurationManager::getInstance()->getMaxPhotons())
0268 {
0269 g4ok->propagateOpticalPhotons(eventid);
0270 G4HCtable* hctable = G4SDManager::GetSDMpointer()->GetHCtable();
0271 for(G4int i = 0; i < hctable->entries(); ++i)
0272 {
0273 std::string sdn = hctable->GetSDname(i);
0274 std::size_t found = sdn.find("PhotonDetector");
0275 if(found != std::string::npos)
0276 {
0277 PhotonSD* aSD =
0278 (PhotonSD*) G4SDManager::GetSDMpointer()->FindSensitiveDetector(
0279 sdn);
0280 aSD->AddOpticksHits();
0281 }
0282 }
0283 g4ok->reset();
0284 }
0285 }
0286 #endif
0287 return true;
0288 }
0289
0290
0291 void lArTPCSD::EndOfEvent(G4HCofThisEvent*)
0292 {
0293 tSphotons = 0;
0294 tCphotons = 0;
0295 G4int NbHits = flArTPCHitsCollection->entries();
0296 if(verbose)
0297 {
0298 G4cout << " Number of lArTPCHits: " << NbHits << G4endl;
0299 }
0300 }
0301
0302
0303 G4double lArTPCSD::NumElectrons(G4double edep, G4double ds)
0304 {
0305 G4double dEdx = std::max((ds <= 0.0) ? 0.0 : edep / ds, 1.0);
0306
0307
0308 const G4double fGeVToElectrons = 4.237e+04;
0309 G4double recomb = 0.0;
0310 if(ds > 0)
0311 {
0312 G4double fModBoxA = 0.930;
0313 G4double fModBoxB = 0.212;
0314
0315 G4double Xi = 2.0 * fModBoxB * dEdx;
0316 recomb = std::log(fModBoxA + Xi) / Xi;
0317 }
0318
0319 return fGeVToElectrons * edep * recomb;
0320 }