Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4PenelopeBremsstrahlungFS Class Reference

#include <G4PenelopeBremsstrahlungFS.hh>

Public Member Functions

 G4PenelopeBremsstrahlungFS (G4int verbosity=0)
 Only master models are supposed to create instances.
 
 ~G4PenelopeBremsstrahlungFS ()
 
G4double GetEffectiveZSquared (const G4Material *mat) const
 
size_t GetNBinsX () const
 
G4double GetMomentumIntegral (G4double *y, G4double up, G4int momOrder) const
 
const G4PhysicsTableGetScaledXSTable (const G4Material *, const G4double cut) const
 
G4double SampleGammaEnergy (G4double energy, const G4Material *, const G4double cut) const
 
void ClearTables (G4bool isMaster=true)
 Reserved for the master model: they build and handle tables.
 
void BuildScaledXSTable (const G4Material *material, G4double cut, G4bool isMaster)
 
void SetVerbosity (G4int ver)
 
G4int GetVerbosity ()
 
G4PenelopeBremsstrahlungFSoperator= (const G4PenelopeBremsstrahlungFS &right)=delete
 
 G4PenelopeBremsstrahlungFS (const G4PenelopeBremsstrahlungFS &)=delete
 

Detailed Description

Definition at line 60 of file G4PenelopeBremsstrahlungFS.hh.

Constructor & Destructor Documentation

◆ G4PenelopeBremsstrahlungFS() [1/2]

G4PenelopeBremsstrahlungFS::G4PenelopeBremsstrahlungFS ( G4int  verbosity = 0)
explicit

Only master models are supposed to create instances.

Definition at line 52 of file G4PenelopeBremsstrahlungFS.cc.

52 :
53 fReducedXSTable(nullptr),fEffectiveZSq(nullptr),fSamplingTable(nullptr),
54 fPBcut(nullptr),fVerbosity(verbosity)
55{
56 fCache.Put(0);
57 G4double tempvector[fNBinsX] =
58 {1.0e-12,0.025e0,0.05e0,0.075e0,0.1e0,0.15e0,0.2e0,0.25e0,
59 0.3e0,0.35e0,0.4e0,0.45e0,0.5e0,0.55e0,0.6e0,0.65e0,0.7e0,
60 0.75e0,0.8e0,0.85e0,0.9e0,0.925e0,0.95e0,0.97e0,0.99e0,
61 0.995e0,0.999e0,0.9995e0,0.9999e0,0.99995e0,0.99999e0,1.0e0};
62
63 for (std::size_t ix=0;ix<fNBinsX;++ix)
64 theXGrid[ix] = tempvector[ix];
65
66 for (std::size_t i=0;i<fNBinsE;++i)
67 theEGrid[i] = 0.;
68
69 fElementData = new std::map<G4int,G4DataVector*>;
70}
double G4double
Definition: G4Types.hh:83
void Put(const value_type &val) const
Definition: G4Cache.hh:321

◆ ~G4PenelopeBremsstrahlungFS()

G4PenelopeBremsstrahlungFS::~G4PenelopeBremsstrahlungFS ( )

Definition at line 74 of file G4PenelopeBremsstrahlungFS.cc.

75{
77
78 //The G4Physics*Vector pointers contained in the fCache are automatically deleted by
79 //the G4AutoDelete so there is no need to take care of them manually
80
81 //Clear manually fElementData
82 if (fElementData)
83 {
84 for (auto& item : (*fElementData))
85 delete item.second;
86 delete fElementData;
87 fElementData = nullptr;
88 }
89}
void ClearTables(G4bool isMaster=true)
Reserved for the master model: they build and handle tables.

◆ G4PenelopeBremsstrahlungFS() [2/2]

G4PenelopeBremsstrahlungFS::G4PenelopeBremsstrahlungFS ( const G4PenelopeBremsstrahlungFS )
delete

Member Function Documentation

◆ BuildScaledXSTable()

void G4PenelopeBremsstrahlungFS::BuildScaledXSTable ( const G4Material material,
G4double  cut,
G4bool  isMaster 
)

Definition at line 175 of file G4PenelopeBremsstrahlungFS.cc.

