Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4BaierKatkov.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// Author: Alexei Sytov
27// Co-author: Gianfranco Paterno (modifications & testing)
28// On the base of the CRYSTALRAD realization of the Baier-Katkov integral:
29// A. I. Sytov, V. V. Tikhomirov, and L. Bandiera PRAB 22, 064601 (2019)
30
31#include "G4BaierKatkov.hh"
32
33#include "Randomize.hh"
34#include "G4Gamma.hh"
35#include "G4Log.hh"
36
38{
39 //sets the default spectrum energy range of integration and
40 //calls ResetRadIntegral()
41 SetSpectrumEnergyRange(0.1*CLHEP::MeV,1.*CLHEP::GeV,110);
42
43 //Do not worry if the maximal energy > particle energy
44 //this elements of spectrum with non-physical energies
45 //will not be processed (they will be 0)
46
47 G4cout << " "<< G4endl;
48 G4cout << "G4BaierKatkov model is activated."<< G4endl;
49 G4cout << " "<< G4endl;
50}
51
52//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
53
55{
56 fAccumSpectrum.clear();
57
58 //reinitialize intermediate integrals with zeros
59 fFa.resize(fNMCPhotons);
60 fSs.resize(fNMCPhotons);
61 fSc.resize(fNMCPhotons);
62 fSsx.resize(fNMCPhotons);
63 fSsy.resize(fNMCPhotons);
64 fScx.resize(fNMCPhotons);
65 fScy.resize(fNMCPhotons);
66 std::fill(fFa.begin(), fFa.end(), 0.);
67 std::fill(fSs.begin(), fSs.end(), 0.);
68 std::fill(fSc.begin(), fSc.end(), 0.);
69 std::fill(fSsx.begin(), fSsx.end(), 0.);
70 std::fill(fSsy.begin(), fSsy.end(), 0.);
71 std::fill(fScx.begin(), fScx.end(), 0.);
72 std::fill(fScy.begin(), fScy.end(), 0.);
73
74 //Reset radiation integral internal variables to defaults
75 fMeanPhotonAngleX =0.; //average angle of
76 //radiated photon direction in sampling, x-plane
77 fParamPhotonAngleX=1.e-3*CLHEP::rad; //a parameter of
78 //radiated photon sampling distribution, x-plane
79 fMeanPhotonAngleY =0.; //average angle of
80 //radiated photon direction in sampling, y-plane
81 fParamPhotonAngleY=1.e-3*CLHEP::rad; //a parameter of
82 //radiated photon sampling distribution, y-plane
83
84 fImin0 = 0;//set the first vector element to 0
85
86 //reset the trajectory
87 fParticleAnglesX.clear();
88 fParticleAnglesY.clear();
89 fScatteringAnglesX.clear();
90 fScatteringAnglesY.clear();
91 fSteps.clear();
92 fGlobalTimes.clear();
93 fParticleCoordinatesXYZ.clear();
94
95 //resets the vector of element numbers at the trajectory start
96 fImax0.clear();
97 //sets 0 element of the vector of element numbers
98 fImax0.push_back(0.);
99
100 //resets the radiation probability
101 fTotalRadiationProbabilityAlongTrajectory.clear();
102 //sets the radiation probability at the trajectory start
103 fTotalRadiationProbabilityAlongTrajectory.push_back(0.);
104}
105
106//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
107
109 G4double emax,
110 G4int numberOfBins)
111{
112 fMinPhotonEnergy = emin;
113 fMaxPhotonEnergy = emax;
114 fNBinsSpectrum = numberOfBins;
115
116 fLogEmaxdEmin = G4Log(fMaxPhotonEnergy/fMinPhotonEnergy);
117
118 //in initializing fNPhotonsPerBin
119 fNPhotonsPerBin.resize(fNBinsSpectrum);
120 std::fill(fNPhotonsPerBin.begin(), fNPhotonsPerBin.end(), 0);
121
122 //initializing the Spectrum
123 fSpectrum.resize(fNBinsSpectrum);
124 std::fill(fSpectrum.begin(), fSpectrum.end(), 0);
125
126 //initializing the fAccumTotalSpectrum
127 fAccumTotalSpectrum.resize(fNBinsSpectrum);
128 std::fill(fAccumTotalSpectrum.begin(), fAccumTotalSpectrum.end(), 0);
129
130 //initializing the fTotalSpectrum
131 fTotalSpectrum.resize(fNBinsSpectrum);
132 std::fill(fTotalSpectrum.begin(), fTotalSpectrum.end(), 0);
133
134 fPhotonEnergyInSpectrum.clear();
135 for (G4int j=0;j<fNBinsSpectrum;j++)
136 {
137 //bin position (mean between 2 bin limits)
138 fPhotonEnergyInSpectrum.push_back(fMinPhotonEnergy*
139 (std::exp(fLogEmaxdEmin*j/fNBinsSpectrum)+
140 std::exp(fLogEmaxdEmin*(j+1)/fNBinsSpectrum))/2.);
141 }
142
143 fItrajectories = 0;
144
146}
147
148//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
149
151 G4double emax,
152 G4int timesPhotonStatistics)
153{
154
155 if(timesPhotonStatistics<=1)
156 {
157 G4cout << "G4BaierKatkov model, "
158 "function AddStatisticsInPhotonEnergyRegion("
159 << emin/CLHEP::MeV << " MeV, "
160 << emax/CLHEP::MeV << " MeV, "
161 << timesPhotonStatistics << ")" << G4endl;
162 G4cout << "Warning: the statistics factor cannot be <=1." << G4endl;
163 G4cout << "The statistics was not added." << G4endl;
164 G4cout << " "<< G4endl;
165 }
166 else if(fMinPhotonEnergy>emin)
167 {
168 G4cout << "G4BaierKatkov model, "
169 "function AddStatisticsInPhotonEnergyRegion("
170 << emin/CLHEP::MeV << " MeV, "
171 << emax/CLHEP::MeV << " MeV, "
172 << timesPhotonStatistics << ")" << G4endl;
173 G4cout << "Warning: the minimal energy inserted is less then "
174 "the minimal energy cut of the spectrum: "
175 << fMinPhotonEnergy/CLHEP::MeV << " MeV." << G4endl;
176 G4cout << "The statistics was not added." << G4endl;
177 G4cout << " "<< G4endl;
178 }
179 else if(emax-emin<DBL_EPSILON)
180 {
181 G4cout << "G4BaierKatkov model, "
182 "function AddStatisticsInPhotonEnergyRegion("
183 << emin/CLHEP::MeV << " MeV, "
184 << emax/CLHEP::MeV << " MeV, "
185 << timesPhotonStatistics << ")" << G4endl;
186 G4cout << "Warning: the maximal energy <= the minimal energy." << G4endl;
187 G4cout << "The statistics was not added." << G4endl;
188 G4cout << " "<< G4endl;
189 }
190 else
191 {
192 G4bool setrange = true;
193 G4double logAddRangeEmindEmin = G4Log(emin/fMinPhotonEnergy);
194 G4double logAddRangeEmaxdEmin = G4Log(emax/fMinPhotonEnergy);
195
196 G4int nAddRange = (G4int)fTimesPhotonStatistics.size();
197 for (G4int j=0;j<nAddRange;j++)
198 {
199 if((logAddRangeEmindEmin>=fLogAddRangeEmindEmin[j]&&
200 logAddRangeEmindEmin< fLogAddRangeEmaxdEmin[j])||
201 (logAddRangeEmaxdEmin> fLogAddRangeEmindEmin[j]&&
202 logAddRangeEmaxdEmin<=fLogAddRangeEmaxdEmin[j])||
203 (logAddRangeEmindEmin<=fLogAddRangeEmindEmin[j]&&
204 logAddRangeEmaxdEmin>=fLogAddRangeEmaxdEmin[j]))
205 {
206 G4cout << "G4BaierKatkov model, "
207 "function AddStatisticsInPhotonEnergyRegion("
208 << emin/CLHEP::MeV << " MeV, "
209 << emax/CLHEP::MeV << " MeV, "
210 << timesPhotonStatistics << ")" << G4endl;
211 G4cout << "Warning: the energy range intersects another "
212 "added energy range." << G4endl;
213 G4cout << "The statistics was not added." << G4endl;
214 G4cout << " "<< G4endl;
215 setrange = false;
216 break;
217 }
218 }
219 if (setrange)
220 {
221 fLogAddRangeEmindEmin.push_back(logAddRangeEmindEmin);
222 fLogAddRangeEmaxdEmin.push_back(logAddRangeEmaxdEmin);
223 fTimesPhotonStatistics.push_back(timesPhotonStatistics);
224
225 G4cout << "G4BaierKatkov model: increasing the statistics of photon sampling "
226 "in Baier-Katkov with a factor of "
227 << timesPhotonStatistics << G4endl;
228 G4cout << "in the energy spectrum range: ("
229 << emin/CLHEP::MeV << " MeV, "
230 << emax/CLHEP::MeV << " MeV)" << G4endl;
231 }
232 }
233}
234
235//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
236
237void G4BaierKatkov::SetPhotonSamplingParameters(G4double ekin,
238 G4double minPhotonAngleX,
239 G4double maxPhotonAngleX,
240 G4double minPhotonAngleY,
241 G4double maxPhotonAngleY)
242{
243 fLogEdEmin = G4Log(ekin/fMinPhotonEnergy);
244 fMeanPhotonAngleX = (maxPhotonAngleX+minPhotonAngleX)/2.;
245 fParamPhotonAngleX = (maxPhotonAngleX-minPhotonAngleX)/2.;
246 fMeanPhotonAngleY = (maxPhotonAngleY+minPhotonAngleY)/2.;
247 fParamPhotonAngleY = (maxPhotonAngleY-minPhotonAngleY)/2.;
248}
249
250//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
251
252void G4BaierKatkov::GeneratePhotonSampling()
253{
254 fPhotonEnergyInIntegral.clear();
255 fPhotonAngleInIntegralX.clear();
256 fPhotonAngleInIntegralY.clear();
257 fPhotonAngleNormCoef.clear();
258 fInsideVirtualCollimator.clear();
259 fIBinsSpectrum.clear();
260
261 G4double ksi=0.;
262 std::vector<G4int> moreStatistics;
263 moreStatistics.resize(fTimesPhotonStatistics.size());
264 std::fill(moreStatistics.begin(), moreStatistics.end(), 0);
265 G4int nAddRange = (G4int)fTimesPhotonStatistics.size();
266
267 //sampling of the energy of a photon emission
268 //(integration variables, Monte Carlo integration)
269 for (G4int j=0;j<fNMCPhotons;j++)
270 {
271 ksi = G4UniformRand()*fLogEdEmin;
272 fIBinsSpectrum.push_back((G4int)std::trunc(
273 ksi*fNBinsSpectrum/fLogEmaxdEmin));
274 //we consider also the energy outside the spectrum output range
275 //(E>Emax => fLogEdEmin>fLogEmaxdEmin)
276 //in this case we don't count the photon in the spectrum output
277 if(fIBinsSpectrum[j]<fNBinsSpectrum) {fNPhotonsPerBin[fIBinsSpectrum[j]]+=1;}
278
279 fPhotonEnergyInIntegral.push_back(fMinPhotonEnergy*std::exp(ksi));
280
281 fPhotonAngleNormCoef.push_back(1.);
282
283 for (G4int j2=0;j2<nAddRange;j2++)
284 {
285 if(ksi>fLogAddRangeEmindEmin[j2]&&
286 ksi<fLogAddRangeEmaxdEmin[j2])
287 {
288 //calculating the current statistics in this region
289 //to increase it proportionally
290 moreStatistics[j2]+=1;
291 fPhotonAngleNormCoef[j]/=fTimesPhotonStatistics[j2];
292 break;
293 }
294 }
295 }
296
297 for (G4int j2=0;j2<nAddRange;j2++)
298 {
299 G4int totalAddRangeStatistics = moreStatistics[j2]*fTimesPhotonStatistics[j2];
300 for (G4int j=moreStatistics[j2];j<totalAddRangeStatistics;j++)
301 {
302 ksi = fLogAddRangeEmindEmin[j2]+
303 G4UniformRand()*(std::min(fLogAddRangeEmaxdEmin[j2],fLogEdEmin)-
304 fLogAddRangeEmindEmin[j2]);
305 fIBinsSpectrum.push_back((G4int)std::trunc(
306 ksi*fNBinsSpectrum/fLogEmaxdEmin));
307 /* //we consider also the energy outside the spectrum output range
308 //(E>Emax => fLogEdEmin>fLogEmaxdEmin)
309 //in this case we don't count the photon in the spectrum output
310 if(fIBinsSpectrum.back()<fNBinsSpectrum)
311 {fNPhotonsPerBin[fIBinsSpectrum.back()]+=1;}*/
312
313 fPhotonEnergyInIntegral.push_back(fMinPhotonEnergy*std::exp(ksi));
314
315 fPhotonAngleNormCoef.push_back(1./fTimesPhotonStatistics[j2]);
316 }
317 }
318
319 G4double rho=1.;
320 const G4double rhocut=15.;//radial angular cut of the distribution
321 G4double norm=std::atan(rhocut*rhocut)*
322 CLHEP::pi*fParamPhotonAngleX*fParamPhotonAngleY;
323
324 //sampling of the angles of a photon emission
325 //(integration variables, Monte Carlo integration)
326 G4int nmctotal = (G4int)fPhotonEnergyInIntegral.size();
327 for (G4int j=0;j<nmctotal;j++)
328 {
329 //photon distribution with long tails (useful to not exclude particle angles
330 //after a strong single scattering)
331 //at ellipsescale < 1 => half of statistics of photons
332 do
333 {
334 rho = std::sqrt(std::tan(CLHEP::halfpi*G4UniformRand()));
335 }
336 while (rho>rhocut);
337
338 ksi = G4UniformRand();
339 fPhotonAngleInIntegralX.push_back(fMeanPhotonAngleX+
340 fParamPhotonAngleX*
341 rho*std::cos(CLHEP::twopi*ksi));
342 fPhotonAngleInIntegralY.push_back(fMeanPhotonAngleY+
343 fParamPhotonAngleY*
344 rho*std::sin(CLHEP::twopi*ksi));
345 fPhotonAngleNormCoef[j]*=(1.+rho*rho*rho*rho)*norm;
346
347 //test if the photon with these angles enter the virtual collimator
348 //(doesn't influence the Geant4 simulations,
349 //but only the accumulation of fTotalSpectrum
350 if(fVirtualCollimatorTypeID == 1) //round or ellipse collimator
351 {
352 fInsideVirtualCollimator.push_back(1. >
353 std::sqrt((fPhotonAngleInIntegralX[j]-fVirtualCollimatorAngularCenterX)*
354 (fPhotonAngleInIntegralX[j]-fVirtualCollimatorAngularCenterX)/
355 fVirtualCollimatorAngularHalfWidthX2 +
356 (fPhotonAngleInIntegralY[j]-fVirtualCollimatorAngularCenterY)*
357 (fPhotonAngleInIntegralY[j]-fVirtualCollimatorAngularCenterY)/
358 fVirtualCollimatorAngularHalfWidthY2));
359 }
360 else if (fVirtualCollimatorTypeID == 2) //rectangular collimator
361 {
362 fInsideVirtualCollimator.push_back(
363 std::abs(fPhotonAngleInIntegralX[j]-fVirtualCollimatorAngularCenterX) <
364 fVirtualCollimatorAngularHalfWidthX&&
365 std::abs(fPhotonAngleInIntegralY[j]-fVirtualCollimatorAngularCenterY) <
366 fVirtualCollimatorAngularHalfWidthY);
367 }
368 else{fInsideVirtualCollimator.push_back(true);}//default - infinite collimator
369 }
370 //reinitialize the vector of radiation CDF for each photon
371 fPhotonProductionCDF.resize(nmctotal+1);//0 element equal to 0
372 std::fill(fPhotonProductionCDF.begin(), fPhotonProductionCDF.end(), 0.);
373
374 //if we have additional photons
375 if (nmctotal>fNMCPhotons)
376 {
377 //reinitialize intermediate integrals with zeros again
378 fFa.resize(nmctotal);
379 fSs.resize(nmctotal);
380 fSc.resize(nmctotal);
381 fSsx.resize(nmctotal);
382 fSsy.resize(nmctotal);
383 fScx.resize(nmctotal);
384 fScy.resize(nmctotal);
385 std::fill(fFa.begin(), fFa.end(), 0.);
386 std::fill(fSs.begin(), fSs.end(), 0.);
387 std::fill(fSc.begin(), fSc.end(), 0.);
388 std::fill(fSsx.begin(), fSsx.end(), 0.);
389 std::fill(fSsy.begin(), fSsy.end(), 0.);
390 std::fill(fScx.begin(), fScx.end(), 0.);
391 std::fill(fScy.begin(), fScy.end(), 0.);
392 }
393}
394
395//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
396
397G4double G4BaierKatkov::RadIntegral(G4double etotal, G4double mass,
398 std::vector<G4double> &vectorParticleAnglesX,
399 std::vector<G4double> &vectorParticleAnglesY,
400 std::vector<G4double> &vectorScatteringAnglesX,
401 std::vector<G4double> &vectorScatteringAnglesY,
402 std::vector<G4double> &vectorSteps,
403 G4int imin)
404{
405 //preliminary values are defined:
406
407 G4double om=0.;// photon energy
408 G4double eprime=0., eprime2=0.; //E'=E-omega eprime2=eprime*eprime
409 G4double omprime=0.,omprimed2=0.;//om'=(E*om/E'), omprimed2=omprime/2
410 G4double vxin =0.,vyin=0.,vxno=0.,vyno=0.;
411
412 G4double dzmod=0.;
413 G4double fa1=0.,faseBefore=0.,faseBeforedz=0.,faseBeforedzd2=0.;
414 G4double faseAfter=0.,fa2dfaseBefore2=0.;
415
416 G4double skJ=0, skIx=0., skIy=0.;
417 G4double sinfa1=0.,cosfa1=0.;
418 G4double i2=0.,j2=0.;// Ix^2+Iy^2 and of BK Jvector^2
419
420 std::size_t nparts=vectorParticleAnglesX.size();
421 G4int kmin = imin;
422 if(imin==0) {kmin=1;}//skipping 0 trajectory element
423
424 //total radiation probability for each photon
425 G4double totalRadiationProbabilityPhj = 0.;
426
427 //total radiation probability along this trajectory (fill with 0 only new elements)
428 fTotalRadiationProbabilityAlongTrajectory.resize(nparts);
429
430 //reset Spectrum
431 std::fill(fSpectrum.begin(), fSpectrum.end(), 0.);
432
433 //intermediate vectors to reduce calculations
434 std::vector<G4double> axt;//acceleration of a charged particle in a horizontal plane
435 axt.resize(nparts);
436 std::vector<G4double> ayt;//acceleration of a charged particle in a vertical plane
437 ayt.resize(nparts);
438 std::vector<G4double> dz;//step in in MeV^-1
439 dz.resize(nparts);
440 //setting values interesting for us
441 for(std::size_t k=kmin;k<nparts;k++)
442 {
443 dz[k]=vectorSteps[k]/CLHEP::hbarc;// dz in MeV^-1
444
445 // accelerations
446 axt[k]=(vectorParticleAnglesX[k]-vectorScatteringAnglesX[k]-
447 vectorParticleAnglesX[k-1])/dz[k];
448 ayt[k]=(vectorParticleAnglesY[k]-vectorScatteringAnglesY[k]-
449 vectorParticleAnglesY[k-1])/dz[k];
450 }
451
452 //intermediate variables to reduce calculations:
453 //the calculations inside for (G4int j=0;j<fNMCPhotons;j++)
454 //{for(G4int k=kmin;k<nparts;k++){...
455 //are the main cpu time consumption
456 G4double e2 = etotal*etotal;
457 G4double gammaInverse2 = mass*mass/(etotal*etotal);// 1/gamma^2 of
458 //the radiating charge particle
459 G4double coefNormLogdNMC = fLogEdEmin/fNMCPhotons;//here fNMCPhotons is correct,
460 //additional photons have been already
461 //taken into account in weights
462 G4double coefNorm = CLHEP::fine_structure_const/(8*(CLHEP::pi2))*coefNormLogdNMC;
463 G4double e2pluseprime2 = 0.;//e2pluseprime2 =e2+eprime2
464 G4double coefNormom2deprime2 = 0.; //coefNormom2deprime2 = coefNorm*om2/eprime2;
465 G4double gammaInverse2om2 = 0.; //gammaInverse2*om*om
466
467 std::size_t nmctotal = fPhotonEnergyInIntegral.size();
468 for (std::size_t j=0;j<nmctotal;j++)
469 //the final number of photons may be different from fNMCPhotons
470 {
471 om = fPhotonEnergyInIntegral[j];
472 eprime=etotal-om; //E'=E-omega
473 eprime2 = eprime*eprime;
474 e2pluseprime2 =e2+eprime2;
475 omprime=etotal*om/eprime;//om'=(E*om/E')
476 omprimed2=omprime/2;
477 coefNormom2deprime2 = coefNorm*om*om/eprime2;
478 gammaInverse2om2 = gammaInverse2*om*om;
479
480 for(std::size_t k=kmin;k<nparts;k++)
481 {
482 //the angles of a photon produced (with incoherent scattering)
483 vxin = vectorParticleAnglesX[k]-fPhotonAngleInIntegralX[j];
484 vyin = vectorParticleAnglesY[k]-fPhotonAngleInIntegralY[j];
485 //the angles of a photon produced (without incoherent scattering)
486 vxno = vxin-vectorScatteringAnglesX[k];
487 vyno = vyin-vectorScatteringAnglesY[k];
488
489 //phase difference before scattering
490 faseBefore=omprimed2*(gammaInverse2+vxno*vxno+vyno*vyno);//phi' t<ti//MeV
491
492 faseBeforedz = faseBefore*dz[k];
493 faseBeforedzd2 = faseBeforedz/2.;
494 fFa[j]+=faseBeforedz; //
495 fa1=fFa[j]-faseBeforedzd2;//
496 dzmod=2*std::sin(faseBeforedzd2)/faseBefore;//MeV^-1
497
498 //phi''/faseBefore^2
499 fa2dfaseBefore2 = omprime*(axt[k]*vxno+ayt[k]*vyno)/(faseBefore*faseBefore);
500
501 //phase difference after scattering
502 faseAfter=omprimed2*(gammaInverse2+vxin*vxin+vyin*vyin);//phi' ti+O//MeV
503
504 skJ=1/faseAfter-1/faseBefore-fa2dfaseBefore2*dzmod;//MeV^-1
505 skIx=vxin/faseAfter-vxno/faseBefore+dzmod*(axt[k]/faseBefore-
506 vxno*fa2dfaseBefore2);
507 skIy=vyin/faseAfter-vyno/faseBefore+dzmod*(ayt[k]/faseBefore-
508 vyno*fa2dfaseBefore2);
509
510 sinfa1 = std::sin(fa1);
511 cosfa1 = std::cos(fa1);
512
513 fSs[j]+=sinfa1*skJ;//sum sin integral J of BK
514 fSc[j]+=cosfa1*skJ;//sum cos integral J of BK
515 fSsx[j]+=sinfa1*skIx;// sum sin integral Ix of BK
516 fSsy[j]+=sinfa1*skIy;// sum sin integral Iy of BK
517 fScx[j]+=cosfa1*skIx;// sum cos integral Ix of BK
518 fScy[j]+=cosfa1*skIy;// sum cos integral Iy of BK
519
520 i2=fSsx[j]*fSsx[j]+fScx[j]*fScx[j]+fSsy[j]*fSsy[j]+fScy[j]*fScy[j];//MeV^-2
521 j2=fSs[j]*fSs[j]+fSc[j]*fSc[j];//MeV^-2
522
523 //updating the total radiation probability along the trajectory
524 totalRadiationProbabilityPhj = coefNormom2deprime2*fPhotonAngleNormCoef[j]*
525 (i2*e2pluseprime2+j2*gammaInverse2om2);
526 fTotalRadiationProbabilityAlongTrajectory[k] += totalRadiationProbabilityPhj;
527 }
528
529 fPhotonProductionCDF[j+1] = fTotalRadiationProbabilityAlongTrajectory.back();
530
531 //filling spectrum (adding photon probabilities to a histogram)
532 //we consider also the energy outside the spectrum output range
533 //(E>Emax => fLogEdEmin>fLogEmaxdEmin)
534 //in this case we don't count the photon in the spectrum output
535 //we fill the spectrum only in case of the angles inside the virtual collimator
536 if((fIBinsSpectrum[j]<fNBinsSpectrum)&&fInsideVirtualCollimator[j])
537 {fSpectrum[fIBinsSpectrum[j]] += totalRadiationProbabilityPhj/
538 (om*coefNormLogdNMC);}
539
540 } // end cycle
541
542 fAccumSpectrum.push_back(fSpectrum);
543
544 return fTotalRadiationProbabilityAlongTrajectory.back();
545}
546
547//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
548
549G4int G4BaierKatkov::FindVectorIndex(std::vector<G4double> &myvector, G4double value)
550{
551 auto iteratorbegin = myvector.begin();
552 auto iteratorend = myvector.end();
553
554 //vector index (for non precise values lower_bound gives upper value)
555 auto loweriterator = std::lower_bound(iteratorbegin, iteratorend, value);
556 //return the index of the vector element
557 return (G4int)std::distance(iteratorbegin, loweriterator);
558}
559
560//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
561
562G4bool G4BaierKatkov::SetPhotonProductionParameters(G4double etotal, G4double mass)
563{
564 //flag if a photon was produced
565 G4bool flagPhotonProduced = false;
566
567 //how many small pieces of a trajectory are
568 //before radiation (all if not radiation)
569 std::size_t nodeNumber = fAccumSpectrum.size()-1;
570
571 //ksi is a random number
572 //Generally ksi = G4UniformRand() is ok, but
573 //we use as a correction for the case
574 //when the radiation probability becomes too high (> 0.1)
575 G4double ksi = -G4Log(G4UniformRand());
576
577 if (ksi< fTotalRadiationProbabilityAlongTrajectory.back()) // photon produced
578 {
579 G4double ksi1 = G4UniformRand()*fTotalRadiationProbabilityAlongTrajectory.back();
580
581 //randomly choosing the photon to be produced from the sampling list
582 //according to the probabilities calculated in the Baier-Katkov integral
583 G4int iphoton = FindVectorIndex(fPhotonProductionCDF,ksi1)-1;//index of
584 //a photon produced
585
586 //energy of the photon produced
587 fEph0 = fPhotonEnergyInIntegral[iphoton];
588 //anagles of the photon produced
589 G4double photonAngleX = fPhotonAngleInIntegralX[iphoton];
590 G4double photonAngleY = fPhotonAngleInIntegralY[iphoton];
591
592 G4double momentumDirectionZ = 1./
593 std::sqrt(1.+std::pow(std::tan(photonAngleX),2)+
594 std::pow(std::tan(photonAngleY),2));
595
596 //momentum direction vector of the photon produced
597 PhMomentumDirection.set(momentumDirectionZ*std::tan(photonAngleX),
598 momentumDirectionZ*std::tan(photonAngleY),
599 momentumDirectionZ);
600
601 //sort fTotalRadiationProbabilityAlongTrajectory
602 //(increasing but oscillating function => non-monotonic)
603 std::vector<G4double> temporaryVector;
604 temporaryVector.assign(fTotalRadiationProbabilityAlongTrajectory.begin(),
605 fTotalRadiationProbabilityAlongTrajectory.end());
606 std::sort(temporaryVector.begin(), temporaryVector.end());
607
608 //index of the point of radiation ("poststep") in sorted vector
609 G4int iNode = FindVectorIndex(temporaryVector,ksi);
610
611 //index of the point of radiation ("poststep") in unsorted vector
612 auto it = std::find_if(fTotalRadiationProbabilityAlongTrajectory.begin(),
613 fTotalRadiationProbabilityAlongTrajectory.end(),
614 [&](G4double value)
615 {return std::abs(value - temporaryVector[iNode]) < DBL_EPSILON;});
616 iNode = (G4int)std::distance(fTotalRadiationProbabilityAlongTrajectory.begin(), it);
617
618 //the piece of trajectory number (necessary only for the spectrum output)
619 nodeNumber = FindVectorIndex(fImax0,iNode*1.)-1;
620
621 //set new parameters of the charged particle
622 //(returning the particle back to the radiation point, i.e.
623 //remembering the new parameters for corresponding get functions)
624 fNewParticleEnergy = etotal-fEph0;
625 fNewParticleAngleX = fParticleAnglesX[iNode];
626 fNewParticleAngleY = fParticleAnglesY[iNode];
627 fNewGlobalTime = fGlobalTimes[iNode];
628 fNewParticleCoordinateXYZ = fParticleCoordinatesXYZ[iNode];
629
630 //particle angle correction from momentum conservation
631 //(important for fEph0 comparable to E,
632 // may kick off a particle from channeling)
633 G4double pratio = fEph0/std::sqrt(etotal*etotal-mass*mass);
634 fNewParticleAngleX -= std::asin(pratio*std::sin(photonAngleX));
635 fNewParticleAngleY -= std::asin(pratio*std::sin(photonAngleY));
636
637 flagPhotonProduced = true;
638 }
639
640 //accumulation during entire code run
641 for (G4int j=0;j<fNBinsSpectrum;j++)
642 {
643 fAccumTotalSpectrum[j] += fAccumSpectrum[nodeNumber][j];
644 //in the case of missing photon in spectrum, probability is 0
645 //(may happen only at the beginning of simulations)
646 if(fNPhotonsPerBin[j]==0)
647 {
648 fTotalSpectrum[j] = 0;
649 }
650 else
651 {
652 fTotalSpectrum[j] = fAccumTotalSpectrum[j]/fNPhotonsPerBin[j]*fItrajectories;
653 }
654 }
655
656 return flagPhotonProduced;
657}
658
659//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
660
662 G4double angleX, G4double angleY,
663 G4double angleScatteringX, G4double angleScatteringY,
664 G4double step, G4double globalTime,
665 G4ThreeVector coordinateXYZ,
666 G4bool flagEndTrajectory)
667{
668 /**
669 DoRadiation description
670
671 The real trajectory is divided onto parts.
672 Every part is accumulated until the radiation cannot be considered as single photon,
673 i.e. the radiation probability exceeds some threshold
674 fSinglePhotonRadiationProbabilityLimit.
675 Typically fSinglePhotonRadiationProbabilityLimit should be between 0.01 and 0.1.
676 Then the photon generation as well as its parameters are simulated
677 in SetPhotonProductionParameters()
678
679 Finally if radiation took place, this function sets the new particle parameters
680 (the parameters at the point of radiation emission)
681 fNewParticleEnergy; fNewParticleAngleX;
682 fNewParticleAngleY; NewStep; fNewGlobalTime; fNewParticleCoordinateXYZ;
683
684 In order to control if the trajectory part reaches this limit,
685 one needs to divide it into smaller pieces (consisting of
686 fNSmallTrajectorySteps elements, typically several hundred) and to calculate the total
687 radiation probability along the trajectory part after each small piece accomplished.
688 If it exceeds the fSinglePhotonRadiationProbabilityLimit,
689 the trajectory part is over and the radiation can be generated.
690
691 In order to calculate the radiation probability the Baier-Katkov integral is called
692 after each small piece of the trajectory. It is summarized with the integral along
693 the previous small pieces for this part of the trajectory.
694
695 To speed-up the simulations, the photon angles are generated only once
696 at the start of the trajectory part.
697 */
698
699 //flag if a photon was produced
700 G4bool flagPhotonProduced = false;
701
702 //adding the next trajectory element to the vectors
703 fParticleAnglesX.push_back(angleX);
704 fParticleAnglesY.push_back(angleY);
705 fScatteringAnglesX.push_back(angleScatteringX);
706 fScatteringAnglesY.push_back(angleScatteringY);
707 fSteps.push_back(step);
708 fGlobalTimes.push_back(globalTime);
709 fParticleCoordinatesXYZ.push_back(coordinateXYZ);
710
711 G4double imax = fSteps.size();
712 if((imax==fImin0+fNSmallTrajectorySteps)||flagEndTrajectory)
713 {
714 //set the angular limits at the start of the trajectory part
715 if(fImin0==0)
716 {
717 //radiation within the angle = +-fRadiationAngleFactor/gamma
718 G4double radiationAngleLimit=fRadiationAngleFactor*mass/etotal;
719
720 SetPhotonSamplingParameters(etotal-mass,
721 *std::min_element(fParticleAnglesX.begin(),
722 fParticleAnglesX.end())-radiationAngleLimit,
723 *std::max_element(fParticleAnglesX.begin(),
724 fParticleAnglesX.end())+radiationAngleLimit,
725 *std::min_element(fParticleAnglesY.begin(),
726 fParticleAnglesY.end())-radiationAngleLimit,
727 *std::max_element(fParticleAnglesY.begin(),
728 fParticleAnglesY.end())+radiationAngleLimit);
729
730 //calculation of angles of photon emission
731 //(these angles are integration variables, Monte Carlo integration)
732 GeneratePhotonSampling();
733 }
734
735 //calculate Baier-Katkov integral after this
736 //small piece of trajectory (fNSmallTrajectorySteps elements)
737 fTotalRadiationProbability = RadIntegral(etotal,mass,
738 fParticleAnglesX,fParticleAnglesY,
739 fScatteringAnglesX,fScatteringAnglesY,
740 fSteps, fImin0);
741
742 //setting the last element of this small trajectory piece
743 fImin0 = imax;
744 fImax0.push_back(imax*1.);
745
746 //if the radiation probability is high enough or if we are finishing
747 //our trajectory => to simulate the photon emission
748 if(fTotalRadiationProbability>fSinglePhotonRadiationProbabilityLimit||
749 flagEndTrajectory)
750 {
751 fItrajectories += 1; //count this trajectory !!!correction 19.07.2023
752
753 flagPhotonProduced = SetPhotonProductionParameters(etotal,mass);
754
755 //reinitialize intermediate integrals fFa, fSs, fSc, fSsx, fSsy, fScx, fScy;
756 //reset radiation integral internal variables to defaults;
757 //reset the trajectory and radiation probability along the trajectory
759 }
760 }
761
762 return flagPhotonProduced;
763}
764
765//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
766
768{
770 PhMomentumDirection,fEph0);
771 //generation of a secondary photon
772 fastStep.CreateSecondaryTrack(theGamma,fNewParticleCoordinateXYZ,fNewGlobalTime,true);
773}
Definition of the G4BaierKatkov class This class is designed for the calculation of radiation probabi...
G4double G4Log(G4double x)
Definition G4Log.hh:169
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
void ResetRadIntegral()
void GeneratePhoton(G4FastStep &fastStep)
void SetSpectrumEnergyRange(G4double emin, G4double emax, G4int numberOfBins)
void AddStatisticsInPhotonEnergyRegion(G4double emin, G4double emax, G4int timesPhotonStatistics)
G4bool DoRadiation(G4double etotal, G4double mass, G4double angleX, G4double angleY, G4double angleScatteringX, G4double angleScatteringY, G4double step, G4double globalTime, G4ThreeVector coordinateXYZ, G4bool flagEndTrajectory=false)
G4Track * CreateSecondaryTrack(const G4DynamicParticle &, G4ThreeVector, G4ThreeVector, G4double, G4bool localCoordinates=true)
static G4Gamma * Gamma()
Definition G4Gamma.cc:81
#define DBL_EPSILON
Definition templates.hh:66