Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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$
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"
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"
58
59////////////////////////////////////////////////////////////////////////////
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
95
98 fTotBin );
99
102 fBinTR );
103
104 fPlasmaCof = 4.0*pi*fine_structure_const*hbarc*hbarc*hbarc/electron_mass_c2;
105
106 fCofTR = fine_structure_const/pi;
107
108 fEnvelope = anEnvelope;
109
110 fPlateNumber = n;
111 if(verboseLevel > 0)
112 G4cout<<"### G4VXTRenergyLoss: the number of TR radiator plates = "
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
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;
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
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 {
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 {
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
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,
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 }
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;
475 G4double energy;
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
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,
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
726
727 if(verboseLevel > 1)
728 {
729 G4cout<<"Start of G4VXTRenergyLoss::PostStepDoIt "<<G4endl;
730 G4cout<<"name of current material = "
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
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
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
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;
1398 return integral.Legendre96(this,&G4VXTRenergyLoss::XTRNSpectralAngleDensity,
1399 0.0,0.2*fMaxThetaTR) +
1400 integral.Legendre10(this,&G4VXTRenergyLoss::XTRNSpectralAngleDensity,
1402}
1403
1404//////////////////////////////////////////////////////////////////////////
1405//
1406// for photon angle distribution tables
1407//
1408
1410{
1413}
1414
1415///////////////////////////////////////////////////////////////////////////
1416//
1417//
1418
1420{
1421 fVarAngle = varAngle;
1423 return integral.Legendre96(this,&G4VXTRenergyLoss::XTRNAngleSpectralDensity,
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
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)
@ JustWarning
@ FatalException
G4ForceCondition
@ NotForced
std::vector< G4Material * > G4MaterialTable
G4ProcessType
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
std::complex< G4double > G4complex
Definition: G4Types.hh:69
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
Hep3Vector unit() const
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:72
G4AffineTransform & Invert()
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4ThreeVector TransformAxis(const G4ThreeVector &axis) const
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4Gamma * Gamma()
Definition: G4Gamma.cc:86
G4VSolid * GetSolid() const
G4Material * GetMaterial() const
static const G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:562
G4SandiaTable * GetSandiaTable() const
Definition: G4Material.hh:228
G4double GetElectronDensity() const
Definition: G4Material.hh:216
const G4String & GetName() const
Definition: G4Material.hh:177
size_t GetIndex() const
Definition: G4Material.hh:261
void AddSecondary(G4Track *aSecondary)
void ProposeEnergy(G4double finalEnergy)
virtual void Initialize(const G4Track &)
G4double GetPDGCharge() const
void PutValue(size_t binNumber, G4double binValue, G4double dataValue)
void insertAt(size_t, G4PhysicsVector *)
virtual G4double GetLowEdgeEnergy(size_t binNumber) const
void PutValue(size_t index, G4double theValue)
G4double GetSandiaCofForMaterial(G4int, G4int)
const G4VTouchable * GetTouchable() const
G4double GetGlobalTime() const
const G4ThreeVector & GetPosition() const
const G4TouchableHandle & GetTouchableHandle() const
Definition: G4Step.hh:78
G4StepPoint * GetPostStepPoint() const
void Stop()
G4double GetUserElapsed() const
Definition: G4Timer.cc:130
void Start()
G4int GetTrackID() const
G4VPhysicalVolume * GetVolume() const
void SetTouchableHandle(const G4TouchableHandle &apValue)
const G4DynamicParticle * GetDynamicParticle() const
void SetParentID(const G4int aValue)
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
void SetNumberOfSecondaries(G4int totSecondaries)
G4LogicalVolume * GetLogicalVolume() const
G4int verboseLevel
Definition: G4VProcess.hh:368
G4VParticleChange * pParticleChange
Definition: G4VProcess.hh:283
const G4String & GetProcessName() const
Definition: G4VProcess.hh:379
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
virtual const G4ThreeVector & GetTranslation(G4int depth=0) const =0
virtual const G4RotationMatrix * GetRotation(G4int depth=0) const =0
G4double GetPlateLinearPhotoAbs(G4double)
G4double AngleSpectralXTRdEdx(G4double energy)
G4double XTRNAngleDensity(G4double varAngle)
G4PhysicsTable * fEnergyDistrTable
G4double GetAngleXTR(G4int iTR, G4double position, G4int iAngle)
G4PhysicsTable * fAngleForEnergyTable
G4PhysicsLogVector * fProtonEnergyVector
G4PhysicsLogVector * fXTREnergyVector
G4double GetGasFormationZone(G4double, G4double, G4double)
G4SandiaTable * fPlatePhotoAbsCof
G4double OneBoundaryXTRNdensity(G4double energy, G4double gamma, G4double varAngle) const
G4PhysicsFreeVector * GetAngleVector(G4double energy, G4int n)
G4double GetMeanFreePath(const G4Track &aTrack, G4double previousStepSize, G4ForceCondition *condition)
G4PhysicsTable * fAngleDistrTable
G4double GetRandomAngle(G4double energyXTR, G4int iTkin)
G4complex GetPlateComplexFZ(G4double, G4double, G4double)
G4complex OneInterfaceXTRdEdx(G4double energy, G4double gamma, G4double varAngle)
G4double GetXTRenergy(G4int iPlace, G4double position, G4int iTransfer)
G4VXTRenergyLoss(G4LogicalVolume *anEnvelope, G4Material *, G4Material *, G4double, G4double, G4int, const G4String &processName="XTRenergyLoss", G4ProcessType type=fElectromagnetic)
G4double XTRNAngleSpectralDensity(G4double energy)
G4double SpectralAngleXTRdEdx(G4double varAngle)
G4double GetXTRrandomEnergy(G4double scaledTkin, G4int iTkin)
G4SandiaTable * fGasPhotoAbsCof
void BuildPhysicsTable(const G4ParticleDefinition &)
G4LogicalVolume * fEnvelope
std::vector< G4PhysicsTable * > fAngleBank
virtual ~G4VXTRenergyLoss()
virtual G4double SpectralXTRdEdx(G4double energy)
G4double GetComptonPerAtom(G4double, G4double)
G4double GetGasCompton(G4double)
G4double XTRNSpectralAngleDensity(G4double varAngle)
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
G4double GetPlateFormationZone(G4double, G4double, G4double)
G4double GetGasLinearPhotoAbs(G4double)
G4double XTRNSpectralDensity(G4double energy)
virtual G4double GetStackFactor(G4double energy, G4double gamma, G4double varAngle)
G4ParticleDefinition * fPtrGamma
G4ParticleChange fParticleChange
G4complex GetGasComplexFZ(G4double, G4double, G4double)
G4double GetPlateCompton(G4double)
G4bool IsApplicable(const G4ParticleDefinition &)
G4double AngleXTRdEdx(G4double varAngle)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
#define DBL_MIN
Definition: templates.hh:75
#define DBL_MAX
Definition: templates.hh:83
#define position
Definition: xmlparse.cc:605