source: trunk/source/processes/electromagnetic/utils/src/G4EmCalculator.cc @ 869

Last change on this file since 869 was 819, checked in by garnier, 16 years ago

import all except CVS

File size: 35.0 KB
Line 
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// $Id: G4EmCalculator.cc,v 1.37 2007/08/16 15:55:42 vnivanch Exp $
27// GEANT4 tag $Name: geant4-09-01-patch-02 $
28//
29// -------------------------------------------------------------------
30//
31// GEANT4 Class file
32//
33//
34// File name:     G4EmCalculator
35//
36// Author:        Vladimir Ivanchenko
37//
38// Creation date: 28.06.2004
39//
40// Modifications:
41// 12.09.2004 Add verbosity (V.Ivanchenko)
42// 17.11.2004 Change signature of methods, add new methods (V.Ivanchenko)
43// 08.04.2005 Major optimisation of internal interfaces (V.Ivantchenko)
44// 08.05.2005 Use updated interfaces (V.Ivantchenko)
45// 23.10.2005 Fix computations for ions (V.Ivantchenko)
46// 11.01.2006 Add GetCSDARange (V.Ivantchenko)
47// 26.01.2006 Rename GetRange -> GetRangeFromRestricteDEDX (V.Ivanchenko)
48// 14.03.2006 correction in GetCrossSectionPerVolume (mma)
49//            suppress GetCrossSectionPerAtom
50//            elm->GetA() in ComputeCrossSectionPerAtom
51// 22.03.2006 Add ComputeElectronicDEDX and ComputeTotalDEDX (V.Ivanchenko)
52// 13.05.2006 Add Corrections for ion stopping (V.Ivanchenko)
53// 29.09.2006 Uncomment computation of smoothing factor (V.Ivanchenko)
54// 27.10.2006 Change test energy to access lowEnergy model from
55//            10 keV to 1 keV (V. Ivanchenko)
56// 15.03.2007 Add ComputeEnergyCutFromRangeCut methods (V.Ivanchenko)
57//
58// Class Description:
59//
60// -------------------------------------------------------------------
61//
62//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
63//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
64
65#include "G4EmCalculator.hh"
66#include "G4LossTableManager.hh"
67#include "G4VEmProcess.hh"
68#include "G4VEnergyLossProcess.hh"
69#include "G4VMultipleScattering.hh"
70#include "G4Material.hh"
71#include "G4MaterialCutsCouple.hh"
72#include "G4ParticleDefinition.hh"
73#include "G4ParticleTable.hh"
74#include "G4PhysicsTable.hh"
75#include "G4ProductionCutsTable.hh"
76#include "G4ProcessManager.hh"
77#include "G4ionEffectiveCharge.hh"
78#include "G4RegionStore.hh"
79#include "G4Element.hh"
80#include "G4EmCorrections.hh"
81#include "G4GenericIon.hh"
82
83//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
84
85G4EmCalculator::G4EmCalculator()
86{
87  manager = G4LossTableManager::Instance();
88  corr    = manager->EmCorrections();
89  nLocalMaterials    = 0;
90  verbose            = 0;
91  currentCoupleIndex = 0;
92  currentCouple      = 0;
93  currentMaterial    = 0;
94  currentParticle    = 0;
95  baseParticle       = 0;
96  currentLambda      = 0;
97  currentModel       = 0;
98  loweModel          = 0;
99  chargeSquare       = 1.0;
100  massRatio          = 1.0;
101  currentParticleName= "";
102  currentMaterialName= "";
103  theGenericIon      = G4GenericIon::GenericIon();
104  ionEffCharge       = new G4ionEffectiveCharge();
105  isIon              = false;
106  isApplicable       = false;
107}
108
109//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
110
111G4EmCalculator::~G4EmCalculator()
112{
113  delete ionEffCharge;
114  for (G4int i=0; i<nLocalMaterials; i++) {
115    delete localCouples[i];
116  }
117}
118
119//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
120
121G4double G4EmCalculator::GetDEDX(G4double kinEnergy, const G4ParticleDefinition* p,
122                                 const G4Material* mat, const G4Region* region)
123{
124  G4double res = 0.0;
125  const G4MaterialCutsCouple* couple = FindCouple(mat, region);
126  if(couple && UpdateParticle(p, kinEnergy) ) {
127    res = manager->GetDEDX(p, kinEnergy, couple);
128    if(verbose>0) {
129      G4cout << "G4EmCalculator::GetDEDX: E(MeV)= " << kinEnergy/MeV
130             << " DEDX(MeV/mm)= " << res*mm/MeV
131             << " DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->GetDensity())
132             << "  " <<  p->GetParticleName()
133             << " in " <<  mat->GetName()
134             << G4endl;
135    }
136  }
137  return res;
138}
139
140//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
141
142G4double G4EmCalculator::GetDEDX(G4double kinEnergy, const G4String& particle,
143                                 const G4String& material, const G4String& reg)
144{
145  return GetDEDX(kinEnergy,FindParticle(particle),
146                 FindMaterial(material),FindRegion(reg));
147}
148
149//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
150
151G4double G4EmCalculator::GetRangeFromRestricteDEDX(G4double kinEnergy, 
152                                                   const G4ParticleDefinition* p,
153                                                   const G4Material* mat,
154                                                   const G4Region* region)
155{
156  G4double res = 0.0;
157  const G4MaterialCutsCouple* couple = FindCouple(mat,region);
158  if(couple && UpdateParticle(p, kinEnergy)) {
159    res = manager->GetRangeFromRestricteDEDX(p, kinEnergy, couple);
160    if(verbose>0) {
161      G4cout << "G4EmCalculator::GetRange: E(MeV)= " << kinEnergy/MeV
162             << " range(mm)= " << res/mm
163             << "  " <<  p->GetParticleName()
164             << " in " <<  mat->GetName()
165             << G4endl;
166    }
167  }
168  return res;
169}
170
171//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
172
173G4double G4EmCalculator::GetCSDARange(G4double kinEnergy, 
174                                      const G4ParticleDefinition* p,
175                                      const G4Material* mat, 
176                                      const G4Region* region)
177{
178  G4double res = 0.0;
179  const G4MaterialCutsCouple* couple = FindCouple(mat,region);
180  if(couple && UpdateParticle(p, kinEnergy)) {
181    res = manager->GetCSDARange(p, kinEnergy, couple);
182    if(verbose>0) {
183      G4cout << "G4EmCalculator::GetRange: E(MeV)= " << kinEnergy/MeV
184             << " range(mm)= " << res/mm
185             << "  " <<  p->GetParticleName()
186             << " in " <<  mat->GetName()
187             << G4endl;
188    }
189  }
190  return res;
191}
192
193//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
194
195G4double G4EmCalculator::GetRange(G4double kinEnergy, 
196                                  const G4ParticleDefinition* p,
197                                  const G4Material* mat, 
198                                  const G4Region* region)
199{
200  G4double res = 0.0;
201  const G4MaterialCutsCouple* couple = FindCouple(mat,region);
202  if(couple && UpdateParticle(p, kinEnergy)) {
203    res = manager->GetRange(p, kinEnergy, couple);
204    if(verbose>0) {
205      G4cout << "G4EmCalculator::GetRange: E(MeV)= " << kinEnergy/MeV
206             << " range(mm)= " << res/mm
207             << "  " <<  p->GetParticleName()
208             << " in " <<  mat->GetName()
209             << G4endl;
210    }
211  }
212  return res;
213}
214
215//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
216
217G4double G4EmCalculator::GetRangeFromRestricteDEDX(G4double kinEnergy, 
218                                                   const G4String& particle,
219                                                   const G4String& material, 
220                                                   const G4String& reg)
221{
222  return GetRangeFromRestricteDEDX(kinEnergy,FindParticle(particle),
223                                   FindMaterial(material),FindRegion(reg));
224}
225
226//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
227
228G4double G4EmCalculator::GetCSDARange(G4double kinEnergy, 
229                                      const G4String& particle,
230                                      const G4String& material, 
231                                      const G4String& reg)
232{
233  return GetCSDARange(kinEnergy,FindParticle(particle),
234                  FindMaterial(material),FindRegion(reg));
235}
236
237//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
238
239G4double G4EmCalculator::GetRange(G4double kinEnergy, 
240                                  const G4String& particle,
241                                  const G4String& material, 
242                                  const G4String& reg)
243{
244  return GetRange(kinEnergy,FindParticle(particle),
245                  FindMaterial(material),FindRegion(reg));
246}
247
248//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
249
250G4double G4EmCalculator::GetKinEnergy(G4double range, 
251                                      const G4ParticleDefinition* p,
252                                      const G4Material* mat,
253                                      const G4Region* region)
254{
255  G4double res = 0.0;
256  const G4MaterialCutsCouple* couple = FindCouple(mat,region);
257  if(couple && UpdateParticle(p, 1.0*GeV)) {
258    res = manager->GetEnergy(p, range, couple);
259    if(verbose>0) {
260      G4cout << "G4EmCalculator::GetKinEnergy: Range(mm)= " << range/mm
261             << " KinE(MeV)= " << res/MeV
262             << "  " <<  p->GetParticleName()
263             << " in " <<  mat->GetName()
264             << G4endl;
265    }
266  }
267  return res;
268}
269
270//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
271
272G4double G4EmCalculator::GetKinEnergy(G4double range, const G4String& particle,
273                                      const G4String& material, const G4String& reg)
274{
275  return GetKinEnergy(range,FindParticle(particle),
276                      FindMaterial(material),FindRegion(reg));
277}
278
279//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
280
281G4double G4EmCalculator::GetCrossSectionPerVolume(G4double kinEnergy,
282                                            const G4ParticleDefinition* p,
283                                            const G4String& processName,
284                                            const G4Material* mat,
285                                            const G4Region* region)
286{
287  G4double res = 0.0;
288  const G4MaterialCutsCouple* couple = FindCouple(mat,region);
289
290  if(couple && UpdateParticle(p, kinEnergy)) {
291    G4int idx = couple->GetIndex();
292    FindLambdaTable(p, processName);
293    if(currentLambda) {
294      G4bool b;
295      G4double e = kinEnergy*massRatio;
296      res = (((*currentLambda)[idx])->GetValue(e,b))*chargeSquare;
297      if(verbose>0) {
298        G4cout << "E(MeV)= " << kinEnergy/MeV
299               << " cross(cm-1)= " << res*cm
300               << "  " <<  p->GetParticleName()
301               << " in " <<  mat->GetName();
302        if(verbose>1) 
303          G4cout << "  idx= " << idx << "  e(MeV)= " << e
304                 << "  q2= " << chargeSquare; 
305        G4cout << G4endl;
306      }
307    }
308  }
309  return res;
310}
311
312//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
313
314G4double G4EmCalculator::GetCrossSectionPerVolume(G4double kinEnergy,
315                                            const G4String& particle,
316                                            const G4String& processName,
317                                            const G4String& material,
318                                            const G4String& reg)
319{
320  return GetCrossSectionPerVolume(kinEnergy,FindParticle(particle),processName,
321                                  FindMaterial(material),FindRegion(reg));
322}
323
324//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
325
326G4double G4EmCalculator::GetMeanFreePath(G4double kinEnergy,
327                                         const G4ParticleDefinition* p,
328                                         const G4String& processName,
329                                         const G4Material* mat,
330                                         const G4Region* region)
331{
332  G4double res = DBL_MAX;
333  G4double x = GetCrossSectionPerVolume(kinEnergy,p, processName, mat,region);
334  if(x > 0.0) res = 1.0/x;
335  if(verbose>1) {
336    G4cout << "G4EmCalculator::GetMeanFreePath: E(MeV)= " << kinEnergy/MeV
337           << " MFP(mm)= " << res/mm
338           << "  " <<  p->GetParticleName()
339           << " in " <<  mat->GetName()
340           << G4endl;
341  }
342  return res;
343}
344
345//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
346
347G4double G4EmCalculator::GetMeanFreePath(G4double kinEnergy,
348                                         const G4String& particle,
349                                         const G4String& processName,
350                                         const G4String& material,
351                                         const G4String& reg)
352{
353  return GetMeanFreePath(kinEnergy,FindParticle(particle),processName,
354                         FindMaterial(material),FindRegion(reg));
355}
356
357//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
358
359void G4EmCalculator::PrintDEDXTable(const G4ParticleDefinition* p)
360{
361  const G4VEnergyLossProcess* elp = FindEnergyLossProcess(p);
362  G4cout << "##### DEDX Table for " << p->GetParticleName() << G4endl;
363  if(elp) G4cout << *(elp->DEDXTable()) << G4endl;
364}
365
366//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
367
368void G4EmCalculator::PrintRangeTable(const G4ParticleDefinition* p)
369{
370  const G4VEnergyLossProcess* elp = FindEnergyLossProcess(p);
371  G4cout << "##### Range Table for " << p->GetParticleName() << G4endl;
372  if(elp) G4cout << *(elp->RangeTableForLoss()) << G4endl;
373}
374
375//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
376
377void G4EmCalculator::PrintInverseRangeTable(const G4ParticleDefinition* p)
378{
379  const G4VEnergyLossProcess* elp = FindEnergyLossProcess(p);
380  G4cout << "### G4EmCalculator: Inverse Range Table for " 
381         << p->GetParticleName() << G4endl;
382  if(elp) G4cout << *(elp->InverseRangeTable()) << G4endl;
383}
384
385//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
386
387G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy,
388                                     const G4ParticleDefinition* p,
389                                     const G4String& processName,
390                                     const G4Material* mat,
391                                           G4double cut)
392{
393  currentMaterial = mat;
394  currentMaterialName = mat->GetName();
395  G4double res = 0.0;
396  if(verbose > 1) {
397    G4cout << "### G4EmCalculator::ComputeDEDX: " << p->GetParticleName()
398           << " in " << currentMaterialName
399           << " e(MeV)= " << kinEnergy/MeV << "  cut(MeV)= " << cut/MeV
400           << G4endl;
401  }
402  if(UpdateParticle(p, kinEnergy)) {
403    if(FindEmModel(p, processName, kinEnergy)) {
404      G4double escaled = kinEnergy*massRatio;
405      if(baseParticle) {
406        res = currentModel->ComputeDEDXPerVolume(
407              mat, baseParticle, escaled, cut) * chargeSquare;
408        if(verbose > 1)
409          G4cout <<  baseParticle->GetParticleName()
410                 << " Escaled(MeV)= " << escaled;
411      } else {
412        res = currentModel->ComputeDEDXPerVolume(mat, p, kinEnergy, cut);
413        if(verbose > 1) G4cout <<  " no basePart E(MeV)= " << kinEnergy;
414      }
415      if(verbose > 1)
416        G4cout << " DEDX(MeV/mm)= " << res*mm/MeV
417               << " DEDX(MeV*cm^2/g)= "
418               << res*gram/(MeV*cm2*mat->GetDensity())
419               << G4endl;
420
421      if(isIon) {
422        if(currentModel->HighEnergyLimit() > 100.*MeV)
423          res += corr->HighOrderCorrections(p,mat,kinEnergy);
424        else
425          res *= corr->EffectiveChargeCorrection(p,mat,kinEnergy);
426        if(verbose > 1)
427          G4cout << "After Corrections: DEDX(MeV/mm)= " << res*mm/MeV
428                 << " DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->GetDensity())
429                 << G4endl;
430      }
431
432     
433      // emulate boundary region for different parameterisations
434      G4double eth = currentModel->LowEnergyLimit();
435      //      G4cout << "massRatio= " << massRatio << " eth= " << eth << G4endl;
436      if(eth > 0.05*MeV && eth < 10.*MeV && escaled > eth && 
437         loweModel != currentModel && loweModel) {
438        G4double res0 = 0.0;
439        G4double res1 = 0.0;
440        if(baseParticle) {
441          res1 = currentModel->ComputeDEDXPerVolume(mat, baseParticle, eth, cut)
442               * chargeSquare;
443          res0 = loweModel->ComputeDEDXPerVolume(mat, baseParticle, eth, cut)
444               * chargeSquare;
445        } else {
446          res1 = currentModel->ComputeDEDXPerVolume(mat, p, eth, cut);
447          res0 = loweModel->ComputeDEDXPerVolume(mat, p, eth, cut);
448        }
449        if(verbose > 1)
450          G4cout << "At boundary energy(MeV)= " << eth/MeV
451                 << " DEDX(MeV/mm)= " << res1*mm/MeV
452                 << G4endl;
453        if(isIon) res1 += corr->HighOrderCorrections(p,mat,eth/massRatio);
454        //G4cout << "eth= " << eth << " escaled= " << escaled
455        //  << " res0= " << res0 << " res1= "
456        //       << res1 <<  "  q2= " << chargeSquare << G4endl;
457        res *= (1.0 + (res0/res1 - 1.0)*eth/escaled);
458      }
459     
460      if(verbose > 0) {
461        G4cout << "E(MeV)= " << kinEnergy/MeV
462               << " DEDX(MeV/mm)= " << res*mm/MeV
463               << " DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->GetDensity())
464               << " cut(MeV)= " << cut/MeV
465               << "  " <<  p->GetParticleName()
466               << " in " <<  currentMaterialName
467               << " Zi^2= " << chargeSquare
468               << G4endl;
469      }
470    }
471  }
472  return res;
473}
474
475//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
476
477G4double G4EmCalculator::ComputeElectronicDEDX(G4double kinEnergy,
478                                               const G4ParticleDefinition* part,
479                                               const G4Material* mat,
480                                               G4double cut)
481{
482  currentMaterial = mat;
483  currentMaterialName = mat->GetName();
484  G4double dedx = 0.0;
485  if(UpdateParticle(part, kinEnergy)) {
486    G4LossTableManager* lManager = G4LossTableManager::Instance();
487    const std::vector<G4VEnergyLossProcess*> vel =
488      lManager->GetEnergyLossProcessVector();
489    G4int n = vel.size();
490    for(G4int i=0; i<n; i++) {
491      const G4ParticleDefinition* p = (vel[i])->Particle();
492      if((!isIon && p == part) || (isIon && p == theGenericIon))
493        dedx += ComputeDEDX(kinEnergy,part,(vel[i])->GetProcessName(),mat,cut);
494    }
495  }
496  return dedx;
497}
498
499//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
500
501G4double G4EmCalculator::ComputeElectronicDEDX(G4double kinEnergy, const G4String& part,
502                                               const G4String& mat, G4double cut)
503{
504  return ComputeElectronicDEDX(kinEnergy,FindParticle(part),FindMaterial(mat),cut);
505}
506
507//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
508
509G4double G4EmCalculator::ComputeTotalDEDX(G4double kinEnergy, const G4ParticleDefinition* part,
510                                          const G4Material* mat, G4double cut)
511{
512  G4double dedx = ComputeElectronicDEDX(kinEnergy,part,mat,cut);
513  if(mass > 700.*MeV) dedx += ComputeNuclearDEDX(kinEnergy,part,mat);
514  return dedx;
515}
516
517//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
518
519G4double G4EmCalculator::ComputeTotalDEDX(G4double kinEnergy, const G4String& part,
520                                          const G4String& mat, G4double cut)
521{
522  return ComputeTotalDEDX(kinEnergy,FindParticle(part),FindMaterial(mat),cut);
523}
524
525//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
526
527G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy,
528                                     const G4String& particle,
529                                     const G4String& processName,
530                                     const G4String& material,
531                                           G4double cut)
532{
533  return ComputeDEDX(kinEnergy,FindParticle(particle),processName,
534                     FindMaterial(material),cut);
535}
536
537//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
538
539G4double G4EmCalculator::ComputeNuclearDEDX(G4double kinEnergy,
540                                      const G4ParticleDefinition* p,
541                                      const G4Material* mat)
542{
543
544  G4double res = corr->NuclearDEDX(p, mat, kinEnergy, false);
545
546  if(verbose > 1) {
547    G4cout <<  p->GetParticleName() << " E(MeV)= " << kinEnergy/MeV
548           << " NuclearDEDX(MeV/mm)= " << res*mm/MeV
549           << " NuclearDEDX(MeV*cm^2/g)= "
550           << res*gram/(MeV*cm2*mat->GetDensity())
551           << G4endl;
552  }
553  return res;
554}
555
556//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
557
558G4double G4EmCalculator::ComputeNuclearDEDX(G4double kinEnergy,
559                                      const G4String& particle,
560                                      const G4String& material)
561{
562  return ComputeNuclearDEDX(kinEnergy,FindParticle(particle),
563                            FindMaterial(material));
564}
565
566//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
567
568G4double G4EmCalculator::ComputeCrossSectionPerVolume(
569                                                   G4double kinEnergy,
570                                             const G4ParticleDefinition* p,
571                                             const G4String& processName,
572                                             const G4Material* mat,
573                                                   G4double cut)
574{
575  currentMaterial = mat;
576  currentMaterialName = mat->GetName();
577  G4double res = 0.0;
578  if(UpdateParticle(p, kinEnergy)) {
579    if(FindEmModel(p, processName, kinEnergy)) {
580      G4double e = kinEnergy;
581      if(baseParticle) {
582        e *= kinEnergy*massRatio;
583        res = currentModel->CrossSectionPerVolume(
584              mat, baseParticle, e, cut, e) * chargeSquare;
585      } else {
586        res = currentModel->CrossSectionPerVolume(mat, p, e, cut, e);
587      }
588      if(verbose>0) {
589        G4cout << "E(MeV)= " << kinEnergy/MeV
590               << " cross(cm-1)= " << res*cm
591               << "  " <<  p->GetParticleName()
592               << " in " <<  mat->GetName()
593               << G4endl;
594      }
595    }
596  }
597  return res;
598}
599
600//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
601
602G4double G4EmCalculator::ComputeCrossSectionPerVolume(
603                                                   G4double kinEnergy,
604                                             const G4String& particle,
605                                             const G4String& processName,
606                                             const G4String& material,
607                                                   G4double cut)
608{
609  return ComputeCrossSectionPerVolume(kinEnergy,FindParticle(particle),
610                                      processName,
611                                      FindMaterial(material),cut);
612}
613
614//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
615
616G4double G4EmCalculator::ComputeCrossSectionPerAtom(
617                                                   G4double kinEnergy,
618                                             const G4ParticleDefinition* p,
619                                             const G4String& processName,
620                                                   G4double Z, G4double A,
621                                                   G4double cut)
622{
623  G4double res = 0.0;
624  if(UpdateParticle(p, kinEnergy)) {
625    if(FindEmModel(p, processName, kinEnergy)) {
626      G4double e = kinEnergy;
627      if(baseParticle) {
628        e *= kinEnergy*massRatio;
629        res = currentModel->ComputeCrossSectionPerAtom(
630              baseParticle, e, Z, A, cut) * chargeSquare;
631      } else {
632        res = currentModel->ComputeCrossSectionPerAtom(p, e, Z, A, cut);
633      }
634      if(verbose>0) {
635        G4cout << "E(MeV)= " << kinEnergy/MeV
636               << " cross(barn)= " << res/barn
637               << "  " <<  p->GetParticleName()
638               << " Z= " <<  Z << " A= " << A/(g/mole) << " g/mole"
639               << G4endl;
640      }
641    }
642  }
643  return res;
644}
645
646//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
647
648G4double G4EmCalculator::ComputeCrossSectionPerAtom(G4double kinEnergy,
649                                              const G4String& particle,
650                                              const G4String& processName,
651                                              const G4Element* elm,
652                                                    G4double cut)
653{
654  return ComputeCrossSectionPerAtom(kinEnergy,FindParticle(particle),
655                                    processName,
656                                    elm->GetZ(),elm->GetA(),cut);
657}
658
659//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
660
661G4double G4EmCalculator::ComputeMeanFreePath(G4double kinEnergy,
662                                             const G4ParticleDefinition* p,
663                                             const G4String& processName,
664                                             const G4Material* mat,
665                                                   G4double cut)
666{
667  G4double mfp = DBL_MAX;
668  G4double x = ComputeCrossSectionPerVolume(kinEnergy, p, processName, mat, cut);
669  if(x > 0.0) mfp = 1.0/x;
670  if(verbose>1) {
671    G4cout << "E(MeV)= " << kinEnergy/MeV
672           << " MFP(mm)= " << mfp/mm
673           << "  " <<  p->GetParticleName()
674           << " in " <<  mat->GetName()
675           << G4endl;
676  }
677  return mfp;
678}
679
680//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
681
682G4double G4EmCalculator::ComputeMeanFreePath(G4double kinEnergy,
683                                             const G4String& particle,
684                                             const G4String& processName,
685                                             const G4String& material,
686                                                   G4double cut)
687{
688  return ComputeMeanFreePath(kinEnergy,FindParticle(particle),processName,
689                             FindMaterial(material),cut);
690}
691
692//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
693
694G4double G4EmCalculator::ComputeEnergyCutFromRangeCut(
695                         G4double range, 
696                         const G4ParticleDefinition* part,
697                         const G4Material* mat)
698{
699  return G4ProductionCutsTable::GetProductionCutsTable()->
700    ConvertRangeToEnergy(part, mat, range);
701}
702
703//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
704
705G4double G4EmCalculator::ComputeEnergyCutFromRangeCut(
706                         G4double range, 
707                         const G4String& particle,
708                         const G4String& material)
709{
710  return ComputeEnergyCutFromRangeCut(range,FindParticle(particle),
711                                      FindMaterial(material));
712}
713
714
715//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
716
717G4bool G4EmCalculator::UpdateParticle(const G4ParticleDefinition* p,
718                                      G4double kinEnergy)
719{
720  if(p != currentParticle) {
721    currentParticle = p;
722    baseParticle    = 0;
723    currentParticleName = p->GetParticleName();
724    massRatio       = 1.0;
725    mass            = p->GetPDGMass();
726    chargeSquare    = 1.0;
727    currentProcess  = FindEnergyLossProcess(p);
728    currentProcessName = "";
729    if(currentProcess) currentProcessName = currentProcess->GetProcessName();
730
731    if(p->GetParticleType() == "nucleus" &&
732       currentParticleName  != "deuteron" && currentParticleName != "triton") {
733      baseParticle = theGenericIon;
734      massRatio = baseParticle->GetPDGMass()/p->GetPDGMass();
735      isIon = true;
736      //      G4cout << p->GetParticleName()
737      // << " in " << currentMaterial->GetName()
738      //       << "  e= " << kinEnergy << G4endl;
739      chargeSquare =
740        ionEffCharge->EffectiveChargeSquareRatio(p, currentMaterial, kinEnergy);
741      //G4cout << "q2= " << chargeSquare << G4endl;
742    } else {
743      isIon = false;
744      if(currentProcess) {
745        baseParticle    = currentProcess->BaseParticle();
746
747        if(baseParticle) {
748          massRatio = baseParticle->GetPDGMass()/p->GetPDGMass();
749          G4double q = baseParticle->GetPDGCharge()/eplus;
750          chargeSquare /= (q*q);
751        }
752      }
753    }
754  }
755  if(isIon) {
756    chargeSquare =
757     ionEffCharge->EffectiveChargeSquareRatio(p, currentMaterial, kinEnergy);
758    if(currentProcess)
759      currentProcess->SetDynamicMassCharge(massRatio,chargeSquare);
760    // G4cout << "massR= " << massRatio << "   q2= " << chargeSquare << G4endl;
761  }
762  return true;
763}
764
765//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
766
767const G4ParticleDefinition* G4EmCalculator::FindParticle(const G4String& name)
768{
769  const G4ParticleDefinition* p = 0;
770  if(name != currentParticleName) {
771    p = G4ParticleTable::GetParticleTable()->FindParticle(name);
772    if(!p) {
773      G4cout << "### WARNING: G4EmCalculator::FindParticle fails to find " 
774             << name << G4endl;
775    }
776  } else {
777    p = currentParticle;
778  }
779  return p;
780}
781
782//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
783
784const G4Material* G4EmCalculator::FindMaterial(const G4String& name)
785{
786  if(name != currentMaterialName) {
787    currentMaterial = G4Material::GetMaterial(name);
788    currentMaterialName = name;
789    if(!currentMaterial)
790      G4cout << "### WARNING: G4EmCalculator::FindMaterial fails to find " 
791             << name << G4endl;
792  }
793  return currentMaterial;
794}
795
796//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
797
798const G4Region* G4EmCalculator::FindRegion(const G4String& reg)
799{
800  const G4Region* r = 0;
801  if(reg != "" || reg != "world")
802    r = G4RegionStore::GetInstance()->GetRegion(reg);
803  else 
804    r = G4RegionStore::GetInstance()->GetRegion("DefaultRegionForTheWorld");
805  return r;
806}
807
808//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
809
810const G4MaterialCutsCouple* G4EmCalculator::FindCouple(
811                            const G4Material* material,
812                            const G4Region* region)
813{
814  if(!material) return 0;
815  currentMaterial = material;
816  currentMaterialName = material->GetName();
817  // Access to materials
818  const G4ProductionCutsTable* theCoupleTable=
819        G4ProductionCutsTable::GetProductionCutsTable();
820  const G4Region* r = region;
821  if(!r) 
822    r = G4RegionStore::GetInstance()->GetRegion("DefaultRegionForTheWorld");
823
824  return theCoupleTable->GetMaterialCutsCouple(material,r->GetProductionCuts());
825
826}
827
828//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
829
830G4bool G4EmCalculator::UpdateCouple(const G4Material* material, G4double cut)
831{
832  if(!material) return false;
833  currentMaterial = material;
834  currentMaterialName = material->GetName();
835  for (G4int i=0; i<nLocalMaterials; i++) {
836    if(material == localMaterials[i] && cut == localCuts[i]) {
837      currentCouple = localCouples[i];
838      currentCoupleIndex = currentCouple->GetIndex();
839      currentCut = cut;
840      return true;
841    }
842  }
843  const G4MaterialCutsCouple* cc = new G4MaterialCutsCouple(material);
844  localMaterials.push_back(material);
845  localCouples.push_back(cc);
846  localCuts.push_back(cut);
847  nLocalMaterials++;
848  currentCouple = cc;
849  currentCoupleIndex = currentCouple->GetIndex();
850  currentCut = cut;
851  return true;
852}
853
854//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
855
856void G4EmCalculator::FindLambdaTable(const G4ParticleDefinition* p,
857                                     const G4String& processName)
858{
859  // Search for the process
860  if (p != currentParticle || processName != currentName) {
861    currentName     = processName;
862    currentLambda   = 0;
863
864    G4String partname =  p->GetParticleName();
865    const G4ParticleDefinition* part = p;
866    if(isIon) part = theGenericIon;
867
868    G4LossTableManager* lManager = G4LossTableManager::Instance();
869    const std::vector<G4VEnergyLossProcess*> vel = 
870      lManager->GetEnergyLossProcessVector();
871    G4int n = vel.size();
872    for(G4int i=0; i<n; i++) {
873      if((vel[i])->GetProcessName() == currentName && 
874         (vel[i])->Particle() == part) 
875      {
876        currentLambda = (vel[i])->LambdaTable();
877        isApplicable    = true;
878        break;
879      }
880    }
881    if(!currentLambda) {
882      const std::vector<G4VEmProcess*> vem = lManager->GetEmProcessVector();
883      G4int n = vem.size();
884      for(G4int i=0; i<n; i++) {
885        if((vem[i])->GetProcessName() == currentName && 
886           (vem[i])->Particle() == part) 
887        {
888          currentLambda = (vem[i])->LambdaTable();
889          isApplicable    = true;
890          break;
891        }
892      }
893    }
894    if(!currentLambda) {
895      const std::vector<G4VMultipleScattering*> vmsc = 
896        lManager->GetMultipleScatteringVector();
897      G4int n = vmsc.size();
898      for(G4int i=0; i<n; i++) {
899        if((vmsc[i])->GetProcessName() == currentName && 
900           (vmsc[i])->Particle() == part) 
901        {
902          currentLambda = (vmsc[i])->LambdaTable();
903          isApplicable    = true;
904          break;
905        }
906      }
907    }
908  }
909}
910
911//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
912
913G4bool G4EmCalculator::FindEmModel(const G4ParticleDefinition* p,
914                                   const G4String& processName,
915                                         G4double kinEnergy)
916{
917  G4bool res = false;
918  if(!p) {
919    G4cout << "G4EmCalculator::FindEmModel WARNING: no particle defined" 
920           << G4endl;
921    return res;
922  }
923  G4String partname =  p->GetParticleName();
924  const G4ParticleDefinition* part = p;
925  G4double scaledEnergy = kinEnergy*massRatio;
926  if(isIon) part = theGenericIon; 
927
928  if(verbose > 1) {
929    G4cout << "G4EmCalculator::FindEmModel for " << partname
930           << " (type= " << p->GetParticleType()
931           << ") and " << processName << " at e(MeV)= " << scaledEnergy;
932    if(p != part) G4cout << "  GenericIon is the base particle";       
933    G4cout << G4endl;
934  }
935
936  // Search for the process
937  currentName = processName;
938  currentModel = 0;
939  loweModel = 0;
940  size_t idx   = 0;
941  G4LossTableManager* lManager = G4LossTableManager::Instance();
942  const std::vector<G4VEnergyLossProcess*> vel = 
943    lManager->GetEnergyLossProcessVector();
944  G4int n = vel.size();
945  for(G4int i=0; i<n; i++) {
946    //    G4cout << "i= " << i << " part= "
947    //  << (vel[i])->Particle()->GetParticleName()
948    //     << "   proc= " << (vel[i])->GetProcessName()  << G4endl;
949    if((vel[i])->GetProcessName() == currentName && 
950       (vel[i])->Particle() == part) 
951    {
952      const G4ParticleDefinition* bp = (vel[i])->BaseParticle();
953      //      G4cout << "i= " << i << " bp= " << bp << G4endl;
954      if(!bp) {
955        currentModel = (vel[i])->SelectModelForMaterial(scaledEnergy, idx);
956        loweModel = (vel[i])->SelectModelForMaterial(keV, idx);
957        isApplicable    = true;
958        break;
959      } else {
960        for(G4int j=0; j<n; j++) {
961          if((vel[j])->Particle() == bp) {
962            currentModel = (vel[j])->SelectModelForMaterial(scaledEnergy, idx);
963            loweModel = (vel[j])->SelectModelForMaterial(keV, idx);
964            isApplicable    = true;
965            break;
966          }
967        }
968      }
969    }
970  }
971  if(!currentModel) {
972    const std::vector<G4VEmProcess*> vem = lManager->GetEmProcessVector();
973    G4int n = vem.size();
974    for(G4int i=0; i<n; i++) {
975      if((vem[i])->GetProcessName() == currentName && 
976         (vem[i])->Particle() == part) 
977      {
978        currentModel = (vem[i])->SelectModelForMaterial(kinEnergy, idx);
979        loweModel = (vem[i])->SelectModelForMaterial(keV, idx);
980        isApplicable    = true;
981        break;
982      }
983    }
984  }
985  if(!currentModel) {
986    const std::vector<G4VMultipleScattering*> vmsc = 
987      lManager->GetMultipleScatteringVector();
988    G4int n = vmsc.size();
989    for(G4int i=0; i<n; i++) {
990      if((vmsc[i])->GetProcessName() == currentName && 
991         (vmsc[i])->Particle() == part) 
992      {
993        currentModel = (vmsc[i])->SelectModelForMaterial(kinEnergy, idx);
994        loweModel = (vmsc[i])->SelectModelForMaterial(keV, idx);
995        isApplicable    = true;
996        break;
997      }
998    }
999  }
1000  if(currentModel) res = true;
1001  return res;
1002}
1003
1004//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1005
1006G4VEnergyLossProcess* G4EmCalculator::FindEnergyLossProcess(
1007                      const G4ParticleDefinition* p)
1008{
1009  G4VEnergyLossProcess* elp = 0;
1010  G4String partname =  p->GetParticleName();
1011  const G4ParticleDefinition* part = p;
1012  if(p->GetParticleType() == "nucleus" && 
1013     partname != "deuteron" && 
1014     partname != "triton") part = G4GenericIon::GenericIon(); 
1015 
1016  G4LossTableManager* lManager = G4LossTableManager::Instance();
1017  const std::vector<G4VEnergyLossProcess*> vel = 
1018    lManager->GetEnergyLossProcessVector();
1019  G4int n = vel.size();
1020  for(G4int i=0; i<n; i++) {
1021    if((vel[i])->Particle() == part) {
1022      elp = vel[i];
1023      break;
1024    }
1025  }
1026  return elp;
1027}
1028
1029//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1030
1031void G4EmCalculator::SetVerbose(G4int verb)
1032{
1033  verbose = verb;
1034}
1035
1036//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1037
Note: See TracBrowser for help on using the repository browser.