Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4IonDEDXHandler.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//
28// ===========================================================================
29// GEANT4 class source file
30//
31// Class: G4IonDEDXHandler
32//
33// Author: Anton Lechner ([email protected])
34//
35// First implementation: 11. 03. 2009
36//
37// Modifications: 12. 11 .2009 - Function BuildDEDXTable: Using adapted build
38// methods of stopping power classes according
39// to interface change in G4VIonDEDXTable.
40// Function UpdateCacheValue: Using adapted
41// ScalingFactorEnergy function according to
42// interface change in G4VIonDEDXScaling-
43// Algorithm (AL)
44//
45// Class description:
46// Ion dE/dx table handler.
47//
48// Comments:
49//
50// ===========================================================================
51
52#include <iomanip>
53
54#include "G4IonDEDXHandler.hh"
55#include "G4SystemOfUnits.hh"
56#include "G4VIonDEDXTable.hh"
59#include "G4Material.hh"
61
62//#define PRINT_DEBUG
63
64
65// #########################################################################
66
68 G4VIonDEDXTable* ionTable,
69 G4VIonDEDXScalingAlgorithm* ionAlgorithm,
70 const G4String& name,
71 G4int maxCacheSize,
72 G4bool splines) :
73 table(ionTable),
74 algorithm(ionAlgorithm),
75 tableName(name),
76 useSplines(splines),
77 maxCacheEntries(maxCacheSize) {
78
79 if(table == 0) {
80 G4cerr << "G4IonDEDXHandler::G4IonDEDXHandler() "
81 << " Pointer to G4VIonDEDXTable object is null-pointer."
82 << G4endl;
83 }
84
85 if(algorithm == 0) {
86 G4cerr << "G4IonDEDXHandler::G4IonDEDXHandler() "
87 << " Pointer to G4VIonDEDXScalingAlgorithm object is null-pointer."
88 << G4endl;
89 }
90
91 if(maxCacheEntries <= 0) {
92 G4cerr << "G4IonDEDXHandler::G4IonDEDXHandler() "
93 << " Cache size <=0. Resetting to 5."
94 << G4endl;
95 maxCacheEntries = 5;
96 }
97}
98
99// #########################################################################
100
102
103 ClearCache();
104
105 // All stopping power vectors built according to Bragg's addivitiy rule
106 // are deleted. All other stopping power vectors are expected to be
107 // deleted by their creator class (sub-class of G4VIonDEDXTable).
108 DEDXTableBraggRule::iterator iter = stoppingPowerTableBragg.begin();
109 DEDXTableBraggRule::iterator iter_end = stoppingPowerTableBragg.end();
110
111 for(;iter != iter_end; iter++) delete iter -> second;
112 stoppingPowerTableBragg.clear();
113
114 stoppingPowerTable.clear();
115
116 if(table != 0) delete table;
117 if(algorithm != 0) delete algorithm;
118}
119
120// #########################################################################
121
123 const G4ParticleDefinition* particle, // Projectile (ion)
124 const G4Material* material) { // Target material
125
126 G4bool isApplicable = true;
127
128 if(table == 0 || algorithm == 0) {
129 isApplicable = false;
130 }
131 else {
132
133 G4int atomicNumberIon = particle -> GetAtomicNumber();
134 G4int atomicNumberBase =
135 algorithm -> AtomicNumberBaseIon(atomicNumberIon, material);
136
137 G4IonKey key = std::make_pair(atomicNumberBase, material);
138
139 DEDXTable::iterator iter = stoppingPowerTable.find(key);
140 if(iter == stoppingPowerTable.end()) isApplicable = false;
141 }
142
143 return isApplicable;
144}
145
146// #########################################################################
147
149 const G4ParticleDefinition* particle, // Projectile (ion)
150 const G4Material* material, // Target material
151 G4double kineticEnergy) { // Kinetic energy of projectile
152
153 G4double dedx = 0.0;
154
155 G4CacheValue value = GetCacheValue(particle, material);
156
157 if(kineticEnergy <= 0.0) dedx = 0.0;
158 else if(value.dedxVector != 0) {
159
160 G4bool b;
161 G4double factor = value.density;
162
163 factor *= algorithm -> ScalingFactorDEDX(particle,
164 material,
165 kineticEnergy);
166 G4double scaledKineticEnergy = kineticEnergy * value.energyScaling;
167
168 if(scaledKineticEnergy < value.lowerEnergyEdge) {
169
170 factor *= std::sqrt(scaledKineticEnergy / value.lowerEnergyEdge);
171 scaledKineticEnergy = value.lowerEnergyEdge;
172 }
173
174 dedx = factor * value.dedxVector -> GetValue(scaledKineticEnergy, b);
175
176 if(dedx < 0.0) dedx = 0.0;
177 }
178 else dedx = 0.0;
179
180#ifdef PRINT_DEBUG
181 G4cout << "G4IonDEDXHandler::GetDEDX() E = "
182 << kineticEnergy / MeV << " MeV * "
183 << value.energyScaling << " = "
184 << kineticEnergy * value.energyScaling / MeV
185 << " MeV, dE/dx = " << dedx / MeV * cm << " MeV/cm"
186 << ", material = " << material -> GetName()
187 << G4endl;
188#endif
189
190 return dedx;
191}
192
193// #########################################################################
194
196 const G4ParticleDefinition* particle, // Projectile (ion)
197 const G4Material* material) { // Target material
198
199 G4int atomicNumberIon = particle -> GetAtomicNumber();
200
201 G4bool isApplicable = BuildDEDXTable(atomicNumberIon, material);
202
203 return isApplicable;
204}
205
206
207// #########################################################################
208
210 G4int atomicNumberIon, // Projectile (ion)
211 const G4Material* material) { // Target material
212
213 G4bool isApplicable = true;
214
215 if(table == 0 || algorithm == 0) {
216 isApplicable = false;
217 return isApplicable;
218 }
219
220 G4int atomicNumberBase =
221 algorithm -> AtomicNumberBaseIon(atomicNumberIon, material);
222
223 // Checking if vector is already built, and returns if this is indeed
224 // the case
225 G4IonKey key = std::make_pair(atomicNumberBase, material);
226
227 DEDXTable::iterator iter = stoppingPowerTable.find(key);
228 if(iter != stoppingPowerTable.end()) return isApplicable;
229
230 // Checking if table contains stopping power vector for given material name
231 // or chemical formula
232 const G4String& chemFormula = material -> GetChemicalFormula();
233 const G4String& materialName = material -> GetName();
234
235 isApplicable = table -> BuildPhysicsVector(atomicNumberBase, chemFormula);
236
237 if(isApplicable) {
238 stoppingPowerTable[key] =
239 table -> GetPhysicsVector(atomicNumberBase, chemFormula);
240 return isApplicable;
241 }
242
243 isApplicable = table -> BuildPhysicsVector(atomicNumberBase, materialName);
244 if(isApplicable) {
245 stoppingPowerTable[key] =
246 table -> GetPhysicsVector(atomicNumberBase, materialName);
247 return isApplicable;
248 }
249
250 // Building the stopping power vector based on Bragg's additivity rule
251 const G4ElementVector* elementVector = material -> GetElementVector() ;
252
253 std::vector<G4PhysicsVector*> dEdxTable;
254
255 size_t nmbElements = material -> GetNumberOfElements();
256
257 for(size_t i = 0; i < nmbElements; i++) {
258
259 G4int atomicNumberMat = G4int((*elementVector)[i] -> GetZ());
260
261 isApplicable = table -> BuildPhysicsVector(atomicNumberBase, atomicNumberMat);
262
263 if(isApplicable) {
264
265 G4PhysicsVector* dEdx =
266 table -> GetPhysicsVector(atomicNumberBase, atomicNumberMat);
267 dEdxTable.push_back(dEdx);
268 }
269 else {
270
271 dEdxTable.clear();
272 break;
273 }
274 }
275
276 if(isApplicable) {
277
278 if(dEdxTable.size() > 0) {
279
280 size_t nmbdEdxBins = dEdxTable[0] -> GetVectorLength();
281 G4double lowerEdge = dEdxTable[0] -> GetLowEdgeEnergy(0);
282 G4double upperEdge = dEdxTable[0] -> GetLowEdgeEnergy(nmbdEdxBins-1);
283
284 G4LPhysicsFreeVector* dEdxBragg =
285 new G4LPhysicsFreeVector(nmbdEdxBins,
286 lowerEdge,
287 upperEdge);
288 dEdxBragg -> SetSpline(useSplines);
289
290 const G4double* massFractionVector = material -> GetFractionVector();
291
292 G4bool b;
293 for(size_t j = 0; j < nmbdEdxBins; j++) {
294
295 G4double edge = dEdxTable[0] -> GetLowEdgeEnergy(j);
296
297 G4double value = 0.0;
298 for(size_t i = 0; i < nmbElements; i++) {
299
300 value += (dEdxTable[i] -> GetValue(edge ,b)) *
301 massFractionVector[i];
302 }
303
304 dEdxBragg -> PutValues(j, edge, value);
305 }
306
307#ifdef PRINT_DEBUG
308 G4cout << "G4IonDEDXHandler::BuildPhysicsVector() for ion with Z="
309 << atomicNumberBase << " in "
310 << material -> GetName()
311 << G4endl;
312
313 G4cout << *dEdxBragg;
314#endif
315
316 stoppingPowerTable[key] = dEdxBragg;
317 stoppingPowerTableBragg[key] = dEdxBragg;
318 }
319 }
320
321 ClearCache();
322
323 return isApplicable;
324}
325
326// #########################################################################
327
328G4CacheValue G4IonDEDXHandler::UpdateCacheValue(
329 const G4ParticleDefinition* particle, // Projectile (ion)
330 const G4Material* material) { // Target material
331
332 G4CacheValue value;
333
334 G4int atomicNumberIon = particle -> GetAtomicNumber();
335 G4int atomicNumberBase =
336 algorithm -> AtomicNumberBaseIon(atomicNumberIon, material);
337
338 G4IonKey key = std::make_pair(atomicNumberBase, material);
339
340 DEDXTable::iterator iter = stoppingPowerTable.find(key);
341
342 if(iter != stoppingPowerTable.end()) {
343 value.dedxVector = iter -> second;
344
345 G4double nmbNucleons = G4double(particle -> GetAtomicMass());
346 value.energyScaling =
347 algorithm -> ScalingFactorEnergy(particle, material) / nmbNucleons;
348
349 size_t nmbdEdxBins = value.dedxVector -> GetVectorLength();
350 value.lowerEnergyEdge = value.dedxVector -> GetLowEdgeEnergy(0);
351
352 value.upperEnergyEdge =
353 value.dedxVector -> GetLowEdgeEnergy(nmbdEdxBins-1);
354 value.density = material -> GetDensity();
355 }
356 else {
357 value.dedxVector = 0;
358 value.energyScaling = 0.0;
359 value.lowerEnergyEdge = 0.0;
360 value.upperEnergyEdge = 0.0;
361 value.density = 0.0;
362 }
363
364#ifdef PRINT_DEBUG
365 G4cout << "G4IonDEDXHandler::UpdateCacheValue() for "
366 << particle -> GetParticleName() << " in "
367 << material -> GetName()
368 << G4endl;
369#endif
370
371 return value;
372}
373
374// #########################################################################
375
376G4CacheValue G4IonDEDXHandler::GetCacheValue(
377 const G4ParticleDefinition* particle, // Projectile (ion)
378 const G4Material* material) { // Target material
379
380 G4CacheKey key = std::make_pair(particle, material);
381
382 G4CacheEntry entry;
383 CacheEntryList::iterator* pointerIter =
384 (CacheEntryList::iterator*) cacheKeyPointers[key];
385
386 if(!pointerIter) {
387 entry.value = UpdateCacheValue(particle, material);
388
389 entry.key = key;
390 cacheEntries.push_front(entry);
391
392 CacheEntryList::iterator* pointerIter1 =
393 new CacheEntryList::iterator();
394 *pointerIter1 = cacheEntries.begin();
395 cacheKeyPointers[key] = pointerIter1;
396
397 if(G4int(cacheEntries.size()) > maxCacheEntries) {
398
399 G4CacheEntry lastEntry = cacheEntries.back();
400
401 void* pointerIter2 = cacheKeyPointers[lastEntry.key];
402 CacheEntryList::iterator* listPointerIter =
403 (CacheEntryList::iterator*) pointerIter2;
404
405 cacheEntries.erase(*listPointerIter);
406
407 delete listPointerIter;
408 cacheKeyPointers.erase(lastEntry.key);
409 }
410 }
411 else {
412 entry = *(*pointerIter);
413 // Cache entries are currently not re-ordered.
414 // Uncomment for activating re-ordering:
415 // cacheEntries.erase(*pointerIter);
416 // cacheEntries.push_front(entry);
417 // *pointerIter = cacheEntries.begin();
418 }
419 return entry.value;
420}
421
422// #########################################################################
423
425
426 CacheIterPointerMap::iterator iter = cacheKeyPointers.begin();
427 CacheIterPointerMap::iterator iter_end = cacheKeyPointers.end();
428
429 for(;iter != iter_end; iter++) {
430 void* pointerIter = iter -> second;
431 CacheEntryList::iterator* listPointerIter =
432 (CacheEntryList::iterator*) pointerIter;
433
434 delete listPointerIter;
435 }
436
437 cacheEntries.clear();
438 cacheKeyPointers.clear();
439}
440
441// #########################################################################
442
444 const G4ParticleDefinition* particle, // Projectile (ion)
445 const G4Material* material, // Target material
446 G4double lowerBoundary, // Minimum energy per nucleon
447 G4double upperBoundary, // Maximum energy per nucleon
448 G4int nmbBins, // Number of bins
449 G4bool logScaleEnergy) { // Logarithmic scaling of energy
450
451 G4double atomicMassNumber = particle -> GetAtomicMass();
452 G4double materialDensity = material -> GetDensity();
453
454 G4cout << "# dE/dx table for " << particle -> GetParticleName()
455 << " in material " << material -> GetName()
456 << " of density " << materialDensity / g * cm3
457 << " g/cm3"
458 << G4endl
459 << "# Projectile mass number A1 = " << atomicMassNumber
460 << G4endl
461 << "# Energy range (per nucleon) of tabulation: "
462 << GetLowerEnergyEdge(particle, material) / atomicMassNumber / MeV
463 << " - "
464 << GetUpperEnergyEdge(particle, material) / atomicMassNumber / MeV
465 << " MeV"
466 << G4endl
467 << "# ------------------------------------------------------"
468 << G4endl;
469 G4cout << "#"
470 << std::setw(13) << std::right << "E"
471 << std::setw(14) << "E/A1"
472 << std::setw(14) << "dE/dx"
473 << std::setw(14) << "1/rho*dE/dx"
474 << G4endl;
475 G4cout << "#"
476 << std::setw(13) << std::right << "(MeV)"
477 << std::setw(14) << "(MeV)"
478 << std::setw(14) << "(MeV/cm)"
479 << std::setw(14) << "(MeV*cm2/mg)"
480 << G4endl
481 << "# ------------------------------------------------------"
482 << G4endl;
483
484 //G4CacheValue value = GetCacheValue(particle, material);
485
486 G4double energyLowerBoundary = lowerBoundary * atomicMassNumber;
487 G4double energyUpperBoundary = upperBoundary * atomicMassNumber;
488
489 if(logScaleEnergy) {
490
491 energyLowerBoundary = std::log(energyLowerBoundary);
492 energyUpperBoundary = std::log(energyUpperBoundary);
493 }
494
495 G4double deltaEnergy = (energyUpperBoundary - energyLowerBoundary) /
496 G4double(nmbBins);
497
498 G4cout.precision(6);
499 for(int i = 0; i < nmbBins + 1; i++) {
500
501 G4double energy = energyLowerBoundary + i * deltaEnergy;
502 if(logScaleEnergy) energy = std::exp(energy);
503
504 G4double loss = GetDEDX(particle, material, energy);
505
506 G4cout << std::setw(14) << std::right << energy / MeV
507 << std::setw(14) << energy / atomicMassNumber / MeV
508 << std::setw(14) << loss / MeV * cm
509 << std::setw(14) << loss / materialDensity / (MeV*cm2/(0.001*g))
510 << G4endl;
511 }
512}
513
514// #########################################################################
515
517 const G4ParticleDefinition* particle, // Projectile (ion)
518 const G4Material* material) { // Target material
519
520 G4double edge = 0.0;
521
522 G4CacheValue value = GetCacheValue(particle, material);
523
524 if(value.energyScaling > 0)
525 edge = value.lowerEnergyEdge / value.energyScaling;
526
527 return edge;
528}
529
530// #########################################################################
531
533 const G4ParticleDefinition* particle, // Projectile (ion)
534 const G4Material* material) { // Target material
535
536 G4double edge = 0.0;
537
538 G4CacheValue value = GetCacheValue(particle, material);
539
540 if(value.energyScaling > 0)
541 edge = value.upperEnergyEdge / value.energyScaling;
542
543 return edge;
544}
545
546// #########################################################################
547
549
550 return tableName;
551}
552
553// #########################################################################
std::vector< G4Element * > G4ElementVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
void PrintDEDXTable(const G4ParticleDefinition *, const G4Material *, G4double, G4double, G4int, G4bool logScaleEnergy=true)
G4bool BuildDEDXTable(const G4ParticleDefinition *, const G4Material *)
G4IonDEDXHandler(G4VIonDEDXTable *tables, G4VIonDEDXScalingAlgorithm *algorithm, const G4String &name, G4int maxCacheSize=5, G4bool splines=true)
G4bool IsApplicable(const G4ParticleDefinition *, const G4Material *)
G4double GetLowerEnergyEdge(const G4ParticleDefinition *, const G4Material *)
G4double GetUpperEnergyEdge(const G4ParticleDefinition *, const G4Material *)
G4double GetDEDX(const G4ParticleDefinition *, const G4Material *, G4double)
G4double upperEnergyEdge
G4double lowerEnergyEdge
G4double density
G4PhysicsVector * dedxVector
G4double energyScaling