177{
178 //Corresponds to subroutines EBRaW and EBRaR of PENELOPE
179 /*
180 This method generates the table of the scaled energy-loss cross section from
181 bremsstrahlung emission for the given material. Original data are read from
182 file. The table is normalized according to the Berger-Seltzer cross section.
183 */
184
185 //Just to check
186 if (!isMaster)
187 G4Exception("G4PenelopeBremsstrahlungFS::BuildScaledXSTable()",
188 "em0100",FatalException,"Worker thread in this method");
189
190 if (fVerbosity > 2)
191 {
192 G4cout << "Entering in G4PenelopeBremsstrahlungFS::BuildScaledXSTable for " <<
193 material->GetName() << G4endl;
194 G4cout << "Threshold = " << cut/keV << " keV, isMaster= " << isMaster <<
195 G4endl;
196 }
197
198 //This method should be accessed by the master only
199 if (!fSamplingTable)
200 fSamplingTable =
201 new std::map< std::pair<const G4Material*,G4double> , G4PhysicsTable*>;
202 if (!fPBcut)
203 fPBcut =
204 new std::map< std::pair<const G4Material*,G4double> , G4PhysicsFreeVector* >;
205
206 //check if the container exists (if not, create it)
207 if (!fReducedXSTable)
208 fReducedXSTable = new std::map< std::pair<const G4Material*,G4double> ,
210 if (!fEffectiveZSq)
211 fEffectiveZSq = new std::map<const G4Material*,G4double>;
212
213 //*********************************************************************
214 //Determine the equivalent atomic number <Z^2>
215 //*********************************************************************
216 std::vector<G4double> *StechiometricFactors = new std::vector<G4double>;
217 std::size_t nElements = material->GetNumberOfElements();
218 const G4ElementVector* elementVector = material->GetElementVector();
219 const G4double* fractionVector = material->GetFractionVector();
220 for (std::size_t i=0;i<nElements;i++)
221 {
222 G4double fraction = fractionVector[i];
223 G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
224 StechiometricFactors->push_back(fraction/atomicWeigth);
225 }
226 //Find max
227 G4double MaxStechiometricFactor = 0.;
228 for (std::size_t i=0;i<nElements;i++)
229 {
230 if ((*StechiometricFactors)[i] > MaxStechiometricFactor)
231 MaxStechiometricFactor = (*StechiometricFactors)[i];
232 }
233 //Normalize
234 for (std::size_t i=0;i<nElements;i++)
235 (*StechiometricFactors)[i] /= MaxStechiometricFactor;
236
237 G4double sumz2 = 0;
238 G4double sums = 0;
239 for (std::size_t i=0;i<nElements;i++)
240 {
241 G4double Z = (*elementVector)[i]->GetZ();
242 sumz2 += (*StechiometricFactors)[i]*Z*Z;
243 sums += (*StechiometricFactors)[i];
244 }
245 G4double ZBR2 = sumz2/sums;
246
247 fEffectiveZSq->insert(std::make_pair(material,ZBR2));
248
249 //*********************************************************************
250 // loop on elements and read data files
251 //*********************************************************************
252 G4DataVector* tempData = new G4DataVector(fNBinsE);
253 G4DataVector* tempMatrix = new G4DataVector(fNBinsE*fNBinsX,0.);
254
255 for (std::size_t iel=0;iel<nElements;iel++)
256 {
257 G4double Z = (*elementVector)[iel]->GetZ();
258 G4int iZ = (G4int) Z;
259 G4double wgt = (*StechiometricFactors)[iel]*Z*Z/ZBR2;
260
261 //the element is not already loaded
262 if (!fElementData->count(iZ))
263 {
264 ReadDataFile(iZ);
265 if (!fElementData->count(iZ))
266 {
268 ed << "Error in G4PenelopeBremsstrahlungFS::BuildScaledXSTable" << G4endl;
269 ed << "Unable to retrieve data for element " << iZ << G4endl;
270 G4Exception("G4PenelopeBremsstrahlungFS::BuildScaledXSTable()",
271 "em2009",FatalException,ed);
272 }
273 }
274
275 G4DataVector* atomData = fElementData->find(iZ)->second;
276
277 for (std::size_t ie=0;ie<fNBinsE;++ie)
278 {
279 (*tempData)[ie] += wgt*(*atomData)[ie*(fNBinsX+1)+fNBinsX]; //last column contains total XS
280 for (std::size_t ix=0;ix<fNBinsX;++ix)
281 (*tempMatrix)[ie*fNBinsX+ix] += wgt*(*atomData)[ie*(fNBinsX+1)+ix];
282 }
283 }
284
285 //*********************************************************************
286 // the total energy loss spectrum is re-normalized to reproduce the total
287 // scaled cross section of Berger and Seltzer
288 //*********************************************************************
289 for (std::size_t ie=0;ie<fNBinsE;++ie)
290 {
291 //for each energy, calculate integral of dSigma/dx over dx
292 G4double* tempData2 = new G4double[fNBinsX];
293 for (std::size_t ix=0;ix<fNBinsX;++ix)
294 tempData2[ix] = (*tempMatrix)[ie*fNBinsX+ix];
295 G4double rsum = GetMomentumIntegral(tempData2,1.0,0);
296 delete[] tempData2;
297 G4double fact = millibarn*(theEGrid[ie]+electron_mass_c2)*(1./fine_structure_const)/
298 (classic_electr_radius*classic_electr_radius*(theEGrid[ie]+2.0*electron_mass_c2));
299 G4double fnorm = (*tempData)[ie]/(rsum*fact);
300 G4double TST = 100.*std::fabs(fnorm-1.0);
301 if (TST > 1.0)
302 {
304 ed << "G4PenelopeBremsstrahlungFS. Corrupted data files?" << G4endl;
305 G4cout << "TST= " << TST << "; fnorm = " << fnorm << G4endl;
306 G4cout << "rsum = " << rsum << G4endl;
307 G4cout << "fact = " << fact << G4endl;
308 G4cout << ie << " " << theEGrid[ie]/keV << " " << (*tempData)[ie]/barn << G4endl;
309 G4Exception("G4PenelopeBremsstrahlungFS::BuildScaledXSTable()",
310 "em2010",FatalException,ed);
311 }
312 for (std::size_t ix=0;ix<fNBinsX;++ix)
313 (*tempMatrix)[ie*fNBinsX+ix] *= fnorm;
314 }
315
316 //*********************************************************************
317 // create and fill the tables
318 //*********************************************************************
319 G4PhysicsTable* thePhysicsTable = new G4PhysicsTable();
320 // the table will contain 32 G4PhysicsFreeVectors with different
321 // values of x. Each of the G4PhysicsFreeVectors has a profile of
322 // log(XS) vs. log(E)
323
324 //reserve space of the vectors. Everything is log-log
325 //I add one extra "fake" point at low energy, since the Penelope
326 //table starts at 1 keV
327 for (std::size_t i=0;i<fNBinsX;++i)
328 thePhysicsTable->push_back(new G4PhysicsFreeVector(fNBinsE+1));
329
330 for (std::size_t ix=0;ix<fNBinsX;++ix)
331 {
332 G4PhysicsFreeVector* theVec =
333 (G4PhysicsFreeVector*) ((*thePhysicsTable)[ix]);
334 for (std::size_t ie=0;ie<fNBinsE;++ie)
335 {
336 G4double logene = G4Log(theEGrid[ie]);
337 G4double aValue = (*tempMatrix)[ie*fNBinsX+ix];
338 if (aValue < 1e-20*millibarn) //protection against log(0)
339 aValue = 1e-20*millibarn;
340 theVec->PutValues(ie+1,logene,G4Log(aValue));
341 }
342 //Add fake point at 1 eV using an extrapolation with the derivative
343 //at the first valid point (Penelope approach)
344 G4double derivative = ((*theVec)[2]-(*theVec)[1])/(theVec->Energy(2) - theVec->Energy(1));
345 G4double log1eV = G4Log(1*eV);
346 G4double val1eV = (*theVec)[1]+derivative*(log1eV-theVec->Energy(1));
347 //fake point at very low energy
348 theVec->PutValues(0,log1eV,val1eV);
349 }
350 std::pair<const G4Material*,G4double> theKey = std::make_pair(material,cut);
351 fReducedXSTable->insert(std::make_pair(theKey,thePhysicsTable));
352
353 delete StechiometricFactors;
354 delete tempData;
355 delete tempMatrix;
356
357 //Do here also the initialization of the energy sampling
358 if (!(fSamplingTable->count(theKey)))
359 InitializeEnergySampling(material,cut);
360
361 return;
362}
std::vector< const G4Element * > G4ElementVector
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
G4double G4Log(G4double x)
Definition: G4Log.hh:227
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:185
const G4double * GetFractionVector() const
Definition: G4Material.hh:189
size_t GetNumberOfElements() const
Definition: G4Material.hh:181
const G4String & GetName() const
Definition: G4Material.hh:172
G4double GetMomentumIntegral(G4double *y, G4double up, G4int momOrder) const
void PutValues(const std::size_t index, const G4double energy, const G4double value)
void push_back(G4PhysicsVector *)
G4double Energy(const std::size_t index) const

