Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/parameterisations/channeling/src/G4CoherentPairProduction.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 (testing)
 28 // Using the key points of G4BaierKatkov and developments of V.V. Tikhomirov,
 29 // partially described in L. Bandiera et al. Eur. Phys. J. C 82, 699 (2022)
 30 
 31 #include "G4CoherentPairProduction.hh"
 32 
 33 #include "Randomize.hh"
 34 #include "G4TouchableHistory.hh"
 35 #include "G4TouchableHandle.hh"
 36 #include "G4SystemOfUnits.hh"
 37 
 38 #include "G4Track.hh"
 39 #include "G4Gamma.hh"
 40 #include "G4Electron.hh"
 41 #include "G4Positron.hh"
 42 
 43 #include "G4ParticleDefinition.hh"
 44 #include "G4ProcessManager.hh"
 45 #include "G4EmProcessSubType.hh"
 46 #include "G4TransportationManager.hh"
 47 
 48 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 49 
 50 G4CoherentPairProduction::G4CoherentPairProduction(const G4String& aName,
 51                                                    G4ProcessType):
 52     G4VDiscreteProcess(aName)
 53 {
 54     SetProcessSubType(fCoherentPairProduction);
 55 }
 56 
 57 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 58 
 59 G4double G4CoherentPairProduction::GetMeanFreePath(const G4Track& aTrack,
 60                                     G4double,
 61                                     G4ForceCondition* condition)
 62 {
 63     //current logical volume
 64     G4LogicalVolume* crystallogic;
 65 
 66     //momentum direction and coordinates (see comments below)
 67     G4ThreeVector momentumDirectionGamma,xyzGamma0,xyzGamma;
 68     //angle of the photon in the local reference system of the volume
 69     G4double txGamma0 = 0, tyGamma0 = 0;
 70 
 71     *condition = NotForced;
 72 
 73     //model activation
 74     G4bool modelTrigger = false;
 75 
 76     //photon energy
 77     G4double eGamma = aTrack.GetTotalEnergy();
 78 
 79     //energy cut, at the beginning, to not check everything else
 80     if(eGamma > ModelMinPrimaryEnergy())
 81     {
 82         //current logical volume
 83         crystallogic = aTrack.GetVolume()->GetLogicalVolume();
 84 
 85         //the model works only in the G4Region fG4RegionName
 86         if(crystallogic->GetRegion()->GetName()==fG4RegionName)
 87         {
 88             fCrystalData->SetGeometryParameters(crystallogic);
 89 
 90             //the momentum direction of the photon in the local reference system of the volume
 91             momentumDirectionGamma =
 92                 (aTrack.GetTouchableHandle()->GetHistory()->
 93                     GetTopTransform().NetRotation().inverse())*aTrack.GetMomentumDirection();
 94 
 95             //the coordinates of the photon in the local reference system of the volume
 96             xyzGamma0 =
 97                 aTrack.GetTouchableHandle()->GetHistory()->
 98                     GetTopTransform().TransformPoint(aTrack.GetPosition());
 99 
100             // the coordinates of the photon in the co-rotating reference system within
101             //a channel (elementary periodic cell)
102             xyzGamma = fCrystalData->CoordinatesFromBoxToLattice(xyzGamma0);
103 
104             //angle of the photon in the local reference system of the volume
105             //(!!! ONLY FORWARD DIRECTION, momentumDirectionGamma.getZ()>0,
106             txGamma0 = std::atan(momentumDirectionGamma.x()/momentumDirectionGamma.z());
107             tyGamma0 = std::atan(momentumDirectionGamma.y()/momentumDirectionGamma.z());
108 
109             //recalculate angle into the lattice reference system
110             G4double angle = fCrystalData->AngleXFromBoxToLattice(txGamma0,xyzGamma.z());
111             if (fCrystalData->GetModel()==2)
112             {
113                 angle = std::sqrt(angle*angle+tyGamma0*tyGamma0);
114             }
115 
116             //Applies the parameterisation not at the last step, only forward local direction
117             //above low energy limit and below angular limit
118             modelTrigger = (momentumDirectionGamma.z()>0. &&
119                             std::abs(angle) < GetHighAngleLimit());
120         }
121     }
122 
123     if(modelTrigger)
124     {
125         //execute the model
126 
127         G4double x=0.,y=0.,z=0.;// the coordinates of charged particles
128             //in the co-rotating reference system within
129             //a channel (elementary periodic cell)
130         G4double tx0=0.,ty0=0.; // the angles of charged particles
131             // in the local reference system of the volume
132         G4double txPreStep0=0.,tyPreStep0=0.; // the same as tx0, ty0 before the step
133             // in the co-rotating reference system within
134             //a channel (elementary periodic cell)
135 
136         G4ThreeVector scatteringAnglesAndEnergyLoss;//output of scattering functions
137 
138         //coordinates in Runge-Kutta calculations
139         G4double x1=0.,x2=0.,x3=0.,x4=0.,y1=0.,y2=0.,y3=0.,y4=0.;
140         //angles in Runge-Kutta calculations
141         G4double tx1=0.,tx2=0.,tx3=0.,tx4=0.,ty1=0.,ty2=0.,ty3=0.,ty4=0.;
142         //variables in Runge-Kutta calculations
143         G4double kvx1=0.,kvx2=0.,kvx3=0.,kvx4=0.,kvy1=0.,kvy2=0.,kvy3=0.,kvy4=0.;
144         //simulation step along z (internal step of the model) and its parts
145         G4double dz=0.,dzd3=0.,dzd8=0.;//dzd3 = dz/3; dzd8 = dz/8;
146         //simulation step along the momentum direction
147         G4double momentumDirectionStep;
148         //effective simulation step (taking into account nuclear density along the trajectory)
149         G4double effectiveStep=0.;
150 
151         // Baier-Katkov variables
152         G4double dzMeV=0.; //step in MeV^-1
153         G4double axt=0.,ayt=0.; //charged particle accelerations
154         G4double vxin=0.,vyin=0.;//the angles vs the photon (with incoherent scattering)
155         G4double vxno=0.,vyno=0.;//the angles vs the photon (without incoherent scattering)
156 
157         G4double dzmod=0.;
158         G4double fa1=0.,faseBefore=0.,faseBeforedz=0.,faseBeforedzd2=0.;
159         G4double faseAfter=0.,fa2dfaseBefore2=0.;
160 
161         G4double skJ=0, skIx=0., skIy=0.;
162         G4double sinfa1=0.,cosfa1=0.;
163 
164         //2-vector is needed for an initial parameter collection of 1 pair
165         //vector of 2-vectors is an initial parameter collection of all sampling pair
166 
167         //collection of etotal for a single pair
168         CLHEP::Hep2Vector twoVectorEtotal(0.,0.);
169 
170         //collection of x for a single pair
171         CLHEP::Hep2Vector twoVectorX(0.,0.);
172 
173         //collection of y for a single pair
174         CLHEP::Hep2Vector twoVectorY(0.,0.);
175 
176         //collection of tx for a single pair
177         CLHEP::Hep2Vector twoVectorTX(0.,0.);
178 
179         //collection of tx for a single pair
180         CLHEP::Hep2Vector twoVectorTY(0.,0.);
181 
182         fullVectorEtotal.clear();
183         fullVectorX.clear();
184         fullVectorY.clear();
185         fullVectorTX.clear();
186         fullVectorTY.clear();
187         fPairProductionCDFdz.clear();
188         fPairProductionCDFdz.push_back(0.);//0th element equal to 0
189 
190         const G4double charge[2] = {-1.,1.}; //particle charge
191         const G4String particleName[2] = {"e-", "e+"};
192 
193         // the coordinates of a charged particle in the reference system within
194         //a channel (elementary periodic cell)
195         G4ThreeVector xyzparticle = xyzGamma;//changed below
196 
197         //the idea of pair production simulation is analogical to radiation in G4BaierKatkov
198         //since the matrix element of these processes is the same => we solve inverse problem
199         //to radiation: sample the pairs, calculate their trajectories and then calculate the
200         //probabilities using Baier-Katkov analogically to radiation
201 
202         //cycle by sampling e+- pairs
203         for(G4int i=0; i<fNMCPairs;i++)
204         {
205             //pair energy uniform sampling
206             G4double etotal = fMass + fPPKineticEnergyCut +
207                               G4UniformRand()*(eGamma-2*(fMass+fPPKineticEnergyCut));//particle
208                                                                                      //total energy
209 
210             G4double phi = CLHEP::twopi*G4UniformRand();//necessary for pair kinematics
211 
212             //the probability of the production of the current pair (will be simulated)
213             //per distance
214             G4double probabilityPPdz = 0.;
215 
216             //cycle e- and e+ within single pair
217             for(G4int j=0; j<2;j++)
218             {
219                 if(j==1){etotal=eGamma-etotal;} //2nd particle energy
220                 twoVectorEtotal[j]=etotal;
221 
222                 //Baier-Katkov input
223                 //intermediate variables to reduce calculations (the same names as in G4BaierKatkov)
224                 G4double e2 = etotal*etotal;
225                 G4double gammaInverse2 = fMass*fMass/(etotal*etotal);// 1/gamma^2
226                 //normalization coefficient
227                 G4double coefNorm = CLHEP::fine_structure_const/(8*(CLHEP::pi2))/(2.*fNMCPairs);
228                 //G4double phi = CLHEP::twopi*G4UniformRand();//necessary for pair kinematics
229                 G4double om = eGamma;
230                 G4double eprime=om-etotal; //E'=omega-E
231                 G4double eprime2 = eprime*eprime;
232                 G4double e2pluseprime2 =e2+eprime2;
233                 G4double omprime=etotal*om/eprime;//om'=E*om/(om-E)
234                 G4double omprimed2=omprime/2;
235 
236                 //difference vs G4BaierKatkov: om -> etotal
237                 G4double coefNorme2deprime2 = coefNorm*e2/eprime2; //e2/om/om;//e2/eprime2;
238 
239                 G4double gammaInverse2om = gammaInverse2*om*om;
240 
241                 //initialize intermediate integrals with zeros
242                 G4double fa=0.,ss=0.,sc=0.,ssx=0.,ssy=0.,scx=0.,scy=0.;
243 
244                 //End of Baier-Katkov input
245 
246                 G4bool fbreak = false;//flag of the trajectory cycle break
247 
248                 //set fCrystalData parameters depending on the particle parameters
249                 fCrystalData->SetParticleProperties(etotal, fMass,
250                                                     charge[j], particleName[j]);
251 
252                 //needed just to setup the correct value of channel No in the crystal
253                 //since later it may be changed during the trajectory calculation
254                 fCrystalData->CoordinatesFromBoxToLattice(xyzGamma0);
255 
256                 //coordinate sampling: random x and y due to coordinate uncertainty
257                 //in the interaction point
258                 if(j==0)
259                 {
260                     x = fCrystalData->GetChannelWidthX()*G4UniformRand();
261                     y = fCrystalData->GetChannelWidthY()*G4UniformRand();
262                 }
263                 else
264                 {
265                     x=twoVectorX[0];
266                     y=twoVectorY[0];
267                 }
268                 twoVectorX[j] = x;
269                 twoVectorY[j] = y;
270                 //definite z as a coordinate of the photon (uncertainty of the
271                 //interaction point is taking into account later by simulation
272                 //of the position of pair production)
273                 z = xyzGamma.z();
274 
275                 //angles of the photon in the co-rotating reference system within a channel =>
276                 //angular distribution center
277                 G4double tx = fCrystalData->AngleXFromBoxToLattice(txGamma0,z);
278                 G4double ty = tyGamma0;
279                 G4double momentumDirectionZGamma = 1./
280                                                    std::sqrt(1.+std::pow(std::tan(tx),2)+
281                                                              std::pow(std::tan(ty),2));
282 
283                 //angle sampling: depends on angular range within a particle trajectory
284                 //defined by the Lindhard angle and on the angle of radiation proportional
285                 //to 1/gamma
286 
287                 //range of MC integration on angles
288                 G4double paramParticleAngle = fChargeParticleAngleFactor*fMass/etotal;
289 
290                 G4double axangle=0.;
291                 if (fCrystalData->GetModel()==1)//1D model (only angle vs plane matters)
292                 {
293                     axangle = std::abs(tx);
294                 }
295                 else if  (fCrystalData->GetModel()==2)//2D model
296                 {
297                     axangle = std::sqrt(tx*tx+ty*ty);
298                 }
299 
300                 if(axangle>fCrystalData->GetLindhardAngle()+DBL_EPSILON)
301                 {
302                     paramParticleAngle+=axangle
303                                           -std::sqrt(axangle*axangle
304                                                       -fCrystalData->GetLindhardAngle()
305                                                             *fCrystalData->GetLindhardAngle());
306                 }
307                 else
308                 {
309                     paramParticleAngle+=fCrystalData->GetLindhardAngle();
310                 }
311 
312 
313                 //ONLY forward direction
314                 if (paramParticleAngle>CLHEP::halfpi-DBL_EPSILON){paramParticleAngle=CLHEP::halfpi;}
315 
316                 G4double rho=1.;
317                 G4double rhocut=CLHEP::halfpi/paramParticleAngle;//radial angular cut of
318                                                                  //the distribution
319                 G4double norm=std::atan(rhocut*rhocut)*
320                                 CLHEP::pi*paramParticleAngle*paramParticleAngle;
321 
322 
323                 //distribution with long tails (useful to not exclude particle angles
324                 //after a strong single scattering)
325                 //at ellipsescale < 1 => half of statistics
326                 do
327                 {
328                     rho = std::sqrt(std::tan(CLHEP::halfpi*G4UniformRand()));
329                 }
330                 while (rho>rhocut);
331 
332                 //normalization coefficient for intergration on angles of charged particles
333                 G4double angleNormCoef = (1.+rho*rho*rho*rho)*norm;
334 
335                 tx+=charge[j]*paramParticleAngle*rho*std::cos(phi);
336                 twoVectorTX[j] = tx;
337                 ty+=charge[j]*paramParticleAngle*rho*std::sin(phi);
338                 twoVectorTY[j] = ty;
339 
340                 G4double zalongGamma = 0;//necessary for renormalization of PP probability
341                     //depending on the trajectory length along Gamma direction
342                 //starting the trajectory
343                 //here we don't care about the boundaries of the crystal volume
344                 //the trajectory is very short and the pair production probability obtained
345                 //in Baier-Katkov will be extrapolated to the real step inside the crystal volume
346                 for(G4int k=0; k<fNTrajectorySteps;k++)
347                 {
348                     //back to the local reference system of the volume
349                     txPreStep0 = fCrystalData->AngleXFromLatticeToBox(tx,z);
350                     tyPreStep0 = ty;
351 
352                     dz = fCrystalData->GetSimulationStep(tx,ty);
353                     dzd3=dz/3;
354                     dzd8=dz/8;
355 
356                     //trajectory calculation:
357                     //Runge-Cutt "3/8"
358                     //fCrystalData->GetCurv(z)*fCrystalData->GetCorrectionZ() is due to dependence
359                     //of the radius on x; GetCurv gets 1/R for the central ("central plane/axis")
360 
361                     //first step
362                     kvx1=fCrystalData->Ex(x,y);
363                     x1=x+tx*dzd3;
364                     tx1=tx+(kvx1-fCrystalData->GetCurv(z)*fCrystalData->GetCorrectionZ())*dzd3;
365                     if (fCrystalData->GetModel()==2)
366                     {
367                         kvy1=fCrystalData->Ey(x,y);
368                         y1=y+ty*dzd3;
369                         ty1=ty+kvy1*dzd3;
370                     }
371 
372                     //second step
373                     kvx2=fCrystalData->Ex(x1,y1);
374                     x2=x-tx*dzd3+tx1*dz;
375                     tx2=tx-(kvx1-fCrystalData->GetCurv(z)*fCrystalData->GetCorrectionZ())*dzd3+
376                           (kvx2-fCrystalData->GetCurv(z)*fCrystalData->GetCorrectionZ())*dz;
377                     if (fCrystalData->GetModel()==2)
378                     {
379                         kvy2=fCrystalData->Ey(x1,y1);
380                         y2=y-ty*dzd3+ty1*dz;
381                         ty2=ty-kvy1*dzd3+kvy2*dz;
382                     }
383 
384                     //third step
385                     kvx3=fCrystalData->Ex(x2,y2);
386                     x3=x+(tx-tx1+tx2)*dz;
387                     tx3=tx+(kvx1-kvx2+kvx3-
388                                 fCrystalData->GetCurv(z)*fCrystalData->GetCorrectionZ())*dz;
389                     if (fCrystalData->GetModel()==2)
390                     {
391                         kvy3=fCrystalData->Ey(x2,y2);
392                         y3=y+(ty-ty1+ty2)*dz;
393                         ty3=ty+(kvy1-kvy2+kvy3)*dz;
394                     }
395 
396                     //fourth step
397                     kvx4=fCrystalData->Ex(x3,y3);
398                     x4=x+(tx+3.*tx1+3.*tx2+tx3)*dzd8;
399                     tx4=tx+(kvx1+3.*kvx2+3.*kvx3+kvx4)*dzd8-
400                           fCrystalData->GetCurv(z)*fCrystalData->GetCorrectionZ()*dz;
401                     if (fCrystalData->GetModel()==2)
402                     {
403                         kvy4=fCrystalData->Ey(x3,y3);
404                         y4=y+(ty+3.*ty1+3.*ty2+ty3)*dzd8;
405                         ty4=ty+(kvy1+3.*kvy2+3.*kvy3+kvy4)*dzd8;
406                     }
407                     else
408                     {
409                         y4 =y+ty*dz;
410                         ty4=ty;
411                     }
412 
413                     x=x4;
414                     tx=tx4;
415                     y=y4;
416                     ty=ty4;
417 
418                     z+=dz*fCrystalData->GetCorrectionZ();//motion along the z coordinate
419                         //("central plane/axis", no current plane/axis)
420 
421                     xyzparticle = fCrystalData->ChannelChange(x,y,z);
422                     x=xyzparticle.x();
423                     y=xyzparticle.y();
424                     z=xyzparticle.z();
425 
426                     momentumDirectionStep =
427                         dz*std::sqrt(1+std::pow(std::tan(tx),2)+std::pow(std::tan(ty),2));
428                     zalongGamma += dz/momentumDirectionZGamma;
429 
430                     //default scattering and energy loss 0
431                     scatteringAnglesAndEnergyLoss.set(0.,0.,0.);
432 
433                     if(fIncoherentScattering)
434                     {
435                         //calculate separately for each element of the crystal
436                         for (G4int ii = 0; ii < fCrystalData->GetNelements(); ii++)
437                         {
438                            //effective step taking into account nuclear density along the trajectory
439                             effectiveStep = momentumDirectionStep*
440                                             fCrystalData->NuclearDensity(x,y,ii);
441                             //Coulomb scattering on screened atomic potential
442                             //(both multiple and single)
443                             scatteringAnglesAndEnergyLoss +=
444                                 fCrystalData->CoulombAtomicScattering(effectiveStep,
445                                                                       momentumDirectionStep,
446                                                                       ii);
447                         }
448                         //electron scattering and coherent part of ionization energy losses
449                         scatteringAnglesAndEnergyLoss += fCrystalData->CoulombElectronScattering(
450                             fCrystalData->MinIonizationEnergy(x,y),
451                             fCrystalData->ElectronDensity(x,y),
452                             momentumDirectionStep);
453                         tx += scatteringAnglesAndEnergyLoss.x();
454                         ty += scatteringAnglesAndEnergyLoss.y();
455                     }
456 
457                     //To avoid backward direction
458                     if(std::abs(tx)>CLHEP::halfpi-DBL_EPSILON||
459                         std::abs(ty)>CLHEP::halfpi-DBL_EPSILON)
460                     {
461                         G4cout << "Warning: particle angle is beyond +-pi/2 range => "
462                                   "skipping the calculation of its probability" << G4endl;
463                         fbreak = true;
464                         break;
465                     }
466 
467                     //**********Baier-Katkov start
468 
469                     //back to the local reference system of the volume
470                     tx0 = fCrystalData->AngleXFromLatticeToBox(tx,z);
471                     ty0 = ty;
472 
473                     dzMeV=momentumDirectionStep/CLHEP::hbarc;// in MeV^-1
474 
475                     // accelerations
476                     axt=(tx0-scatteringAnglesAndEnergyLoss.x()-txPreStep0)/dzMeV;
477                     ayt=(ty0-scatteringAnglesAndEnergyLoss.y()-tyPreStep0)/dzMeV;
478 
479                     //the angles vs the photon (with incoherent scattering)
480                     vxin = tx0-txGamma0;
481                     vyin = ty0-tyGamma0;
482                     //the angles vs the photon (without incoherent scattering)
483                     vxno = vxin-scatteringAnglesAndEnergyLoss.x();
484                     vyno = vyin-scatteringAnglesAndEnergyLoss.y();
485 
486                     //phase difference before scattering
487                     faseBefore=omprimed2*(gammaInverse2+vxno*vxno+vyno*vyno);//phi' t<ti//MeV
488 
489                     faseBeforedz = faseBefore*dzMeV;
490                     faseBeforedzd2 = faseBeforedz/2.;
491                     fa+=faseBeforedz; //
492                     fa1=fa-faseBeforedzd2;//
493                     dzmod=2*std::sin(faseBeforedzd2)/faseBefore;//MeV^-1
494 
495                     //phi''/faseBefore^2
496                     fa2dfaseBefore2 = omprime*(axt*vxno+ayt*vyno)/(faseBefore*faseBefore);
497 
498                     //phase difference after scattering
499                     faseAfter=omprimed2*(gammaInverse2+vxin*vxin+vyin*vyin);//phi' ti+O//MeV
500 
501                     skJ=1/faseAfter-1/faseBefore-fa2dfaseBefore2*dzmod;//MeV^-1
502                     skIx=vxin/faseAfter-vxno/faseBefore+dzmod*(axt/faseBefore-
503                                                                            vxno*fa2dfaseBefore2);
504                     skIy=vyin/faseAfter-vyno/faseBefore+dzmod*(ayt/faseBefore-
505                                                                            vyno*fa2dfaseBefore2);
506 
507                     sinfa1 = std::sin(fa1);
508                     cosfa1 = std::cos(fa1);
509 
510                     ss+=sinfa1*skJ;//sum sin integral J of BK
511                     sc+=cosfa1*skJ;//sum cos integral J of BK
512                     ssx+=sinfa1*skIx;// sum sin integral Ix of BK
513                     ssy+=sinfa1*skIy;// sum sin integral Iy of BK
514                     scx+=cosfa1*skIx;// sum cos integral Ix of BK
515                     scy+=cosfa1*skIy;// sum cos integral Iy of BK
516                 }
517 
518                 //only of the trajectory cycle was not broken
519                 if(!fbreak)
520                 {
521                     G4double i2=ssx*ssx+scx*scx+ssy*ssy+scy*scy;//MeV^-2
522                     G4double j2=ss*ss+sc*sc;//MeV^-2
523 
524                     probabilityPPdz += coefNorme2deprime2*angleNormCoef*
525                                        (i2*e2pluseprime2+j2*gammaInverse2om)/zalongGamma;
526                 }
527             }
528 
529             //filling the CDF of probabilities of the production of sampling pairs
530             fPairProductionCDFdz.push_back(fPairProductionCDFdz[i]+probabilityPPdz);
531             //**********Baier-Katkov end
532 
533             //accumulation of initial parameters of sampling pairs
534             fullVectorEtotal.push_back(twoVectorEtotal);
535             fullVectorX.push_back(twoVectorX);
536             fullVectorY.push_back(twoVectorY);
537             fullVectorTX.push_back(twoVectorTX);
538             fullVectorTY.push_back(twoVectorTY);
539         }
540 
541         //photon mean free path
542         //fPairProductionCDFdz.back() = full pair production probability
543         //simulated for the current photon along photon direction
544         G4double lMeanFreePath = 1/fPairProductionCDFdz.back();
545 
546         fEffectiveLrad = 7.*lMeanFreePath/9.;//only for scoring purpose
547 
548         return lMeanFreePath;
549     }
550     else
551     {
552         //dummy process, does not occur
553         return DBL_MAX;
554     }
555 
556 }
557 
558 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
559 
560 G4VParticleChange* G4CoherentPairProduction::PostStepDoIt(const G4Track& aTrack,
561                                            const G4Step& aStep)
562 {
563   //example with no physical sense
564     aParticleChange.Initialize(aTrack);
565     //G4LogicalVolume* aLV = aTrack.GetVolume()->GetLogicalVolume();
566 
567     const G4ParticleDefinition* chargedParticleDefinition[2] =
568         {G4Electron::Electron(),G4Positron::Positron()};
569 
570     // the coordinates of the photon in the local reference system of the volume
571     G4ThreeVector xyzGamma0 =
572         aTrack.GetTouchableHandle()->GetHistory()->
573             GetTopTransform().TransformPoint(aTrack.GetPosition());
574 
575     // the coordinates of the photon in the co-rotating reference system within
576     //a channel (elementary periodic cell)
577     G4ThreeVector xyzGamma = fCrystalData->CoordinatesFromBoxToLattice(xyzGamma0);
578 
579     //global time
580     G4double tGlobalGamma = aTrack.GetGlobalTime();
581 
582     G4double ksi1 = G4UniformRand()*fPairProductionCDFdz.back();
583 
584     //randomly choosing the pair to be produced from the sampling list
585     //according to the probabilities calculated in the Baier-Katkov integral
586     G4int ipair = FindVectorIndex(fPairProductionCDFdz,ksi1)-1;//index of
587         //a pair produced
588 
589     // the coordinates of a charged particle in the reference system within
590     //a channel (elementary periodic cell)
591     G4ThreeVector xyzparticle;
592     //cycle e- and e+ within single pair
593     for(G4int j=0; j<2;j++)
594     {
595         xyzparticle.set(fullVectorX[ipair][j],fullVectorY[ipair][j],xyzGamma.z());
596 
597         //in the local reference system of the volume
598         G4ThreeVector newParticleCoordinateXYZ =
599                 fCrystalData->CoordinatesFromLatticeToBox(xyzparticle);
600         //the same in the global reference system
601         newParticleCoordinateXYZ =
602             aTrack.GetTouchableHandle()->GetHistory()->
603                 GetTopTransform().Inverse().TransformPoint(newParticleCoordinateXYZ);
604 
605         //back to the local reference system of the volume
606         G4double tx0 = fCrystalData->AngleXFromLatticeToBox(fullVectorTX[ipair][j],xyzGamma.z());
607         G4double ty0 = fullVectorTY[ipair][j];
608 
609         G4double momentumDirectionZ = 1./
610                                       std::sqrt(1.+std::pow(std::tan(tx0),2)+
611                                                 std::pow(std::tan(ty0),2));
612 
613         //momentum direction vector of the charged particle produced
614         //in the local reference system of the volume
615         G4ThreeVector momentumDirectionParticle = G4ThreeVector(momentumDirectionZ*std::tan(tx0),
616                                                                 momentumDirectionZ*std::tan(ty0),
617                                                                 momentumDirectionZ);
618         //the same in the global reference system
619         momentumDirectionParticle =
620             (aTrack.GetTouchableHandle()->GetHistory()->GetTopTransform().NetRotation()) *
621                 momentumDirectionParticle;
622 
623         G4DynamicParticle* chargedParticle =
624             new G4DynamicParticle(chargedParticleDefinition[j],
625                               momentumDirectionParticle,
626                               fullVectorEtotal[ipair][j]-fMass);
627 
628         // Create the track for the secondary particle
629         G4Track* secondaryTrack = new G4Track(chargedParticle,
630                                               tGlobalGamma,
631                                               newParticleCoordinateXYZ);
632         secondaryTrack->SetTouchableHandle(aStep.GetPostStepPoint()->GetTouchableHandle());
633         secondaryTrack->SetParentID(aTrack.GetTrackID());
634 
635         //generation of a secondary charged particle
636         aParticleChange.AddSecondary(secondaryTrack);
637     }
638 
639     //killing the photon
640     aParticleChange.ProposeTrackStatus(fStopAndKill);
641 
642     return &aParticleChange;
643 }
644 
645 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
646 
647 G4int G4CoherentPairProduction::FindVectorIndex(std::vector<G4double> &myvector, G4double value)
648 {
649     auto iteratorbegin = myvector.begin();
650     auto iteratorend   = myvector.end();
651 
652     //vector index (for non precise values lower_bound gives upper value)
653     auto loweriterator = std::lower_bound(iteratorbegin, iteratorend, value);
654     //return the index of the vector element
655     return (G4int)std::distance(iteratorbegin, loweriterator);
656 }
657 
658 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
659 
660 void G4CoherentPairProduction::Input(const G4Material *crystal,
661                                      const G4String &lattice,
662                                      const G4String &filePath)
663 {
664     //initializing the class with containing all
665     //the crystal material and crystal lattice data and
666     //Channeling scattering and ionization processes
667     fCrystalData = new G4ChannelingFastSimCrystalData();
668     //setting all the crystal material and lattice data
669     fCrystalData->SetMaterialProperties(crystal,lattice,filePath);
670 }
671 
672 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
673 
674 void G4CoherentPairProduction::Input(const G4ChannelingFastSimCrystalData *crystalData)
675 {
676     //setting the class with containing all
677     //the crystal material and crystal lattice data and
678     //Channeling scattering and ionization processes
679     //fCrystalData = new G4ChannelingFastSimCrystalData();
680 
681     fCrystalData = const_cast<G4ChannelingFastSimCrystalData*>(crystalData);
682 }
683 
684 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
685 
686 void G4CoherentPairProduction::ProcessDescription(std::ostream& out) const
687 {
688     out << "  Coherent pair production";
689     G4VDiscreteProcess::ProcessDescription(out);
690 }
691 
692 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
693