Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4EmUtility.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// Geant4 class G4EmUtility
28//
29// Author V.Ivanchenko 14.03.2022
30//
31
32#include "G4EmUtility.hh"
33#include "G4RegionStore.hh"
35#include "G4VEmProcess.hh"
36#include "G4EmParameters.hh"
37#include "G4PhysicsVector.hh"
38#include "Randomize.hh"
39#include "G4Log.hh"
40#include "G4Exp.hh"
41
42//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
43
44static const G4double g4log10 = G4Log(10.);
45
46const G4Region*
47G4EmUtility::FindRegion(const G4String& regionName, const G4int verbose)
48{
49 const G4Region* reg = nullptr;
51 G4String r = regionName;
52 if(r == "") { r = "DefaultRegionForTheWorld"; }
53 reg = regStore->GetRegion(r, true);
54 if(nullptr == reg && verbose > 0) {
55 G4cout << "### G4EmUtility WARNING: fails to find a region <"
56 << r << G4endl;
57 } else if(verbose > 1) {
58 G4cout << "### G4EmUtility finds out G4Region <" << r << ">"
59 << G4endl;
60 }
61 return reg;
62}
63
64//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
65
67{
68 const G4Element* elm = mat->GetElement(0);
69 std::size_t nElements = mat->GetNumberOfElements();
70 if(1 < nElements) {
72 const G4double* y = mat->GetVecNbOfAtomsPerVolume();
73 for(std::size_t i=0; i<nElements; ++i) {
74 elm = mat->GetElement((G4int)i);
75 x -= y[i]*elm->GetZ();
76 if(x <= 0.0) { break; }
77 }
78 }
79 return elm;
80}
81
82//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
83
85{
86 const std::size_t ni = elm->GetNumberOfIsotopes();
87 const G4Isotope* iso = elm->GetIsotope(0);
88 if(ni > 1) {
89 const G4double* ab = elm->GetRelativeAbundanceVector();
91 for(std::size_t idx=0; idx<ni; ++idx) {
92 x -= ab[idx];
93 if (x <= 0.0) {
94 iso = elm->GetIsotope((G4int)idx);
95 break;
96 }
97 }
98 }
99 return iso;
100}
101
102//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
103
105{
106 std::vector<G4double>* ptr = nullptr;
107 if(nullptr == p) { return ptr; }
108
109 const std::size_t n = p->length();
110 ptr = new std::vector<G4double>;
111 ptr->resize(n, DBL_MAX);
112
113 G4bool isPeak = false;
114 G4double e, ss, ee, xs;
115
116 // first loop on existing vectors
117 for (std::size_t i=0; i<n; ++i) {
118 const G4PhysicsVector* pv = (*p)[i];
119 xs = ee = 0.0;
120 if(nullptr != pv) {
121 G4int nb = (G4int)pv->GetVectorLength();
122 for (G4int j=0; j<nb; ++j) {
123 e = pv->Energy(j);
124 ss = (*pv)(j);
125 if(ss >= xs) {
126 xs = ss;
127 ee = e;
128 continue;
129 } else {
130 isPeak = true;
131 (*ptr)[i] = ee;
132 break;
133 }
134 }
135 }
136 }
137
138 // there is no peak for any material
139 if(!isPeak) {
140 delete ptr;
141 ptr = nullptr;
142 }
143 return ptr;
144}
145
146//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
147
148std::vector<G4double>*
150 const G4ParticleDefinition* part)
151{
152 std::vector<G4double>* ptr = nullptr;
153 if(nullptr == p || nullptr == part) { return ptr; }
154 /*
155 G4cout << "G4EmUtility::FindCrossSectionMax for "
156 << p->GetProcessName() << " and " << part->GetParticleName() << G4endl;
157 */
158 G4EmParameters* theParameters = G4EmParameters::Instance();
159 G4double tmin = theParameters->MinKinEnergy();
160 G4double tmax = theParameters->MaxKinEnergy();
161
162 const G4ProductionCutsTable* theCoupleTable=
164 std::size_t n = theCoupleTable->GetTableSize();
165 ptr = new std::vector<G4double>;
166 ptr->resize(n, DBL_MAX);
167
168 G4bool isPeak = false;
169 G4double scale = theParameters->NumberOfBinsPerDecade()/g4log10;
170
171 G4double e, sig, ee, x, sm, em, emin, emax;
172
173 // first loop on existing vectors
174 for (std::size_t i=0; i<n; ++i) {
175 auto couple = theCoupleTable->GetMaterialCutsCouple((G4int)i);
176 emin = std::max(p->MinPrimaryEnergy(part, couple->GetMaterial()), tmin);
177 emax = std::max(tmax, 2*emin);
178 ee = G4Log(emax/emin);
179
180 G4int nbin = G4lrint(ee*scale);
181 if(nbin < 4) { nbin = 4; }
182 x = G4Exp(ee/nbin);
183 sm = 0.0;
184 em = 0.0;
185 e = emin;
186 for(G4int j=0; j<=nbin; ++j) {
187 sig = p->GetCrossSection(e, couple);
188 if(sig >= sm) {
189 em = e;
190 sm = sig;
191 e = (j+1 < nbin) ? e*x : emax;
192 } else {
193 isPeak = true;
194 (*ptr)[i] = em;
195 break;
196 }
197 }
198 //G4cout << i << ". em=" << em << " sm=" << sm << G4endl;
199 }
200 // there is no peak for any couple
201 if(!isPeak) {
202 delete ptr;
203 ptr = nullptr;
204 }
205 return ptr;
206}
207
208//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
209
210std::vector<G4TwoPeaksXS*>*
212{
213 std::vector<G4TwoPeaksXS*>* ptr = nullptr;
214 if(nullptr == p) { return ptr; }
215
216 const G4int n = (G4int)p->length();
217 ptr = new std::vector<G4TwoPeaksXS*>;
218 ptr->resize(n, nullptr);
219
220 G4double e, ss, xs, ee;
221 G4double e1peak, e1deep, e2peak, e2deep, e3peak;
222 G4bool isDeep = false;
223
224 // first loop on existing vectors
225 for (G4int i=0; i<n; ++i) {
226 const G4PhysicsVector* pv = (*p)[i];
227 ee = xs = 0.0;
228 e1peak = e1deep = e2peak = e2deep = e3peak = DBL_MAX;
229 if(nullptr != pv) {
230 G4int nb = (G4int)pv->GetVectorLength();
231 for (G4int j=0; j<nb; ++j) {
232 e = pv->Energy(j);
233 ss = (*pv)(j);
234 // find out 1st peak
235 if(e1peak == DBL_MAX) {
236 if(ss >= xs) {
237 xs = ss;
238 ee = e;
239 continue;
240 } else {
241 e1peak = ee;
242 }
243 }
244 // find out the deep
245 if(e1deep == DBL_MAX) {
246 if(ss <= xs) {
247 xs = ss;
248 ee = e;
249 continue;
250 } else {
251 e1deep = ee;
252 isDeep = true;
253 }
254 }
255 // find out 2nd peak
256 if(e2peak == DBL_MAX) {
257 if(ss >= xs) {
258 xs = ss;
259 ee = e;
260 continue;
261 } else {
262 e2peak = ee;
263 }
264 }
265 if(e2deep == DBL_MAX) {
266 if(ss <= xs) {
267 xs = ss;
268 ee = e;
269 continue;
270 } else {
271 e2deep = ee;
272 break;
273 }
274 }
275 // find out 3d peak
276 if(e3peak == DBL_MAX) {
277 if(ss >= xs) {
278 xs = ss;
279 ee = e;
280 continue;
281 } else {
282 e3peak = ee;
283 }
284 }
285 }
286 }
287 G4TwoPeaksXS* x = (*ptr)[i];
288 if(nullptr == x) {
289 x = new G4TwoPeaksXS();
290 (*ptr)[i] = x;
291 }
292 x->e1peak = e1peak;
293 x->e1deep = e1deep;
294 x->e2peak = e2peak;
295 x->e2deep = e2deep;
296 x->e3peak = e3peak;
297 }
298 // case of no 1st peak in all vectors
299 if(!isDeep) {
300 delete ptr;
301 ptr = nullptr;
302 return ptr;
303 }
304 // check base particles
305 if(!bld->GetBaseMaterialFlag()) { return ptr; }
306
307 auto theDensityIdx = bld->GetCoupleIndexes();
308 // second loop using base materials
309 for (G4int i=0; i<n; ++i) {
310 const G4PhysicsVector* pv = (*p)[i];
311 if (nullptr == pv) {
312 G4int j = (*theDensityIdx)[i];
313 if(j == i) { continue; }
314 G4TwoPeaksXS* x = (*ptr)[i];
315 G4TwoPeaksXS* y = (*ptr)[j];
316 if(nullptr == x) {
317 x = new G4TwoPeaksXS();
318 (*ptr)[i] = x;
319 }
320 x->e1peak = y->e1peak;
321 x->e1deep = y->e1deep;
322 x->e2peak = y->e2peak;
323 x->e2deep = y->e2deep;
324 x->e3peak = y->e3peak;
325 }
326 }
327 return ptr;
328}
329
330//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
331
333 const G4ParticleDefinition* part,
334 const G4DataVector& cuts,
335 const G4double elow,
336 const G4double ehigh)
337{
338 // using spline for element selectors should be investigated in details
339 // because small number of points may provide biased results
340 // large number of points requires significant increase of memory
341 G4bool spline = false;
342
344
345 G4ProductionCutsTable* theCoupleTable=
347 std::size_t numOfCouples = theCoupleTable->GetTableSize();
348
349 // prepare vector
350 auto elmSelectors = mod->GetElementSelectors();
351 if(nullptr == elmSelectors) {
352 elmSelectors = new std::vector<G4EmElementSelector*>;
353 }
354 std::size_t nSelectors = elmSelectors->size();
355 if(numOfCouples > nSelectors) {
356 for(std::size_t i=nSelectors; i<numOfCouples; ++i) {
357 elmSelectors->push_back(nullptr);
358 }
359 nSelectors = numOfCouples;
360 }
361
362 // initialise vector
363 for(std::size_t i=0; i<numOfCouples; ++i) {
364
365 // no need in element selectors for infinite cuts
366 if(cuts[i] == DBL_MAX) { continue; }
367
368 auto couple = theCoupleTable->GetMaterialCutsCouple((G4int)i);
369 auto mat = couple->GetMaterial();
370 mod->SetCurrentCouple(couple);
371
372 // selector already exist then delete
373 delete (*elmSelectors)[i];
374
375 G4double emin = std::max(elow, mod->MinPrimaryEnergy(mat, part, cuts[i]));
376 G4double emax = std::max(ehigh, 10*emin);
377 static const G4double invlog106 = 1.0/(6*G4Log(10.));
378 G4int nbins = G4lrint(nbinsPerDec*G4Log(emax/emin)*invlog106);
379 nbins = std::max(nbins, 3);
380
381 (*elmSelectors)[i] = new G4EmElementSelector(mod,mat,nbins,
382 emin,emax,spline);
383 ((*elmSelectors)[i])->Initialise(part, cuts[i]);
384 /*
385 G4cout << "G4VEmModel::InitialiseElmSelectors i= " << i
386 << " " << part->GetParticleName()
387 << " for " << mod->GetName() << " cut= " << cuts[i]
388 << " " << (*elmSelectors)[i] << G4endl;
389 ((*elmSelectors)[i])->Dump(part);
390 */
391 }
392 mod->SetElementSelectors(elmSelectors);
393}
394
395//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
G4double G4Log(G4double x)
Definition: G4Log.hh:227
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
G4double * GetRelativeAbundanceVector() const
Definition: G4Element.hh:167
G4double GetZ() const
Definition: G4Element.hh:131
const G4Isotope * GetIsotope(G4int iso) const
Definition: G4Element.hh:170
size_t GetNumberOfIsotopes() const
Definition: G4Element.hh:159
static G4EmParameters * Instance()
G4double MinKinEnergy() const
G4int NumberOfBinsPerDecade() const
G4double MaxKinEnergy() const
static const G4Element * SampleRandomElement(const G4Material *)
Definition: G4EmUtility.cc:66
static std::vector< G4TwoPeaksXS * > * FillPeaksStructure(G4PhysicsTable *, G4LossTableBuilder *)
Definition: G4EmUtility.cc:211
static const G4Isotope * SampleRandomIsotope(const G4Element *)
Definition: G4EmUtility.cc:84
static void InitialiseElementSelectors(G4VEmModel *, const G4ParticleDefinition *, const G4DataVector &cuts, const G4double emin, const G4double emax)
Definition: G4EmUtility.cc:332
static const G4Region * FindRegion(const G4String &regionName, const G4int verbose=0)
Definition: G4EmUtility.cc:47
static std::vector< G4double > * FindCrossSectionMax(G4PhysicsTable *)
Definition: G4EmUtility.cc:104
const std::vector< G4int > * GetCoupleIndexes() const
const G4Material * GetMaterial() const
const G4Element * GetElement(G4int iel) const
Definition: G4Material.hh:197
G4double GetTotNbOfElectPerVolume() const
Definition: G4Material.hh:207
size_t GetNumberOfElements() const
Definition: G4Material.hh:181
const G4double * GetVecNbOfAtomsPerVolume() const
Definition: G4Material.hh:201
std::size_t length() const
G4double Energy(const std::size_t index) const
std::size_t GetVectorLength() const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
static G4RegionStore * GetInstance()
G4Region * GetRegion(const G4String &name, G4bool verbose=true) const
virtual G4double GetCrossSection(const G4double, const G4MaterialCutsCouple *)
virtual G4double MinPrimaryEnergy(const G4ParticleDefinition *, const G4Material *)
virtual G4double MinPrimaryEnergy(const G4Material *, const G4ParticleDefinition *, G4double cut=0.0)
Definition: G4VEmModel.cc:358
void SetElementSelectors(std::vector< G4EmElementSelector * > *)
Definition: G4VEmModel.hh:831
std::vector< G4EmElementSelector * > * GetElementSelectors()
Definition: G4VEmModel.hh:823
void SetCurrentCouple(const G4MaterialCutsCouple *)
Definition: G4VEmModel.hh:468
G4double e1peak
G4double e3peak
G4double e2deep
G4double e1deep
G4double e2peak
int G4lrint(double ad)
Definition: templates.hh:134
#define DBL_MAX
Definition: templates.hh:62