Referenced by G4PenelopeBremsstrahlungModel::Initialise().

◆ ClearTables()

void G4PenelopeBremsstrahlungFS::ClearTables ( G4bool  isMaster = true)

Reserved for the master model: they build and handle tables.

Definition at line 94 of file G4PenelopeBremsstrahlungFS.cc.

95{
96 //Just to check
97 if (!isMaster)
98 G4Exception("G4PenelopeBremsstrahlungFS::ClearTables()",
99 "em0100",FatalException,"Worker thread in this method");
100
101 if (fReducedXSTable)
102 {
103 for (auto& item : (*fReducedXSTable))
104 {
105 G4PhysicsTable* tab = item.second;
106 tab->clearAndDestroy();
107 delete tab;
108 }
109 fReducedXSTable->clear();
110 delete fReducedXSTable;
111 fReducedXSTable = nullptr;
112 }
113
114 if (fSamplingTable)
115 {
116 for (auto& item : (*fSamplingTable))
117 {
118 G4PhysicsTable* tab = item.second;
119 tab->clearAndDestroy();
120 delete tab;
121 }
122 fSamplingTable->clear();
123 delete fSamplingTable;
124 fSamplingTable = nullptr;
125 }
126 if (fPBcut)
127 {
128 /*
129 std::map< std::pair<const G4Material*,G4double> ,G4PhysicsFreeVector*>::iterator kk;
130 for (kk=fPBcut->begin(); kk != fPBcut->end(); kk++)
131 delete kk->second;
132 */
133 delete fPBcut;
134 fPBcut = nullptr;
135 }
136
137 if (fEffectiveZSq)
138 {
139 delete fEffectiveZSq;
140 fEffectiveZSq = nullptr;
141 }
142
143 return;
144}
void clearAndDestroy()

