9 #include "G4LogicalVolumeStore.hh" 10 #include "G4LogicalVolume.hh" 13 #include "G4VProcess.hh" 14 #include "G4Poisson.hh" 25 #include "G4SystemOfUnits.hh" 26 #include "G4PhysicalConstants.hh" 32 CaloSD(name, cpv, clg, p, manager) {
45 edm::LogInfo(
"EcalSim") <<
"Constructing a DreamSD with name " << GetName() <<
"\n" 46 <<
"DreamSD:: Use of Birks law is set to " 47 << useBirk <<
" with three constants kB = " 48 << birk1 <<
", C1 = " << birk2 <<
", C2 = " 50 <<
" Slope for Light yield is set to " 52 <<
" Parameterization of Cherenkov is set to " 53 << doCherenkov_ <<
" and readout both sides is " 63 <<
"please add it to config file";
65 ntuple_ = tfile->
make<TTree>(
"tree",
"Cherenkov photons");
81 if (aStep ==
nullptr) {
105 G4String nameVolume =
preStepPoint->GetPhysicalVolume()->GetName();
112 LogDebug(
"EcalSim") <<
"DreamSD:: " << nameVolume <<
" Side " <<
side 113 <<
" Light Collection Efficiency " << weight
123 double time = (aStep->GetPostStepPoint()->GetGlobalTime())/nanosecond;
125 if (
side < 0) unitID++;
134 if (primaryID == 0) {
135 edm::LogWarning(
"EcalSim") <<
"CaloSD: Problem with primaryID **** set by " 136 <<
"force to TkID **** " 137 <<
theTrack->GetTrackID() <<
" in Volume " 138 <<
preStepPoint->GetTouchable()->GetVolume(0)->GetName();
142 bool flag = (unitID > 0);
143 G4TouchableHistory* touch =(G4TouchableHistory*)(
theTrack->GetTouchable());
147 LogDebug(
"EcalSim") <<
"CaloSD:: GetStepInfo for" 148 <<
" PV " << touch->GetVolume(0)->GetName()
149 <<
" PVid = " << touch->GetReplicaNumber(0)
150 <<
" MVid = " << touch->GetReplicaNumber(1)
154 LogDebug(
"EcalSim") <<
"CaloSD:: GetStepInfo for" 155 <<
" PV " << touch->GetVolume(0)->GetName()
156 <<
" PVid = " << touch->GetReplicaNumber(0)
157 <<
" MVid = " << touch->GetReplicaNumber(1)
158 <<
" Unit " << std::hex << unitID <<
std::dec 170 DimensionMap::const_iterator ite =
xtalLMap.begin();
171 const G4LogicalVolume* lv = (ite->first);
172 G4Material* material = lv->GetMaterial();
173 edm::LogInfo(
"EcalSim") <<
"DreamSD::initRun: Initializes for material " 174 << material->GetName() <<
" in " << lv->GetName();
178 edm::LogWarning(
"EcalSim") <<
"Couldn't retrieve material properties table\n" 179 <<
" Material = " << material->GetName();
188 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
189 uint32_t
id = (touch->GetReplicaNumber(1))*10 + (touch->GetReplicaNumber(0));
198 G4String attribute =
"ReadOutName";
203 const G4LogicalVolumeStore * lvs = G4LogicalVolumeStore::GetInstance();
204 std::vector<G4LogicalVolume *>::const_iterator lvcite;
210 G4LogicalVolume* lv=
nullptr;
211 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
212 if ((*lvcite)->GetName() ==
name) {
216 LogDebug(
"EcalSim") <<
"DreamSD::initMap (for " << sd <<
"): Solid " 217 << name <<
" Shape " << sol.
shape() <<
" Parameter 0 = " 218 << paras[0] <<
" Logical Volume " << lv;
219 double length = 0,
width = 0;
221 std::sort( paras.begin(), paras.end() );
222 length = 2.0*paras.back();
223 width = 2.0*paras.front();
227 LogDebug(
"EcalSim") <<
"DreamSD: Length Table for " << attribute <<
" = " 229 DimensionMap::const_iterator ite =
xtalLMap.begin();
231 for (; ite !=
xtalLMap.end(); ite++, i++) {
232 G4String
name =
"Unknown";
233 if (ite->first !=
nullptr) name = (ite->first)->GetName();
234 LogDebug(
"EcalSim") <<
" " << i <<
" " << ite->first <<
" " << name
235 <<
" L = " << ite->second.first
236 <<
" W = " << ite->second.second;
243 const G4StepPoint* stepPoint = aStep->GetPreStepPoint();
244 G4LogicalVolume* lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
245 G4String nameVolume= lv->GetName();
248 G4ThreeVector localPoint =
setToLocal(stepPoint->GetPosition(),
249 stepPoint->GetTouchable());
251 double localz = localPoint.x();
252 double dapd = 0.5 * crlength - flag*localz;
253 if (dapd >= -0.1 || dapd <= crlength+0.1) {
257 edm::LogWarning(
"EcalSim") <<
"DreamSD: light coll curve : wrong distance " 258 <<
"to APD " << dapd <<
" crlength = " 259 << crlength <<
" crystal name = " << nameVolume
260 <<
" z of localPoint = " << localz
261 <<
" take weight = " <<
weight;
263 LogDebug(
"EcalSim") <<
"DreamSD, light coll curve : " << dapd
264 <<
" crlength = " << crlength
265 <<
" crystal name = " << nameVolume
266 <<
" z of localPoint = " << localz
267 <<
" take weight = " <<
weight;
275 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
276 if (ite !=
xtalLMap.end()) length = ite->second.first;
285 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
286 if (ite !=
xtalLMap.end()) width = ite->second.second;
297 double cherenkovEnergy = 0;
299 G4Material* material = aStep->GetTrack()->GetMaterial();
303 if ( Rindex ==
nullptr ) {
305 return cherenkovEnergy;
310 int Rlength = Rindex->GetVectorLength() - 1;
311 double Pmin = Rindex->Energy(0);
312 double Pmax = Rindex->Energy(Rlength);
313 LogDebug(
"EcalSim") <<
"Material properties: " <<
"\n" 314 <<
" Pmin = " << Pmin
315 <<
" Pmax = " <<
Pmax;
318 const G4StepPoint* pPreStepPoint = aStep->GetPreStepPoint();
319 const G4StepPoint* pPostStepPoint = aStep->GetPostStepPoint();
320 const G4ThreeVector& x0 = pPreStepPoint->GetPosition();
321 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
322 const G4DynamicParticle* aParticle = aStep->GetTrack()->GetDynamicParticle();
323 const double charge = aParticle->GetDefinition()->GetPDGCharge();
325 double beta = 0.5*( pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta() );
326 double BetaInverse = 1.0/
beta;
328 LogDebug(
"EcalSim") <<
"Particle properties: " <<
"\n" 329 <<
" charge = " << charge
330 <<
" beta = " <<
beta;
334 if ( meanNumberOfPhotons <= 0.0 ) {
335 LogDebug(
"EcalSim") <<
"Mean number of photons is zero: " << meanNumberOfPhotons
336 <<
", stopping here";
337 return cherenkovEnergy;
341 meanNumberOfPhotons *= aStep->GetStepLength();
344 int numPhotons =
static_cast<int>( G4Poisson(meanNumberOfPhotons) );
346 if ( numPhotons <= 0 ) {
347 LogDebug(
"EcalSim") <<
"Poission number of photons is zero: " << numPhotons
348 <<
", stopping here";
349 return cherenkovEnergy;
353 double dp = Pmax - Pmin;
354 double maxCos = BetaInverse / (*Rindex)[Rlength];
355 double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
358 for (
int iPhoton = 0; iPhoton<numPhotons; ++iPhoton ) {
362 double sampledMomentum, sampledRI;
363 double cosTheta, sin2Theta;
367 randomNumber = G4UniformRand();
368 sampledMomentum = Pmin + randomNumber *
dp;
369 sampledRI = Rindex->Value(sampledMomentum);
370 cosTheta = BetaInverse / sampledRI;
372 sin2Theta = (1.0 - cosTheta)*(1.0 + cosTheta);
373 randomNumber = G4UniformRand();
375 }
while (randomNumber*maxSin2 > sin2Theta);
379 randomNumber = G4UniformRand();
381 double phi = twopi*randomNumber;
382 double sinPhi =
sin(phi);
383 double cosPhi =
cos(phi);
388 double sinTheta =
sqrt(sin2Theta);
389 double px = sinTheta*cosPhi;
390 double py = sinTheta*sinPhi;
391 double pz = cosTheta;
392 G4ThreeVector photonDirection(px, py, pz);
395 photonDirection.rotateUz(p0);
398 randomNumber = G4UniformRand();
399 G4ThreeVector photonPosition = x0 + randomNumber * aStep->GetDeltaPosition();
400 G4ThreeVector photonMomentum = sampledMomentum*photonDirection;
407 px_[iPhoton] = photonMomentum.x();
408 py_[iPhoton] = photonMomentum.y();
409 pz_[iPhoton] = photonMomentum.z();
410 x_[iPhoton] = photonPosition.x();
411 y_[iPhoton] = photonPosition.y();
412 z_[iPhoton] = photonPosition.z();
419 return cherenkovEnergy;
429 const G4Material* aMaterial,
430 const G4MaterialPropertyVector* Rindex )
432 const G4double rFact = 369.81/(eV * cm);
434 if( beta <= 0.0 )
return 0.0;
436 double BetaInverse = 1./
beta;
443 int Rlength = Rindex->GetVectorLength() - 1;
444 double Pmin = Rindex->Energy(0);
445 double Pmax = Rindex->Energy(Rlength);
448 double nMin = (*Rindex)[0];
449 double nMax = (*Rindex)[Rlength];
454 double dp = 0., ge = 0., CAImin = 0.;
457 if ( nMax < BetaInverse) { }
460 else if (nMin > BetaInverse) {
470 Pmin = Rindex->Value(BetaInverse);
475 ge = CAImax - CAImin;
480 double numPhotons = rFact * charge/eplus * charge/eplus *
481 (dp - ge * BetaInverse*BetaInverse);
483 LogDebug(
"EcalSim") <<
"@SUB=getAverageNumberOfPhotons" 484 <<
"CAImin = " << CAImin <<
"\n" 485 <<
"CAImax = " << CAImax <<
"\n" 486 <<
"dp = " << dp <<
", ge = " << ge <<
"\n" 487 <<
"numPhotons = " << numPhotons;
502 if ( pbWO2Name != aMaterial->GetName() ) {
504 <<
"expecting " << pbWO2Name
505 <<
", got " << aMaterial->GetName();
509 G4MaterialPropertiesTable* table =
new G4MaterialPropertiesTable();
513 const int nEntries = 14;
514 double PhotonEnergy[nEntries] = { 1.7712*eV, 1.8368*eV, 1.90745*eV, 1.98375*eV, 2.0664*eV,
515 2.15625*eV, 2.25426*eV, 2.3616*eV, 2.47968*eV, 2.61019*eV,
516 2.75521*eV, 2.91728*eV, 3.09961*eV, 3.30625*eV };
517 double RefractiveIndex[nEntries] = { 2.17728, 2.18025, 2.18357, 2.18753, 2.19285,
518 2.19813, 2.20441, 2.21337, 2.22328, 2.23619,
519 2.25203, 2.27381, 2.30282, 2.34666 };
521 table->AddProperty(
"RINDEX", PhotonEnergy, RefractiveIndex, nEntries );
522 aMaterial->SetMaterialPropertiesTable(table);
529 double currentRI = RefractiveIndex[
index];
530 double currentPM = PhotonEnergy[
index];
531 double currentCAI = 0.0;
533 double prevPM = currentPM;
534 double prevCAI = currentCAI;
535 double prevRI = currentRI;
536 while ( ++index < nEntries ) {
537 currentRI = RefractiveIndex[
index];
538 currentPM = PhotonEnergy[
index];
539 currentCAI = 0.5*(1.0/(prevRI*prevRI) + 1.0/(currentRI*currentRI));
540 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
545 prevCAI = currentCAI;
549 LogDebug(
"EcalSim") <<
"Material properties set for " << aMaterial->GetName();
562 const G4ThreeVector&
x,
563 const G4Step* aStep )
576 G4StepPoint* stepPoint = aStep->GetPreStepPoint();
577 G4LogicalVolume* lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
578 G4String nameVolume= lv->GetName();
582 double dapd = 0.5 * crlength - x.x();
583 double y = p.y()/p.x()*dapd;
585 LogDebug(
"EcalSim") <<
"Distance to APD: " << dapd
586 <<
" - y at APD: " <<
y;
589 if ( fabs(y)>crwidth*0.5 ) {
594 double waveLength = p.mag()*1.239e8;
599 LogDebug(
"EcalSim") <<
"Wavelength: " << waveLength <<
" - Energy: " << energy;
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
double getAttenuation(const G4Step *aStep, double birk1, double birk2, double birk3)
const std::vector< double > & parameters(void) const
Give the parameters of the solid.
const DDLogicalPart & logicalPart() const
The logical-part of the current node in the filtered-view.
double getPhotonEnergyDeposit_(const G4ParticleMomentum &p, const G4ThreeVector &x, const G4Step *aStep)
Returns energy deposit for a given photon.
std::pair< double, double > Doubles
Sin< T >::type sin(const T &t)
uint32_t setDetUnitId(const G4Step *) override
bool setPbWO2MaterialProperties_(G4Material *aMaterial)
Sets material properties at run-time...
T * make(const Args &...args) const
make new ROOT object
const DDSolid & solid(void) const
Returns a reference object of the solid being the shape of this LogicalPart.
type of data representation of DDCompactView
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
A DDSolid represents the shape of a part.
bool next()
set current node to the next node in the filtered tree
double cherenkovDeposit_(const G4Step *aStep)
Returns the total energy due to Cherenkov radiation.
Cos< T >::type cos(const T &t)
double getAverageNumberOfPhotons_(const double charge, const double beta, const G4Material *aMaterial, const G4MaterialPropertyVector *rIndex)
Returns average number of photons created by track.
DDSolidShape shape(void) const
The type of the solid.
G4MaterialPropertiesTable * materialPropertiesTable
double curve_LY(const G4Step *, int)
const double crystalWidth(G4LogicalVolume *) const
void setID(uint32_t unitID, double timeSlice, int trackID, uint16_t depth=0)
G4StepPoint * preStepPoint
std::unique_ptr< G4PhysicsOrderedFreeVector > chAngleIntegrals_
Table of Cherenkov angle integrals vs photon momentum.
DreamSD(const std::string &, const DDCompactView &, const SensitiveDetectorCatalog &, edm::ParameterSet const &, const SimTrackManager *)
bool firstChild()
set the current node to the first child ...
bool ProcessHits(G4Step *step, G4TouchableHistory *tHistory) override
const double crystalLength(G4LogicalVolume *) const
const std::string & name() const
Returns the name.
void initMap(const std::string &, const DDCompactView &)
static const double getEfficiency(const double &waveLengthNm)
Return efficiency for given photon wavelength (in nm)
CaloG4Hit * createNewHit()
G4bool getStepInfo(G4Step *aStep) override
G4ThreeVector setToLocal(const G4ThreeVector &, const G4VTouchable *)