9 #include "G4LogicalVolumeStore.hh" 10 #include "G4LogicalVolume.hh" 13 #include "G4VProcess.hh" 14 #include "G4Poisson.hh" 23 #include "G4SystemOfUnits.hh" 24 #include "G4PhysicalConstants.hh" 30 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 " 64 double edep = aStep->GetTotalEnergyDeposit() *
weight;
68 LogDebug(
"EcalSim") <<
"DreamSD:: " << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName()
70 <<
" Light Collection Efficiency " << weight
71 <<
" Weighted Energy Deposit " << edep/
MeV 81 DimensionMap::const_iterator ite =
xtalLMap.begin();
82 const G4LogicalVolume* lv = (ite->first);
83 G4Material* material = lv->GetMaterial();
84 edm::LogInfo(
"EcalSim") <<
"DreamSD::initRun: Initializes for material " 85 << material->GetName() <<
" in " << lv->GetName();
89 edm::LogWarning(
"EcalSim") <<
"Couldn't retrieve material properties table\n" 90 <<
" Material = " << material->GetName();
99 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
100 uint32_t
id = (touch->GetReplicaNumber(1))*10 + (touch->GetReplicaNumber(0));
111 G4String attribute =
"ReadOutName";
116 const G4LogicalVolumeStore * lvs = G4LogicalVolumeStore::GetInstance();
117 std::vector<G4LogicalVolume *>::const_iterator lvcite;
123 G4LogicalVolume* lv=
nullptr;
124 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
125 if ((*lvcite)->GetName() ==
name) {
129 LogDebug(
"EcalSim") <<
"DreamSD::initMap (for " << sd <<
"): Solid " 130 << name <<
" Shape " << sol.
shape() <<
" Parameter 0 = " 131 << paras[0] <<
" Logical Volume " << lv;
132 double length = 0,
width = 0;
134 std::sort( paras.begin(), paras.end() );
135 length = 2.0*paras.back();
136 width = 2.0*paras.front();
140 LogDebug(
"EcalSim") <<
"DreamSD: Length Table for " << attribute <<
" = " 142 DimensionMap::const_iterator ite =
xtalLMap.begin();
144 for (; ite !=
xtalLMap.end(); ite++, i++) {
145 G4String
name =
"Unknown";
146 if (ite->first !=
nullptr) name = (ite->first)->GetName();
147 LogDebug(
"EcalSim") <<
" " << i <<
" " << ite->first <<
" " << name
148 <<
" L = " << ite->second.first
149 <<
" W = " << ite->second.second;
156 auto const stepPoint = aStep->GetPreStepPoint();
157 auto const lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
158 G4String nameVolume= lv->GetName();
161 G4ThreeVector localPoint =
setToLocal(stepPoint->GetPosition(),
162 stepPoint->GetTouchable());
164 double localz = localPoint.x();
165 double dapd = 0.5 * crlength - flag*localz;
166 if (dapd >= -0.1 || dapd <= crlength+0.1) {
170 edm::LogWarning(
"EcalSim") <<
"DreamSD: light coll curve : wrong distance " 171 <<
"to APD " << dapd <<
" crlength = " 172 << crlength <<
" crystal name = " << nameVolume
173 <<
" z of localPoint = " << localz
174 <<
" take weight = " <<
weight;
176 LogDebug(
"EcalSim") <<
"DreamSD, light coll curve : " << dapd
177 <<
" crlength = " << crlength
178 <<
" crystal name = " << nameVolume
179 <<
" z of localPoint = " << localz
180 <<
" take weight = " <<
weight;
188 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
189 if (ite !=
xtalLMap.end()) length = ite->second.first;
198 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
199 if (ite !=
xtalLMap.end()) width = ite->second.second;
210 double cherenkovEnergy = 0;
212 G4Material* material = aStep->GetTrack()->GetMaterial();
216 if ( Rindex ==
nullptr ) {
218 return cherenkovEnergy;
223 int Rlength = Rindex->GetVectorLength() - 1;
224 double Pmin = Rindex->Energy(0);
225 double Pmax = Rindex->Energy(Rlength);
226 LogDebug(
"EcalSim") <<
"Material properties: " <<
"\n" 227 <<
" Pmin = " << Pmin
228 <<
" Pmax = " <<
Pmax;
231 const G4StepPoint* pPreStepPoint = aStep->GetPreStepPoint();
232 const G4StepPoint* pPostStepPoint = aStep->GetPostStepPoint();
233 const G4ThreeVector& x0 = pPreStepPoint->GetPosition();
234 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
235 const G4DynamicParticle* aParticle = aStep->GetTrack()->GetDynamicParticle();
236 const double charge = aParticle->GetDefinition()->GetPDGCharge();
238 double beta = 0.5*( pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta() );
239 double BetaInverse = 1.0/
beta;
241 LogDebug(
"EcalSim") <<
"Particle properties: " <<
"\n" 242 <<
" charge = " << charge
243 <<
" beta = " <<
beta;
247 if ( meanNumberOfPhotons <= 0.0 ) {
248 LogDebug(
"EcalSim") <<
"Mean number of photons is zero: " << meanNumberOfPhotons
249 <<
", stopping here";
250 return cherenkovEnergy;
254 meanNumberOfPhotons *= aStep->GetStepLength();
257 int numPhotons =
static_cast<int>( G4Poisson(meanNumberOfPhotons) );
259 if ( numPhotons <= 0 ) {
260 LogDebug(
"EcalSim") <<
"Poission number of photons is zero: " << numPhotons
261 <<
", stopping here";
262 return cherenkovEnergy;
266 double dp = Pmax - Pmin;
267 double maxCos = BetaInverse / (*Rindex)[Rlength];
268 double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
271 for (
int iPhoton = 0; iPhoton<numPhotons; ++iPhoton ) {
275 double sampledMomentum, sampledRI;
276 double cosTheta, sin2Theta;
280 randomNumber = G4UniformRand();
281 sampledMomentum = Pmin + randomNumber * dp;
282 sampledRI = Rindex->Value(sampledMomentum);
283 cosTheta = BetaInverse / sampledRI;
285 sin2Theta = (1.0 - cosTheta)*(1.0 + cosTheta);
286 randomNumber = G4UniformRand();
288 }
while (randomNumber*maxSin2 > sin2Theta);
292 randomNumber = G4UniformRand();
294 double phi = twopi*randomNumber;
295 double sinPhi =
sin(phi);
296 double cosPhi =
cos(phi);
301 double sinTheta =
sqrt(sin2Theta);
302 double px = sinTheta*cosPhi;
303 double py = sinTheta*sinPhi;
304 double pz = cosTheta;
305 G4ThreeVector photonDirection(px, py, pz);
308 photonDirection.rotateUz(p0);
311 randomNumber = G4UniformRand();
312 G4ThreeVector photonPosition = x0 + randomNumber * aStep->GetDeltaPosition();
313 G4ThreeVector photonMomentum = sampledMomentum*photonDirection;
318 return cherenkovEnergy;
327 const G4Material* aMaterial,
328 const G4MaterialPropertyVector* Rindex )
330 const double rFact = 369.81/(eV * cm);
332 if( beta <= 0.0 )
return 0.0;
334 double BetaInverse = 1./
beta;
341 int Rlength = Rindex->GetVectorLength() - 1;
342 double Pmin = Rindex->Energy(0);
343 double Pmax = Rindex->Energy(Rlength);
346 double nMin = (*Rindex)[0];
347 double nMax = (*Rindex)[Rlength];
352 double dp = 0., ge = 0., CAImin = 0.;
355 if ( nMax < BetaInverse) { }
358 else if (nMin > BetaInverse) {
368 Pmin = Rindex->Value(BetaInverse);
373 ge = CAImax - CAImin;
378 double numPhotons = rFact * charge/eplus * charge/eplus *
379 (dp - ge * BetaInverse*BetaInverse);
381 LogDebug(
"EcalSim") <<
"@SUB=getAverageNumberOfPhotons" 382 <<
"CAImin = " << CAImin <<
"\n" 383 <<
"CAImax = " << CAImax <<
"\n" 384 <<
"dp = " << dp <<
", ge = " << ge <<
"\n" 385 <<
"numPhotons = " << numPhotons;
400 if ( pbWO2Name != aMaterial->GetName() ) {
402 <<
"expecting " << pbWO2Name
403 <<
", got " << aMaterial->GetName();
407 G4MaterialPropertiesTable* table =
new G4MaterialPropertiesTable();
411 const int nEntries = 14;
412 double PhotonEnergy[nEntries] = { 1.7712*eV, 1.8368*eV, 1.90745*eV, 1.98375*eV, 2.0664*eV,
413 2.15625*eV, 2.25426*eV, 2.3616*eV, 2.47968*eV, 2.61019*eV,
414 2.75521*eV, 2.91728*eV, 3.09961*eV, 3.30625*eV };
415 double RefractiveIndex[nEntries] = { 2.17728, 2.18025, 2.18357, 2.18753, 2.19285,
416 2.19813, 2.20441, 2.21337, 2.22328, 2.23619,
417 2.25203, 2.27381, 2.30282, 2.34666 };
419 table->AddProperty(
"RINDEX", PhotonEnergy, RefractiveIndex, nEntries );
420 aMaterial->SetMaterialPropertiesTable(table);
427 double currentRI = RefractiveIndex[
index];
428 double currentPM = PhotonEnergy[
index];
429 double currentCAI = 0.0;
431 double prevPM = currentPM;
432 double prevCAI = currentCAI;
433 double prevRI = currentRI;
434 while ( ++index < nEntries ) {
435 currentRI = RefractiveIndex[
index];
436 currentPM = PhotonEnergy[
index];
437 currentCAI = 0.5*(1.0/(prevRI*prevRI) + 1.0/(currentRI*currentRI));
438 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
443 prevCAI = currentCAI;
447 LogDebug(
"EcalSim") <<
"Material properties set for " << aMaterial->GetName();
460 const G4ThreeVector&
x,
461 const G4Step* aStep )
474 G4StepPoint* stepPoint = aStep->GetPreStepPoint();
475 G4LogicalVolume* lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
476 G4String nameVolume= lv->GetName();
480 double dapd = 0.5 * crlength - x.x();
481 double y = p.y()/p.x()*dapd;
483 LogDebug(
"EcalSim") <<
"Distance to APD: " << dapd
484 <<
" - y at APD: " <<
y;
492 double waveLength = p.mag()*1.239e8;
496 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)
uint32_t setDetUnitId(const G4Step *) override
bool setPbWO2MaterialProperties_(G4Material *aMaterial)
Sets material properties at run-time...
const DDSolid & solid(void) const
Returns a reference object of the solid being the shape of this LogicalPart.
Compact representation of the geometrical detector hierarchy.
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.
static double getEfficiency(const double &waveLengthNm)
Return efficiency for given photon wavelength (in nm)
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)
Abs< T >::type abs(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.
double crystalWidth(G4LogicalVolume *) const
G4MaterialPropertiesTable * materialPropertiesTable
double curve_LY(const G4Step *, int)
G4ThreeVector setToLocal(const G4ThreeVector &, const G4VTouchable *) const
double crystalLength(G4LogicalVolume *) const
std::unique_ptr< G4PhysicsOrderedFreeVector > chAngleIntegrals_
Table of Cherenkov angle integrals vs photon momentum.
double getEnergyDeposit(const G4Step *) override
double getAttenuation(const G4Step *aStep, double birk1, double birk2, double birk3) const
DreamSD(const std::string &, const DDCompactView &, const SensitiveDetectorCatalog &, edm::ParameterSet const &, const SimTrackManager *)
bool firstChild()
set the current node to the first child ...
const std::string & name() const
Returns the name.
void initMap(const std::string &, const DDCompactView &)