Referenced by ~G4PenelopeBremsstrahlungFS().

◆ GetEffectiveZSquared()

G4double G4PenelopeBremsstrahlungFS::GetEffectiveZSquared ( const G4Material mat) const

Master and workers (do not touch tables) All of them are const

Definition at line 148 of file G4PenelopeBremsstrahlungFS.cc.

149{
150 if (!fEffectiveZSq)
151 {
153 ed << "The container for the <Z^2> values is not initialized" << G4endl;
154 G4Exception("G4PenelopeBremsstrahlungFS::GetEffectiveZSquared()",
155 "em2007",FatalException,ed);
156 return 0;
157 }
158 //found in the table: return it
159 if (fEffectiveZSq->count(material))
160 return fEffectiveZSq->find(material)->second;
161 else
162 {
164 ed << "The value of <Z^2> is not properly set for material " <<
165 material->GetName() << G4endl;
166 //requires running of BuildScaledXSTable()
167 G4Exception("G4PenelopeBremsstrahlungFS::GetEffectiveZSquared()",
168 "em2008",FatalException,ed);
169 }
170 return 0;
171}

◆ GetMomentumIntegral()

G4double G4PenelopeBremsstrahlungFS::GetMomentumIntegral ( G4double y,
G4double  up,
G4int  momOrder 
) const

Definition at line 435 of file G4PenelopeBremsstrahlungFS.cc.

