Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4VRangeToEnergyConverter.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// G4VRangeToEnergyConverter class implementation
27//
28// Author: H.Kurashige, 05 October 2002 - First implementation
29// --------------------------------------------------------------------
30
32#include "G4ParticleTable.hh"
33#include "G4Material.hh"
34#include "G4MaterialTable.hh"
35#include "G4PhysicsLogVector.hh"
36
37#include "G4ios.hh"
38#include "G4SystemOfUnits.hh"
39
43
44// --------------------------------------------------------------------
46{
47}
48
49// --------------------------------------------------------------------
52{
53 *this = right;
54}
55
56// --------------------------------------------------------------------
59{
60 if (this == &right) return *this;
61
62 if (theLossTable != nullptr)
63 {
65 delete theLossTable;
66 }
67
71 verboseLevel = right.verboseLevel;
72
73 // create the loss table
76 // fill the loss table
77 for (std::size_t j=0; j<std::size_t(NumberOfElements); ++j)
78 {
80 for (std::size_t i=0; i<=std::size_t(TotBin); ++i)
81 {
82 G4double Value = (*((*right.theLossTable)[j]))[i];
83 aVector->PutValue(i,Value);
84 }
85 theLossTable->insert(aVector);
86 }
87
88 // clean up range vector store
89 for (std::size_t idx=0; idx<fRangeVectorStore.size(); ++idx)
90 {
91 delete fRangeVectorStore.at(idx);
92 }
93 fRangeVectorStore.clear();
94
95 // copy range vector store
96 for (std::size_t j=0; j<((right.fRangeVectorStore).size()); ++j)
97 {
98 G4RangeVector* vector = (right.fRangeVectorStore).at(j);
99 G4RangeVector* rangeVector = nullptr;
100 if (vector != nullptr )
101 {
102 rangeVector = new G4RangeVector(LowestEnergy, MaxEnergyCut, TotBin);
104 for (std::size_t i=0; i<=std::size_t(TotBin); ++i)
105 {
106 G4double Value = (*vector)[i];
107 rangeVector->PutValue(i,Value);
108 }
109 }
110 fRangeVectorStore.push_back(rangeVector);
111 }
112 return *this;
113}
114
115// --------------------------------------------------------------------
117{
118 Reset();
119}
120
121// --------------------------------------------------------------------
122G4bool
124{
125 return this == &r;
126}
127
128// --------------------------------------------------------------------
129G4bool
131{
132 return this != &r;
133}
134
135// **********************************************************************
136// ************************* Convert ***********************************
137// **********************************************************************
139 const G4Material* material)
140{
141#ifdef G4VERBOSE
142 if (GetVerboseLevel()>3)
143 {
144 G4cout << "G4VRangeToEnergyConverter::Convert() - ";
145 G4cout << "Convert for " << material->GetName()
146 << " with Range Cut " << rangeCut/mm << "[mm]" << G4endl;
147 }
148#endif
149
150 G4double theKineticEnergyCuts = 0.;
151
153 {
155 // clear loss table and range vectors
156 Reset();
157 }
158
159 // Build the energy loss table
161
162 // Build range vector for every material, convert cut into energy-cut,
163 // fill theKineticEnergyCuts and delete the range vector
164 static const G4double tune = 0.025*mm*g/cm3, lowen = 30.*keV ;
165
166 // check density
167 G4double density = material->GetDensity() ;
168 if(density <= 0.)
169 {
170#ifdef G4VERBOSE
171 if (GetVerboseLevel()>0)
172 {
173 G4cout << "G4VRangeToEnergyConverter::Convert() - ";
174 G4cout << material->GetName() << "has zero density "
175 << "( " << density << ")" << G4endl;
176 }
177#endif
178 return 0.;
179 }
180
181 // initialise RangeVectorStore
183 G4int ext_size = table->size() - fRangeVectorStore.size();
184 for (G4int i=0; i<ext_size; ++i) fRangeVectorStore.push_back(nullptr);
185
186 // Build Range Vector
187 G4int idx = material->GetIndex();
188 G4RangeVector* rangeVector = fRangeVectorStore.at(idx);
189 if (rangeVector == nullptr)
190 {
191 rangeVector = new G4RangeVector(LowestEnergy, MaxEnergyCut, TotBin);
192 BuildRangeVector(material, rangeVector);
193 fRangeVectorStore.at(idx) = rangeVector;
194 }
195
196 // Convert Range Cut ro Kinetic Energy Cut
197 theKineticEnergyCuts = ConvertCutToKineticEnergy(rangeVector, rangeCut, idx);
198
199 if( ((theParticle->GetParticleName()=="e-")
200 ||(theParticle->GetParticleName()=="e+"))
201 &&(theKineticEnergyCuts < lowen) )
202 {
203 // corr. should be switched on smoothly
204 theKineticEnergyCuts /= (1.+(1.-theKineticEnergyCuts/lowen)
205 * tune/(rangeCut*density));
206 }
207
208 if(theKineticEnergyCuts < LowestEnergy)
209 {
210 theKineticEnergyCuts = LowestEnergy;
211 }
212 else if(theKineticEnergyCuts > MaxEnergyCut)
213 {
214 theKineticEnergyCuts = MaxEnergyCut;
215 }
216
217 return theKineticEnergyCuts;
218}
219
220// **********************************************************************
221// ************************ SetEnergyRange *****************************
222// **********************************************************************
224 G4double highedge)
225{
226 // check LowestEnergy/ HighestEnergy
227 if ( (lowedge<0.0)||(highedge<=lowedge) )
228 {
229#ifdef G4VERBOSE
230 G4cerr << "Error in G4VRangeToEnergyConverter::SetEnergyRange()";
231 G4cerr << ": illegal energy range" << "(" << lowedge/GeV;
232 G4cerr << "," << highedge/GeV << ") [GeV]" << G4endl;
233#endif
234 G4Exception( "G4VRangeToEnergyConverter::SetEnergyRange()",
235 "ProcCuts101", JustWarning, "Illegal energy range");
236 }
237 else
238 {
239 LowestEnergy = lowedge;
240 HighestEnergy = highedge;
241 }
242}
243
244// --------------------------------------------------------------------
246{
247 return LowestEnergy;
248}
249
250// --------------------------------------------------------------------
252{
253 return HighestEnergy;
254}
255
256// **********************************************************************
257// ******************* Get/SetMaxEnergyCut *****************************
258// **********************************************************************
260{
261 return MaxEnergyCut;
262}
263
264// --------------------------------------------------------------------
266{
267 MaxEnergyCut = value;
268}
269
270// **********************************************************************
271// ************************ Reset **************************************
272// **********************************************************************
274{
275 // delete loss table
276 if (theLossTable != nullptr)
277 {
279 delete theLossTable;
280 }
281 theLossTable = nullptr;
283
284 // clear RangeVectorStore
285 for (std::size_t idx=0; idx<fRangeVectorStore.size(); ++idx)
286 {
287 delete fRangeVectorStore.at(idx);
288 }
289 fRangeVectorStore.clear();
290}
291
292// **********************************************************************
293// ************************ BuildLossTable ******************************
294// **********************************************************************
296{
297 // Create Energy Loss Table for charged particles
298 // (cross-section table for neutral)
299
300 if (std::size_t(NumberOfElements) == G4Element::GetNumberOfElements()) return;
301
302 // clear Loss table and Range vectors
303 Reset();
304
305 // Build dE/dx tables for elements
309#ifdef G4VERBOSE
310 if (GetVerboseLevel()>3)
311 {
312 G4cout << "G4VRangeToEnergyConverter::BuildLossTable() - ";
313 G4cout << "Create theLossTable[" << theLossTable << "]";
314 G4cout << " NumberOfElements=" << NumberOfElements << G4endl;
315 }
316#endif
317
318 // fill the loss table
319 for (std::size_t j=0; j<std::size_t(NumberOfElements); ++j)
320 {
321 G4double Value;
322 G4LossVector* aVector = nullptr;
324 for (std::size_t i=0; i<=std::size_t(TotBin); ++i)
325 {
326 Value = ComputeLoss( (*G4Element::GetElementTable())[j]->GetZ(),
327 aVector->Energy(i) );
328 aVector->PutValue(i,Value);
329 }
330 theLossTable->insert(aVector);
331 }
332}
333
334// **********************************************************************
335// ************************ BuildRangeVector ****************************
336// **********************************************************************
338 G4PhysicsLogVector* rangeVector)
339{
340 // create range vector for a material
341
342 const G4ElementVector* elementVector
343 = aMaterial->GetElementVector();
344 const G4double* atomicNumDensityVector
345 = aMaterial->GetAtomicNumDensityVector();
346 G4int NumEl = aMaterial->GetNumberOfElements();
347
348 // calculate parameters of the low energy part first
349 std::size_t i;
350 std::vector<G4double> lossV;
351 for ( std::size_t ib=0; ib<=std::size_t(TotBin); ++ib)
352 {
353 G4double loss=0.;
354 for (i=0; i<std::size_t(NumEl); ++i)
355 {
356 G4int IndEl = (*elementVector)[i]->GetIndex();
357 loss += atomicNumDensityVector[i]*
358 (*((*theLossTable)[IndEl]))[ib];
359 }
360 lossV.push_back(loss);
361 }
362
363 // Integrate with Simpson formula with logarithmic binning
364 G4double dltau = 1.0;
365 if (LowestEnergy>0.)
366 {
367 G4double ltt =std::log(MaxEnergyCut/LowestEnergy);
368 dltau = ltt/TotBin;
369 }
370
371 G4double s0 = 0.;
372 G4double Value;
373 for ( i=0; i<=std::size_t(TotBin); ++i )
374 {
375 G4double t = rangeVector->GetLowEdgeEnergy(i);
376 G4double q = t/lossV[i];
377 if (i==0) s0 += 0.5*q;
378 else s0 += q;
379
380 if (i==0)
381 {
382 Value = (s0 + 0.5*q)*dltau ;
383 }
384 else
385 {
386 Value = (s0 - 0.5*q)*dltau ;
387 }
388 rangeVector->PutValue(i,Value);
389 }
390}
391
392// **********************************************************************
393// ****************** ConvertCutToKineticEnergy *************************
394// **********************************************************************
396 G4RangeVector* rangeVector,
397 G4double theCutInLength,
398#ifdef G4VERBOSE
399 std::size_t materialIndex
400#else
401 std::size_t
402#endif
403 ) const
404{
405 const G4double epsilon = 0.01;
406
407 // find max. range and the corresponding energy (rmax,Tmax)
408 G4double rmax= -1.e10*mm;
409
411 G4double r1 =(*rangeVector)[0] ;
412
414
415 // check theCutInLength < r1
416 if ( theCutInLength <= r1 ) { return T1; }
417
418 // scan range vector to find nearest bin
419 // ( suppose that r(Ti) > r(Tj) if Ti >Tj )
420 for (std::size_t ibin=0; ibin<=std::size_t(TotBin); ++ibin)
421 {
422 G4double T=rangeVector->GetLowEdgeEnergy(ibin);
423 G4double r=(*rangeVector)[ibin];
424 if ( r>rmax ) rmax=r;
425 if (r <theCutInLength )
426 {
427 T1 = T;
428 r1 = r;
429 }
430 else if (r >theCutInLength )
431 {
432 T2 = T;
433 break;
434 }
435 }
436
437 // check cut in length is smaller than range max
438 if ( theCutInLength >= rmax )
439 {
440#ifdef G4VERBOSE
441 if (GetVerboseLevel()>2)
442 {
443 G4cout << "G4VRangeToEnergyConverter::ConvertCutToKineticEnergy ";
444 G4cout << " for " << theParticle->GetParticleName() << G4endl;
445 G4cout << "The cut in range [" << theCutInLength/mm << " (mm)] ";
446 G4cout << " is too big " ;
447 G4cout << " for material idx=" << materialIndex <<G4endl;
448 }
449#endif
450 return MaxEnergyCut;
451 }
452
453 // convert range to energy
454 G4double T3 = std::sqrt(T1*T2);
455 G4double r3 = rangeVector->Value(T3);
456 const std::size_t MAX_LOOP = 1000;
457 for (std::size_t loop_count=0; loop_count<MAX_LOOP; ++loop_count)
458 {
459 if (std::fabs(1.-r3/theCutInLength)<epsilon ) break;
460 if ( theCutInLength <= r3 )
461 {
462 T2 = T3;
463 }
464 else
465 {
466 T1 = T3;
467 }
468 T3 = std::sqrt(T1*T2);
469 r3 = rangeVector->Value(T3);
470 }
471 return T3;
472}
double epsilon(double density, double temperature)
std::vector< G4Element * > G4ElementVector
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::vector< G4Material * > G4MaterialTable
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
static G4ElementTable * GetElementTable()
Definition: G4Element.cc:397
static size_t GetNumberOfElements()
Definition: G4Element.cc:404
G4double GetDensity() const
Definition: G4Material.hh:178
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:188
size_t GetNumberOfElements() const
Definition: G4Material.hh:184
const G4double * GetAtomicNumDensityVector() const
Definition: G4Material.hh:214
static G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:637
const G4String & GetName() const
Definition: G4Material.hh:175
size_t GetIndex() const
Definition: G4Material.hh:258
const G4String & GetParticleName() const
void clearAndDestroy()
void insert(G4PhysicsVector *)
G4double Energy(std::size_t index) const
G4double Value(G4double theEnergy, std::size_t &lastidx) const
G4double GetLowEdgeEnergy(std::size_t binNumber) const
void PutValue(std::size_t index, G4double theValue)
std::vector< G4RangeVector * > fRangeVectorStore
virtual void BuildRangeVector(const G4Material *aMaterial, G4RangeVector *rangeVector)
G4bool operator!=(const G4VRangeToEnergyConverter &r) const
G4bool operator==(const G4VRangeToEnergyConverter &r) const
virtual G4double Convert(G4double rangeCut, const G4Material *material)
virtual G4double ComputeLoss(G4double AtomicNumber, G4double KineticEnergy)=0
G4double ConvertCutToKineticEnergy(G4RangeVector *theRangeVector, G4double theCutInLength, std::size_t materialIndex) const
static void SetMaxEnergyCut(G4double value)
static void SetEnergyRange(G4double lowedge, G4double highedge)
const G4ParticleDefinition * theParticle
G4VRangeToEnergyConverter & operator=(const G4VRangeToEnergyConverter &r)