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