Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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