Geant4.10
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 //
27 // $Id: G4VRangeToEnergyConverter.cc 79177 2014-02-19 16:10:41Z gcosmo $
28 //
29 //
30 // --------------------------------------------------------------
31 // GEANT 4 class implementation file/ History:
32 // 5 Oct. 2002, H.Kuirashige : Structure created based on object model
33 // --------------------------------------------------------------
34 
36 #include "G4ParticleTable.hh"
37 #include "G4Material.hh"
38 #include "G4MaterialTable.hh"
39 #include "G4PhysicsLogVector.hh"
40 
41 #include "G4ios.hh"
42 #include "G4SystemOfUnits.hh"
43 
47 
49  theParticle(0), theLossTable(0), NumberOfElements(0), TotBin(300),
50  verboseLevel(1)
51 {
52  fMaxEnergyCut = 0.;
53 }
54 
55 G4VRangeToEnergyConverter::G4VRangeToEnergyConverter(const G4VRangeToEnergyConverter& right) : theParticle(right.theParticle), theLossTable(0), TotBin(right.TotBin)
56 {
57  fMaxEnergyCut = 0.;
58  if (theLossTable) {
60  delete theLossTable;
61  theLossTable=0;
62  }
63  *this = right;
64 }
65 
67 {
68  if (this == &right) return *this;
69  if (theLossTable) {
71  delete theLossTable;
72  theLossTable=0;
73  }
74 
75  LowestEnergy = right.LowestEnergy;
77  MaxEnergyCut = right.MaxEnergyCut;
80  theParticle = right.theParticle;
81  verboseLevel = right.verboseLevel;
82 
83  // create the loss table
84  theLossTable = new G4LossTable();
86  // fill the loss table
87  for (size_t j=0; j<size_t(NumberOfElements); j++){
89  for (size_t i=0; i<=size_t(TotBin); i++) {
90  G4double Value = (*((*right.theLossTable)[j]))[i];
91  aVector->PutValue(i,Value);
92  }
93  theLossTable->insert(aVector);
94  }
95 
96  // clean up range vector store
97  for (size_t idx=0; idx<fRangeVectorStore.size(); idx++){
98  delete fRangeVectorStore.at(idx);
99  }
100  fRangeVectorStore.clear();
101 
102  // copy range vector store
103  for (size_t j=0; j<((right.fRangeVectorStore).size()); j++){
104  G4RangeVector* vector = (right.fRangeVectorStore).at(j);
105  G4RangeVector* rangeVector = 0;
106  if (vector !=0 ) {
107  rangeVector = new G4RangeVector(LowestEnergy, MaxEnergyCut, TotBin);
109  for (size_t i=0; i<=size_t(TotBin); i++) {
110  G4double Value = (*vector)[i];
111  rangeVector->PutValue(i,Value);
112  }
113  }
114  fRangeVectorStore.push_back(rangeVector);
115  }
116  return *this;
117 }
118 
119 
121 {
122  // Reset();
123  // Comment out Reset() for MT application
124 
125  // delete loss table without deleteing vectors
126  if (theLossTable) {
127  delete theLossTable;
128  }
129  theLossTable=0;
131 
132  //clear RangeVectorStore without deleteing vectors
133  fRangeVectorStore.clear();
134 
135 }
136 
138 {
139  return this == &right;
140 }
141 
143 {
144  return this != &right;
145 }
146 
147 
148 // **********************************************************************
149 // ************************* Convert ***********************************
150 // **********************************************************************
152  const G4Material* material)
153 {
154 #ifdef G4VERBOSE
155  if (GetVerboseLevel()>3) {
156  G4cout << "G4VRangeToEnergyConverter::Convert() ";
157  G4cout << "Convert for " << material->GetName()
158  << " with Range Cut " << rangeCut/mm << "[mm]" << G4endl;
159  }
160 #endif
161 
162  G4double theKineticEnergyCuts = 0.;
163 
164  if (fMaxEnergyCut != MaxEnergyCut) {
166  // clear loss table and renge vectors
167  Reset();
168  }
169 
170  // Build the energy loss table
171  BuildLossTable();
172 
173  // Build range vector for every material, convert cut into energy-cut,
174  // fill theKineticEnergyCuts and delete the range vector
175  static const G4double tune = 0.025*mm*g/cm3 ,lowen = 30.*keV ;
176 
177  // check density
178  G4double density = material->GetDensity() ;
179  if(density <= 0.) {
180 #ifdef G4VERBOSE
181  if (GetVerboseLevel()>0) {
182  G4cout << "G4VRangeToEnergyConverter::Convert() ";
183  G4cout << material->GetName() << "has zero density "
184  << "( " << density << ")" << G4endl;
185  }
186 #endif
187  return 0.;
188  }
189 
190  // initialize RangeVectorStore
192  G4int ext_size = table->size() - fRangeVectorStore.size();
193  for (int i=0; i<ext_size; i++) fRangeVectorStore.push_back(0);
194 
195  // Build Range Vector
196  G4int idx = material->GetIndex();
197  G4RangeVector* rangeVector = fRangeVectorStore.at(idx);
198  if (rangeVector == 0) {
199  rangeVector = new G4RangeVector(LowestEnergy, MaxEnergyCut, TotBin);
200  BuildRangeVector(material, rangeVector);
201  fRangeVectorStore.at(idx) = rangeVector;
202  }
203 
204  // Convert Range Cut ro Kinetic Energy Cut
205  theKineticEnergyCuts = ConvertCutToKineticEnergy(rangeVector, rangeCut, idx);
206 
207  if( ((theParticle->GetParticleName()=="e-")||(theParticle->GetParticleName()=="e+"))
208  && (theKineticEnergyCuts < lowen) ) {
209  // corr. should be switched on smoothly
210  theKineticEnergyCuts /= (1.+(1.-theKineticEnergyCuts/lowen)*
211  tune/(rangeCut*density));
212  }
213 
214  if(theKineticEnergyCuts < LowestEnergy) {
215  theKineticEnergyCuts = LowestEnergy ;
216  } else if(theKineticEnergyCuts > MaxEnergyCut) {
217  theKineticEnergyCuts = MaxEnergyCut;
218  }
219 
220  return theKineticEnergyCuts;
221 }
222 
223 // **********************************************************************
224 // ************************ SetEnergyRange *****************************
225 // **********************************************************************
227  G4double highedge)
228 {
229  // check LowestEnergy/ HighestEnergy
230  if ( (lowedge<0.0)||(highedge<=lowedge) ){
231 #ifdef G4VERBOSE
232  G4cerr << "Error in G4VRangeToEnergyConverter::SetEnergyRange";
233  G4cerr << " : illegal energy range" << "(" << lowedge/GeV;
234  G4cerr << "," << highedge/GeV << ") [GeV]" << G4endl;
235 #endif
236  G4Exception( "G4VRangeToEnergyConverter::SetEnergyRange()",
237  "ProcCuts101",
238  JustWarning, "Illegal energy range ");
239  } else {
240  LowestEnergy = lowedge;
241  HighestEnergy = highedge;
242  }
243 }
244 
245 
247 {
248  return LowestEnergy;
249 }
250 
251 
253 {
254  return HighestEnergy;
255 }
256 
257 // **********************************************************************
258 // ******************* Get/SetMaxEnergyCut *****************************
259 // **********************************************************************
261 {
262  return MaxEnergyCut;
263 }
264 
266 {
268 }
269 
270 // **********************************************************************
271 // ************************ Reset **************************************
272 // **********************************************************************
274 {
275  // delete loss table
276  if (theLossTable) {
278  delete theLossTable;
279  }
280  theLossTable=0;
282 
283  //clear RangeVectorStore
284  for (size_t idx=0; idx<fRangeVectorStore.size(); idx++){
285  delete fRangeVectorStore.at(idx);
286  }
287  fRangeVectorStore.clear();
288 }
289 
290 
291 // **********************************************************************
292 // ************************ BuildLossTable ******************************
293 // **********************************************************************
294 // create Energy Loss Table for charged particles
295 // (cross section tabel for neutral )
297 {
298  if (size_t(NumberOfElements) == G4Element::GetNumberOfElements()) return;
299 
300  // clear Loss table and Range vectors
301  Reset();
302 
303  // Build dE/dx tables for elements
305  theLossTable = new G4LossTable();
307 #ifdef G4VERBOSE
308  if (GetVerboseLevel()>3) {
309  G4cout << "G4VRangeToEnergyConverter::BuildLossTable() ";
310  G4cout << "Create theLossTable[" << theLossTable << "]";
311  G4cout << " NumberOfElements=" << NumberOfElements <<G4endl;
312  }
313 #endif
314 
315 
316  // fill the loss table
317  for (size_t j=0; j<size_t(NumberOfElements); j++){
318  G4double Value;
319  G4LossVector* aVector= 0;
321  for (size_t i=0; i<=size_t(TotBin); i++) {
322  Value = ComputeLoss( (*G4Element::GetElementTable())[j]->GetZ(),
323  aVector->Energy(i)
324  );
325  aVector->PutValue(i,Value);
326  }
327  theLossTable->insert(aVector);
328  }
329 }
330 
331 // **********************************************************************
332 // ************************ BuildRangeVector ****************************
333 // **********************************************************************
335  G4PhysicsLogVector* rangeVector)
336 {
337  // create range vector for a material
338  const G4ElementVector* elementVector = aMaterial->GetElementVector();
339  const G4double* atomicNumDensityVector = aMaterial->GetAtomicNumDensityVector();
340  G4int NumEl = aMaterial->GetNumberOfElements();
341 
342  // calculate parameters of the low energy part first
343  size_t i;
344  std::vector<G4double> lossV;
345  for ( size_t ib=0; ib<=size_t(TotBin); ib++) {
346  G4double loss=0.;
347  for (i=0; i<size_t(NumEl); i++) {
348  G4int IndEl = (*elementVector)[i]->GetIndex();
349  loss += atomicNumDensityVector[i]*
350  (*((*theLossTable)[IndEl]))[ib];
351  }
352  lossV.push_back(loss);
353  }
354 
355  // Integrate with Simpson formula with logarithmic binning
356  G4double ltt = std::log(MaxEnergyCut/LowestEnergy);
357  G4double dltau = ltt/TotBin;
358 
359  G4double s0 = 0.;
360  G4double Value;
361  for ( i=0; i<=size_t(TotBin); i++) {
362  G4double t = rangeVector->GetLowEdgeEnergy(i);
363  G4double q = t/lossV[i];
364  if (i==0) s0 += 0.5*q;
365  else s0 += q;
366 
367  if (i==0) {
368  Value = (s0 + 0.5*q)*dltau ;
369  } else {
370  Value = (s0 - 0.5*q)*dltau ;
371  }
372  rangeVector->PutValue(i,Value);
373  }
374 }
375 
376 // **********************************************************************
377 // ****************** ConvertCutToKineticEnergy *************************
378 // **********************************************************************
380  G4RangeVector* rangeVector,
381  G4double theCutInLength,
382 #ifdef G4VERBOSE
383  size_t materialIndex
384 #else
385  size_t
386 #endif
387  ) const
388 {
389  const G4double epsilon=0.01;
390 
391  // find max. range and the corresponding energy (rmax,Tmax)
392  G4double rmax= -1.e10*mm;
393 
394  G4double T1 = LowestEnergy;
395  G4double r1 =(*rangeVector)[0] ;
396 
397  G4double T2 = MaxEnergyCut;
398 
399  // check theCutInLength < r1
400  if ( theCutInLength <= r1 ) { return T1; }
401 
402  // scan range vector to find nearest bin
403  // ( suppose that r(Ti) > r(Tj) if Ti >Tj )
404  for (size_t ibin=0; ibin<=size_t(TotBin); ibin++) {
405  G4double T=rangeVector->GetLowEdgeEnergy(ibin);
406  G4double r=(*rangeVector)[ibin];
407  if ( r>rmax ) rmax=r;
408  if (r <theCutInLength ) {
409  T1 = T;
410  r1 = r;
411  } else if (r >theCutInLength ) {
412  T2 = T;
413  break;
414  }
415  }
416 
417  // check cut in length is smaller than range max
418  if ( theCutInLength >= rmax ) {
419 #ifdef G4VERBOSE
420  if (GetVerboseLevel()>2) {
421  G4cout << "G4VRangeToEnergyConverter::ConvertCutToKineticEnergy ";
422  G4cout << " for " << theParticle->GetParticleName() << G4endl;
423  G4cout << "The cut in range [" << theCutInLength/mm << " (mm)] ";
424  G4cout << " is too big " ;
425  G4cout << " for material idx=" << materialIndex <<G4endl;
426  }
427 #endif
428  return MaxEnergyCut;
429  }
430 
431  // convert range to energy
432  G4double T3 = std::sqrt(T1*T2);
433  G4double r3 = rangeVector->Value(T3);
434  while ( std::fabs(1.-r3/theCutInLength)>epsilon ) {
435  if ( theCutInLength <= r3 ) {
436  T2 = T3;
437  } else {
438  T1 = T3;
439  }
440  T3 = std::sqrt(T1*T2);
441  r3 = rangeVector->Value(T3);
442  }
443 
444  return T3;
445 }
446 
G4int operator!=(const G4VRangeToEnergyConverter &right) const
std::vector< G4Element * > G4ElementVector
void insert(G4PhysicsVector *)
size_t GetIndex() const
Definition: G4Material.hh:260
const G4String & GetName() const
Definition: G4Material.hh:176
static G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:564
std::vector< G4Material * > G4MaterialTable
G4double GetDensity() const
Definition: G4Material.hh:178
virtual void BuildRangeVector(const G4Material *aMaterial, G4RangeVector *rangeVector)
G4double GetLowEdgeEnergy(size_t binNumber) const
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:188
int G4int
Definition: G4Types.hh:78
const G4String & GetParticleName() const
string material
Definition: eplot.py:19
G4double density
Definition: TRTMaterials.hh:39
function g(Y1, Y2, PT2)
Definition: hijing1.383.f:5205
virtual G4double ComputeLoss(G4double AtomicNumber, G4double KineticEnergy)=0
G4GLOB_DLL std::ostream G4cout
G4double ConvertCutToKineticEnergy(G4RangeVector *theRangeVector, G4double theCutInLength, size_t materialIndex) const
static size_t GetNumberOfElements()
Definition: G4Element.cc:402
virtual G4double Convert(G4double rangeCut, const G4Material *material)
G4int operator==(const G4VRangeToEnergyConverter &right) const
static void SetMaxEnergyCut(G4double value)
void PutValue(size_t index, G4double theValue)
G4VRangeToEnergyConverter & operator=(const G4VRangeToEnergyConverter &right)
static void SetEnergyRange(G4double lowedge, G4double highedge)
G4double Energy(size_t index) const
G4double Value(G4double theEnergy, size_t &lastidx) const
const G4double * GetAtomicNumDensityVector() const
Definition: G4Material.hh:214
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
std::vector< G4RangeVector * > fRangeVectorStore
const XML_Char int const XML_Char * value
#define G4endl
Definition: G4ios.hh:61
size_t GetNumberOfElements() const
Definition: G4Material.hh:184
double G4double
Definition: G4Types.hh:76
static G4ElementTable * GetElementTable()
Definition: G4Element.cc:395
void clearAndDestroy()
const G4ParticleDefinition * theParticle
G4GLOB_DLL std::ostream G4cerr