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

Last change on this file since 1036 was 1007, checked in by garnier, 17 years ago

update to geant4.9.2

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