438{
439 //Corresponds to the function RLMOM of Penelope
440 //This method performs the calculation of the integral of (x^momOrder)*y over the interval
441 //from x[0] to xup, obtained by linear interpolation on a table of y.
442 //The independent variable is assumed to take positive values only.
443 //
444 std::size_t size = fNBinsX;
445 const G4double eps = 1e-35;
446
447 //Check that the call is valid
448 if (momOrder<-1 || size<2 || theXGrid[0]<0)
449 {
450 G4Exception("G4PenelopeBremsstrahlungFS::GetMomentumIntegral()",
451 "em2011",FatalException,"Invalid call");
452 }
453
454 for (std::size_t i=1;i<size;++i)
455 {
456 if (theXGrid[i]<0 || theXGrid[i]<theXGrid[i-1])
457 {
459 ed << "Invalid call for bin " << i << G4endl;
460 G4Exception("G4PenelopeBremsstrahlungFS::GetMomentumIntegral()",
461 "em2012",FatalException,ed);
462 }
463 }
464
465 //Compute the integral
466 G4double result = 0;
467 if (xup < theXGrid[0])
468 return result;
469 G4bool loopAgain = true;
470 G4double xt = std::min(xup,theXGrid[size-1]);
471 G4double xtc = 0;
472 for (std::size_t i=0;i<size-1;++i)
473 {
474 G4double x1 = std::max(theXGrid[i],eps);
475 G4double y1 = y[i];
476 G4double x2 = std::max(theXGrid[i+1],eps);
477 G4double y2 = y[i+1];
478 if (xt < x2)
479 {
480 xtc = xt;
481 loopAgain = false;
482 }
483 else
484 xtc = x2;
485 G4double dx = x2-x1;
486 G4double dy = y2-y1;
487 G4double ds = 0;
488 if (std::fabs(dx)>1e-14*std::fabs(dy))
489 {
490 G4double b=dy/dx;
491 G4double a=y1-b*x1;
492 if (momOrder == -1)
493 ds = a*G4Log(xtc/x1)+b*(xtc-x1);
494 else if (momOrder == 0) //speed it up, not using pow()
495 ds = a*(xtc-x1) + 0.5*b*(xtc*xtc-x1*x1);
496 else
497 ds = a*(std::pow(xtc,momOrder+1)-std::pow(x1,momOrder+1))/((G4double) (momOrder + 1))
498 + b*(std::pow(xtc,momOrder+2)-std::pow(x1,momOrder+2))/((G4double) (momOrder + 2));
499 }
500 else
501 ds = 0.5*(y1+y2)*(xtc-x1)*std::pow(xtc,momOrder);
502 result += ds;
503 if (!loopAgain)
504 return result;
505 }
506 return result;
507}
bool G4bool
Definition: G4Types.hh:86

Referenced by BuildScaledXSTable().

◆ GetNBinsX()

size_t G4PenelopeBremsstrahlungFS::GetNBinsX ( ) const
inline

Definition at line 72 of file G4PenelopeBremsstrahlungFS.hh.

72{return fNBinsX;};

◆ GetScaledXSTable()

const G4PhysicsTable * G4PenelopeBremsstrahlungFS::GetScaledXSTable ( const G4Material mat,
const G4double  cut 
) const

Definition at line 511 of file G4PenelopeBremsstrahlungFS.cc.

513{
514 //check if it already contains the entry
515 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
516
517 if (!(fReducedXSTable->count(theKey)))
518 {
519 G4Exception("G4PenelopeBremsstrahlungFS::GetScaledXSTable()",
520 "em2013",FatalException,"Unable to retrieve the cross section table");
521 }
522
523 return fReducedXSTable->find(theKey)->second;
524}

◆ GetVerbosity()

G4int G4PenelopeBremsstrahlungFS::GetVerbosity ( )
inline

Definition at line 86 of file G4PenelopeBremsstrahlungFS.hh.

86{return fVerbosity;};

◆ operator=()

G4PenelopeBremsstrahlungFS & G4PenelopeBremsstrahlungFS::operator= ( const G4PenelopeBremsstrahlungFS right)
delete

◆ SampleGammaEnergy()

G4double G4PenelopeBremsstrahlungFS::SampleGammaEnergy ( G4double  energy,
const G4Material mat,
const G4double  cut 
) const

Definition at line 603 of file G4PenelopeBremsstrahlungFS.cc.

