Geant4  9.6.p02
 All Classes 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$
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 
44 // energy range
47 
48 // max energy cut
50 
52  theParticle(0), theLossTable(0), NumberOfElements(0), TotBin(300),
53  verboseLevel(1)
54 {
55  fMaxEnergyCut = 0.;
56 }
57 
58 G4VRangeToEnergyConverter::G4VRangeToEnergyConverter(const G4VRangeToEnergyConverter& right) : theParticle(right.theParticle), theLossTable(0), TotBin(right.TotBin)
59 {
60  fMaxEnergyCut = 0.;
61  *this = right;
62 }
63 
65 {
66  if (this == &right) return *this;
67  if (theLossTable) {
69  delete theLossTable;
70  theLossTable=0;
71  }
72 
74  theParticle = right.theParticle;
75  verboseLevel = right.verboseLevel;
76 
77  // create the loss table
78  theLossTable = new G4LossTable();
80  // fill the loss table
81  for (size_t j=0; j<size_t(NumberOfElements); j++){
82  G4LossVector* aVector= new
84  for (size_t i=0; i<size_t(TotBin); i++) {
85  G4double Value = (*((*right.theLossTable)[j]))[i];
86  aVector->PutValue(i,Value);
87  }
88  theLossTable->insert(aVector);
89  }
90 
91  // clean up range vector store
92  for (size_t idx=0; idx<fRangeVectorStore.size(); idx++){
93  delete fRangeVectorStore.at(idx);
94  }
95  fRangeVectorStore.clear();
96 
97  // copy range vector store
98  for (size_t j=0; j<((right.fRangeVectorStore).size()); j++){
99  G4RangeVector* vector = (right.fRangeVectorStore).at(j);
100  G4RangeVector* rangeVector = 0;
101  if (vector !=0 ) {
102  rangeVector = new G4RangeVector(LowestEnergy, MaxEnergyCut, TotBin);
104  for (size_t i=0; i<size_t(TotBin); i++) {
105  G4double Value = (*vector)[i];
106  rangeVector->PutValue(i,Value);
107  }
108  }
109  fRangeVectorStore.push_back(rangeVector);
110  }
111  return *this;
112 }
113 
114 
116 {
117  Reset();
118 }
119 
121 {
122  return this == &right;
123 }
124 
126 {
127  return this != &right;
128 }
129 
130 
131 // **********************************************************************
132 // ************************* Convert ***********************************
133 // **********************************************************************
135  const G4Material* material)
136 {
137 #ifdef G4VERBOSE
138  if (GetVerboseLevel()>3) {
139  G4cout << "G4VRangeToEnergyConverter::Convert() ";
140  G4cout << "Convert for " << material->GetName()
141  << " with Range Cut " << rangeCut/mm << "[mm]" << G4endl;
142  }
143 #endif
144 
145  G4double theKineticEnergyCuts = 0.;
146 
147  if (fMaxEnergyCut != MaxEnergyCut) {
149  // clear loss table and renge vectors
150  Reset();
151  }
152 
153  // Build the energy loss table
154  BuildLossTable();
155 
156  // Build range vector for every material, convert cut into energy-cut,
157  // fill theKineticEnergyCuts and delete the range vector
158  G4double tune = 0.025*mm*g/cm3 ,lowen = 30.*keV ;
159 
160  // check density
161  G4double density = material->GetDensity() ;
162  if(density <= 0.) {
163  #ifdef G4VERBOSE
164  if (GetVerboseLevel()>0) {
165  G4cout << "G4VRangeToEnergyConverter::Convert() ";
166  G4cout << material->GetName() << "has zero density "
167  << "( " << density << ")" << G4endl;
168  }
169 #endif
170  return 0.;
171  }
172 
173  // initialize RangeVectorStore
175  G4int ext_size = table->size() - fRangeVectorStore.size();
176  for (int i=0; i<ext_size; i++) fRangeVectorStore.push_back(0);
177 
178  // Build Range Vector
179  G4int idx = material->GetIndex();
180  G4RangeVector* rangeVector = fRangeVectorStore.at(idx);
181  if (rangeVector == 0) {
182  rangeVector = new G4RangeVector(LowestEnergy, MaxEnergyCut, TotBin);
183  BuildRangeVector(material, rangeVector);
184  fRangeVectorStore.at(idx) = rangeVector;
185  }
186 
187  // Convert Range Cut ro Kinetic Energy Cut
188  theKineticEnergyCuts = ConvertCutToKineticEnergy(rangeVector, rangeCut, idx);
189 
190  if( ((theParticle->GetParticleName()=="e-")||(theParticle->GetParticleName()=="e+"))
191  && (theKineticEnergyCuts < lowen) ) {
192  // corr. should be switched on smoothly
193  theKineticEnergyCuts /= (1.+(1.-theKineticEnergyCuts/lowen)*
194  tune/(rangeCut*density));
195  }
196 
197  if(theKineticEnergyCuts < LowestEnergy) {
198  theKineticEnergyCuts = LowestEnergy ;
199  } else if(theKineticEnergyCuts > MaxEnergyCut) {
200  theKineticEnergyCuts = MaxEnergyCut;
201  }
202 
203  return theKineticEnergyCuts;
204 }
205 
206 // **********************************************************************
207 // ************************ SetEnergyRange *****************************
208 // **********************************************************************
210  G4double highedge)
211 {
212  // check LowestEnergy/ HighestEnergy
213  if ( (lowedge<0.0)||(highedge<=lowedge) ){
214 #ifdef G4VERBOSE
215  G4cerr << "Error in G4VRangeToEnergyConverter::SetEnergyRange";
216  G4cerr << " : illegal energy range" << "(" << lowedge/GeV;
217  G4cerr << "," << highedge/GeV << ") [GeV]" << G4endl;
218 #endif
219  G4Exception( "G4VRangeToEnergyConverter::SetEnergyRange()",
220  "ProcCuts101",
221  JustWarning, "Illegal energy range ");
222  } else {
223  LowestEnergy = lowedge;
224  HighestEnergy = highedge;
225  }
226 }
227 
228 
230 {
231  return LowestEnergy;
232 }
233 
234 
236 {
237  return HighestEnergy;
238 }
239 
240 // **********************************************************************
241 // ******************* Get/SetMaxEnergyCut *****************************
242 // **********************************************************************
244 {
245  return MaxEnergyCut;
246 }
247 
249 {
251 }
252 
253 // **********************************************************************
254 // ************************ Reset **************************************
255 // **********************************************************************
257 {
258  // delete loss table
259  if (theLossTable) {
261  delete theLossTable;
262  }
263  theLossTable=0;
265 
266  //clear RangeVectorStore
267  for (size_t idx=0; idx<fRangeVectorStore.size(); idx++){
268  delete fRangeVectorStore.at(idx);
269  }
270  fRangeVectorStore.clear();
271 }
272 
273 
274 // **********************************************************************
275 // ************************ BuildLossTable ******************************
276 // **********************************************************************
277 // create Energy Loss Table for charged particles
278 // (cross section tabel for neutral )
280 {
281  if (size_t(NumberOfElements) == G4Element::GetNumberOfElements()) return;
282 
283  // clear Loss table and Range vectors
284  Reset();
285 
286  // Build dE/dx tables for elements
288  theLossTable = new G4LossTable();
290 #ifdef G4VERBOSE
291  if (GetVerboseLevel()>3) {
292  G4cout << "G4VRangeToEnergyConverter::BuildLossTable() ";
293  G4cout << "Create theLossTable[" << theLossTable << "]";
294  G4cout << " NumberOfElements=" << NumberOfElements <<G4endl;
295  }
296 #endif
297 
298 
299  // fill the loss table
300  for (size_t j=0; j<size_t(NumberOfElements); j++){
301  G4double Value;
302  G4LossVector* aVector= 0;
304  for (size_t i=0; i<size_t(TotBin); i++) {
305  Value = ComputeLoss( (*G4Element::GetElementTable())[j]->GetZ(),
306  aVector->GetLowEdgeEnergy(i)
307  );
308  aVector->PutValue(i,Value);
309  }
310  theLossTable->insert(aVector);
311  }
312 }
313 
314 // **********************************************************************
315 // ************************ BuildRangeVector ****************************
316 // **********************************************************************
318  G4PhysicsLogVector* rangeVector)
319 {
320  // create range vector for a material
321  const G4ElementVector* elementVector = aMaterial->GetElementVector();
322  const G4double* atomicNumDensityVector = aMaterial->GetAtomicNumDensityVector();
323  G4int NumEl = aMaterial->GetNumberOfElements();
324 
325  // calculate parameters of the low energy part first
326  size_t i;
327  std::vector<G4double> lossV;
328  for ( size_t ib=0; ib<size_t(TotBin); ib++) {
329  G4double loss=0.;
330  for (i=0; i<size_t(NumEl); i++) {
331  G4int IndEl = (*elementVector)[i]->GetIndex();
332  loss += atomicNumDensityVector[i]*
333  (*((*theLossTable)[IndEl]))[ib];
334  }
335  lossV.push_back(loss);
336  }
337 
338  // Integrate with Simpson formula with logarithmic binning
339  G4double ltt = std::log(MaxEnergyCut/LowestEnergy);
340  G4double dltau = ltt/TotBin;
341 
342  G4double s0 = 0.;
343  G4double Value;
344  for ( i=0; i<size_t(TotBin); i++) {
345  G4double t = rangeVector->GetLowEdgeEnergy(i);
346  G4double q = t/lossV[i];
347  if (i==0) s0 += 0.5*q;
348  else s0 += q;
349 
350  if (i==0) {
351  Value = (s0 + 0.5*q)*dltau ;
352  } else {
353  Value = (s0 - 0.5*q)*dltau ;
354  }
355  rangeVector->PutValue(i,Value);
356  }
357 }
358 
359 // **********************************************************************
360 // ****************** ConvertCutToKineticEnergy *************************
361 // **********************************************************************
363  G4RangeVector* rangeVector,
364  G4double theCutInLength,
365 #ifdef G4VERBOSE
366  size_t materialIndex
367 #else
368  size_t
369 #endif
370  ) const
371 {
372  const G4double epsilon=0.01;
373 
374  // find max. range and the corresponding energy (rmax,Tmax)
375  G4double rmax= -1.e10*mm;
376 
377  G4double T1 = LowestEnergy;
378  G4double r1 =(*rangeVector)[0] ;
379 
380  G4double T2 = MaxEnergyCut;
381 
382  // check theCutInLength < r1
383  if ( theCutInLength <= r1 ) { return T1; }
384 
385  // scan range vector to find nearest bin
386  // ( suppose that r(Ti) > r(Tj) if Ti >Tj )
387  for (size_t ibin=0; ibin<size_t(TotBin); ibin++) {
388  G4double T=rangeVector->GetLowEdgeEnergy(ibin);
389  G4double r=(*rangeVector)[ibin];
390  if ( r>rmax ) rmax=r;
391  if (r <theCutInLength ) {
392  T1 = T;
393  r1 = r;
394  } else if (r >theCutInLength ) {
395  T2 = T;
396  break;
397  }
398  }
399 
400  // check cut in length is smaller than range max
401  if ( theCutInLength >= rmax ) {
402 #ifdef G4VERBOSE
403  if (GetVerboseLevel()>2) {
404  G4cout << "G4VRangeToEnergyConverter::ConvertCutToKineticEnergy ";
405  G4cout << " for " << theParticle->GetParticleName() << G4endl;
406  G4cout << "The cut in range [" << theCutInLength/mm << " (mm)] ";
407  G4cout << " is too big " ;
408  G4cout << " for material idx=" << materialIndex <<G4endl;
409  }
410 #endif
411  return MaxEnergyCut;
412  }
413 
414  // convert range to energy
415  G4double T3 = std::sqrt(T1*T2);
416  G4double r3 = rangeVector->Value(T3);
417  while ( std::fabs(1.-r3/theCutInLength)>epsilon ) {
418  if ( theCutInLength <= r3 ) {
419  T2 = T3;
420  } else {
421  T1 = T3;
422  }
423  T3 = std::sqrt(T1*T2);
424  r3 = rangeVector->Value(T3);
425  }
426 
427  return T3;
428 }
429