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) {
43 edm::LogInfo(
"EcalSim") <<
"Constructing a DreamSD with name " << GetName() <<
"\n" 44 <<
"DreamSD:: Use of Birks law is set to " 45 << useBirk <<
" with three constants kB = " 46 << birk1 <<
", C1 = " << birk2 <<
", C2 = " 48 <<
" Slope for Light yield is set to " 50 <<
" Parameterization of Cherenkov is set to " 51 << doCherenkov_ <<
" and readout both sides is " 61 <<
"please add it to config file";
63 ntuple_ = tfile->
make<TTree>(
"tree",
"Cherenkov photons");
79 if (aStep ==
nullptr) {
103 G4String nameVolume =
preStepPoint->GetPhysicalVolume()->GetName();
110 LogDebug(
"EcalSim") <<
"DreamSD:: " << nameVolume <<
" Side " <<
side 111 <<
" Light Collection Efficiency " << weight
121 double time = (aStep->GetPostStepPoint()->GetGlobalTime())/nanosecond;
123 if (
side < 0) unitID++;
132 if (primaryID == 0) {
133 edm::LogWarning(
"EcalSim") <<
"CaloSD: Problem with primaryID **** set by " 134 <<
"force to TkID **** " 135 <<
theTrack->GetTrackID() <<
" in Volume " 136 <<
preStepPoint->GetTouchable()->GetVolume(0)->GetName();
140 bool flag = (unitID > 0);
141 G4TouchableHistory* touch =(G4TouchableHistory*)(
theTrack->GetTouchable());
145 LogDebug(
"EcalSim") <<
"CaloSD:: GetStepInfo for" 146 <<
" PV " << touch->GetVolume(0)->GetName()
147 <<
" PVid = " << touch->GetReplicaNumber(0)
148 <<
" MVid = " << touch->GetReplicaNumber(1)
152 LogDebug(
"EcalSim") <<
"CaloSD:: GetStepInfo for" 153 <<
" PV " << touch->GetVolume(0)->GetName()
154 <<
" PVid = " << touch->GetReplicaNumber(0)
155 <<
" MVid = " << touch->GetReplicaNumber(1)
156 <<
" Unit " << std::hex << unitID <<
std::dec 168 DimensionMap::const_iterator ite =
xtalLMap.begin();
169 G4LogicalVolume* lv = (ite->first);
170 G4Material* material = lv->GetMaterial();
171 edm::LogInfo(
"EcalSim") <<
"DreamSD::initRun: Initializes for material " 172 << material->GetName() <<
" in " << lv->GetName();
176 edm::LogWarning(
"EcalSim") <<
"Couldn't retrieve material properties table\n" 177 <<
" Material = " << material->GetName();
186 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
187 uint32_t
id = (touch->GetReplicaNumber(1))*10 + (touch->GetReplicaNumber(0));
196 G4String attribute =
"ReadOutName";
201 const G4LogicalVolumeStore * lvs = G4LogicalVolumeStore::GetInstance();
202 std::vector<G4LogicalVolume *>::const_iterator lvcite;
208 G4LogicalVolume* lv=
nullptr;
209 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
210 if ((*lvcite)->GetName() ==
name) {
214 LogDebug(
"EcalSim") <<
"DreamSD::initMap (for " << sd <<
"): Solid " 215 << name <<
" Shape " << sol.
shape() <<
" Parameter 0 = " 216 << paras[0] <<
" Logical Volume " << lv;
217 double length = 0,
width = 0;
219 std::sort( paras.begin(), paras.end() );
220 length = 2.0*paras.back();
221 width = 2.0*paras.front();
225 LogDebug(
"EcalSim") <<
"DreamSD: Length Table for " << attribute <<
" = " 227 DimensionMap::const_iterator ite =
xtalLMap.begin();
229 for (; ite !=
xtalLMap.end(); ite++, i++) {
230 G4String
name =
"Unknown";
231 if (ite->first !=
nullptr) name = (ite->first)->GetName();
232 LogDebug(
"EcalSim") <<
" " << i <<
" " << ite->first <<
" " << name
233 <<
" L = " << ite->second.first
234 <<
" W = " << ite->second.second;
241 G4StepPoint* stepPoint = aStep->GetPreStepPoint();
242 G4LogicalVolume* lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
243 G4String nameVolume= lv->GetName();
246 G4ThreeVector localPoint =
setToLocal(stepPoint->GetPosition(),
247 stepPoint->GetTouchable());
249 double localz = localPoint.x();
250 double dapd = 0.5 * crlength - flag*localz;
251 if (dapd >= -0.1 || dapd <= crlength+0.1) {
255 edm::LogWarning(
"EcalSim") <<
"DreamSD: light coll curve : wrong distance " 256 <<
"to APD " << dapd <<
" crlength = " 257 << crlength <<
" crystal name = " << nameVolume
258 <<
" z of localPoint = " << localz
259 <<
" take weight = " <<
weight;
261 LogDebug(
"EcalSim") <<
"DreamSD, light coll curve : " << dapd
262 <<
" crlength = " << crlength
263 <<
" crystal name = " << nameVolume
264 <<
" z of localPoint = " << localz
265 <<
" take weight = " <<
weight;
273 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
274 if (ite !=
xtalLMap.end()) length = ite->second.first;
283 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
284 if (ite !=
xtalLMap.end()) width = ite->second.second;
295 double cherenkovEnergy = 0;
297 G4Material* material = aStep->GetTrack()->GetMaterial();
301 if ( Rindex ==
nullptr ) {
303 return cherenkovEnergy;
308 int Rlength = Rindex->GetVectorLength() - 1;
309 double Pmin = Rindex->Energy(0);
310 double Pmax = Rindex->Energy(Rlength);
311 LogDebug(
"EcalSim") <<
"Material properties: " <<
"\n" 312 <<
" Pmin = " << Pmin
313 <<
" Pmax = " <<
Pmax;
316 G4StepPoint* pPreStepPoint = aStep->GetPreStepPoint();
317 G4StepPoint* pPostStepPoint = aStep->GetPostStepPoint();
318 const G4ThreeVector& x0 = pPreStepPoint->GetPosition();
319 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
320 const G4DynamicParticle* aParticle = aStep->GetTrack()->GetDynamicParticle();
321 const double charge = aParticle->GetDefinition()->GetPDGCharge();
323 double beta = 0.5*( pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta() );
324 double BetaInverse = 1.0/
beta;
326 LogDebug(
"EcalSim") <<
"Particle properties: " <<
"\n" 327 <<
" charge = " << charge
328 <<
" beta = " <<
beta;
332 if ( meanNumberOfPhotons <= 0.0 ) {
333 LogDebug(
"EcalSim") <<
"Mean number of photons is zero: " << meanNumberOfPhotons
334 <<
", stopping here";
335 return cherenkovEnergy;
339 meanNumberOfPhotons *= aStep->GetStepLength();
342 int numPhotons =
static_cast<int>( G4Poisson(meanNumberOfPhotons) );
344 if ( numPhotons <= 0 ) {
345 LogDebug(
"EcalSim") <<
"Poission number of photons is zero: " << numPhotons
346 <<
", stopping here";
347 return cherenkovEnergy;
351 double dp = Pmax - Pmin;
352 double maxCos = BetaInverse / (*Rindex)[Rlength];
353 double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
356 for (
int iPhoton = 0; iPhoton<numPhotons; ++iPhoton ) {
360 double sampledMomentum, sampledRI;
361 double cosTheta, sin2Theta;
365 randomNumber = G4UniformRand();
366 sampledMomentum = Pmin + randomNumber *
dp;
367 sampledRI = Rindex->Value(sampledMomentum);
368 cosTheta = BetaInverse / sampledRI;
370 sin2Theta = (1.0 - cosTheta)*(1.0 + cosTheta);
371 randomNumber = G4UniformRand();
373 }
while (randomNumber*maxSin2 > sin2Theta);
377 randomNumber = G4UniformRand();
379 double phi = twopi*randomNumber;
380 double sinPhi =
sin(phi);
381 double cosPhi =
cos(phi);
386 double sinTheta =
sqrt(sin2Theta);
387 double px = sinTheta*cosPhi;
388 double py = sinTheta*sinPhi;
389 double pz = cosTheta;
390 G4ThreeVector photonDirection(px, py, pz);
393 photonDirection.rotateUz(p0);
396 randomNumber = G4UniformRand();
397 G4ThreeVector photonPosition = x0 + randomNumber * aStep->GetDeltaPosition();
398 G4ThreeVector photonMomentum = sampledMomentum*photonDirection;
405 px_[iPhoton] = photonMomentum.x();
406 py_[iPhoton] = photonMomentum.y();
407 pz_[iPhoton] = photonMomentum.z();
408 x_[iPhoton] = photonPosition.x();
409 y_[iPhoton] = photonPosition.y();
410 z_[iPhoton] = photonPosition.z();
417 return cherenkovEnergy;
427 const G4Material* aMaterial,
428 G4MaterialPropertyVector* Rindex )
430 const G4double rFact = 369.81/(eV * cm);
432 if( beta <= 0.0 )
return 0.0;
434 double BetaInverse = 1./
beta;
441 int Rlength = Rindex->GetVectorLength() - 1;
442 double Pmin = Rindex->Energy(0);
443 double Pmax = Rindex->Energy(Rlength);
446 double nMin = (*Rindex)[0];
447 double nMax = (*Rindex)[Rlength];
452 double dp = 0., ge = 0., CAImin = 0.;
455 if ( nMax < BetaInverse) { }
458 else if (nMin > BetaInverse) {
468 Pmin = Rindex->Value(BetaInverse);
473 ge = CAImax - CAImin;
478 double numPhotons = rFact * charge/eplus * charge/eplus *
479 (dp - ge * BetaInverse*BetaInverse);
481 LogDebug(
"EcalSim") <<
"@SUB=getAverageNumberOfPhotons" 482 <<
"CAImin = " << CAImin <<
"\n" 483 <<
"CAImax = " << CAImax <<
"\n" 484 <<
"dp = " << dp <<
", ge = " << ge <<
"\n" 485 <<
"numPhotons = " << numPhotons;
500 if ( pbWO2Name != aMaterial->GetName() ) {
502 <<
"expecting " << pbWO2Name
503 <<
", got " << aMaterial->GetName();
507 G4MaterialPropertiesTable* table =
new G4MaterialPropertiesTable();
511 const int nEntries = 14;
512 double PhotonEnergy[nEntries] = { 1.7712*eV, 1.8368*eV, 1.90745*eV, 1.98375*eV, 2.0664*eV,
513 2.15625*eV, 2.25426*eV, 2.3616*eV, 2.47968*eV, 2.61019*eV,
514 2.75521*eV, 2.91728*eV, 3.09961*eV, 3.30625*eV };
515 double RefractiveIndex[nEntries] = { 2.17728, 2.18025, 2.18357, 2.18753, 2.19285,
516 2.19813, 2.20441, 2.21337, 2.22328, 2.23619,
517 2.25203, 2.27381, 2.30282, 2.34666 };
519 table->AddProperty(
"RINDEX", PhotonEnergy, RefractiveIndex, nEntries );
520 aMaterial->SetMaterialPropertiesTable(table);
525 std::auto_ptr<G4PhysicsOrderedFreeVector>(
new G4PhysicsOrderedFreeVector() );
528 double currentRI = RefractiveIndex[
index];
529 double currentPM = PhotonEnergy[
index];
530 double currentCAI = 0.0;
532 double prevPM = currentPM;
533 double prevCAI = currentCAI;
534 double prevRI = currentRI;
535 while ( ++index < nEntries ) {
536 currentRI = RefractiveIndex[
index];
537 currentPM = PhotonEnergy[
index];
538 currentCAI = 0.5*(1.0/(prevRI*prevRI) + 1.0/(currentRI*currentRI));
539 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
544 prevCAI = currentCAI;
548 LogDebug(
"EcalSim") <<
"Material properties set for " << aMaterial->GetName();
561 const G4ThreeVector&
x,
562 const G4Step* aStep )
575 G4StepPoint* stepPoint = aStep->GetPreStepPoint();
576 G4LogicalVolume* lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
577 G4String nameVolume= lv->GetName();
581 double dapd = 0.5 * crlength - x.x();
582 double y = p.y()/p.x()*dapd;
584 LogDebug(
"EcalSim") <<
"Distance to APD: " << dapd
585 <<
" - y at APD: " <<
y;
588 if ( fabs(y)>crwidth*0.5 ) {
593 double waveLength = p.mag()*1.239e8;
598 LogDebug(
"EcalSim") <<
"Wavelength: " << waveLength <<
" - Energy: " << energy;
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
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)
double getAverageNumberOfPhotons_(const double charge, const double beta, const G4Material *aMaterial, G4MaterialPropertyVector *rIndex)
Returns average number of photons created by track.
bool setPbWO2MaterialProperties_(G4Material *aMaterial)
Sets material properties at run-time...
T * make(const Args &...args) const
make new ROOT object
std::auto_ptr< G4PhysicsOrderedFreeVector > chAngleIntegrals_
Table of Cherenkov angle integrals vs photon momentum.
const DDSolid & solid(void) const
Returns a reference object of the solid being the shape of this LogicalPart.
type of data representation of DDCompactView
DreamSD(G4String, const DDCompactView &, const SensitiveDetectorCatalog &, edm::ParameterSet const &, const SimTrackManager *)
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
uint32_t setDetUnitId(G4Step *) override
Cos< T >::type cos(const T &t)
DDSolidShape shape(void) const
The type of the solid.
double getAttenuation(G4Step *aStep, double birk1, double birk2, double birk3)
G4MaterialPropertiesTable * materialPropertiesTable
const double crystalWidth(G4LogicalVolume *) const
void setID(uint32_t unitID, double timeSlice, int trackID, uint16_t depth=0)
G4StepPoint * preStepPoint
double cherenkovDeposit_(G4Step *aStep)
Returns the total energy due to Cherenkov radiation.
bool firstChild()
set the current node to the first child ...
bool ProcessHits(G4Step *step, G4TouchableHistory *tHistory) override
const double crystalLength(G4LogicalVolume *) const
void initMap(G4String, const DDCompactView &)
const std::string & name() const
Returns the name.
double curve_LY(G4Step *, int)
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 *)