605{
606 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
607 if (!(fSamplingTable->count(theKey)) || !(fPBcut->count(theKey)))
608 {
610 ed << "Unable to retrieve the SamplingTable: " <<
611 fSamplingTable->count(theKey) << " " <<
612 fPBcut->count(theKey) << G4endl;
613 G4Exception("G4PenelopeBremsstrahlungFS::SampleGammaEnergy()",
614 "em2014",FatalException,ed);
615 }
616 const G4PhysicsTable* theTableInte = fSamplingTable->find(theKey)->second;
617 const G4PhysicsTable* theTableRed = fReducedXSTable->find(theKey)->second;
618
619 //Find the energy bin using bi-partition
620 std::size_t eBin = 0;
621 G4bool firstOrLastBin = false;
622
623 if (energy < theEGrid[0]) //below first bin
624 {
625 eBin = 0;
626 firstOrLastBin = true;
627 }
628 else if (energy > theEGrid[fNBinsE-1]) //after last bin
629 {
630 eBin = fNBinsE-1;
631 firstOrLastBin = true;
632 }
633 else
634 {
635 std::size_t i=0;
636 std::size_t j=fNBinsE-1;
637 while ((j-i)>1)
638 {
639 std::size_t k = (i+j)/2;
640 if (energy > theEGrid[k])
641 i = k;
642 else
643 j = k;
644 }
645 eBin = i;
646 }
647
648 //Get the appropriate physics vector
649 const G4PhysicsFreeVector* theVec1 = (G4PhysicsFreeVector*) (*theTableInte)[eBin];
650
651 //Use a "temporary" vector which contains the linear interpolation of the x spectra
652 //in energy. The temporary vector is thread-local, so that there is no conflict.
653 //This is achieved via G4Cache. The theTempVect is allocated only once per thread
654 //(member variable), but it is overwritten at every call of this method
655 //(because the interpolation factors change!)
656 G4PhysicsFreeVector* theTempVec = fCache.Get();
657 if (!theTempVec) //First time this thread gets the cache
658 {
659 theTempVec = new G4PhysicsFreeVector(fNBinsX);
660 fCache.Put(theTempVec);
661 // The G4AutoDelete takes care here to clean up the vectors
662 G4AutoDelete::Register(theTempVec);
663 if (fVerbosity > 4)
664 G4cout << "Creating new instance of G4PhysicsFreeVector() on the worker" << G4endl;
665 }
666
667 //theTempVect is allocated only once (member variable), but it is overwritten at
668 //every call of this method (because the interpolation factors change!)
669 if (!firstOrLastBin)
670 {
671 const G4PhysicsFreeVector* theVec2 = (G4PhysicsFreeVector*) (*theTableInte)[eBin+1];
672 for (std::size_t iloop=0;iloop<fNBinsX;++iloop)
673 {
674 G4double val = (*theVec1)[iloop]+(((*theVec2)[iloop]-(*theVec1)[iloop]))*
675 (energy-theEGrid[eBin])/(theEGrid[eBin+1]-theEGrid[eBin]);
676 theTempVec->PutValues(iloop,theXGrid[iloop],val);
677 }
678 }
679 else //first or last bin, no interpolation
680 {
681 for (std::size_t iloop=0;iloop<fNBinsX;++iloop)
682 theTempVec->PutValues(iloop,theXGrid[iloop],(*theVec1)[iloop]);
683 }
684
685 //Start the game
686 G4double pbcut = (*(fPBcut->find(theKey)->second))[eBin];
687
688 if (!firstOrLastBin) //linear interpolation on pbcut as well
689 {
690 pbcut = (*(fPBcut->find(theKey)->second))[eBin] +
691 ((*(fPBcut->find(theKey)->second))[eBin+1]-(*(fPBcut->find(theKey)->second))[eBin])*
692 (energy-theEGrid[eBin])/(theEGrid[eBin+1]-theEGrid[eBin]);
693 }
694
695 G4double pCumulative = (*theTempVec)[fNBinsX-1]; //last value
696
697 G4double eGamma = 0;
698 G4int nIterations = 0;
699 do
700 {
701 G4double pt = pbcut + G4UniformRand()*(pCumulative - pbcut);
702 nIterations++;
703
704 //find where it is
705 std::size_t ibin = 0;
706 if (pt < (*theTempVec)[0])
707 ibin = 0;
708 else if (pt > (*theTempVec)[fNBinsX-1])
709 {
710 //We observed problems due to numerical rounding here (STT).
711 //delta here is a tiny positive number
712 G4double delta = pt-(*theTempVec)[fNBinsX-1];
713 if (delta < pt*1e-10) // very small! Numerical rounding only
714 {
715 ibin = fNBinsX-2;
717 ed << "Found that (pt > (*theTempVec)[fNBinsX-1]) with pt = " << pt <<
718 " , (*theTempVec)[fNBinsX-1] = " << (*theTempVec)[fNBinsX-1] << " and delta = " <<
719 (pt-(*theTempVec)[fNBinsX-1]) << G4endl;
720 ed << "Possible symptom of problem with numerical precision" << G4endl;
721 G4Exception("G4PenelopeBremsstrahlungFS::SampleGammaEnergy()",
722 "em2015",JustWarning,ed);
723 }
724 else //real problem
725 {
727 ed << "Crash at (pt > (*theTempVec)[fNBinsX-1]) with pt = " << pt <<
728 " , (*theTempVec)[fNBinsX-1]=" << (*theTempVec)[fNBinsX-1] << " and fNBinsX = " <<
729 fNBinsX << G4endl;
730 ed << "Material: " << mat->GetName() << ", energy = " << energy/keV << " keV" <<
731 G4endl;
732 G4Exception("G4PenelopeBremsstrahlungFS::SampleGammaEnergy()",
733 "em2015",FatalException,ed);
734 }
735 }
736 else
737 {
738 std::size_t i=0;
739 std::size_t j=fNBinsX-1;
740 while ((j-i)>1)
741 {
742 std::size_t k = (i+j)/2;
743 if (pt > (*theTempVec)[k])
744 i = k;
745 else
746 j = k;
747 }
748 ibin = i;
749 }
750
751 G4double w1 = theXGrid[ibin];
752 G4double w2 = theXGrid[ibin+1];
753
754 const G4PhysicsFreeVector* v1 = (G4PhysicsFreeVector*) (*theTableRed)[ibin];
755 const G4PhysicsFreeVector* v2 = (G4PhysicsFreeVector*) (*theTableRed)[ibin+1];
756 //Remember: the table fReducedXSTable has a fake first point in energy
757 //so, it contains one more bin than fNBinsE.
758 G4double pdf1 = G4Exp((*v1)[eBin+1]);
759 G4double pdf2 = G4Exp((*v2)[eBin+1]);
760 G4double deltaW = w2-w1;
761 G4double dpdfb = pdf2-pdf1;
762 G4double B = dpdfb/deltaW;
763 G4double A = pdf1-B*w1;
764 //I already made an interpolation in energy, so I can use the actual value for the
765 //calculation of the wbcut, instead of the grid values (except for the last bin)
766 G4double wbcut = (cut < energy) ? cut/energy : 1.0;
767 if (firstOrLastBin) //this is an particular case: no interpolation available
768 wbcut = (cut < theEGrid[eBin]) ? cut/theEGrid[eBin] : 1.0;
769
770 if (w1 < wbcut)
771 w1 = wbcut;
772 if (w2 < w1)
773 {
774 //This configuration can happen if initially wbcut > w2 > w1. Due to the previous
775 //statement, (w1 = wbcut), it becomes wbcut = w1 > w2. In this case, it is not a
776 //real problem. It becomes a problem if w2 < w1 before the w1 = wbcut statement. Issue
777 //a warning only in this specific case.
778 if (w2 > wbcut)
779 {
781 ed << "Warning in G4PenelopeBremsstrahlungFS::SampleX()" << G4endl;
782 ed << "Conflicting end-point values: w1=" << w1 << "; w2 = " << w2 << G4endl;
783 ed << "wbcut = " << wbcut << " energy= " << energy/keV << " keV" << G4endl;
784 ed << "cut = " << cut/keV << " keV" << G4endl;
785 G4Exception("G4PenelopeBremsstrahlungFS::SampleGammaEnergy()","em2015",
786 JustWarning,ed);
787 }
788 return w1*energy;
789 }
790
791 G4double pmax = std::max(A+B*w1,A+B*w2);
792 G4bool loopAgain = false;
793 do
794 {
795 loopAgain = false;
796 eGamma = w1* std::pow((w2/w1),G4UniformRand());
797 if (G4UniformRand()*pmax > (A+B*eGamma))
798 loopAgain = true;
799 }while(loopAgain);
800 eGamma *= energy;
801 if (nIterations > 100) //protection against infinite loops
802 return eGamma;
803 }while(eGamma < cut); //repeat if sampled sub-cut!
804
805 return eGamma;
806}
G4double B(G4double temperature)
@ JustWarning
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
const G4double A[17]
#define G4UniformRand()
Definition: Randomize.hh:52
value_type & Get() const
Definition: G4Cache.hh:315
void Register(T *inst)
Definition: G4AutoDelete.hh:65
G4double energy(const ThreeVector &p, const G4double m)

Referenced by G4PenelopeBremsstrahlungModel::SampleSecondaries().

◆ SetVerbosity()

void G4PenelopeBremsstrahlungFS::SetVerbosity ( G4int  ver)
inline

Definition at line 85 of file G4PenelopeBremsstrahlungFS.hh.

85{fVerbosity=ver;};

The documentation for this class was generated from the following files: