165{
166
167
168
169
170
171
172 if (verboseLevel > 3)
173 G4cout <<
"Calling SampleSecondaries() of G4LivermorePolarizedComptonModel" <<
G4endl;
174
177
178
179
180
181
183
184
185
186
187 if(!(gammaPolarization0.
isOrthogonal(gammaDirection0, 1e-6))||(gammaPolarization0.
mag()==0))
188 {
189 gammaPolarization0 = GetRandomPolarization(gammaDirection0);
190 }
191 else
192 {
194 {
195 gammaPolarization0 = GetPerpendicularPolarization(gammaDirection0, gammaPolarization0);
196 }
197 }
198
199
200
201
202
203 if(gammaEnergy0 <= lowEnergyLimit)
204 {
208 return;
209 }
210
211 G4double E0_m = gammaEnergy0 / electron_mass_c2 ;
212
213
214
218
219
220
221 G4double epsilon, epsilonSq, onecost, sinThetaSqr, greject ;
222
223 G4double epsilon0Local = 1./(1. + 2*E0_m);
224 G4double epsilon0Sq = epsilon0Local*epsilon0Local;
225 G4double alpha1 = - std::log(epsilon0Local);
226 G4double alpha2 = 0.5*(1.- epsilon0Sq);
227
228 G4double wlGamma = h_Planck*c_light/gammaEnergy0;
231
232 do {
234 {
236 epsilonSq = epsilon*epsilon;
237 }
238 else
239 {
241 epsilon = std::sqrt(epsilonSq);
242 }
243
244 onecost = (1.- epsilon)/(epsilon*E0_m);
245 sinThetaSqr = onecost*(2.-onecost);
246
247
248 if (sinThetaSqr > 1.)
249 {
251 << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
252 << "sin(theta)**2 = "
253 << sinThetaSqr
254 << "; set to 1"
256 sinThetaSqr = 1.;
257 }
258 if (sinThetaSqr < 0.)
259 {
261 << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
262 << "sin(theta)**2 = "
263 << sinThetaSqr
264 << "; set to 0"
266 sinThetaSqr = 0.;
267 }
268
269
270 G4double x = std::sqrt(onecost/2.) / (wlGamma/cm);;
272 greject = (1. - epsilon*sinThetaSqr/(1.+ epsilonSq))*scatteringFunction;
273
275
276
277
278
279
280
281 G4double phi = SetPhi(epsilon,sinThetaSqr);
282
283
284
285
286
288
289
290
291 if (cosTheta > 1.)
292 {
294 << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
295 << "cosTheta = "
296 << cosTheta
297 << "; set to 1"
299 cosTheta = 1.;
300 }
301 if (cosTheta < -1.)
302 {
304 << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
305 << "cosTheta = "
306 << cosTheta
307 << "; set to -1"
309 cosTheta = -1.;
310 }
311
312
313
314 G4double sinTheta = std::sqrt (sinThetaSqr);
315
316
317 if (sinTheta > 1.)
318 {
320 << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
321 << "sinTheta = "
322 << sinTheta
323 << "; set to 1"
325 sinTheta = 1.;
326 }
327 if (sinTheta < -1.)
328 {
330 << " -- Warning -- G4LivermorePolarizedComptonModel::SampleSecondaries "
331 << "sinTheta = "
332 << sinTheta
333 << "; set to -1"
335 sinTheta = -1.;
336 }
337
338
339
340 G4double dirx = sinTheta*std::cos(phi);
341 G4double diry = sinTheta*std::sin(phi);
343
344
345
346
347
348
349
350
351
352
353
354 G4int maxDopplerIterations = 1000;
356 G4double photonEoriginal = epsilon * gammaEnergy0;
360
361 do
362 {
363 iteration++;
364
367
368 eMax = gammaEnergy0 - bindingE;
369
370
372
373 G4double pDoppler = pSample * fine_structure_const;
374 G4double pDoppler2 = pDoppler * pDoppler;
375 G4double var2 = 1. + onecost * E0_m;
376 G4double var3 = var2*var2 - pDoppler2;
377 G4double var4 = var2 - pDoppler2 * cosTheta;
378 G4double var = var4*var4 - var3 + pDoppler2 * var3;
379 if (var > 0.)
380 {
382 G4double scale = gammaEnergy0 / var3;
383
384 if (
G4UniformRand() < 0.5) photonE = (var4 - varSqrt) * scale;
385 else photonE = (var4 + varSqrt) * scale;
386 }
387 else
388 {
389 photonE = -1.;
390 }
391 } while ( iteration <= maxDopplerIterations &&
392 (photonE < 0. || photonE > eMax || photonE < eMax*
G4UniformRand()) );
393
394
395
396 if (iteration >= maxDopplerIterations)
397 {
398 photonE = photonEoriginal;
399 bindingE = 0.;
400 }
401
402 gammaEnergy1 = photonE;
403
404
405
406
407
408
409
410
411
412
413 G4ThreeVector gammaPolarization1 = SetNewPolarization(epsilon,
414 sinThetaSqr,
415 phi,
416 cosTheta);
417
418
420 gammaDirection1 = tmpDirection1;
421
422
423
424 SystemOfRefChange(gammaDirection0,gammaDirection1,
425 gammaPolarization0,gammaPolarization1);
426
427 if (gammaEnergy1 > 0.)
428 {
432 }
433 else
434 {
435 gammaEnergy1 = 0.;
438 }
439
440
441
442
443
444 G4double ElecKineEnergy = gammaEnergy0 - gammaEnergy1 -bindingE;
445
446
447
448 if(ElecKineEnergy < 0.0) {
450 return;
451 }
452
453
454
455 G4double ElecMomentum = std::sqrt(ElecKineEnergy*(ElecKineEnergy+2.*electron_mass_c2));
456
457 G4ThreeVector ElecDirection((gammaEnergy0 * gammaDirection0 -
458 gammaEnergy1 * gammaDirection1) * (1./ElecMomentum));
459
461
463 fvect->push_back(dp);
464
465}
bool isOrthogonal(const Hep3Vector &v, double epsilon=tolerance) const
double howOrthogonal(const Hep3Vector &v) const
G4double RandomSelectMomentum(G4int Z, G4int shellIndex) const
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4ThreeVector & GetPolarization() const
static G4Electron * Electron()
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposePolarization(const G4ThreeVector &dir)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4double BindingEnergy(G4int Z, G4int shellIndex) const
G4int SelectRandomShell(G4int Z) const
virtual G4double FindValue(G4double x, G4int componentId=0) const =0
const G4Element * SelectRandomAtom(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)