Geant4  10.01.p02
G4VXTRenergyLoss.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 //
27 // $Id: G4VXTRenergyLoss.cc 84716 2014-10-20 07:38:47Z gcosmo $
28 //
29 // History:
30 // 2001-2002 R&D by V.Grichine
31 // 19.06.03 V. Grichine, modifications in BuildTable for the integration
32 // in respect of angle: range is increased, accuracy is
33 // improved
34 // 28.07.05, P.Gumplinger add G4ProcessType to constructor
35 // 28.09.07, V.Ivanchenko general cleanup without change of algorithms
36 //
37 
38 #include "G4VXTRenergyLoss.hh"
39 
40 #include "G4Timer.hh"
41 #include "G4PhysicalConstants.hh"
42 #include "G4SystemOfUnits.hh"
43 
44 #include "G4Poisson.hh"
45 #include "G4MaterialTable.hh"
46 #include "G4VDiscreteProcess.hh"
47 #include "G4VParticleChange.hh"
48 #include "G4VSolid.hh"
49 
50 #include "G4RotationMatrix.hh"
51 #include "G4ThreeVector.hh"
52 #include "G4AffineTransform.hh"
53 #include "G4SandiaTable.hh"
54 
55 #include "G4PhysicsVector.hh"
56 #include "G4PhysicsFreeVector.hh"
57 #include "G4PhysicsLinearVector.hh"
58 
60 //
61 // Constructor, destructor
62 
64  G4Material* foilMat,G4Material* gasMat,
65  G4double a, G4double b,
66  G4int n,const G4String& processName,
67  G4ProcessType type) :
68  G4VDiscreteProcess(processName, type),
69  fGammaCutInKineticEnergy(0),
70  fGammaTkinCut(0),
71  fAngleDistrTable(0),
72  fEnergyDistrTable(0),
73  fPlatePhotoAbsCof(0),
74  fGasPhotoAbsCof(0),
75  fAngleForEnergyTable(0)
76 {
77  verboseLevel = 1;
78 
79  fPtrGamma = 0;
82 
83  // Initialization of local constants
84  fTheMinEnergyTR = 1.0*keV;
85  fTheMaxEnergyTR = 100.0*keV;
86  fTheMaxAngle = 1.0e-2;
87  fTheMinAngle = 5.0e-6;
88  fBinTR = 50;
89 
90  fMinProtonTkin = 100.0*GeV;
91  fMaxProtonTkin = 100.0*TeV;
92  fTotBin = 50;
93 
94  // Proton energy vector initialization
97  fTotBin );
98 
101  fBinTR );
102 
103  fPlasmaCof = 4.0*pi*fine_structure_const*hbarc*hbarc*hbarc/electron_mass_c2;
104 
105  fCofTR = fine_structure_const/pi;
106 
107  fEnvelope = anEnvelope;
108 
109  fPlateNumber = n;
110  if(verboseLevel > 0)
111  G4cout<<"### G4VXTRenergyLoss: the number of TR radiator plates = "
112  <<fPlateNumber<<G4endl;
113  if(fPlateNumber == 0)
114  {
115  G4Exception("G4VXTRenergyLoss::G4VXTRenergyLoss()","VXTRELoss01",
116  FatalException,"No plates in X-ray TR radiator");
117  }
118  // default is XTR dEdx, not flux after radiator
119 
120  fExitFlux = false;
121  fAngleRadDistr = false;
122  fCompton = false;
123 
124  fLambda = DBL_MAX;
125  // Mean thicknesses of plates and gas gaps
126 
127  fPlateThick = a;
128  fGasThick = b;
130  if(verboseLevel > 0)
131  G4cout<<"total radiator thickness = "<<fTotalDist/cm<<" cm"<<G4endl;
132 
133  // index of plate material
134  fMatIndex1 = foilMat->GetIndex();
135  if(verboseLevel > 0)
136  G4cout<<"plate material = "<<foilMat->GetName()<<G4endl;
137 
138  // index of gas material
139  fMatIndex2 = gasMat->GetIndex();
140  if(verboseLevel > 0)
141  G4cout<<"gas material = "<<gasMat->GetName()<<G4endl;
142 
143  // plasma energy squared for plate material
144 
146  // fSigma1 = (20.9*eV)*(20.9*eV);
147  if(verboseLevel > 0)
148  G4cout<<"plate plasma energy = "<<std::sqrt(fSigma1)/eV<<" eV"<<G4endl;
149 
150  // plasma energy squared for gas material
151 
153  if(verboseLevel > 0)
154  G4cout<<"gas plasma energy = "<<std::sqrt(fSigma2)/eV<<" eV"<<G4endl;
155 
156  // Compute cofs for preparation of linear photo absorption
157 
160 
162 }
163 
165 
167 {
168  if(fEnvelope) delete fEnvelope;
169  delete fProtonEnergyVector;
170  delete fXTREnergyVector;
171  if(fEnergyDistrTable) {
173  delete fEnergyDistrTable;
174  }
175  if(fAngleRadDistr) {
177  delete fAngleDistrTable;
178  }
181  delete fAngleForEnergyTable;
182  }
183 }
184 
186 //
187 // Returns condition for application of the model depending on particle type
188 
189 
191 {
192  return ( particle.GetPDGCharge() != 0.0 );
193 }
194 
196 //
197 // Calculate step size for XTR process inside raaditor
198 
200  G4double, // previousStepSize,
202 {
203  G4int iTkin, iPlace;
204  G4double lambda, sigma, kinEnergy, mass, gamma;
205  G4double charge, chargeSq, massRatio, TkinScaled;
206  G4double E1,E2,W,W1,W2;
207 
208  *condition = NotForced;
209 
210  if( aTrack.GetVolume()->GetLogicalVolume() != fEnvelope ) lambda = DBL_MAX;
211  else
212  {
213  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
214  kinEnergy = aParticle->GetKineticEnergy();
215  mass = aParticle->GetDefinition()->GetPDGMass();
216  gamma = 1.0 + kinEnergy/mass;
217  if(verboseLevel > 1)
218  {
219  G4cout<<" gamma = "<<gamma<<"; fGamma = "<<fGamma<<G4endl;
220  }
221 
222  if ( std::fabs( gamma - fGamma ) < 0.05*gamma ) lambda = fLambda;
223  else
224  {
225  charge = aParticle->GetDefinition()->GetPDGCharge();
226  chargeSq = charge*charge;
227  massRatio = proton_mass_c2/mass;
228  TkinScaled = kinEnergy*massRatio;
229 
230  for(iTkin = 0; iTkin < fTotBin; iTkin++)
231  {
232  if( TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break;
233  }
234  iPlace = iTkin - 1;
235 
236  if(iTkin == 0) lambda = DBL_MAX; // Tkin is too small, neglect of TR photon generation
237  else // general case: Tkin between two vectors of the material
238  {
239  if(iTkin == fTotBin)
240  {
241  sigma = (*(*fEnergyDistrTable)(iPlace))(0)*chargeSq;
242  }
243  else
244  {
245  E1 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin - 1);
247  W = 1.0/(E2 - E1);
248  W1 = (E2 - TkinScaled)*W;
249  W2 = (TkinScaled - E1)*W;
250  sigma = ( (*(*fEnergyDistrTable)(iPlace ))(0)*W1 +
251  (*(*fEnergyDistrTable)(iPlace+1))(0)*W2 )*chargeSq;
252 
253  }
254  if (sigma < DBL_MIN) lambda = DBL_MAX;
255  else lambda = 1./sigma;
256  fLambda = lambda;
257  fGamma = gamma;
258  if(verboseLevel > 1)
259  {
260  G4cout<<" lambda = "<<lambda/mm<<" mm"<<G4endl;
261  }
262  }
263  }
264  }
265  return lambda;
266 }
267 
269 //
270 // Interface for build table from physics list
271 
273 {
274  if(pd.GetPDGCharge() == 0.)
275  {
276  G4Exception("G4VXTRenergyLoss::BuildPhysicsTable", "Notification", JustWarning,
277  "XTR initialisation for neutral particle ?!" );
278  }
280 
281  if (fAngleRadDistr)
282  {
283  if(verboseLevel > 0)
284  {
285  G4cout<<"Build angle for energy distribution according the current radiator"
286  <<G4endl;
287  }
289  }
290 }
291 
292 
294 //
295 // Build integral energy distribution of XTR photons
296 
298 {
299  G4int iTkin, iTR, iPlace;
300  G4double radiatorCof = 1.0; // for tuning of XTR yield
301  G4double energySum = 0.0;
302 
305 
306  fGammaTkinCut = 0.0;
307 
308  // setting of min/max TR energies
309 
312 
315 
317 
318  G4cout.precision(4);
319  G4Timer timer;
320  timer.Start();
321 
322  if(verboseLevel > 0)
323  {
324  G4cout<<G4endl;
325  G4cout<<"Lorentz Factor"<<"\t"<<"XTR photon number"<<G4endl;
326  G4cout<<G4endl;
327  }
328  for( iTkin = 0; iTkin < fTotBin; iTkin++ ) // Lorentz factor loop
329  {
331  fMaxEnergyTR,
332  fBinTR );
333 
334  fGamma = 1.0 + (fProtonEnergyVector->
335  GetLowEdgeEnergy(iTkin)/proton_mass_c2);
336 
337  fMaxThetaTR = 2500.0/(fGamma*fGamma) ; // theta^2
338 
339  fTheMinAngle = 1.0e-3; // was 5.e-6, e-6 !!!, e-5, e-4
340 
343 
344  energySum = 0.0;
345 
346  energyVector->PutValue(fBinTR-1,energySum);
347 
348  for( iTR = fBinTR - 2; iTR >= 0; iTR-- )
349  {
350  // Legendre96 or Legendre10
351 
352  energySum += radiatorCof*fCofTR*integral.Legendre10(
354  energyVector->GetLowEdgeEnergy(iTR),
355  energyVector->GetLowEdgeEnergy(iTR+1) );
356 
357  energyVector->PutValue(iTR,energySum/fTotalDist);
358  }
359  iPlace = iTkin;
360  fEnergyDistrTable->insertAt(iPlace,energyVector);
361 
362  if(verboseLevel > 0)
363  {
364  G4cout
365  // <<iTkin<<"\t"
366  // <<"fGamma = "
367  <<fGamma<<"\t" // <<" fMaxThetaTR = "<<fMaxThetaTR
368  // <<"sumN = "
369  <<energySum // <<"; sumA = "<<angleSum
370  <<G4endl;
371  }
372  }
373  timer.Stop();
374  G4cout.precision(6);
375  if(verboseLevel > 0)
376  {
377  G4cout<<G4endl;
378  G4cout<<"total time for build X-ray TR energy loss tables = "
379  <<timer.GetUserElapsed()<<" s"<<G4endl;
380  }
381  fGamma = 0.;
382  return;
383 }
384 
386 //
387 // Bank of angle distributions for given energies (slow!)
388 
390 {
391  if( this->GetProcessName() == "TranspRegXTRadiator" ||
392  this->GetProcessName() == "TranspRegXTRmodel" ||
393  this->GetProcessName() == "RegularXTRadiator" ||
394  this->GetProcessName() == "RegularXTRmodel" )
395  {
396  BuildAngleTable();
397  return;
398  }
399  G4int i, iTkin, iTR;
400  G4double angleSum = 0.0;
401 
402 
403  fGammaTkinCut = 0.0;
404 
405  // setting of min/max TR energies
406 
409 
412 
414  fMaxEnergyTR,
415  fBinTR );
416 
418 
419  G4cout.precision(4);
420  G4Timer timer;
421  timer.Start();
422 
423  for( iTkin = 0; iTkin < fTotBin; iTkin++ ) // Lorentz factor loop
424  {
425 
426  fGamma = 1.0 + (fProtonEnergyVector->
427  GetLowEdgeEnergy(iTkin)/proton_mass_c2);
428 
429  fMaxThetaTR = 2500.0/(fGamma*fGamma) ; // theta^2
430 
431  fTheMinAngle = 1.0e-3; // was 5.e-6, e-6 !!!, e-5, e-4
432 
435 
437 
438  for( iTR = 0; iTR < fBinTR; iTR++ )
439  {
440  angleSum = 0.0;
441  fEnergy = energyVector->GetLowEdgeEnergy(iTR);
442  G4PhysicsLinearVector* angleVector = new G4PhysicsLinearVector(0.0,
443  fMaxThetaTR,
444  fBinTR );
445 
446  angleVector ->PutValue(fBinTR - 1, angleSum);
447 
448  for( i = fBinTR - 2; i >= 0; i-- )
449  {
450  // Legendre96 or Legendre10
451 
452  angleSum += integral.Legendre10(
454  angleVector->GetLowEdgeEnergy(i),
455  angleVector->GetLowEdgeEnergy(i+1) );
456 
457  angleVector ->PutValue(i, angleSum);
458  }
459  fAngleForEnergyTable->insertAt(iTR, angleVector);
460  }
461  fAngleBank.push_back(fAngleForEnergyTable);
462  }
463  timer.Stop();
464  G4cout.precision(6);
465  if(verboseLevel > 0)
466  {
467  G4cout<<G4endl;
468  G4cout<<"total time for build X-ray TR angle for energy loss tables = "
469  <<timer.GetUserElapsed()<<" s"<<G4endl;
470  }
471  fGamma = 0.;
472  delete energyVector;
473 }
474 
476 //
477 // Build XTR angular distribution at given energy based on the model
478 // of transparent regular radiator
479 
481 {
482  G4int iTkin, iTR;
484 
485  fGammaTkinCut = 0.0;
486 
487  // setting of min/max TR energies
488 
491 
494 
495  G4cout.precision(4);
496  G4Timer timer;
497  timer.Start();
498  if(verboseLevel > 0)
499  {
500  G4cout<<G4endl;
501  G4cout<<"Lorentz Factor"<<"\t"<<"XTR photon number"<<G4endl;
502  G4cout<<G4endl;
503  }
504  for( iTkin = 0; iTkin < fTotBin; iTkin++ ) // Lorentz factor loop
505  {
506 
507  fGamma = 1.0 + (fProtonEnergyVector->
508  GetLowEdgeEnergy(iTkin)/proton_mass_c2);
509 
510  fMaxThetaTR = 25.0/(fGamma*fGamma); // theta^2
511 
512  fTheMinAngle = 1.0e-3; // was 5.e-6, e-6 !!!, e-5, e-4
513 
515  else
516  {
518  }
519 
521 
522  for( iTR = 0; iTR < fBinTR; iTR++ )
523  {
524  // energy = fMinEnergyTR*(iTR+1);
525 
526  energy = fXTREnergyVector->GetLowEdgeEnergy(iTR);
527 
528  G4PhysicsFreeVector* angleVector = GetAngleVector(energy,fBinTR);
529  // G4cout<<G4endl;
530 
531  fAngleForEnergyTable->insertAt(iTR,angleVector);
532  }
533 
534  fAngleBank.push_back(fAngleForEnergyTable);
535  }
536  timer.Stop();
537  G4cout.precision(6);
538  if(verboseLevel > 0)
539  {
540  G4cout<<G4endl;
541  G4cout<<"total time for build XTR angle for given energy tables = "
542  <<timer.GetUserElapsed()<<" s"<<G4endl;
543  }
544  fGamma = 0.;
545 
546  return;
547 }
548 
550 //
551 // Vector of angles and angle integral distributions
552 
554 {
555  G4double theta=0., result, tmp=0., cof1, cof2, cofMin, cofPHC, angleSum = 0.;
556  G4int iTheta, k, /*kMax,*/ kMin;
557 
558  G4PhysicsFreeVector* angleVector = new G4PhysicsFreeVector(n);
559 
560  cofPHC = 4*pi*hbarc;
561  tmp = (fSigma1 - fSigma2)/cofPHC/energy;
562  cof1 = fPlateThick*tmp;
563  cof2 = fGasThick*tmp;
564 
565  cofMin = energy*(fPlateThick + fGasThick)/fGamma/fGamma;
566  cofMin += (fPlateThick*fSigma1 + fGasThick*fSigma2)/energy;
567  cofMin /= cofPHC;
568 
569  kMin = G4int(cofMin);
570  if (cofMin > kMin) kMin++;
571 
572  //kMax = kMin + fBinTR -1;
573 
574  if(verboseLevel > 2)
575  {
576  G4cout<<"n-1 = "<<n-1<<"; theta = "
577  <<std::sqrt(fMaxThetaTR)*fGamma<<"; tmp = "
578  <<0.
579  <<"; angleSum = "<<angleSum<<G4endl;
580  }
581  // angleVector->PutValue(n-1,fMaxThetaTR, angleSum);
582 
583  for( iTheta = n - 1; iTheta >= 1; iTheta-- )
584  {
585 
586  k = iTheta- 1 + kMin;
587 
588  tmp = pi*fPlateThick*(k + cof2)/(fPlateThick + fGasThick);
589 
590  result = (k - cof1)*(k - cof1)*(k + cof2)*(k + cof2);
591 
592  tmp = std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
593 
594  if( k == kMin && kMin == G4int(cofMin) )
595  {
596  angleSum += 0.5*tmp; // 0.5*std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
597  }
598  else if(iTheta == n-1);
599  else
600  {
601  angleSum += tmp; // std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result;
602  }
603  theta = std::abs(k-cofMin)*cofPHC/energy/(fPlateThick + fGasThick);
604 
605  if(verboseLevel > 2)
606  {
607  G4cout<<"iTheta = "<<iTheta<<"; k = "<<k<<"; theta = "
608  <<std::sqrt(theta)*fGamma<<"; tmp = "
609  <<tmp // std::sin(tmp)*std::sin(tmp)*std::abs(k-cofMin)/result
610  <<"; angleSum = "<<angleSum<<G4endl;
611  }
612  angleVector->PutValue( iTheta, theta, angleSum );
613  }
614  if (theta > 0.)
615  {
616  angleSum += 0.5*tmp;
617  theta = 0.;
618  }
619  if(verboseLevel > 2)
620  {
621  G4cout<<"iTheta = "<<iTheta<<"; theta = "
622  <<std::sqrt(theta)*fGamma<<"; tmp = "
623  <<tmp
624  <<"; angleSum = "<<angleSum<<G4endl;
625  }
626  angleVector->PutValue( iTheta, theta, angleSum );
627 
628  return angleVector;
629 }
630 
632 //
633 // Build XTR angular distribution based on the model of transparent regular radiator
634 
636 {
637  G4int iTkin, iTR, iPlace;
638  G4double radiatorCof = 1.0; // for tuning of XTR yield
639  G4double angleSum;
641 
642  fGammaTkinCut = 0.0;
643 
644  // setting of min/max TR energies
645 
648 
651 
652  G4cout.precision(4);
653  G4Timer timer;
654  timer.Start();
655  if(verboseLevel > 0) {
656  G4cout<<G4endl;
657  G4cout<<"Lorentz Factor"<<"\t"<<"XTR photon number"<<G4endl;
658  G4cout<<G4endl;
659  }
660  for( iTkin = 0; iTkin < fTotBin; iTkin++ ) // Lorentz factor loop
661  {
662 
663  fGamma = 1.0 + (fProtonEnergyVector->
664  GetLowEdgeEnergy(iTkin)/proton_mass_c2);
665 
666  fMaxThetaTR = 25.0/(fGamma*fGamma); // theta^2
667 
668  fTheMinAngle = 1.0e-3; // was 5.e-6, e-6 !!!, e-5, e-4
669 
671  else
672  {
674  }
675  G4PhysicsLinearVector* angleVector = new G4PhysicsLinearVector(0.0,
676  fMaxThetaTR,
677  fBinTR );
678 
679  angleSum = 0.0;
680 
682 
683 
684  angleVector->PutValue(fBinTR-1,angleSum);
685 
686  for( iTR = fBinTR - 2; iTR >= 0; iTR-- )
687  {
688 
689  angleSum += radiatorCof*fCofTR*integral.Legendre96(
691  angleVector->GetLowEdgeEnergy(iTR),
692  angleVector->GetLowEdgeEnergy(iTR+1) );
693 
694  angleVector ->PutValue(iTR,angleSum);
695  }
696  if(verboseLevel > 1) {
697  G4cout
698  // <<iTkin<<"\t"
699  // <<"fGamma = "
700  <<fGamma<<"\t" // <<" fMaxThetaTR = "<<fMaxThetaTR
701  // <<"sumN = "<<energySum // <<"; sumA = "
702  <<angleSum
703  <<G4endl;
704  }
705  iPlace = iTkin;
706  fAngleDistrTable->insertAt(iPlace,angleVector);
707  }
708  timer.Stop();
709  G4cout.precision(6);
710  if(verboseLevel > 0) {
711  G4cout<<G4endl;
712  G4cout<<"total time for build X-ray TR angle tables = "
713  <<timer.GetUserElapsed()<<" s"<<G4endl;
714  }
715  fGamma = 0.;
716 
717  return;
718 }
719 
720 
722 //
723 // The main function which is responsible for the treatment of a particle passage
724 // trough G4Envelope with discrete generation of G4Gamma
725 
727  const G4Step& aStep )
728 {
729  G4int iTkin /*, iPlace*/;
730  G4double energyTR, theta,theta2, phi, dirX, dirY, dirZ;
731 
732 
733  fParticleChange.Initialize(aTrack);
734 
735  if(verboseLevel > 1)
736  {
737  G4cout<<"Start of G4VXTRenergyLoss::PostStepDoIt "<<G4endl;
738  G4cout<<"name of current material = "
739  <<aTrack.GetVolume()->GetLogicalVolume()->GetMaterial()->GetName()<<G4endl;
740  }
741  if( aTrack.GetVolume()->GetLogicalVolume() != fEnvelope )
742  {
743  if(verboseLevel > 0)
744  {
745  G4cout<<"Go out from G4VXTRenergyLoss::PostStepDoIt: wrong volume "<<G4endl;
746  }
747  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
748  }
749  else
750  {
751  G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
752  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
753 
754  // Now we are ready to Generate one TR photon
755 
756  G4double kinEnergy = aParticle->GetKineticEnergy();
757  G4double mass = aParticle->GetDefinition()->GetPDGMass();
758  G4double gamma = 1.0 + kinEnergy/mass;
759 
760  if(verboseLevel > 1 )
761  {
762  G4cout<<"gamma = "<<gamma<<G4endl;
763  }
764  G4double massRatio = proton_mass_c2/mass;
765  G4double TkinScaled = kinEnergy*massRatio;
766  G4ThreeVector position = pPostStepPoint->GetPosition();
767  G4ParticleMomentum direction = aParticle->GetMomentumDirection();
768  G4double startTime = pPostStepPoint->GetGlobalTime();
769 
770  for( iTkin = 0; iTkin < fTotBin; iTkin++ )
771  {
772  if(TkinScaled < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break;
773  }
774  //iPlace = iTkin - 1;
775 
776  if(iTkin == 0) // Tkin is too small, neglect of TR photon generation
777  {
778  if( verboseLevel > 0)
779  {
780  G4cout<<"Go out from G4VXTRenergyLoss::PostStepDoIt:iTkin = "<<iTkin<<G4endl;
781  }
782  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
783  }
784  else // general case: Tkin between two vectors of the material
785  {
787 
788  energyTR = GetXTRrandomEnergy(TkinScaled,iTkin);
789 
790  if( verboseLevel > 1)
791  {
792  G4cout<<"energyTR = "<<energyTR/keV<<" keV"<<G4endl;
793  }
794  if (fAngleRadDistr)
795  {
796  // theta = std::fabs(G4RandGauss::shoot(0.0,pi/gamma));
797  theta2 = GetRandomAngle(energyTR,iTkin);
798  if(theta2 > 0.) theta = std::sqrt(theta2);
799  else theta = 0.; // theta2;
800  }
801  else theta = std::fabs(G4RandGauss::shoot(0.0,pi/gamma));
802 
803  // theta = 0.; // check no spread
804 
805  if( theta >= 0.1 ) theta = 0.1;
806 
807  // G4cout<<" : theta = "<<theta<<endl;
808 
809  phi = twopi*G4UniformRand();
810 
811  dirX = std::sin(theta)*std::cos(phi);
812  dirY = std::sin(theta)*std::sin(phi);
813  dirZ = std::cos(theta);
814 
815  G4ThreeVector directionTR(dirX,dirY,dirZ);
816  directionTR.rotateUz(direction);
817  directionTR.unit();
818 
820  directionTR, energyTR);
821 
822  // A XTR photon is set on the particle track inside the radiator
823  // and is moved to the G4Envelope surface for standard X-ray TR models
824  // only. The case of fExitFlux=true
825 
826  if( fExitFlux )
827  {
828  const G4RotationMatrix* rotM = pPostStepPoint->GetTouchable()->GetRotation();
829  G4ThreeVector transl = pPostStepPoint->GetTouchable()->GetTranslation();
830  G4AffineTransform transform = G4AffineTransform(rotM,transl);
831  transform.Invert();
832  G4ThreeVector localP = transform.TransformPoint(position);
833  G4ThreeVector localV = transform.TransformAxis(directionTR);
834 
835  G4double distance = fEnvelope->GetSolid()->DistanceToOut(localP, localV);
836  if(verboseLevel > 1)
837  {
838  G4cout<<"distance to exit = "<<distance/mm<<" mm"<<G4endl;
839  }
840  position += distance*directionTR;
841  startTime += distance/c_light;
842  }
843  G4Track* aSecondaryTrack = new G4Track( aPhotonTR,
844  startTime, position );
845  aSecondaryTrack->SetTouchableHandle(
847  aSecondaryTrack->SetParentID( aTrack.GetTrackID() );
848 
849  fParticleChange.AddSecondary(aSecondaryTrack);
850  fParticleChange.ProposeEnergy(kinEnergy);
851  }
852  }
853  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
854 }
855 
857 //
858 // This function returns the spectral and angle density of TR quanta
859 // in X-ray energy region generated forward when a relativistic
860 // charged particle crosses interface between two materials.
861 // The high energy small theta approximation is applied.
862 // (matter1 -> matter2, or 2->1)
863 // varAngle =2* (1 - std::cos(theta)) or approximately = theta*theta
864 //
865 
867  G4double gamma,
868  G4double varAngle )
869 {
870  G4complex Z1 = GetPlateComplexFZ(energy,gamma,varAngle);
871  G4complex Z2 = GetGasComplexFZ(energy,gamma,varAngle);
872 
873  G4complex zOut = (Z1 - Z2)*(Z1 - Z2)
874  * (varAngle*energy/hbarc/hbarc);
875  return zOut;
876 
877 }
878 
879 
881 //
882 // For photon energy distribution tables. Integrate first over angle
883 //
884 
886 {
887  G4double result = GetStackFactor(fEnergy,fGamma,varAngle);
888  if(result < 0.0) result = 0.0;
889  return result;
890 }
891 
893 //
894 // For second integration over energy
895 
897 {
898  G4int i, iMax = 8;
899  G4double angleSum = 0.0;
900 
901  G4double lim[8] = { 0.0, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0 };
902 
903  for( i = 0; i < iMax; i++ ) lim[i] *= fMaxThetaTR;
904 
906 
907  fEnergy = energy;
908  /*
909  if( fAngleRadDistr && ( fEnergy == fEnergyForAngle ) )
910  {
911  fAngleVector ->PutValue(fBinTR - 1, angleSum);
912 
913  for( i = fBinTR - 2; i >= 0; i-- )
914  {
915 
916  angleSum += integral.Legendre10(
917  this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
918  fAngleVector->GetLowEdgeEnergy(i),
919  fAngleVector->GetLowEdgeEnergy(i+1) );
920 
921  fAngleVector ->PutValue(i, angleSum);
922  }
923  }
924  else
925  */
926  {
927  for( i = 0; i < iMax-1; i++ )
928  {
929  angleSum += integral.Legendre96(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
930  lim[i],lim[i+1]);
931  // result += integral.Legendre10(this,&G4VXTRenergyLoss::SpectralAngleXTRdEdx,
932  // lim[i],lim[i+1]);
933  }
934  }
935  return angleSum;
936 }
937 
939 //
940 // for photon angle distribution tables
941 //
942 
944 {
945  G4double result = GetStackFactor(energy,fGamma,fVarAngle);
946  if(result < 0) result = 0.0;
947  return result;
948 }
949 
951 //
952 // The XTR angular distribution based on transparent regular radiator
953 
955 {
956  // G4cout<<"angle2 = "<<varAngle<<"; fGamma = "<<fGamma<<G4endl;
957 
958  G4double result;
959  G4double sum = 0., tmp1, tmp2, tmp=0., cof1, cof2, cofMin, cofPHC, energy1, energy2;
960  G4int k, kMax, kMin, i;
961 
962  cofPHC = twopi*hbarc;
963 
964  cof1 = (fPlateThick + fGasThick)*(1./fGamma/fGamma + varAngle);
966 
967  // G4cout<<"cof1 = "<<cof1<<"; cof2 = "<<cof2<<"; cofPHC = "<<cofPHC<<G4endl;
968 
969  cofMin = std::sqrt(cof1*cof2);
970  cofMin /= cofPHC;
971 
972  kMin = G4int(cofMin);
973  if (cofMin > kMin) kMin++;
974 
975  kMax = kMin + 9; // 9; // kMin + G4int(tmp);
976 
977  // G4cout<<"cofMin = "<<cofMin<<"; kMin = "<<kMin<<"; kMax = "<<kMax<<G4endl;
978 
979  for( k = kMin; k <= kMax; k++ )
980  {
981  tmp1 = cofPHC*k;
982  tmp2 = std::sqrt(tmp1*tmp1-cof1*cof2);
983  energy1 = (tmp1+tmp2)/cof1;
984  energy2 = (tmp1-tmp2)/cof1;
985 
986  for(i = 0; i < 2; i++)
987  {
988  if( i == 0 )
989  {
990  if (energy1 > fTheMaxEnergyTR || energy1 < fTheMinEnergyTR) continue;
991  tmp1 = ( energy1*energy1*(1./fGamma/fGamma + varAngle) + fSigma1 )
992  * fPlateThick/(4*hbarc*energy1);
993  tmp2 = std::sin(tmp1);
994  tmp = energy1*tmp2*tmp2;
995  tmp2 = fPlateThick/(4*tmp1);
996  tmp1 = hbarc*energy1/( energy1*energy1*(1./fGamma/fGamma + varAngle) + fSigma2 );
997  tmp *= (tmp1-tmp2)*(tmp1-tmp2);
998  tmp1 = cof1/(4*hbarc) - cof2/(4*hbarc*energy1*energy1);
999  tmp2 = std::abs(tmp1);
1000  if(tmp2 > 0.) tmp /= tmp2;
1001  else continue;
1002  }
1003  else
1004  {
1005  if (energy2 > fTheMaxEnergyTR || energy2 < fTheMinEnergyTR) continue;
1006  tmp1 = ( energy2*energy2*(1./fGamma/fGamma + varAngle) + fSigma1 )
1007  * fPlateThick/(4*hbarc*energy2);
1008  tmp2 = std::sin(tmp1);
1009  tmp = energy2*tmp2*tmp2;
1010  tmp2 = fPlateThick/(4*tmp1);
1011  tmp1 = hbarc*energy2/( energy2*energy2*(1./fGamma/fGamma + varAngle) + fSigma2 );
1012  tmp *= (tmp1-tmp2)*(tmp1-tmp2);
1013  tmp1 = cof1/(4*hbarc) - cof2/(4*hbarc*energy2*energy2);
1014  tmp2 = std::abs(tmp1);
1015  if(tmp2 > 0.) tmp /= tmp2;
1016  else continue;
1017  }
1018  sum += tmp;
1019  }
1020  // G4cout<<"k = "<<k<<"; energy1 = "<<energy1/keV<<" keV; energy2 = "<<energy2/keV
1021  // <<" keV; tmp = "<<tmp<<"; sum = "<<sum<<G4endl;
1022  }
1023  result = 4.*pi*fPlateNumber*sum*varAngle;
1024  result /= hbarc*hbarc;
1025 
1026  // old code based on general numeric integration
1027  // fVarAngle = varAngle;
1028  // G4Integrator<G4VXTRenergyLoss,G4double(G4VXTRenergyLoss::*)(G4double)> integral;
1029  // result = integral.Legendre10(this,&G4VXTRenergyLoss::AngleSpectralXTRdEdx,
1030  // fMinEnergyTR,fMaxEnergyTR);
1031  return result;
1032 }
1033 
1034 
1038 //
1039 // Calculates formation zone for plates. Omega is energy !!!
1040 
1042  G4double gamma ,
1043  G4double varAngle )
1044 {
1045  G4double cof, lambda;
1046  lambda = 1.0/gamma/gamma + varAngle + fSigma1/omega/omega;
1047  cof = 2.0*hbarc/omega/lambda;
1048  return cof;
1049 }
1050 
1052 //
1053 // Calculates complex formation zone for plates. Omega is energy !!!
1054 
1056  G4double gamma ,
1057  G4double varAngle )
1058 {
1059  G4double cof, length,delta, real_v, image_v;
1060 
1061  length = 0.5*GetPlateFormationZone(omega,gamma,varAngle);
1062  delta = length*GetPlateLinearPhotoAbs(omega);
1063  cof = 1.0/(1.0 + delta*delta);
1064 
1065  real_v = length*cof;
1066  image_v = real_v*delta;
1067 
1068  G4complex zone(real_v,image_v);
1069  return zone;
1070 }
1071 
1073 //
1074 // Computes matrix of Sandia photo absorption cross section coefficients for
1075 // plate material
1076 
1078 {
1079  const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
1080  const G4Material* mat = (*theMaterialTable)[fMatIndex1];
1082 
1083  return;
1084 }
1085 
1086 
1087 
1089 //
1090 // Returns the value of linear photo absorption coefficient (in reciprocal
1091 // length) for plate for given energy of X-ray photon omega
1092 
1094 {
1095  // G4int i;
1096  G4double omega2, omega3, omega4;
1097 
1098  omega2 = omega*omega;
1099  omega3 = omega2*omega;
1100  omega4 = omega2*omega2;
1101 
1102  const G4double* SandiaCof = fPlatePhotoAbsCof->GetSandiaCofForMaterial(omega);
1103  G4double cross = SandiaCof[0]/omega + SandiaCof[1]/omega2 +
1104  SandiaCof[2]/omega3 + SandiaCof[3]/omega4;
1105  return cross;
1106 }
1107 
1108 
1110 //
1111 // Calculates formation zone for gas. Omega is energy !!!
1112 
1114  G4double gamma ,
1115  G4double varAngle )
1116 {
1117  G4double cof, lambda;
1118  lambda = 1.0/gamma/gamma + varAngle + fSigma2/omega/omega;
1119  cof = 2.0*hbarc/omega/lambda;
1120  return cof;
1121 }
1122 
1123 
1125 //
1126 // Calculates complex formation zone for gas gaps. Omega is energy !!!
1127 
1129  G4double gamma ,
1130  G4double varAngle )
1131 {
1132  G4double cof, length,delta, real_v, image_v;
1133 
1134  length = 0.5*GetGasFormationZone(omega,gamma,varAngle);
1135  delta = length*GetGasLinearPhotoAbs(omega);
1136  cof = 1.0/(1.0 + delta*delta);
1137 
1138  real_v = length*cof;
1139  image_v = real_v*delta;
1140 
1141  G4complex zone(real_v,image_v);
1142  return zone;
1143 }
1144 
1145 
1146 
1148 //
1149 // Computes matrix of Sandia photo absorption cross section coefficients for
1150 // gas material
1151 
1153 {
1154  const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
1155  const G4Material* mat = (*theMaterialTable)[fMatIndex2];
1157  return;
1158 }
1159 
1161 //
1162 // Returns the value of linear photo absorption coefficient (in reciprocal
1163 // length) for gas
1164 
1166 {
1167  G4double omega2, omega3, omega4;
1168 
1169  omega2 = omega*omega;
1170  omega3 = omega2*omega;
1171  omega4 = omega2*omega2;
1172 
1173  const G4double* SandiaCof = fGasPhotoAbsCof->GetSandiaCofForMaterial(omega);
1174  G4double cross = SandiaCof[0]/omega + SandiaCof[1]/omega2 +
1175  SandiaCof[2]/omega3 + SandiaCof[3]/omega4;
1176  return cross;
1177 
1178 }
1179 
1181 //
1182 // Calculates the product of linear cof by formation zone for plate.
1183 // Omega is energy !!!
1184 
1186  G4double gamma ,
1187  G4double varAngle )
1188 {
1189  return GetPlateFormationZone(omega,gamma,varAngle)
1190  * GetPlateLinearPhotoAbs(omega);
1191 }
1193 //
1194 // Calculates the product of linear cof by formation zone for plate.
1195 // G4cout and output in file in some energy range.
1196 
1198 {
1199  std::ofstream outPlate("plateZmu.dat", std::ios::out );
1200  outPlate.setf( std::ios::scientific, std::ios::floatfield );
1201 
1202  G4int i;
1203  G4double omega, varAngle, gamma;
1204  gamma = 10000.;
1205  varAngle = 1/gamma/gamma;
1206  if(verboseLevel > 0)
1207  G4cout<<"energy, keV"<<"\t"<<"Zmu for plate"<<G4endl;
1208  for(i=0;i<100;i++)
1209  {
1210  omega = (1.0 + i)*keV;
1211  if(verboseLevel > 1)
1212  G4cout<<omega/keV<<"\t"<<GetPlateZmuProduct(omega,gamma,varAngle)<<"\t";
1213  if(verboseLevel > 0)
1214  outPlate<<omega/keV<<"\t\t"<<GetPlateZmuProduct(omega,gamma,varAngle)<<G4endl;
1215  }
1216  return;
1217 }
1218 
1220 //
1221 // Calculates the product of linear cof by formation zone for gas.
1222 // Omega is energy !!!
1223 
1225  G4double gamma ,
1226  G4double varAngle )
1227 {
1228  return GetGasFormationZone(omega,gamma,varAngle)*GetGasLinearPhotoAbs(omega);
1229 }
1231 //
1232 // Calculates the product of linear cof byformation zone for gas.
1233 // G4cout and output in file in some energy range.
1234 
1236 {
1237  std::ofstream outGas("gasZmu.dat", std::ios::out );
1238  outGas.setf( std::ios::scientific, std::ios::floatfield );
1239  G4int i;
1240  G4double omega, varAngle, gamma;
1241  gamma = 10000.;
1242  varAngle = 1/gamma/gamma;
1243  if(verboseLevel > 0)
1244  G4cout<<"energy, keV"<<"\t"<<"Zmu for gas"<<G4endl;
1245  for(i=0;i<100;i++)
1246  {
1247  omega = (1.0 + i)*keV;
1248  if(verboseLevel > 1)
1249  G4cout<<omega/keV<<"\t"<<GetGasZmuProduct(omega,gamma,varAngle)<<"\t";
1250  if(verboseLevel > 0)
1251  outGas<<omega/keV<<"\t\t"<<GetGasZmuProduct(omega,gamma,varAngle)<<G4endl;
1252  }
1253  return;
1254 }
1255 
1257 //
1258 // Computes Compton cross section for plate material in 1/mm
1259 
1261 {
1262  G4int i, numberOfElements;
1263  G4double xSection = 0., nowZ, sumZ = 0.;
1264 
1265  const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
1266  numberOfElements = (*theMaterialTable)[fMatIndex1]->GetNumberOfElements();
1267 
1268  for( i = 0; i < numberOfElements; i++ )
1269  {
1270  nowZ = (*theMaterialTable)[fMatIndex1]->GetElement(i)->GetZ();
1271  sumZ += nowZ;
1272  xSection += GetComptonPerAtom(omega,nowZ); // *nowZ;
1273  }
1274  xSection /= sumZ;
1275  xSection *= (*theMaterialTable)[fMatIndex1]->GetElectronDensity();
1276  return xSection;
1277 }
1278 
1279 
1281 //
1282 // Computes Compton cross section for gas material in 1/mm
1283 
1285 {
1286  G4int i, numberOfElements;
1287  G4double xSection = 0., nowZ, sumZ = 0.;
1288 
1289  const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
1290  numberOfElements = (*theMaterialTable)[fMatIndex2]->GetNumberOfElements();
1291 
1292  for( i = 0; i < numberOfElements; i++ )
1293  {
1294  nowZ = (*theMaterialTable)[fMatIndex2]->GetElement(i)->GetZ();
1295  sumZ += nowZ;
1296  xSection += GetComptonPerAtom(omega,nowZ); // *nowZ;
1297  }
1298  xSection /= sumZ;
1299  xSection *= (*theMaterialTable)[fMatIndex2]->GetElectronDensity();
1300  return xSection;
1301 }
1302 
1304 //
1305 // Computes Compton cross section per atom with Z electrons for gamma with
1306 // the energy GammaEnergy
1307 
1309 {
1310  G4double CrossSection = 0.0;
1311  if ( Z < 0.9999 ) return CrossSection;
1312  if ( GammaEnergy < 0.1*keV ) return CrossSection;
1313  if ( GammaEnergy > (100.*GeV/Z) ) return CrossSection;
1314 
1315  static const G4double a = 20.0 , b = 230.0 , c = 440.0;
1316 
1317  static const G4double
1318  d1= 2.7965e-1*barn, d2=-1.8300e-1*barn, d3= 6.7527 *barn, d4=-1.9798e+1*barn,
1319  e1= 1.9756e-5*barn, e2=-1.0205e-2*barn, e3=-7.3913e-2*barn, e4= 2.7079e-2*barn,
1320  f1=-3.9178e-7*barn, f2= 6.8241e-5*barn, f3= 6.0480e-5*barn, f4= 3.0274e-4*barn;
1321 
1322  G4double p1Z = Z*(d1 + e1*Z + f1*Z*Z), p2Z = Z*(d2 + e2*Z + f2*Z*Z),
1323  p3Z = Z*(d3 + e3*Z + f3*Z*Z), p4Z = Z*(d4 + e4*Z + f4*Z*Z);
1324 
1325  G4double T0 = 15.0*keV;
1326  if (Z < 1.5) T0 = 40.0*keV;
1327 
1328  G4double X = std::max(GammaEnergy, T0) / electron_mass_c2;
1329  CrossSection = p1Z*std::log(1.+2.*X)/X
1330  + (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
1331 
1332  // modification for low energy. (special case for Hydrogen)
1333 
1334  if (GammaEnergy < T0)
1335  {
1336  G4double dT0 = 1.*keV;
1337  X = (T0+dT0) / electron_mass_c2;
1338  G4double sigma = p1Z*std::log(1.+2*X)/X
1339  + (p2Z + p3Z*X + p4Z*X*X)/(1. + a*X + b*X*X + c*X*X*X);
1340  G4double c1 = -T0*(sigma-CrossSection)/(CrossSection*dT0);
1341  G4double c2 = 0.150;
1342  if (Z > 1.5) c2 = 0.375-0.0556*std::log(Z);
1343  G4double y = std::log(GammaEnergy/T0);
1344  CrossSection *= std::exp(-y*(c1+c2*y));
1345  }
1346  // G4cout << "e= " << GammaEnergy << " Z= " << Z << " cross= " << CrossSection << G4endl;
1347  return CrossSection;
1348 }
1349 
1350 
1352 //
1353 // This function returns the spectral and angle density of TR quanta
1354 // in X-ray energy region generated forward when a relativistic
1355 // charged particle crosses interface between two materials.
1356 // The high energy small theta approximation is applied.
1357 // (matter1 -> matter2, or 2->1)
1358 // varAngle =2* (1 - std::cos(theta)) or approximately = theta*theta
1359 //
1360 
1361 G4double
1363  G4double varAngle ) const
1364 {
1365  G4double formationLength1, formationLength2;
1366  formationLength1 = 1.0/
1367  (1.0/(gamma*gamma)
1368  + fSigma1/(energy*energy)
1369  + varAngle);
1370  formationLength2 = 1.0/
1371  (1.0/(gamma*gamma)
1372  + fSigma2/(energy*energy)
1373  + varAngle);
1374  return (varAngle/energy)*(formationLength1 - formationLength2)
1375  *(formationLength1 - formationLength2);
1376 
1377 }
1378 
1380  G4double varAngle )
1381 {
1382  // return stack factor corresponding to one interface
1383 
1384  return std::real( OneInterfaceXTRdEdx(energy,gamma,varAngle) );
1385 }
1386 
1388 //
1389 // For photon energy distribution tables. Integrate first over angle
1390 //
1391 
1393 {
1394  return OneBoundaryXTRNdensity(fEnergy,fGamma,varAngle)*
1395  GetStackFactor(fEnergy,fGamma,varAngle);
1396 }
1397 
1399 //
1400 // For second integration over energy
1401 
1403 {
1404  fEnergy = energy;
1407  0.0,0.2*fMaxThetaTR) +
1409  0.2*fMaxThetaTR,fMaxThetaTR);
1410 }
1411 
1413 //
1414 // for photon angle distribution tables
1415 //
1416 
1418 {
1419  return OneBoundaryXTRNdensity(energy,fGamma,fVarAngle)*
1421 }
1422 
1424 //
1425 //
1426 
1428 {
1429  fVarAngle = varAngle;
1433 }
1434 
1436 //
1437 // Check number of photons for a range of Lorentz factors from both energy
1438 // and angular tables
1439 
1441 {
1442  G4int iTkin;
1443  G4double gamma, numberE;
1444 
1445  std::ofstream outEn("numberE.dat", std::ios::out );
1446  outEn.setf( std::ios::scientific, std::ios::floatfield );
1447 
1448  std::ofstream outAng("numberAng.dat", std::ios::out );
1449  outAng.setf( std::ios::scientific, std::ios::floatfield );
1450 
1451  for(iTkin=0;iTkin<fTotBin;iTkin++) // Lorentz factor loop
1452  {
1453  gamma = 1.0 + (fProtonEnergyVector->
1454  GetLowEdgeEnergy(iTkin)/proton_mass_c2);
1455  numberE = (*(*fEnergyDistrTable)(iTkin))(0);
1456  // numberA = (*(*fAngleDistrTable)(iTkin))(0);
1457  if(verboseLevel > 1)
1458  G4cout<<gamma<<"\t\t"<<numberE<<"\t" // <<numberA
1459  <<G4endl;
1460  if(verboseLevel > 0)
1461  outEn<<gamma<<"\t\t"<<numberE<<G4endl;
1462  }
1463  return;
1464 }
1465 
1467 //
1468 // Returns randon energy of a X-ray TR photon for given scaled kinetic energy
1469 // of a charged particle
1470 
1472 {
1473  G4int iTransfer, iPlace;
1474  G4double transfer = 0.0, position, E1, E2, W1, W2, W;
1475 
1476  iPlace = iTkin - 1;
1477 
1478  // G4cout<<"iPlace = "<<iPlace<<endl;
1479 
1480  if(iTkin == fTotBin) // relativistic plato, try from left
1481  {
1482  position = (*(*fEnergyDistrTable)(iPlace))(0)*G4UniformRand();
1483 
1484  for(iTransfer=0;;iTransfer++)
1485  {
1486  if(position >= (*(*fEnergyDistrTable)(iPlace))(iTransfer)) break;
1487  }
1488  transfer = GetXTRenergy(iPlace,position,iTransfer);
1489  }
1490  else
1491  {
1492  E1 = fProtonEnergyVector->GetLowEdgeEnergy(iTkin - 1);
1494  W = 1.0/(E2 - E1);
1495  W1 = (E2 - scaledTkin)*W;
1496  W2 = (scaledTkin - E1)*W;
1497 
1498  position =( (*(*fEnergyDistrTable)(iPlace))(0)*W1 +
1499  (*(*fEnergyDistrTable)(iPlace+1))(0)*W2 )*G4UniformRand();
1500 
1501  // G4cout<<position<<"\t";
1502 
1503  for(iTransfer=0;;iTransfer++)
1504  {
1505  if( position >=
1506  ( (*(*fEnergyDistrTable)(iPlace))(iTransfer)*W1 +
1507  (*(*fEnergyDistrTable)(iPlace+1))(iTransfer)*W2) ) break;
1508  }
1509  transfer = GetXTRenergy(iPlace,position,iTransfer);
1510 
1511  }
1512  // G4cout<<"XTR transfer = "<<transfer/keV<<" keV"<<endl;
1513  if(transfer < 0.0 ) transfer = 0.0;
1514  return transfer;
1515 }
1516 
1518 //
1519 // Returns approximate position of X-ray photon energy during random sampling
1520 // over integral energy distribution
1521 
1523  G4double /* position */,
1524  G4int iTransfer )
1525 {
1526  G4double x1, x2, y1, y2, result;
1527 
1528  if(iTransfer == 0)
1529  {
1530  result = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1531  }
1532  else
1533  {
1534  y1 = (*(*fEnergyDistrTable)(iPlace))(iTransfer-1);
1535  y2 = (*(*fEnergyDistrTable)(iPlace))(iTransfer);
1536 
1537  x1 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1);
1538  x2 = (*fEnergyDistrTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1539 
1540  if ( x1 == x2 ) result = x2;
1541  else
1542  {
1543  if ( y1 == y2 ) result = x1 + (x2 - x1)*G4UniformRand();
1544  else
1545  {
1546  // result = x1 + (position - y1)*(x2 - x1)/(y2 - y1);
1547  result = x1 + (x2 - x1)*G4UniformRand();
1548  }
1549  }
1550  }
1551  return result;
1552 }
1553 
1555 //
1556 // Get XTR photon angle at given energy and Tkin
1557 
1559 {
1560  G4int iTR, iAngle;
1561  G4double position, angle;
1562 
1563  if (iTkin == fTotBin) iTkin--;
1564 
1566 
1567  for( iTR = 0; iTR < fBinTR; iTR++ )
1568  {
1569  if( energyXTR < fXTREnergyVector->GetLowEdgeEnergy(iTR) ) break;
1570  }
1571  if (iTR == fBinTR) iTR--;
1572 
1573  position = (*(*fAngleForEnergyTable)(iTR))(0)*G4UniformRand();
1574 
1575  for(iAngle = 0;;iAngle++)
1576  {
1577  if(position >= (*(*fAngleForEnergyTable)(iTR))(iAngle)) break;
1578  }
1579  angle = GetAngleXTR(iTR,position,iAngle);
1580  return angle;
1581 }
1582 
1584 //
1585 // Returns approximate position of X-ray photon angle at given energy during random sampling
1586 // over integral energy distribution
1587 
1589  G4double position,
1590  G4int iTransfer )
1591 {
1592  G4double x1, x2, y1, y2, result;
1593 
1594  if(iTransfer == 0)
1595  {
1596  result = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1597  }
1598  else
1599  {
1600  y1 = (*(*fAngleForEnergyTable)(iPlace))(iTransfer-1);
1601  y2 = (*(*fAngleForEnergyTable)(iPlace))(iTransfer);
1602 
1603  x1 = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1);
1604  x2 = (*fAngleForEnergyTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1605 
1606  if ( x1 == x2 ) result = x2;
1607  else
1608  {
1609  if ( y1 == y2 ) result = x1 + (x2 - x1)*G4UniformRand();
1610  else
1611  {
1612  result = x1 + (position - y1)*(x2 - x1)/(y2 - y1);
1613  }
1614  }
1615  }
1616  return result;
1617 }
1618 
1619 
1620 //
1621 //
1623 
static const G4double d3
static const double cm
Definition: G4SIunits.hh:106
G4double condition(const G4ErrorSymMatrix &m)
G4double Legendre10(T &typeT, F f, G4double a, G4double b)
G4double GetXTRrandomEnergy(G4double scaledTkin, G4int iTkin)
G4PhysicsTable * fEnergyDistrTable
ThreeVector shoot(const G4int Ap, const G4int Af)
static c2_factory< G4double > c2
static const G4double d1
G4double GetGasFormationZone(G4double, G4double, G4double)
G4double Legendre96(T &typeT, F f, G4double a, G4double b)
G4int verboseLevel
Definition: G4VProcess.hh:368
void PutValue(size_t binNumber, G4double binValue, G4double dataValue)
static const G4double f2
G4double GetKineticEnergy() const
CLHEP::Hep3Vector G4ThreeVector
G4double GetPlateLinearPhotoAbs(G4double)
G4double XTRNSpectralDensity(G4double energy)
CLHEP::HepRotation G4RotationMatrix
const G4DynamicParticle * GetDynamicParticle() const
G4LogicalVolume * fEnvelope
G4double GetPlateCompton(G4double)
G4Material * GetMaterial() const
size_t GetIndex() const
Definition: G4Material.hh:262
G4double GetSandiaCofForMaterial(G4int, G4int) const
const G4String & GetName() const
Definition: G4Material.hh:178
const G4double pi
G4double GetGasLinearPhotoAbs(G4double)
static G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:588
std::vector< G4Material * > G4MaterialTable
static const G4double e2
void SetTouchableHandle(const G4TouchableHandle &apValue)
G4ParticleDefinition * GetDefinition() const
G4double a
Definition: TRTMaterials.hh:39
const G4VTouchable * GetTouchable() const
G4double GetLowEdgeEnergy(size_t binNumber) const
static const G4double e4
int G4int
Definition: G4Types.hh:78
G4double GetPlateFormationZone(G4double, G4double, G4double)
G4double GetComptonPerAtom(G4double, G4double)
G4complex GetPlateComplexFZ(G4double, G4double, G4double)
G4SandiaTable * GetSandiaTable() const
Definition: G4Material.hh:229
G4AffineTransform & Invert()
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
std::complex< G4double > G4complex
Definition: G4Types.hh:81
#define position
Definition: xmlparse.cc:605
#define G4UniformRand()
Definition: Randomize.hh:93
G4GLOB_DLL std::ostream G4cout
G4PhysicsLogVector * fProtonEnergyVector
const G4ThreeVector & GetPosition() const
G4double GetElectronDensity() const
Definition: G4Material.hh:217
G4double GetXTRenergy(G4int iPlace, G4double position, G4int iTransfer)
bool G4bool
Definition: G4Types.hh:79
const G4ThreeVector & GetMomentumDirection() const
G4double GetUserElapsed() const
Definition: G4Timer.cc:130
static const G4double f4
void PutValue(size_t index, G4double theValue)
void BuildPhysicsTable(const G4ParticleDefinition &)
G4double OneBoundaryXTRNdensity(G4double energy, G4double gamma, G4double varAngle) const
static const double GeV
Definition: G4SIunits.hh:196
Definition: G4Step.hh:76
G4double XTRNSpectralAngleDensity(G4double varAngle)
G4int GetTrackID() const
const G4int n
static const G4double c1
static G4Gamma * Gamma()
Definition: G4Gamma.cc:86
static const G4double f1
const G4String & GetProcessName() const
Definition: G4VProcess.hh:408
static const G4double e1
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4PhysicsFreeVector * GetAngleVector(G4double energy, G4int n)
virtual void Initialize(const G4Track &)
static const double eV
Definition: G4SIunits.hh:194
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4SandiaTable * fGasPhotoAbsCof
virtual const G4ThreeVector & GetTranslation(G4int depth=0) const =0
static const G4double f3
G4LogicalVolume * GetLogicalVolume() const
G4double GetPDGMass() const
G4double GetAngleXTR(G4int iTR, G4double position, G4int iAngle)
T max(const T t1, const T t2)
brief Return the largest of the two arguments
G4double energy(const ThreeVector &p, const G4double m)
void SetNumberOfSecondaries(G4int totSecondaries)
void Stop()
void SetParentID(const G4int aValue)
G4StepPoint * GetPostStepPoint() const
virtual ~G4VXTRenergyLoss()
G4ThreeVector TransformAxis(const G4ThreeVector &axis) const
G4double SpectralAngleXTRdEdx(G4double varAngle)
virtual G4double SpectralXTRdEdx(G4double energy)
G4bool IsApplicable(const G4ParticleDefinition &)
G4VParticleChange * pParticleChange
Definition: G4VProcess.hh:283
G4PhysicsLogVector * fXTREnergyVector
void ProposeEnergy(G4double finalEnergy)
#define DBL_MIN
Definition: templates.hh:75
G4VXTRenergyLoss(G4LogicalVolume *anEnvelope, G4Material *, G4Material *, G4double, G4double, G4int, const G4String &processName="XTRenergyLoss", G4ProcessType type=fElectromagnetic)
G4VPhysicalVolume * GetVolume() const
std::vector< G4PhysicsTable * > fAngleBank
void AddSecondary(G4Track *aSecondary)
void insertAt(size_t, G4PhysicsVector *)
G4double GetRandomAngle(G4double energyXTR, G4int iTkin)
G4complex OneInterfaceXTRdEdx(G4double energy, G4double gamma, G4double varAngle)
G4PhysicsTable * fAngleForEnergyTable
#define G4endl
Definition: G4ios.hh:61
G4double GetGlobalTime() const
G4double GetGasCompton(G4double)
G4PhysicsTable * fAngleDistrTable
static const double TeV
Definition: G4SIunits.hh:197
static const double barn
Definition: G4SIunits.hh:95
static const double keV
Definition: G4SIunits.hh:195
G4SandiaTable * fPlatePhotoAbsCof
void Start()
G4double XTRNAngleDensity(G4double varAngle)
G4complex GetGasComplexFZ(G4double, G4double, G4double)
double G4double
Definition: G4Types.hh:76
G4ParticleDefinition * fPtrGamma
G4ParticleChange fParticleChange
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
G4double GetMeanFreePath(const G4Track &aTrack, G4double previousStepSize, G4ForceCondition *condition)
G4ForceCondition
static const G4double e3
G4double GetPDGCharge() const
static const G4double d2
G4ThreeVector G4ParticleMomentum
G4double XTRNAngleSpectralDensity(G4double energy)
#define DBL_MAX
Definition: templates.hh:83
static const double mm
Definition: G4SIunits.hh:102
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
const G4TouchableHandle & GetTouchableHandle() const
static const G4double dT0
static const G4double d4
void clearAndDestroy()
G4VSolid * GetSolid() const
G4double AngleSpectralXTRdEdx(G4double energy)
virtual const G4RotationMatrix * GetRotation(G4int depth=0) const =0
virtual G4double GetStackFactor(G4double energy, G4double gamma, G4double varAngle)
G4ProcessType
G4double AngleXTRdEdx(G4double varAngle)