49{
53 return false;
54 }
55 }
56
57 if(verboseLevel>5)
58 {
59 G4cout << "AFP_TDSensitiveDetector::ProcessHits" << G4endl;
60 }
61
62 bool bRes=false;
63
64 int nTrackID=-1;
65 int nParticleEncoding=-1;
66 float fKineticEnergy=0.0;
67 float fEnergyDeposit=0.0;
68 float fWaveLength=0.0;
69 float fPreStepX=0.0;
70 float fPreStepY=0.0;
71 float fPreStepZ=0.0;
72 float fPostStepX=0.0;
73 float fPostStepY=0.0;
74 float fPostStepZ=0.0;
75 float fGlobalTime=0.0;
76 int nStationID=-1;
77 int nDetectorID=-1;
78 int nQuarticID=-1;
79
80
81
82
83 G4Track* pTrack = pStep->GetTrack();
84 G4ParticleDefinition* pParticleDefinition = pTrack->GetDefinition();
85 G4StepPoint* pPreStepPoint = pStep->GetPreStepPoint();
86 G4StepPoint* pPostStepPoint = pStep->GetPostStepPoint();
87 G4ThreeVector PreStepPointPos = pPreStepPoint->GetPosition();
88 G4ThreeVector PostStepPointPos = pPostStepPoint->GetPosition();
89
90 nTrackID=pTrack->GetTrackID();
91 fKineticEnergy = pPreStepPoint->GetKineticEnergy();
92 fEnergyDeposit = pStep->GetTotalEnergyDeposit();
93
94 fPreStepX = PreStepPointPos.x();
95 fPreStepY = PreStepPointPos.y();
96 fPreStepZ = PreStepPointPos.z();
97 fPostStepX = PostStepPointPos.x();
98 fPostStepY = PostStepPointPos.y();
99 fPostStepZ = PostStepPointPos.z();
100 nParticleEncoding = pParticleDefinition->GetPDGEncoding();
101 fGlobalTime = pStep->GetPreStepPoint()->GetGlobalTime()/CLHEP::picosecond;
102
103
104 G4TouchableHandle touch1 = pPreStepPoint->GetTouchableHandle();
105 G4VPhysicalVolume* volume = touch1->GetVolume();
106 G4String VolumeName = volume->GetName();
107
108
109
110
111
112 if(verboseLevel>5)
113 {
114 G4cout << "hit volume name is " << VolumeName << G4endl;
115
116 G4cout << "global, x_pre: " << fPreStepX << ", y_pre: " << fPreStepY << ", z_pre: " << fPreStepZ << G4endl;
117 G4cout << "global, x_post: " << fPostStepX << ", y_post: " << fPostStepY << ", z_post: " << fPostStepZ << G4endl;
118 }
119
120 char* ppv1, *ppv2;
121 char szbuff[32];
122 memset(&szbuff[0],0,sizeof(szbuff));
123 strncpy(szbuff,VolumeName.data(),sizeof(szbuff));
124 szbuff[sizeof(szbuff)-1] = '\0';
125 ppv1=strchr(szbuff,'[');
126 ppv2=strchr(szbuff,']');
127 if(!ppv2 || !ppv1){
128 G4cout << "ERROR: Invalid format of volume name " << VolumeName << G4endl;
129 return false;
130 }
131 else *ppv2='\0';
132
133 nStationID=10*(szbuff[3]-0x30)+(szbuff[4]-0x30);
134 nDetectorID=
atoi(ppv1+1);
135
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174#if G4VERSION_NUMBER < 1100
175 if ( (VolumeName.contains("TDQuarticBarVacBorder")) && pParticleDefinition->GetPDGCharge() !=0 )
176#else
177 if ( (G4StrUtil::contains(VolumeName, "TDQuarticBarVacBorder")) && pParticleDefinition->GetPDGCharge() !=0 )
178#endif
179 {
180 nQuarticID=szbuff[7]-0x30;
181
182
183
184
185
186
187
188
189 }
190
192#if G4VERSION_NUMBER < 1100
193 if ( (bRes=VolumeName.contains("TDQuarticBar[")) )
194#else
195 if ( (bRes=G4StrUtil::contains(VolumeName, "TDQuarticBar[")) )
196#endif
197 {
198 nQuarticID=szbuff[7]-0x30;
199
200
201 if (
m_HitColl->HasReachedLimit(nStationID, nQuarticID, nDetectorID))
return 1;
202
203
204 const G4TouchableHistory* myTouch = static_cast<const G4TouchableHistory*>(pPreStepPoint->GetTouchable());
205
206
207
208 const G4AffineTransform transformation = myTouch->GetHistory()->GetTopTransform();
209 G4ThreeVector PreStepPointPos2 = transformation.TransformPoint(PreStepPointPos);
210 G4ThreeVector PostStepPointPos2 = transformation.TransformPoint(PostStepPointPos);
211
212 G4String shape( myTouch->GetSolid()->GetEntityType() );
213
214 G4ThreeVector normpX( 1., 0., 0.);
215 G4ThreeVector normnX(-1., 0., 0.);
216 G4ThreeVector normpY( 0., 1., 0.);
217 G4ThreeVector normnY( 0.,-1., 0.);
218 G4ThreeVector normpZ( 0., 0., 1.);
219 G4ThreeVector normnZ( 0., 0.,-1.);
220
221
222
223
224
225
226
227
228
229
230
231
232 G4double PreProtonX = PreStepPointPos2.x();
233 G4double PreProtonY = PreStepPointPos2.y();
234 G4double PreProtonZ = PreStepPointPos2.z();
235
236 G4double PostProtonX = PostStepPointPos2.x();
237 G4double PostProtonY = PostStepPointPos2.y();
238 G4double PostProtonZ = PostStepPointPos2.z();
239
240 G4ThreeVector
p0 = pStep->GetDeltaPosition().unit();
241
242 G4Material*
mat = pStep->GetTrack()->GetMaterial();
243 G4MaterialPropertiesTable *matPropTable =
mat->GetMaterialPropertiesTable();
244
245 G4MaterialPropertyVector* Rind = matPropTable->GetProperty("RINDEX");
246
247 G4MaterialPropertyVector* Alen = matPropTable->GetProperty("ABSLENGTH");
248
249 const G4double
charge = pParticleDefinition->GetPDGCharge();
250 const G4double
beta = (pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta()) / 2.;
251 G4double BetaInverse = 1. /
beta;
252
253
254
255#if G4VERSION_NUMBER < 1100
256 G4double Pmin = Rind->GetMinLowEdgeEnergy();
257
258 G4double Pmax = Rind->GetMaxLowEdgeEnergy();
259#else
260 G4double Pmin = Rind->GetMinEnergy();
261 G4double Pmax = Rind->GetMaxEnergy();
262#endif
263 G4double
dp = Pmax - Pmin;
264
265 G4double maxCosTheta = BetaInverse / Rind->GetMinValue();
266 G4double maxSin2Theta = (1.0 - maxCosTheta) * (1.0 + maxCosTheta);
267
268
269 G4double meanRI = .5*(Rind->GetMinValue() + Rind->GetMaxValue());
270
271
272 G4double MeanNumberOfPhotons = 370.*(
charge/CLHEP::eplus)*(
charge/CLHEP::eplus)* (1.0 - 1.0/(
beta * meanRI *
beta * meanRI)) / (CLHEP::cm*CLHEP::eV);
273 if (MeanNumberOfPhotons <= 0.0) return 1;
274
275 G4double step_length = pStep->GetStepLength();
276
277 MeanNumberOfPhotons = MeanNumberOfPhotons * step_length *
dp;
278 G4int NumPhotons = (G4int) G4Poisson( MeanNumberOfPhotons );
279 if (NumPhotons <= 0) return 1;
280
281
282 G4int NumPhotonsCuts=0;
283 for (G4int
I = 0;
I < NumPhotons;
I++) {
284
286 G4double sampledEnergy, sampledRI;
287 G4double cosTheta, sin2Theta;
288
289
290 do {
291 rand = G4UniformRand();
292 sampledEnergy = Pmin +
rand *
dp;
293
294 sampledRI = Rind->Value(sampledEnergy);
295 cosTheta = BetaInverse / sampledRI;
296
297 sin2Theta = (1.0 - cosTheta)*(1.0 + cosTheta);
298 rand = G4UniformRand();
299
300 } while (rand * maxSin2Theta > sin2Theta);
301
302
303 rand = G4UniformRand();
305 G4double sinPhi =
sin(
phi);
306 G4double cosPhi =
cos(
phi);
307
308
309
310
311 G4double sinTheta = sqrt(sin2Theta);
312 G4double
px = sinTheta*cosPhi;
313 G4double
py = sinTheta*sinPhi;
314 G4double
pz = cosTheta;
315 G4ParticleMomentum photonMomentum(px, py, pz);
316 photonMomentum.rotateUz(p0);
317
318 G4double PX = photonMomentum.getX();
319 G4double PY = photonMomentum.getY();
320 G4double PZ = photonMomentum.getZ();
321
322
323
324 G4double PYp = PY/sqrt(PX*PX+PY*PY+PZ*PZ);
325 G4double PZp = PZ/sqrt(PX*PX+PY*PY+PZ*PZ);
326
327 G4double PYt = PY/sqrt(PY*PY+PZ*PZ);
328 G4double PZt = PZ/sqrt(PY*PY+PZ*PZ);
329
330
331 cosPhi = (PYp*PYt + PZp*PZt);
332 if (nStationID == 0) cosTheta = ( -PYt*
sin(48.*CLHEP::deg) + PZt*
cos(48.*CLHEP::deg) );
333 else cosTheta = ( -PYt*
sin(48.*CLHEP::deg) - PZt*
cos(48.*CLHEP::deg) );
334
335
336 G4double cosThetaC = sqrt(1.-1./sampledRI/sampledRI);
337 if (sqrt(1.-cosPhi*cosPhi)>cosThetaC) continue;
338 if (sqrt(1.-cosTheta*cosTheta)*cosPhi>cosThetaC) continue;
339
340
341 rand = G4UniformRand();
342 G4double PhotonX = PreProtonX + (PostProtonX-PreProtonX)*rand;
343 G4double PhotonY = PreProtonY + (PostProtonY-PreProtonY)*rand;
344 G4double PhotonZ = PreProtonZ + (PostProtonZ-PreProtonZ)*rand;
345 G4ThreeVector PhotonPos(PhotonX,PhotonY,PhotonZ);
346 G4double PhotonR = sqrt( (PreProtonX-PhotonX)*(PreProtonX-PhotonX) + (PreProtonY-PhotonY)*(PreProtonY-PhotonY) + (PreProtonZ-PhotonZ)*(PreProtonZ-PhotonZ) );
347
348 G4double Y0;
349
350 if (cosTheta>=0)
351 {
352 Y0 = static_cast<G4ReflectedSolid *>(myTouch->GetSolid())->DistanceToOut(PhotonPos, normnY);
353 Y0 = Y0/cosTheta/cosPhi;
354 }
355 else
356 {
357 continue;
358
359
360 }
361
362
363
364 float Pabs = 1. -
exp( - Y0/Alen->Value(sampledEnergy) );
365 rand = G4UniformRand();
366 if (Pabs>rand) continue;
367
368
369 rand = G4UniformRand();
372
373 NumPhotonsCuts++;
374
375 float fGlobalTime2 = fGlobalTime;
376 fGlobalTime2 += ( PhotonR * BetaInverse / CLHEP::c_light )/CLHEP::picosecond;
377
378
379 float EdndE;
380
381 if (sampledEnergy > (Pmin+.5*dp)) EdndE = (sampledRI - Rind->Value(sampledEnergy-0.0001*CLHEP::eV))/0.0001*sampledEnergy/CLHEP::eV;
382
383 else EdndE = (Rind->Value(sampledEnergy+0.0001*CLHEP::eV) - sampledRI)/0.0001*sampledEnergy/CLHEP::eV;
384 fGlobalTime2 += ( (sampledRI + EdndE)* Y0 * BetaInverse / CLHEP::c_light )/CLHEP::picosecond;
385
386 if (verboseLevel>5)
387 {
388 G4cout << "FastCher EdndE: " << EdndE << G4endl;
389 }
390 fWaveLength = 2.*
M_PI*CLHEP::hbarc/sampledEnergy/(CLHEP::MeV*CLHEP::nm);
391
392
393 if (
m_HitColl->HasReachedLimit(nStationID, nQuarticID, nDetectorID))
return 1;
394
395 int nSensitiveElementID=-1;
396 if(nQuarticID==0) { nSensitiveElementID=1; }
397 else if(nQuarticID==1) { nSensitiveElementID=3; }
398
399 m_HitColl->Emplace(
m_nHitID,nTrackID,nParticleEncoding,fKineticEnergy,fEnergyDeposit,
400 fWaveLength,PhotonX,PhotonY,PhotonZ,(PhotonX+PX),(PhotonY+PY),(PhotonZ+PZ),
401 fGlobalTime2,nStationID,nDetectorID,nSensitiveElementID);
402 m_HitColl->CountHit(nStationID, nQuarticID, nDetectorID);
403 }
404 if(verboseLevel>5)
405 {
406 G4cout << "FastCher number of photons: " << NumPhotonsCuts << G4endl;
407 }
408 }
410 return true;
411}
Scalar phi() const
phi method
double charge(const T &p)
static constexpr double TDMaxQEff
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...