11 #include "G4LogicalVolume.hh" 12 #include "G4LogicalVolumeStore.hh" 13 #include "G4Poisson.hh" 16 #include "G4VProcess.hh" 27 #include "G4PhysicalConstants.hh" 28 #include "G4SystemOfUnits.hh" 36 :
CaloSD(name, es, clg, p, manager) {
48 edm::LogInfo(
"EcalSim") <<
"Constructing a DreamSD with name " << GetName() <<
"\n" 49 <<
"DreamSD:: Use of Birks law is set to " << useBirk
50 <<
" with three constants kB = " << birk1 <<
", C1 = " << birk2 <<
", C2 = " << birk3 <<
"\n" 51 <<
" Slope for Light yield is set to " << slopeLY <<
"\n" 52 <<
" Parameterization of Cherenkov is set to " << doCherenkov_
64 double edep = aStep->GetTotalEnergyDeposit() *
weight;
70 LogDebug(
"EcalSim") <<
"DreamSD:: " << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() <<
" Side " <<
side 71 <<
" Light Collection Efficiency " << weight <<
" Weighted Energy Deposit " << edep /
MeV 80 DimensionMap::const_iterator ite =
xtalLMap.begin();
81 const G4LogicalVolume *lv = (ite->first);
82 G4Material *material = lv->GetMaterial();
83 edm::LogInfo(
"EcalSim") <<
"DreamSD::initRun: Initializes for material " << material->GetName() <<
" in " 88 edm::LogWarning(
"EcalSim") <<
"Couldn't retrieve material properties table\n" 89 <<
" Material = " << material->GetName();
97 const G4VTouchable *touch = aStep->GetPreStepPoint()->GetTouchable();
98 uint32_t
id = (touch->GetReplicaNumber(1)) * 10 + (touch->GetReplicaNumber(0));
112 G4String attribute =
"ReadOutName";
117 const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
118 std::vector<G4LogicalVolume *>::const_iterator lvcite;
124 G4LogicalVolume *lv =
nullptr;
125 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
126 if ((*lvcite)->GetName() ==
name) {
130 LogDebug(
"EcalSim") <<
"DreamSD::initMap (for " << sd <<
"): Solid " << name <<
" Shape " << sol.
shape()
131 <<
" Parameter 0 = " << 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 <<
" = " << sd <<
":";
141 DimensionMap::const_iterator ite =
xtalLMap.begin();
143 for (; ite !=
xtalLMap.end(); ite++, i++) {
144 G4String
name =
"Unknown";
145 if (ite->first !=
nullptr)
146 name = (ite->first)->GetName();
147 LogDebug(
"EcalSim") <<
" " << i <<
" " << ite->first <<
" " << name <<
" L = " << ite->second.first
148 <<
" W = " << ite->second.second;
154 auto const stepPoint = aStep->GetPreStepPoint();
155 auto const lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
156 G4String nameVolume = lv->GetName();
159 G4ThreeVector localPoint =
setToLocal(stepPoint->GetPosition(), stepPoint->GetTouchable());
161 double localz = localPoint.x();
162 double dapd = 0.5 * crlength - flag * localz;
163 if (dapd >= -0.1 || dapd <= crlength + 0.1) {
167 edm::LogWarning(
"EcalSim") <<
"DreamSD: light coll curve : wrong distance " 168 <<
"to APD " << dapd <<
" crlength = " << crlength <<
" crystal name = " << nameVolume
169 <<
" z of localPoint = " << localz <<
" take weight = " <<
weight;
171 LogDebug(
"EcalSim") <<
"DreamSD, light coll curve : " << dapd <<
" crlength = " << crlength
172 <<
" crystal name = " << nameVolume <<
" z of localPoint = " << localz
173 <<
" take weight = " <<
weight;
180 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
182 length = ite->second.first;
189 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
191 width = ite->second.second;
199 double cherenkovEnergy = 0;
201 return cherenkovEnergy;
202 G4Material *material = aStep->GetTrack()->GetMaterial();
206 if (Rindex ==
nullptr) {
208 return cherenkovEnergy;
213 int Rlength = Rindex->GetVectorLength() - 1;
214 double Pmin = Rindex->Energy(0);
215 double Pmax = Rindex->Energy(Rlength);
216 LogDebug(
"EcalSim") <<
"Material properties: " 218 <<
" Pmin = " << Pmin <<
" Pmax = " <<
Pmax;
221 const G4StepPoint *pPreStepPoint = aStep->GetPreStepPoint();
222 const G4StepPoint *pPostStepPoint = aStep->GetPostStepPoint();
223 const G4ThreeVector &x0 = pPreStepPoint->GetPosition();
224 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
225 const G4DynamicParticle *aParticle = aStep->GetTrack()->GetDynamicParticle();
226 const double charge = aParticle->GetDefinition()->GetPDGCharge();
228 double beta = 0.5 * (pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta());
229 double BetaInverse = 1.0 /
beta;
231 LogDebug(
"EcalSim") <<
"Particle properties: " 233 <<
" charge = " << charge <<
" beta = " <<
beta;
237 if (meanNumberOfPhotons <= 0.0) {
238 LogDebug(
"EcalSim") <<
"Mean number of photons is zero: " << meanNumberOfPhotons <<
", stopping here";
239 return cherenkovEnergy;
243 meanNumberOfPhotons *= aStep->GetStepLength();
246 int numPhotons =
static_cast<int>(G4Poisson(meanNumberOfPhotons));
248 if (numPhotons <= 0) {
249 LogDebug(
"EcalSim") <<
"Poission number of photons is zero: " << numPhotons <<
", stopping here";
250 return cherenkovEnergy;
254 double dp = Pmax - Pmin;
255 double maxCos = BetaInverse / (*Rindex)[Rlength];
256 double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
259 for (
int iPhoton = 0; iPhoton < numPhotons; ++iPhoton) {
262 double sampledMomentum, sampledRI;
263 double cosTheta, sin2Theta;
267 randomNumber = G4UniformRand();
268 sampledMomentum = Pmin + randomNumber *
dp;
269 sampledRI = Rindex->Value(sampledMomentum);
270 cosTheta = BetaInverse / sampledRI;
272 sin2Theta = (1.0 - cosTheta) * (1.0 + cosTheta);
273 randomNumber = G4UniformRand();
275 }
while (randomNumber * maxSin2 > sin2Theta);
279 randomNumber = G4UniformRand();
281 double phi = twopi * randomNumber;
282 double sinPhi =
sin(phi);
283 double cosPhi =
cos(phi);
288 double sinTheta =
sqrt(sin2Theta);
289 double px = sinTheta * cosPhi;
290 double py = sinTheta * sinPhi;
291 double pz = cosTheta;
292 G4ThreeVector photonDirection(px, py, pz);
295 photonDirection.rotateUz(p0);
298 randomNumber = G4UniformRand();
299 G4ThreeVector photonPosition = x0 + randomNumber * aStep->GetDeltaPosition();
300 G4ThreeVector photonMomentum = sampledMomentum * photonDirection;
305 return cherenkovEnergy;
313 const G4Material *aMaterial,
314 const G4MaterialPropertyVector *Rindex) {
315 const double rFact = 369.81 / (eV * cm);
320 double BetaInverse = 1. /
beta;
327 int Rlength = Rindex->GetVectorLength() - 1;
328 double Pmin = Rindex->Energy(0);
329 double Pmax = Rindex->Energy(Rlength);
332 double nMin = (*Rindex)[0];
333 double nMax = (*Rindex)[Rlength];
338 double dp = 0., ge = 0., CAImin = 0.;
341 if (nMax < BetaInverse) {
345 else if (nMin > BetaInverse) {
355 Pmin = Rindex->Value(BetaInverse);
360 ge = CAImax - CAImin;
364 double numPhotons = rFact * charge / eplus * charge / eplus * (dp - ge * BetaInverse * BetaInverse);
366 LogDebug(
"EcalSim") <<
"@SUB=getAverageNumberOfPhotons" 367 <<
"CAImin = " << CAImin <<
"\n" 368 <<
"CAImax = " << CAImax <<
"\n" 369 <<
"dp = " << dp <<
", ge = " << ge <<
"\n" 370 <<
"numPhotons = " << numPhotons;
380 if (pbWO2Name != aMaterial->GetName()) {
382 <<
"expecting " << pbWO2Name <<
", got " << aMaterial->GetName();
386 G4MaterialPropertiesTable *
table =
new G4MaterialPropertiesTable();
390 const int nEntries = 14;
391 double PhotonEnergy[nEntries] = {1.7712 * eV,
405 double RefractiveIndex[nEntries] = {2.17728,
420 table->AddProperty(
"RINDEX", PhotonEnergy, RefractiveIndex, nEntries);
421 aMaterial->SetMaterialPropertiesTable(table);
428 double currentRI = RefractiveIndex[
index];
429 double currentPM = PhotonEnergy[
index];
430 double currentCAI = 0.0;
432 double prevPM = currentPM;
433 double prevCAI = currentCAI;
434 double prevRI = currentRI;
435 while (++index < nEntries) {
436 currentRI = RefractiveIndex[
index];
437 currentPM = PhotonEnergy[
index];
438 currentCAI = 0.5 * (1.0 / (prevRI * prevRI) + 1.0 / (currentRI * currentRI));
439 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
444 prevCAI = currentCAI;
448 LogDebug(
"EcalSim") <<
"Material properties set for " << aMaterial->GetName();
469 G4StepPoint *stepPoint = aStep->GetPreStepPoint();
470 G4LogicalVolume *lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
471 G4String nameVolume = lv->GetName();
475 double dapd = 0.5 * crlength - x.x();
476 double y = p.y() / p.x() * dapd;
478 LogDebug(
"EcalSim") <<
"Distance to APD: " << dapd <<
" - y at APD: " <<
y;
485 double waveLength = p.mag() * 1.239e8;
489 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.
Sin< T >::type sin(const T &t)
uint32_t setDetUnitId(const G4Step *) override
bool setPbWO2MaterialProperties_(G4Material *aMaterial)
Sets material properties at run-time...
void initMap(const std::string &, const edm::EventSetup &)
const DDSolid & solid(void) const
Returns a reference object of the solid being the shape of this LogicalPart.
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
std::pair< double, double > Doubles
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 edm::EventSetup &, 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.