ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4ForwardXrayTR.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4ForwardXrayTR.cc
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 //
27 //
28 // G4ForwardXrayTR class -- implementation file
29 //
30 // History:
31 // 1st version 11.09.97 V. Grichine (Vladimir.Grichine@cern.ch )
32 // 2nd version 17.12.97 V. Grichine
33 // 17-09-01, migration of Materials to pure STL (mma)
34 // 10-03-03, migration to "cut per region" (V.Ivanchenko)
35 // 03.06.03, V.Ivanchenko fix compilation warnings
36 
37 #include "G4ForwardXrayTR.hh"
38 
39 #include "globals.hh"
40 #include "G4PhysicalConstants.hh"
41 #include "G4SystemOfUnits.hh"
42 #include "G4Poisson.hh"
43 #include "G4Material.hh"
44 #include "G4PhysicsTable.hh"
45 #include "G4PhysicsVector.hh"
46 #include "G4PhysicsLinearVector.hh"
47 #include "G4PhysicsLogVector.hh"
48 #include "G4ProductionCutsTable.hh"
49 #include "G4GeometryTolerance.hh"
50 
51 // Initialization of local constants
52 
54 
60 
64 
67 
69 
70 
72 //
73 // Constructor for creation of physics tables (angle and energy TR
74 // distributions) for a couple of selected materials.
75 //
76 // Recommended for use in applications with many materials involved,
77 // when only few (usually couple) materials are interested for generation
78 // of TR on the interface between them
79 
80 
82 G4ForwardXrayTR( const G4String& matName1, // G4Material* pMat1,
83  const G4String& matName2, // G4Material* pMat2,
84  const G4String& processName )
85  : G4TransitionRadiation(processName)
86 {
87  fPtrGamma = nullptr;
88  fGammaCutInKineticEnergy = nullptr;
90  fSigma1 = fSigma2 = 0.0;
91  fAngleDistrTable = nullptr;
92  fEnergyDistrTable = nullptr;
93  fMatIndex1 = fMatIndex2 = 0;
94 
95  // Proton energy vector initialization
96  //
99  G4int iMat;
100  const G4ProductionCutsTable* theCoupleTable=
102  G4int numOfCouples = theCoupleTable->GetTableSize();
103 
104  G4bool build = true;
105 
106  for(iMat=0;iMat<numOfCouples;iMat++) // check first material name
107  {
108  const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(iMat);
109  if( matName1 == couple->GetMaterial()->GetName() )
110  {
111  fMatIndex1 = couple->GetIndex();
112  break;
113  }
114  }
115  if(iMat == numOfCouples)
116  {
117  G4Exception("G4ForwardXrayTR::G4ForwardXrayTR", "ForwardXrayTR01", JustWarning, "Invalid first material name in G4ForwardXrayTR constructor!");
118  build = false;
119  }
120 
121  if(build) {
122  for(iMat=0;iMat<numOfCouples;iMat++) // check second material name
123  {
124  const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(iMat);
125  if( matName2 == couple->GetMaterial()->GetName() )
126  {
127  fMatIndex2 = couple->GetIndex();
128  break;
129  }
130  }
131  if(iMat == numOfCouples)
132  {
133  G4Exception("G4ForwardXrayTR::G4ForwardXrayTR", "ForwardXrayTR02", JustWarning, "Invalid second material name in G4ForwardXrayTR constructor!");
134  build = false;
135  }
136  }
137  // G4cout<<"G4ForwardXray constructor is called"<<G4endl;
138  if(build) { BuildXrayTRtables(); }
139 }
140 
142 //
143 // Constructor used by X-ray transition radiation parametrisation models
144 
146 G4ForwardXrayTR( const G4String& processName )
147  : G4TransitionRadiation(processName)
148 {
149  fPtrGamma = nullptr;
150  fGammaCutInKineticEnergy = nullptr;
152  fSigma1 = fSigma2 = 0.0;
153  fAngleDistrTable = nullptr;
154  fEnergyDistrTable = nullptr;
155  fMatIndex1 = fMatIndex2 = 0;
156 
157  // Proton energy vector initialization
158  //
161 }
162 
163 
165 //
166 // Destructor
167 //
168 
170 {
171  delete fAngleDistrTable;
172  delete fEnergyDistrTable;
173  delete fProtonEnergyVector;
174 }
175 
177  G4double,
179 {
180  *condition = Forced;
181  return DBL_MAX; // so TR doesn't limit mean free path
182 }
183 
185 //
186 // Build physics tables for energy and angular distributions of X-ray TR photon
187 
189 {
190  G4int iMat, jMat, iTkin, iTR, iPlace;
191  const G4ProductionCutsTable* theCoupleTable=
193  G4int numOfCouples = theCoupleTable->GetTableSize();
194 
196 
199 
200 
201  for(iMat=0;iMat<numOfCouples;iMat++) // loop over pairs of different materials
202  {
203  if( iMat != fMatIndex1 && iMat != fMatIndex2 ) continue;
204 
205  for(jMat=0;jMat<numOfCouples;jMat++) // transition iMat -> jMat !!!
206  {
207  if( iMat == jMat || ( jMat != fMatIndex1 && jMat != fMatIndex2 ) )
208  {
209  continue;
210  }
211  else
212  {
213  const G4MaterialCutsCouple* iCouple = theCoupleTable->GetMaterialCutsCouple(iMat);
214  const G4MaterialCutsCouple* jCouple = theCoupleTable->GetMaterialCutsCouple(jMat);
215  const G4Material* mat1 = iCouple->GetMaterial();
216  const G4Material* mat2 = jCouple->GetMaterial();
217 
220 
221  // fGammaTkinCut = fGammaCutInKineticEnergy[jMat]; // TR photon in jMat !
222 
223  fGammaTkinCut = 0.0;
224 
225  if(fGammaTkinCut > fTheMinEnergyTR) // setting of min/max TR energies
226  {
228  }
229  else
230  {
232  }
233  if(fGammaTkinCut > fTheMaxEnergyTR)
234  {
235  fMaxEnergyTR = 2.0*fGammaTkinCut; // usually very low TR rate
236  }
237  else
238  {
240  }
241  for(iTkin=0;iTkin<fTotBin;iTkin++) // Lorentz factor loop
242  {
244  energyVector = new G4PhysicsLogVector( fMinEnergyTR,
245  fMaxEnergyTR,
246  fBinTR );
247 
248  fGamma = 1.0 + (fProtonEnergyVector->
249  GetLowEdgeEnergy(iTkin)/proton_mass_c2);
250 
251  fMaxThetaTR = 10000.0/(fGamma*fGamma);
252 
254  {
256  }
257  else
258  {
260  {
262  }
263  }
264  // G4cout<<G4endl<<"fGamma = "<<fGamma<<" fMaxThetaTR = "<<fMaxThetaTR<<G4endl;
266  angleVector = new G4PhysicsLinearVector( 0.0,
267  fMaxThetaTR,
268  fBinTR );
269  G4double energySum = 0.0;
270  G4double angleSum = 0.0;
271 
272  energyVector->PutValue(fBinTR-1,energySum);
273  angleVector->PutValue(fBinTR-1,angleSum);
274 
275  for(iTR=fBinTR-2;iTR>=0;iTR--)
276  {
277  energySum += fCofTR*EnergySum(energyVector->GetLowEdgeEnergy(iTR),
278  energyVector->GetLowEdgeEnergy(iTR+1));
279 
280  angleSum += fCofTR*AngleSum(angleVector->GetLowEdgeEnergy(iTR),
281  angleVector->GetLowEdgeEnergy(iTR+1));
282 
283  energyVector->PutValue(iTR,energySum);
284  angleVector ->PutValue(iTR,angleSum);
285  }
286  // G4cout<<"sumE = "<<energySum<<"; sumA = "<<angleSum<<G4endl;
287 
288  if(jMat < iMat)
289  {
290  iPlace = fTotBin+iTkin; // (iMat*(numOfMat-1)+jMat)*
291  }
292  else // jMat > iMat right part of matrices (jMat-1) !
293  {
294  iPlace = iTkin; // (iMat*(numOfMat-1)+jMat-1)*fTotBin+
295  }
296  fEnergyDistrTable->insertAt(iPlace,energyVector);
297  fAngleDistrTable->insertAt(iPlace,angleVector);
298  } // iTkin
299  } // jMat != iMat
300  } // jMat
301  } // iMat
302  // G4cout<<"G4ForwardXrayTR::BuildXrayTRtables have been called"<<G4endl;
303 }
304 
306 //
307 // This function returns the spectral and angle density of TR quanta
308 // in X-ray energy region generated forward when a relativistic
309 // charged particle crosses interface between two materials.
310 // The high energy small theta approximation is applied.
311 // (matter1 -> matter2)
312 // varAngle =2* (1 - std::cos(Theta)) or approximately = Theta*Theta
313 //
314 
315 G4double
317  G4double varAngle ) const
318 {
319  G4double formationLength1, formationLength2;
320  formationLength1 = 1.0/
321  (1.0/(fGamma*fGamma)
322  + fSigma1/(energy*energy)
323  + varAngle);
324  formationLength2 = 1.0/
325  (1.0/(fGamma*fGamma)
326  + fSigma2/(energy*energy)
327  + varAngle);
328  return (varAngle/energy)*(formationLength1 - formationLength2)
329  *(formationLength1 - formationLength2);
330 
331 }
332 
333 
335 //
336 // Analytical formula for angular density of X-ray TR photons
337 //
338 
340  G4double varAngle ) const
341 {
342  G4double x, x2, /*a, b,*/ c, d, f, a2, b2, a4, b4;
343  G4double cof1, cof2, cof3;
344  x = 1.0/energy;
345  x2 = x*x;
346  c = 1.0/fSigma1;
347  d = 1.0/fSigma2;
348  f = (varAngle + 1.0/(fGamma*fGamma));
349  a2 = c*f;
350  b2 = d*f;
351  a4 = a2*a2;
352  b4 = b2*b2;
353  //a = std::sqrt(a2);
354  // b = std::sqrt(b2);
355  cof1 = c*c*(0.5/(a2*(x2 +a2)) +0.5*std::log(x2/(x2 +a2))/a4);
356  cof3 = d*d*(0.5/(b2*(x2 +b2)) +0.5*std::log(x2/(x2 +b2))/b4);
357  cof2 = -c*d*(std::log(x2/(x2 +b2))/b2 - std::log(x2/(x2 +a2))/a2)/(a2 - b2) ;
358  return -varAngle*(cof1 + cof2 + cof3);
359 }
360 
362 //
363 // Definite integral of X-ray TR spectral-angle density from energy1
364 // to energy2
365 //
366 
368  G4double energy2,
369  G4double varAngle ) const
370 {
371  return AngleDensity(energy2,varAngle)
372  - AngleDensity(energy1,varAngle);
373 }
374 
376 //
377 // Integral angle distribution of X-ray TR photons based on analytical
378 // formula for angle density
379 //
380 
382  G4double varAngle2 ) const
383 {
384  G4int i;
385  G4double h , sumEven = 0.0 , sumOdd = 0.0;
386  h = 0.5*(varAngle2 - varAngle1)/fSympsonNumber;
387  for(i=1;i<fSympsonNumber;i++)
388  {
389  sumEven += EnergyInterval(fMinEnergyTR,fMaxEnergyTR,varAngle1 + 2*i*h );
391  varAngle1 + (2*i - 1)*h );
392  }
394  varAngle1 + (2*fSympsonNumber - 1)*h );
395 
396  return h*(EnergyInterval(fMinEnergyTR,fMaxEnergyTR,varAngle1)
398  + 4.0*sumOdd + 2.0*sumEven )/3.0;
399 }
400 
402 //
403 // Analytical Expression for spectral density of Xray TR photons
404 // x = 2*(1 - std::cos(Theta)) ~ Theta^2
405 //
406 
408  G4double x ) const
409 {
410  G4double a, b;
411  a = 1.0/(fGamma*fGamma)
412  + fSigma1/(energy*energy) ;
413  b = 1.0/(fGamma*fGamma)
414  + fSigma2/(energy*energy) ;
415  return ( (a + b)*std::log((x + b)/(x + a))/(a - b)
416  + a/(x + a) + b/(x + b) )/energy;
417 
418 }
419 
421 //
422 // The spectral density in some angle interval from varAngle1 to
423 // varAngle2
424 //
425 
427  G4double varAngle1,
428  G4double varAngle2 ) const
429 {
430  return SpectralDensity(energy,varAngle2)
431  - SpectralDensity(energy,varAngle1);
432 }
433 
435 //
436 // Integral spectral distribution of X-ray TR photons based on
437 // analytical formula for spectral density
438 //
439 
441  G4double energy2 ) const
442 {
443  G4int i;
444  G4double h , sumEven = 0.0 , sumOdd = 0.0;
445  h = 0.5*(energy2 - energy1)/fSympsonNumber;
446  for(i=1;i<fSympsonNumber;i++)
447  {
448  sumEven += AngleInterval(energy1 + 2*i*h,0.0,fMaxThetaTR);
449  sumOdd += AngleInterval(energy1 + (2*i - 1)*h,0.0,fMaxThetaTR);
450  }
451  sumOdd += AngleInterval(energy1 + (2*fSympsonNumber - 1)*h,
452  0.0,fMaxThetaTR);
453 
454  return h*( AngleInterval(energy1,0.0,fMaxThetaTR)
455  + AngleInterval(energy2,0.0,fMaxThetaTR)
456  + 4.0*sumOdd + 2.0*sumEven )/3.0;
457 }
458 
460 //
461 // PostStepDoIt function for creation of forward X-ray photons in TR process
462 // on boubndary between two materials with really different plasma energies
463 //
464 
466  const G4Step& aStep)
467 {
468  aParticleChange.Initialize(aTrack);
469  // G4cout<<"call G4ForwardXrayTR::PostStepDoIt"<<G4endl;
470  G4int iMat, jMat, iTkin, iPlace, numOfTR, iTR, iTransfer;
471 
472  G4double energyPos, anglePos, energyTR, theta, phi, dirX, dirY, dirZ;
473  G4double W, W1, W2, E1, E2;
474 
475  G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
476  G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
478 
479  if (pPostStepPoint->GetStepStatus() != fGeomBoundary)
480  {
481  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
482  }
483  if (aTrack.GetStepLength() <= tol)
484  {
485  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
486  }
487  // Come on boundary, so begin to try TR
488 
489  const G4MaterialCutsCouple* iCouple = pPreStepPoint ->GetPhysicalVolume()->
490  GetLogicalVolume()->GetMaterialCutsCouple();
491  const G4MaterialCutsCouple* jCouple = pPostStepPoint ->GetPhysicalVolume()->
492  GetLogicalVolume()->GetMaterialCutsCouple();
493  const G4Material* iMaterial = iCouple->GetMaterial();
494  const G4Material* jMaterial = jCouple->GetMaterial();
495  iMat = iCouple->GetIndex();
496  jMat = jCouple->GetIndex();
497 
498  // The case of equal or approximate (in terms of plasma energy) materials
499  // No TR photons ?!
500 
501  if ( iMat == jMat
502  || ( (fMatIndex1 >= 0 && fMatIndex2 >= 0)
503  && ( iMat != fMatIndex1 && iMat != fMatIndex2 )
504  && ( jMat != fMatIndex1 && jMat != fMatIndex2 ) )
505 
506  || iMaterial->GetState() == jMaterial->GetState()
507 
508  ||(iMaterial->GetState() == kStateSolid && jMaterial->GetState() == kStateLiquid )
509 
510  ||(iMaterial->GetState() == kStateLiquid && jMaterial->GetState() == kStateSolid ) )
511  {
512  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
513  }
514 
515  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
516  G4double charge = aParticle->GetDefinition()->GetPDGCharge();
517 
518  if(charge == 0.0) // Uncharged particle doesn't Generate TR photons
519  {
520  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
521  }
522  // Now we are ready to Generate TR photons
523 
524  G4double chargeSq = charge*charge;
525  G4double kinEnergy = aParticle->GetKineticEnergy();
526  G4double massRatio = proton_mass_c2/aParticle->GetDefinition()->GetPDGMass();
527  G4double TkinScaled = kinEnergy*massRatio;
528  for(iTkin=0;iTkin<fTotBin;iTkin++)
529  {
530  if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) // <= ?
531  {
532  break;
533  }
534  }
535  if(jMat < iMat)
536  {
537  iPlace = fTotBin + iTkin - 1; // (iMat*(numOfMat - 1) + jMat)*
538  }
539  else
540  {
541  iPlace = iTkin - 1; // (iMat*(numOfMat - 1) + jMat - 1)*fTotBin +
542  }
543  // G4PhysicsVector* energyVector1 = (*fEnergyDistrTable)(iPlace) ;
544  // G4PhysicsVector* energyVector2 = (*fEnergyDistrTable)(iPlace + 1);
545 
546  // G4PhysicsVector* angleVector1 = (*fAngleDistrTable)(iPlace) ;
547  // G4PhysicsVector* angleVector2 = (*fAngleDistrTable)(iPlace + 1) ;
548 
549  G4ParticleMomentum particleDir = aParticle->GetMomentumDirection();
550 
551  if(iTkin == fTotBin) // TR plato, try from left
552  {
553  // G4cout<<iTkin<<" mean TR number = "<<( (*(*fEnergyDistrTable)(iPlace))(0) +
554  // (*(*fAngleDistrTable)(iPlace))(0) )
555  // *chargeSq*0.5<<G4endl;
556 
557  numOfTR = G4Poisson( ( (*(*fEnergyDistrTable)(iPlace))(0) +
558  (*(*fAngleDistrTable)(iPlace))(0) )
559  *chargeSq*0.5 );
560  if(numOfTR == 0)
561  {
562  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
563  }
564  else
565  {
566  // G4cout<<"Number of X-ray TR photons = "<<numOfTR<<G4endl;
567 
569 
570  for(iTR=0;iTR<numOfTR;iTR++)
571  {
572  energyPos = (*(*fEnergyDistrTable)(iPlace))(0)*G4UniformRand();
573  for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
574  {
575  if(energyPos >= (*(*fEnergyDistrTable)(iPlace))(iTransfer)) break;
576  }
577  energyTR = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
578 
579  // G4cout<<"energyTR = "<<energyTR/keV<<"keV"<<G4endl;
580 
581  kinEnergy -= energyTR;
582  aParticleChange.ProposeEnergy(kinEnergy);
583 
584  anglePos = (*(*fAngleDistrTable)(iPlace))(0)*G4UniformRand();
585  for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
586  {
587  if(anglePos > (*(*fAngleDistrTable)(iPlace))(iTransfer)) break;
588  }
589  theta = std::sqrt((*fAngleDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1));
590 
591  // G4cout<<iTransfer<<" : theta = "<<theta<<G4endl;
592 
593  phi = twopi*G4UniformRand();
594  dirX = std::sin(theta)*std::cos(phi) ;
595  dirY = std::sin(theta)*std::sin(phi) ;
596  dirZ = std::cos(theta) ;
597  G4ThreeVector directionTR(dirX,dirY,dirZ);
598  directionTR.rotateUz(particleDir);
600  directionTR,
601  energyTR );
602  aParticleChange.AddSecondary(aPhotonTR);
603  }
604  }
605  }
606  else
607  {
608  if(iTkin == 0) // Tkin is too small, neglect of TR photon generation
609  {
610  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
611  }
612  else // general case: Tkin between two vectors of the material
613  {
614  E1 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin - 1);
616  W = 1.0/(E2 - E1);
617  W1 = (E2 - TkinScaled)*W;
618  W2 = (TkinScaled - E1)*W;
619 
620  // G4cout<<iTkin<<" mean TR number = "<<(((*(*fEnergyDistrTable)(iPlace))(0)+
621  // (*(*fAngleDistrTable)(iPlace))(0))*W1 +
622  // ((*(*fEnergyDistrTable)(iPlace + 1))(0)+
623  // (*(*fAngleDistrTable)(iPlace + 1))(0))*W2)
624  // *chargeSq*0.5<<G4endl;
625 
626  numOfTR = G4Poisson((((*(*fEnergyDistrTable)(iPlace))(0)+
627  (*(*fAngleDistrTable)(iPlace))(0))*W1 +
628  ((*(*fEnergyDistrTable)(iPlace + 1))(0)+
629  (*(*fAngleDistrTable)(iPlace + 1))(0))*W2)
630  *chargeSq*0.5 );
631  if(numOfTR == 0)
632  {
633  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
634  }
635  else
636  {
637  // G4cout<<"Number of X-ray TR photons = "<<numOfTR<<G4endl;
638 
640  for(iTR=0;iTR<numOfTR;iTR++)
641  {
642  energyPos = ((*(*fEnergyDistrTable)(iPlace))(0)*W1+
643  (*(*fEnergyDistrTable)(iPlace + 1))(0)*W2)*G4UniformRand();
644  for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
645  {
646  if(energyPos >= ((*(*fEnergyDistrTable)(iPlace))(iTransfer)*W1+
647  (*(*fEnergyDistrTable)(iPlace + 1))(iTransfer)*W2)) break;
648  }
649  energyTR = ((*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer))*W1+
650  ((*fEnergyDistrTable)(iPlace + 1)->GetLowEdgeEnergy(iTransfer))*W2;
651 
652  // G4cout<<"energyTR = "<<energyTR/keV<<"keV"<<G4endl;
653 
654  kinEnergy -= energyTR;
655  aParticleChange.ProposeEnergy(kinEnergy);
656 
657  anglePos = ((*(*fAngleDistrTable)(iPlace))(0)*W1+
658  (*(*fAngleDistrTable)(iPlace + 1))(0)*W2)*G4UniformRand();
659  for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
660  {
661  if(anglePos > ((*(*fAngleDistrTable)(iPlace))(iTransfer)*W1+
662  (*(*fAngleDistrTable)(iPlace + 1))(iTransfer)*W2)) break;
663  }
664  theta = std::sqrt(((*fAngleDistrTable)(iPlace)->
665  GetLowEdgeEnergy(iTransfer-1))*W1+
666  ((*fAngleDistrTable)(iPlace + 1)->
667  GetLowEdgeEnergy(iTransfer-1))*W2);
668 
669  // G4cout<<iTransfer<<" : theta = "<<theta<<G4endl;
670 
671  phi = twopi*G4UniformRand();
672  dirX = std::sin(theta)*std::cos(phi) ;
673  dirY = std::sin(theta)*std::sin(phi) ;
674  dirZ = std::cos(theta) ;
675  G4ThreeVector directionTR(dirX,dirY,dirZ);
676  directionTR.rotateUz(particleDir);
678  directionTR,
679  energyTR );
680  aParticleChange.AddSecondary(aPhotonTR);
681  }
682  }
683  }
684  }
685  return &aParticleChange;
686 }
687 
689 //
690 // Test function for checking of PostStepDoIt random preparation of TR photon
691 // energy
692 //
693 
694 G4double
696 {
697  G4int iPlace, numOfTR, iTR, iTransfer;
698  G4double energyTR = 0.0; // return this value for no TR photons
699  G4double energyPos ;
700  G4double W1, W2;
701 
702  const G4ProductionCutsTable* theCoupleTable=
704  G4int numOfCouples = theCoupleTable->GetTableSize();
705 
706  // The case of equal or approximate (in terms of plasma energy) materials
707  // No TR photons ?!
708 
709  const G4MaterialCutsCouple* iCouple = theCoupleTable->GetMaterialCutsCouple(iMat);
710  const G4MaterialCutsCouple* jCouple = theCoupleTable->GetMaterialCutsCouple(jMat);
711  const G4Material* iMaterial = iCouple->GetMaterial();
712  const G4Material* jMaterial = jCouple->GetMaterial();
713 
714  if ( iMat == jMat
715 
716  || iMaterial->GetState() == jMaterial->GetState()
717 
718  ||(iMaterial->GetState() == kStateSolid && jMaterial->GetState() == kStateLiquid )
719 
720  ||(iMaterial->GetState() == kStateLiquid && jMaterial->GetState() == kStateSolid ) )
721 
722  {
723  return energyTR;
724  }
725 
726  if(jMat < iMat)
727  {
728  iPlace = (iMat*(numOfCouples - 1) + jMat)*fTotBin + iTkin - 1;
729  }
730  else
731  {
732  iPlace = (iMat*(numOfCouples - 1) + jMat - 1)*fTotBin + iTkin - 1;
733  }
734  G4PhysicsVector* energyVector1 = (*fEnergyDistrTable)(iPlace) ;
735  G4PhysicsVector* energyVector2 = (*fEnergyDistrTable)(iPlace + 1);
736 
737  if(iTkin == fTotBin) // TR plato, try from left
738  {
739  numOfTR = G4Poisson( (*energyVector1)(0) );
740  if(numOfTR == 0)
741  {
742  return energyTR;
743  }
744  else
745  {
746  for(iTR=0;iTR<numOfTR;iTR++)
747  {
748  energyPos = (*energyVector1)(0)*G4UniformRand();
749  for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
750  {
751  if(energyPos >= (*energyVector1)(iTransfer)) break;
752  }
753  energyTR += energyVector1->GetLowEdgeEnergy(iTransfer);
754  }
755  }
756  }
757  else
758  {
759  if(iTkin == 0) // Tkin is too small, neglect of TR photon generation
760  {
761  return energyTR;
762  }
763  else // general case: Tkin between two vectors of the material
764  { // use trivial mean half/half
765  W1 = 0.5;
766  W2 = 0.5;
767  numOfTR = G4Poisson( (*energyVector1)(0)*W1 +
768  (*energyVector2)(0)*W2 );
769  if(numOfTR == 0)
770  {
771  return energyTR;
772  }
773  else
774  {
775  G4cout<<"It is still OK in GetEnergyTR(int,int,int)"<<G4endl;
776  for(iTR=0;iTR<numOfTR;iTR++)
777  {
778  energyPos = ((*energyVector1)(0)*W1+
779  (*energyVector2)(0)*W2)*G4UniformRand();
780  for(iTransfer=0;iTransfer<fBinTR-1;iTransfer++)
781  {
782  if(energyPos >= ((*energyVector1)(iTransfer)*W1+
783  (*energyVector2)(iTransfer)*W2)) break;
784  }
785  energyTR += (energyVector1->GetLowEdgeEnergy(iTransfer))*W1+
786  (energyVector2->GetLowEdgeEnergy(iTransfer))*W2;
787 
788  }
789  }
790  }
791  }
792 
793  return energyTR;
794 }
795 
797 //
798 // Test function for checking of PostStepDoIt random preparation of TR photon
799 // theta angle relative to particle direction
800 //
801 
802 G4double
804 {
805  return 0.0;
806 }
807 
809 {
810  return fSympsonNumber;
811 }
812 
814 {
815  return fBinTR;
816 }
817 
819 {
820  return fMinProtonTkin;
821 }
822 
824 {
825  return fMaxProtonTkin;
826 }
827 
829 {
830  return fTotBin;
831 }
832 
833 // end of G4ForwardXrayTR implementation file
834 //