source: trunk/source/processes/electromagnetic/utils/src/G4VEnergyLoss.cc@ 1315

Last change on this file since 1315 was 1228, checked in by garnier, 16 years ago

update geant4.9.3 tag

File size: 35.3 KB
RevLine 
[819]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: G4VEnergyLoss.cc,v 1.46 2006/06/29 19:55:21 gunter Exp $
[1228]28// GEANT4 tag $Name: geant4-09-03 $
[819]29//
30
31// --------------------------------------------------------------
32//
33// bug fixed in fluct., L.Urban 01/02/01
34// bug fixed in fluct., L.Urban 26/05/00
35// bug fixed in fluct., L.Urban 22/11/00
36// bugfix in fluct.
37// (some variables are doubles instead of ints now),L.Urban 23/03/01
38// 18/05/01 V.Ivanchenko Clean up againist Linux ANSI compilation
39// 17-09-01 migration of Materials to pure STL (mma)
40// 26-10-01 static inline functions moved from .hh file (mma)
41// 08.11.01 some static methods,data members are not static L.Urban
42// 11.02.02 subSecFlag = false --> No sucutoff generation (mma)
43// 14.02.02 initial value of data member finalRange has been changed L.Urban
44// 26.02.02 initial value of data member finalRange = 1 mm (mma)
45// 21.07.02 V.Ivanchenko Fix at low energies - if tmax below ionisation
46// potential then only Gaussian fluctuations are sampled.
47// 15.01.03 Migrade to cut per region (V.Ivanchenko)
48// 05.02.03 Minor fix for several region case (V.Ivanchenko)
49// 25.03.03 add finalRangeRequested (mma)
50//
51//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
52//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
53
54#include "G4VEnergyLoss.hh"
55#include "G4EnergyLossMessenger.hh"
56#include "G4ProductionCutsTable.hh"
57#include "G4LossTableManager.hh"
58
59//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
60
61G4bool G4VEnergyLoss::rndmStepFlag = false;
62G4bool G4VEnergyLoss::EnlossFlucFlag = true;
63
64G4bool G4VEnergyLoss::subSecFlag = false;
65G4double G4VEnergyLoss::MinDeltaCutInRange = 0.100*mm;
66G4double* G4VEnergyLoss::MinDeltaEnergy = 0;
67G4bool* G4VEnergyLoss::LowerLimitForced = 0;
68G4bool G4VEnergyLoss::setMinDeltaCutInRange = false;
69
70G4double G4VEnergyLoss::dRoverRange = 20*perCent;
71G4double G4VEnergyLoss::finalRange = 1*mm;
72G4double G4VEnergyLoss::finalRangeRequested = -1*mm;
73G4double G4VEnergyLoss::c1lim = dRoverRange;
74G4double G4VEnergyLoss::c2lim = 2.*(1.-dRoverRange)*finalRange;
75G4double G4VEnergyLoss::c3lim = -(1.-dRoverRange)*finalRange*finalRange;
76
77G4EnergyLossMessenger* G4VEnergyLoss::ELossMessenger = 0;
78
79//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
80
81G4VEnergyLoss::G4VEnergyLoss()
82 :G4VContinuousDiscreteProcess("No Name Loss Process"),
83 lastMaterial(NULL),
84 nmaxCont1(4),
85 nmaxCont2(16)
86{
87 G4Exception("G4VEnergyLoss:: default constructor is called");
88}
89
90//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
91
92G4VEnergyLoss::G4VEnergyLoss(const G4String& aName , G4ProcessType aType)
93 : G4VContinuousDiscreteProcess(aName, aType),
94 lastMaterial(NULL),
95 nmaxCont1(4),
96 nmaxCont2(16)
97{
98 //create (only once) EnergyLoss messenger
99// if(!ELossMessenger) ELossMessenger = new G4EnergyLossMessenger();
100 if(!ELossMessenger) ELossMessenger = G4LossTableManager::Instance()->GetMessenger();
101}
102
103//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
104
105G4VEnergyLoss::~G4VEnergyLoss()
106{}
107
108//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
109
110G4VEnergyLoss::G4VEnergyLoss(G4VEnergyLoss& right)
111 : G4VContinuousDiscreteProcess(right),
112 lastMaterial(NULL),
113 nmaxCont1(4),
114 nmaxCont2(16)
115{}
116
117//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
118
119void G4VEnergyLoss::SetRndmStep(G4bool value) {rndmStepFlag = value;}
120
121//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
122
123void G4VEnergyLoss::SetEnlossFluc(G4bool value) {EnlossFlucFlag = value;}
124
125//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
126
127void G4VEnergyLoss::SetSubSec(G4bool value) {subSecFlag = value;}
128
129//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
130
131void G4VEnergyLoss::SetMinDeltaCutInRange(G4double value)
132{MinDeltaCutInRange = value; setMinDeltaCutInRange = true;}
133
134//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
135
136void G4VEnergyLoss::SetStepFunction(G4double c1, G4double c2)
137{
138 dRoverRange = c1; finalRangeRequested = c2;
139 c1lim=dRoverRange;
140 c2lim=2.*(1-dRoverRange)*finalRangeRequested;
141 c3lim=-(1.-dRoverRange)*finalRangeRequested*finalRangeRequested;
142}
143
144//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
145
146G4PhysicsTable* G4VEnergyLoss::BuildRangeTable(
147 G4PhysicsTable* theDEDXTable,G4PhysicsTable* theRangeTable,
148 G4double LowestKineticEnergy,G4double HighestKineticEnergy,G4int TotBin)
149// Build range table from the energy loss table
150{
151 size_t numOfMaterials = theDEDXTable->length();
152
153 if(theRangeTable)
154 { theRangeTable->clearAndDestroy();
155 delete theRangeTable; }
156 theRangeTable = new G4PhysicsTable(numOfMaterials);
157
158 // loop for materials
159
160 for (size_t J=0; J<numOfMaterials; J++)
161 {
162 G4PhysicsLogVector* aVector;
163 aVector = new G4PhysicsLogVector(LowestKineticEnergy,
164 HighestKineticEnergy,TotBin);
165
166 BuildRangeVector(theDEDXTable,LowestKineticEnergy,HighestKineticEnergy,
167 TotBin,J,aVector);
168 theRangeTable->insert(aVector);
169 }
170 return theRangeTable ;
171}
172
173//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
174
175void G4VEnergyLoss::BuildRangeVector(G4PhysicsTable* theDEDXTable,
176 G4double,G4double HighestKineticEnergy,G4int TotBin,
177 G4int materialIndex,G4PhysicsLogVector* rangeVector)
178// create range vector for a material
179{
180 G4int nbin=100,i;
181 G4bool isOut;
182
183 const G4double small = 1.e-6 ;
184 const G4double masslimit = 0.52*MeV ;
185
186 G4double tlim=2.*MeV,t1=0.1*MeV,t2=0.025*MeV ;
187 G4double tlime=0.2*keV,factor=2.*electron_mass_c2 ;
188 G4double loss1,loss2,ca,cb,cba ;
189 G4double losslim,clim ;
190 G4double taulim,rangelim,ltaulim,ltaumax,
191 LowEdgeEnergy,tau,Value,tau1,sqtau1 ;
192 G4double oldValue,tauold ;
193
194 G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
195
196 // cure 'accidental' 0. dE/dx vales first .....
197 G4double lossmin = +1.e10 ;
198 for (G4int i1=0; i1<TotBin; i1++)
199 {
200 LowEdgeEnergy = rangeVector->GetLowEdgeEnergy(i1) ;
201 Value = physicsVector->GetValue(LowEdgeEnergy,isOut);
202 if((Value < lossmin)&&(Value > 0.))
203 lossmin = Value ;
204 }
205 for (G4int i2=0; i2<TotBin; i2++)
206 {
207 LowEdgeEnergy = rangeVector->GetLowEdgeEnergy(i2) ;
208 Value = physicsVector->GetValue(LowEdgeEnergy,isOut);
209 if(Value < lossmin)
210 physicsVector->PutValue(i2,small*lossmin) ;
211 }
212
213 // low energy part first...
214 // heavy particle
215 if(ParticleMass > masslimit)
216 {
217 loss1 = physicsVector->GetValue(t1,isOut);
218 loss2 = physicsVector->GetValue(t2,isOut);
219 tau1 = t1/ParticleMass ;
220 sqtau1 = std::sqrt(tau1) ;
221 ca = (4.*loss2-loss1)/sqtau1 ;
222 cb = (2.*loss1-4.*loss2)/tau1 ;
223 cba = cb/ca ;
224 taulim = tlim/ParticleMass ;
225 ltaulim = std::log(taulim) ;
226 ltaumax = std::log(HighestKineticEnergy/ParticleMass) ;
227
228 i=-1;
229 oldValue = 0. ;
230
231 do
232 {
233 i += 1 ;
234 LowEdgeEnergy = rangeVector->GetLowEdgeEnergy(i);
235 tau = LowEdgeEnergy/ParticleMass;
236 if ( tau <= tau1 )
237 {
238 Value = 2.*ParticleMass*std::log(1.+cba*std::sqrt(tau))/cb ;
239 }
240 else
241 {
242 Value = 2.*ParticleMass*std::log(1.+cba*sqtau1)/cb ;
243 if(tau<=taulim)
244 {
245 taulow = tau1 ;
246 tauhigh = tau ;
247 Value += RangeIntLin(physicsVector,nbin);
248 }
249 else
250 {
251
252 taulow = tau1 ;
253 tauhigh = taulim ;
254 Value += RangeIntLin(physicsVector,nbin) ;
255 ltaulow = ltaulim ;
256 ltauhigh = std::log(tau) ;
257 Value += RangeIntLog(physicsVector,nbin);
258 }
259 }
260
261 rangeVector->PutValue(i,Value);
262 oldValue = Value ;
263 tauold = tau ;
264 } while (tau<=taulim) ;
265 }
266 else
267 // electron/positron
268 {
269 losslim = physicsVector->GetValue(tlime,isOut) ;
270
271 taulim = tlime/electron_mass_c2;
272 clim = losslim;
273 ltaulim = std::log(taulim);
274 ltaumax = std::log(HighestKineticEnergy/electron_mass_c2);
275
276 i=-1;
277 oldValue = 0.;
278
279 do
280 {
281 i += 1 ;
282 LowEdgeEnergy = rangeVector->GetLowEdgeEnergy(i);
283 tau = LowEdgeEnergy/electron_mass_c2;
284 if (tau <= taulim) Value = factor*std::sqrt(tau*taulim)/clim;
285 else {
286 rangelim = factor*taulim/losslim ;
287 ltaulow = std::log(taulim);
288 ltauhigh = std::log(tau);
289 Value = rangelim+RangeIntLog(physicsVector,nbin);
290 }
291 rangeVector->PutValue(i,Value);
292 oldValue = Value;
293 tauold = tau;
294
295 } while (tau<=taulim);
296
297 }
298
299 i += 1 ;
300 for (G4int j=i; j<TotBin; j++)
301 {
302 LowEdgeEnergy = rangeVector->GetLowEdgeEnergy(j);
303 tau = LowEdgeEnergy/ParticleMass;
304 ltaulow = std::log(tauold);
305 ltauhigh = std::log(tau);
306 Value = oldValue+RangeIntLog(physicsVector,nbin);
307 rangeVector->PutValue(j,Value);
308 oldValue = Value ;
309
310 tauold = tau ;
311 }
312}
313
314//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
315
316G4double G4VEnergyLoss::RangeIntLin(G4PhysicsVector* physicsVector,
317 G4int nbin)
318// num. integration, linear binning
319{
320 G4double dtau,Value,taui,ti,lossi,ci;
321 G4bool isOut;
322 dtau = (tauhigh-taulow)/nbin;
323 Value = 0.;
324
325 for (G4int i=0; i<=nbin; i++)
326 {
327 taui = taulow + dtau*i ;
328 ti = ParticleMass*taui;
329 lossi = physicsVector->GetValue(ti,isOut);
330 if(i==0)
331 ci=0.5;
332 else
333 {
334 if(i<nbin)
335 ci=1.;
336 else
337 ci=0.5;
338 }
339 Value += ci/lossi;
340 }
341 Value *= ParticleMass*dtau;
342 return Value;
343}
344
345//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
346
347G4double G4VEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
348 G4int nbin)
349// num. integration, logarithmic binning
350{
351 G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
352 G4bool isOut;
353 ltt = ltauhigh-ltaulow;
354 dltau = ltt/nbin;
355 Value = 0.;
356
357 for (G4int i=0; i<=nbin; i++)
358 {
359 ui = ltaulow+dltau*i;
360 taui = std::exp(ui);
361 ti = ParticleMass*taui;
362 lossi = physicsVector->GetValue(ti,isOut);
363 if(i==0)
364 ci=0.5;
365 else
366 {
367 if(i<nbin)
368 ci=1.;
369 else
370 ci=0.5;
371 }
372 Value += ci*taui/lossi;
373 }
374 Value *= ParticleMass*dltau;
375 return Value;
376}
377
378//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
379
380G4PhysicsTable* G4VEnergyLoss::BuildLabTimeTable(G4PhysicsTable* theDEDXTable,
381 G4PhysicsTable* theLabTimeTable,
382 G4double LowestKineticEnergy,
383 G4double HighestKineticEnergy,G4int TotBin)
384
385{
386 size_t numOfMaterials = theDEDXTable->length();
387
388 if(theLabTimeTable)
389 { theLabTimeTable->clearAndDestroy();
390 delete theLabTimeTable; }
391 theLabTimeTable = new G4PhysicsTable(numOfMaterials);
392
393
394 for (size_t J=0; J<numOfMaterials; J++)
395 {
396 G4PhysicsLogVector* aVector;
397
398 aVector = new G4PhysicsLogVector(LowestKineticEnergy,
399 HighestKineticEnergy,TotBin);
400
401 BuildLabTimeVector(theDEDXTable,
402 LowestKineticEnergy,HighestKineticEnergy,TotBin,J,aVector);
403 theLabTimeTable->insert(aVector);
404
405
406 }
407 return theLabTimeTable ;
408}
409
410//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
411
412G4PhysicsTable* G4VEnergyLoss::BuildProperTimeTable(G4PhysicsTable* theDEDXTable,
413 G4PhysicsTable* theProperTimeTable,
414 G4double LowestKineticEnergy,
415 G4double HighestKineticEnergy,G4int TotBin)
416
417{
418 size_t numOfMaterials = theDEDXTable->length();
419
420 if(theProperTimeTable)
421 { theProperTimeTable->clearAndDestroy();
422 delete theProperTimeTable; }
423 theProperTimeTable = new G4PhysicsTable(numOfMaterials);
424
425
426 for (size_t J=0; J<numOfMaterials; J++)
427 {
428 G4PhysicsLogVector* aVector;
429
430 aVector = new G4PhysicsLogVector(LowestKineticEnergy,
431 HighestKineticEnergy,TotBin);
432
433 BuildProperTimeVector(theDEDXTable,
434 LowestKineticEnergy,HighestKineticEnergy,TotBin,J,aVector);
435 theProperTimeTable->insert(aVector);
436
437
438 }
439 return theProperTimeTable ;
440}
441
442//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
443
444void G4VEnergyLoss::BuildLabTimeVector(G4PhysicsTable* theDEDXTable,
445 G4double,
446 G4double HighestKineticEnergy,G4int TotBin,
447 G4int materialIndex, G4PhysicsLogVector* timeVector)
448// create lab time vector for a material
449{
450
451 G4int nbin=100;
452 G4bool isOut;
453 G4double tlim=5.*keV,parlowen=0.4,ppar=0.5-parlowen ;
454 G4double losslim,clim,taulim,timelim,ltaulim,ltaumax,
455 LowEdgeEnergy,tau,Value ;
456
457 G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
458
459 // low energy part first...
460 losslim = physicsVector->GetValue(tlim,isOut);
461 taulim=tlim/ParticleMass ;
462 clim=std::sqrt(ParticleMass*tlim/2.)/(c_light*losslim*ppar) ;
463 ltaulim = std::log(taulim);
464 ltaumax = std::log(HighestKineticEnergy/ParticleMass) ;
465
466 G4int i=-1;
467 G4double oldValue = 0. ;
468 G4double tauold ;
469 do
470 {
471 i += 1 ;
472 LowEdgeEnergy = timeVector->GetLowEdgeEnergy(i);
473 tau = LowEdgeEnergy/ParticleMass ;
474 if ( tau <= taulim )
475 {
476 Value = clim*std::exp(ppar*std::log(tau/taulim)) ;
477 }
478 else
479 {
480 timelim=clim ;
481 ltaulow = std::log(taulim);
482 ltauhigh = std::log(tau);
483 Value = timelim+LabTimeIntLog(physicsVector,nbin);
484 }
485 timeVector->PutValue(i,Value);
486 oldValue = Value ;
487 tauold = tau ;
488 } while (tau<=taulim) ;
489 i += 1 ;
490 for (G4int j=i; j<TotBin; j++)
491 {
492 LowEdgeEnergy = timeVector->GetLowEdgeEnergy(j);
493 tau = LowEdgeEnergy/ParticleMass ;
494 ltaulow = std::log(tauold);
495 ltauhigh = std::log(tau);
496 Value = oldValue+LabTimeIntLog(physicsVector,nbin);
497 timeVector->PutValue(j,Value);
498 oldValue = Value ;
499 tauold = tau ;
500 }
501}
502
503//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
504
505void G4VEnergyLoss::BuildProperTimeVector(G4PhysicsTable* theDEDXTable,
506 G4double,
507 G4double HighestKineticEnergy,G4int TotBin,
508 G4int materialIndex, G4PhysicsLogVector* timeVector)
509// create proper time vector for a material
510{
511 G4int nbin=100;
512 G4bool isOut;
513 G4double tlim=5.*keV,parlowen=0.4,ppar=0.5-parlowen ;
514 G4double losslim,clim,taulim,timelim,ltaulim,ltaumax,
515 LowEdgeEnergy,tau,Value ;
516
517 G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
518
519 // low energy part first...
520 losslim = physicsVector->GetValue(tlim,isOut);
521 taulim=tlim/ParticleMass ;
522 clim=std::sqrt(ParticleMass*tlim/2.)/(c_light*losslim*ppar) ;
523 ltaulim = std::log(taulim);
524 ltaumax = std::log(HighestKineticEnergy/ParticleMass) ;
525
526 G4int i=-1;
527 G4double oldValue = 0. ;
528 G4double tauold ;
529 do
530 {
531 i += 1 ;
532 LowEdgeEnergy = timeVector->GetLowEdgeEnergy(i);
533 tau = LowEdgeEnergy/ParticleMass ;
534 if ( tau <= taulim )
535 {
536 Value = clim*std::exp(ppar*std::log(tau/taulim)) ;
537 }
538 else
539 {
540 timelim=clim ;
541 ltaulow = std::log(taulim);
542 ltauhigh = std::log(tau);
543 Value = timelim+ProperTimeIntLog(physicsVector,nbin);
544 }
545 timeVector->PutValue(i,Value);
546 oldValue = Value ;
547 tauold = tau ;
548 } while (tau<=taulim) ;
549 i += 1 ;
550 for (G4int j=i; j<TotBin; j++)
551 {
552 LowEdgeEnergy = timeVector->GetLowEdgeEnergy(j);
553 tau = LowEdgeEnergy/ParticleMass ;
554 ltaulow = std::log(tauold);
555 ltauhigh = std::log(tau);
556 Value = oldValue+ProperTimeIntLog(physicsVector,nbin);
557 timeVector->PutValue(j,Value);
558 oldValue = Value ;
559 tauold = tau ;
560 }
561}
562
563//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
564
565G4double G4VEnergyLoss::LabTimeIntLog(G4PhysicsVector* physicsVector,
566 G4int nbin)
567// num. integration, logarithmic binning
568{
569 G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
570 G4bool isOut;
571 ltt = ltauhigh-ltaulow;
572 dltau = ltt/nbin;
573 Value = 0.;
574
575 for (G4int i=0; i<=nbin; i++)
576 {
577 ui = ltaulow+dltau*i;
578 taui = std::exp(ui);
579 ti = ParticleMass*taui;
580 lossi = physicsVector->GetValue(ti,isOut);
581 if(i==0)
582 ci=0.5;
583 else
584 {
585 if(i<nbin)
586 ci=1.;
587 else
588 ci=0.5;
589 }
590 Value += ci*taui*(ti+ParticleMass)/(std::sqrt(ti*(ti+2.*ParticleMass))*lossi);
591 }
592 Value *= ParticleMass*dltau/c_light;
593 return Value;
594}
595
596//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
597
598G4double G4VEnergyLoss::ProperTimeIntLog(G4PhysicsVector* physicsVector,
599 G4int nbin)
600// num. integration, logarithmic binning
601{
602 G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
603 G4bool isOut;
604 ltt = ltauhigh-ltaulow;
605 dltau = ltt/nbin;
606 Value = 0.;
607
608 for (G4int i=0; i<=nbin; i++)
609 {
610 ui = ltaulow+dltau*i;
611 taui = std::exp(ui);
612 ti = ParticleMass*taui;
613 lossi = physicsVector->GetValue(ti,isOut);
614 if(i==0)
615 ci=0.5;
616 else
617 {
618 if(i<nbin)
619 ci=1.;
620 else
621 ci=0.5;
622 }
623 Value += ci*taui*ParticleMass/(std::sqrt(ti*(ti+2.*ParticleMass))*lossi);
624 }
625 Value *= ParticleMass*dltau/c_light;
626 return Value;
627}
628
629//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
630
631G4PhysicsTable* G4VEnergyLoss::BuildInverseRangeTable(G4PhysicsTable* theRangeTable,
632 G4PhysicsTable* theRangeCoeffATable,
633 G4PhysicsTable* theRangeCoeffBTable,
634 G4PhysicsTable* theRangeCoeffCTable,
635 G4PhysicsTable* theInverseRangeTable,
636 G4double LowestKineticEnergy,
637 G4double HighestKineticEnergy,G4int TotBin)
638// Build inverse table of the range table
639{
640 G4double SmallestRange,BiggestRange ;
641 G4bool isOut ;
642 size_t numOfMaterials = theRangeTable->length();
643
644 if(theInverseRangeTable)
645 { theInverseRangeTable->clearAndDestroy();
646 delete theInverseRangeTable; }
647 theInverseRangeTable = new G4PhysicsTable(numOfMaterials);
648
649 // loop for materials
650 for (size_t J=0; J<numOfMaterials; J++)
651 {
652 SmallestRange = (*theRangeTable)(J)->
653 GetValue(LowestKineticEnergy,isOut) ;
654 BiggestRange = (*theRangeTable)(J)->
655 GetValue(HighestKineticEnergy,isOut) ;
656 G4PhysicsLogVector* aVector;
657 aVector = new G4PhysicsLogVector(SmallestRange,
658 BiggestRange,TotBin);
659
660 InvertRangeVector(theRangeTable,
661 theRangeCoeffATable,
662 theRangeCoeffBTable,
663 theRangeCoeffCTable,
664 LowestKineticEnergy,HighestKineticEnergy,TotBin,J, aVector);
665
666 theInverseRangeTable->insert(aVector);
667 }
668 return theInverseRangeTable ;
669}
670
671//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
672
673void G4VEnergyLoss::InvertRangeVector(G4PhysicsTable* theRangeTable,
674 G4PhysicsTable* theRangeCoeffATable,
675 G4PhysicsTable* theRangeCoeffBTable,
676 G4PhysicsTable* theRangeCoeffCTable,
677 G4double LowestKineticEnergy,
678 G4double HighestKineticEnergy,G4int TotBin,
679 G4int materialIndex,G4PhysicsLogVector* aVector)
680// invert range vector for a material
681{
682 G4double LowEdgeRange,A,B,C,discr,KineticEnergy ;
683 G4double RTable = std::exp(std::log(HighestKineticEnergy/LowestKineticEnergy)/TotBin) ;
684 G4double Tbin = LowestKineticEnergy/RTable ;
685 G4double rangebin = 0.0 ;
686 G4int binnumber = -1 ;
687 G4bool isOut ;
688
689 //loop for range values
690 for( G4int i=0; i<TotBin; i++)
691 {
692 LowEdgeRange = aVector->GetLowEdgeEnergy(i) ; //i.e. GetLowEdgeValue(i)
693 if( rangebin < LowEdgeRange )
694 {
695 do
696 {
697 binnumber += 1 ;
698 Tbin *= RTable ;
699 rangebin = (*theRangeTable)(materialIndex)->GetValue(Tbin,isOut) ;
700 }
701 while ((rangebin < LowEdgeRange) && (binnumber < TotBin )) ;
702 }
703
704 if(binnumber == 0)
705 KineticEnergy = LowestKineticEnergy ;
706 else if(binnumber == TotBin-1)
707 KineticEnergy = HighestKineticEnergy ;
708 else
709 {
710 A = (*(*theRangeCoeffATable)(materialIndex))(binnumber-1) ;
711 B = (*(*theRangeCoeffBTable)(materialIndex))(binnumber-1) ;
712 C = (*(*theRangeCoeffCTable)(materialIndex))(binnumber-1) ;
713 if(A==0.)
714 KineticEnergy = (LowEdgeRange -C )/B ;
715 else
716 {
717 discr = B*B - 4.*A*(C-LowEdgeRange);
718 discr = discr>0. ? std::sqrt(discr) : 0.;
719 KineticEnergy = 0.5*(discr-B)/A ;
720 }
721 }
722
723 aVector->PutValue(i,KineticEnergy) ;
724 }
725}
726
727//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
728
729G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffATable(G4PhysicsTable* theRangeTable,
730 G4PhysicsTable* theRangeCoeffATable,
731 G4double LowestKineticEnergy,
732 G4double HighestKineticEnergy,G4int TotBin)
733// Build tables of coefficients for the energy loss calculation
734// create table for coefficients "A"
735{
736 G4int numOfMaterials = theRangeTable->length();
737
738 if(theRangeCoeffATable)
739 { theRangeCoeffATable->clearAndDestroy();
740 delete theRangeCoeffATable; }
741 theRangeCoeffATable = new G4PhysicsTable(numOfMaterials);
742
743 G4double RTable = std::exp(std::log(HighestKineticEnergy/LowestKineticEnergy)/TotBin) ;
744 G4double R2 = RTable*RTable ;
745 G4double R1 = RTable+1.;
746 G4double w = R1*(RTable-1.)*(RTable-1.);
747 G4double w1 = RTable/w , w2 = -RTable*R1/w , w3 = R2/w ;
748 G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
749 G4bool isOut;
750
751 // loop for materials
752 for (G4int J=0; J<numOfMaterials; J++)
753 {
754 G4int binmax=TotBin ;
755 G4PhysicsLinearVector* aVector =
756 new G4PhysicsLinearVector(0.,binmax, TotBin);
757 Ti = LowestKineticEnergy ;
758 G4PhysicsVector* rangeVector= (*theRangeTable)[J];
759
760 for ( G4int i=0; i<TotBin; i++)
761 {
762 Ri = rangeVector->GetValue(Ti,isOut) ;
763 if ( i==0 )
764 Rim = 0. ;
765 else
766 {
767 Tim = Ti/RTable ;
768 Rim = rangeVector->GetValue(Tim,isOut);
769 }
770 if ( i==(TotBin-1))
771 Rip = Ri ;
772 else
773 {
774 Tip = Ti*RTable ;
775 Rip = rangeVector->GetValue(Tip,isOut);
776 }
777 Value = (w1*Rip + w2*Ri + w3*Rim)/(Ti*Ti) ;
778
779 aVector->PutValue(i,Value);
780 Ti = RTable*Ti ;
781 }
782
783 theRangeCoeffATable->insert(aVector);
784 }
785 return theRangeCoeffATable ;
786}
787
788//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
789
790G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffBTable(G4PhysicsTable* theRangeTable,
791 G4PhysicsTable* theRangeCoeffBTable,
792 G4double LowestKineticEnergy,
793 G4double HighestKineticEnergy,G4int TotBin)
794// Build tables of coefficients for the energy loss calculation
795// create table for coefficients "B"
796{
797 G4int numOfMaterials = theRangeTable->length();
798
799 if(theRangeCoeffBTable)
800 { theRangeCoeffBTable->clearAndDestroy();
801 delete theRangeCoeffBTable; }
802 theRangeCoeffBTable = new G4PhysicsTable(numOfMaterials);
803
804 G4double RTable = std::exp(std::log(HighestKineticEnergy/LowestKineticEnergy)/TotBin) ;
805 G4double R2 = RTable*RTable ;
806 G4double R1 = RTable+1.;
807 G4double w = R1*(RTable-1.)*(RTable-1.);
808 G4double w1 = -R1/w , w2 = R1*(R2+1.)/w , w3 = -R2*R1/w ;
809 G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
810 G4bool isOut;
811
812 // loop for materials
813 for (G4int J=0; J<numOfMaterials; J++)
814 {
815 G4int binmax=TotBin ;
816 G4PhysicsLinearVector* aVector =
817 new G4PhysicsLinearVector(0.,binmax, TotBin);
818 Ti = LowestKineticEnergy ;
819 G4PhysicsVector* rangeVector= (*theRangeTable)[J];
820
821 for ( G4int i=0; i<TotBin; i++)
822 {
823 Ri = rangeVector->GetValue(Ti,isOut) ;
824 if ( i==0 )
825 Rim = 0. ;
826 else
827 {
828 Tim = Ti/RTable ;
829 Rim = rangeVector->GetValue(Tim,isOut);
830 }
831 if ( i==(TotBin-1))
832 Rip = Ri ;
833 else
834 {
835 Tip = Ti*RTable ;
836 Rip = rangeVector->GetValue(Tip,isOut);
837 }
838 Value = (w1*Rip + w2*Ri + w3*Rim)/Ti;
839
840 aVector->PutValue(i,Value);
841 Ti = RTable*Ti ;
842 }
843 theRangeCoeffBTable->insert(aVector);
844 }
845 return theRangeCoeffBTable ;
846}
847
848//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
849
850G4PhysicsTable* G4VEnergyLoss::BuildRangeCoeffCTable(G4PhysicsTable* theRangeTable,
851 G4PhysicsTable* theRangeCoeffCTable,
852 G4double LowestKineticEnergy,
853 G4double HighestKineticEnergy,G4int TotBin)
854// Build tables of coefficients for the energy loss calculation
855// create table for coefficients "C"
856{
857 G4int numOfMaterials = theRangeTable->length();
858
859 if(theRangeCoeffCTable)
860 { theRangeCoeffCTable->clearAndDestroy();
861 delete theRangeCoeffCTable; }
862 theRangeCoeffCTable = new G4PhysicsTable(numOfMaterials);
863
864 G4double RTable = std::exp(std::log(HighestKineticEnergy/LowestKineticEnergy)/TotBin) ;
865 G4double R2 = RTable*RTable ;
866 G4double R1 = RTable+1.;
867 G4double w = R1*(RTable-1.)*(RTable-1.);
868 G4double w1 = 1./w , w2 = -RTable*R1/w , w3 = RTable*R2/w ;
869 G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
870 G4bool isOut;
871
872 // loop for materials
873 for (G4int J=0; J<numOfMaterials; J++)
874 {
875 G4int binmax=TotBin ;
876 G4PhysicsLinearVector* aVector =
877 new G4PhysicsLinearVector(0.,binmax, TotBin);
878 Ti = LowestKineticEnergy ;
879 G4PhysicsVector* rangeVector= (*theRangeTable)[J];
880
881 for ( G4int i=0; i<TotBin; i++)
882 {
883 Ri = rangeVector->GetValue(Ti,isOut) ;
884 if ( i==0 )
885 Rim = 0. ;
886 else
887 {
888 Tim = Ti/RTable ;
889 Rim = rangeVector->GetValue(Tim,isOut);
890 }
891 if ( i==(TotBin-1))
892 Rip = Ri ;
893 else
894 {
895 Tip = Ti*RTable ;
896 Rip = rangeVector->GetValue(Tip,isOut);
897 }
898 Value = w1*Rip + w2*Ri + w3*Rim ;
899
900 aVector->PutValue(i,Value);
901 Ti = RTable*Ti ;
902 }
903 theRangeCoeffCTable->insert(aVector);
904 }
905 return theRangeCoeffCTable ;
906}
907
908//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
909
910G4double G4VEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
911 const G4MaterialCutsCouple* couple,
912 G4double ChargeSquare,
913 G4double MeanLoss,
914 G4double step )
915// calculate actual loss from the mean loss
916// The model used to get the fluctuation is essentially the same as in Glandz in Geant3.
917{
918 const G4double minLoss = 1.*eV ;
919 const G4double probLim = 0.01 ;
920 const G4double sumaLim = -std::log(probLim) ;
921 const G4double alim=10.;
922 const G4double kappa = 10. ;
923 const G4double factor = twopi_mc2_rcl2 ;
924 const G4Material* aMaterial = couple->GetMaterial();
925
926 // check if the material has changed ( cache mechanism)
927
928 if (aMaterial != lastMaterial)
929 {
930 lastMaterial = aMaterial;
931 imat = couple->GetIndex();
932 f1Fluct = aMaterial->GetIonisation()->GetF1fluct();
933 f2Fluct = aMaterial->GetIonisation()->GetF2fluct();
934 e1Fluct = aMaterial->GetIonisation()->GetEnergy1fluct();
935 e2Fluct = aMaterial->GetIonisation()->GetEnergy2fluct();
936 e1LogFluct = aMaterial->GetIonisation()->GetLogEnergy1fluct();
937 e2LogFluct = aMaterial->GetIonisation()->GetLogEnergy2fluct();
938 rateFluct = aMaterial->GetIonisation()->GetRateionexcfluct();
939 ipotFluct = aMaterial->GetIonisation()->GetMeanExcitationEnergy();
940 ipotLogFluct = aMaterial->GetIonisation()->GetLogMeanExcEnergy();
941 }
942 G4double threshold,w1,w2,C,
943 beta2,suma,e0,loss,lossc ,w,electronDensity;
944 G4double a1,a2,a3;
945 G4double p1,p2,p3 ;
946 G4int nb;
947 G4double Corrfac, na,alfa,rfac,namean,sa,alfa1,ea,sea;
948 G4double dp3;
949 G4double siga ;
950
951 // shortcut for very very small loss
952 if(MeanLoss < minLoss) return MeanLoss ;
953
954 // get particle data
955 G4double Tkin = aParticle->GetKineticEnergy();
956 ParticleMass = aParticle->GetMass() ;
957
958 threshold = (*((G4ProductionCutsTable::GetProductionCutsTable())
959 ->GetEnergyCutsVector(1)))[imat];
960 G4double rmass = electron_mass_c2/ParticleMass;
961 G4double tau = Tkin/ParticleMass, tau1 = tau+1., tau2 = tau*(tau+2.);
962 G4double Tm = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass);
963
964 if(Tm > threshold) Tm = threshold;
965
966 beta2 = tau2/(tau1*tau1);
967
968 // Gaussian fluctuation ?
969 if(MeanLoss >= kappa*Tm || Tm < kappa*ipotFluct)
970 {
971 electronDensity = aMaterial->GetElectronDensity() ;
972 siga = std::sqrt(Tm*(1.0-0.5*beta2)*step*
973 factor*electronDensity*ChargeSquare/beta2) ;
974 do {
975 loss = G4RandGauss::shoot(MeanLoss,siga) ;
976 } while (loss < 0. || loss > 2.*MeanLoss);
977 return loss;
978 }
979
980 w1 = Tm/ipotFluct;
981 w2 = std::log(2.*electron_mass_c2*tau2);
982
983 C = MeanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
984
985 a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
986 a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
987 a3 = rateFluct*MeanLoss*(Tm-ipotFluct)/(ipotFluct*Tm*std::log(w1));
988 if(a1 < 0.) a1 = 0.;
989 if(a2 < 0.) a2 = 0.;
990 if(a3 < 0.) a3 = 0.;
991
992 suma = a1+a2+a3;
993
994 loss = 0. ;
995
996 if(suma < sumaLim) // very small Step
997 {
998 e0 = aMaterial->GetIonisation()->GetEnergy0fluct();
999
1000 if(Tm == ipotFluct)
1001 {
1002 a3 = MeanLoss/e0;
1003
1004 if(a3>alim)
1005 {
1006 siga=std::sqrt(a3) ;
1007 p3 = std::max(0.,G4RandGauss::shoot(a3,siga)+0.5);
1008 }
1009 else
1010 p3 = G4float(G4Poisson(a3));
1011
1012 loss = p3*e0 ;
1013
1014 if(p3 > 0)
1015 loss += (1.-2.*G4UniformRand())*e0 ;
1016
1017 }
1018 else
1019 {
1020 Tm = Tm-ipotFluct+e0 ;
1021 a3 = MeanLoss*(Tm-e0)/(Tm*e0*std::log(Tm/e0));
1022
1023 if(a3>alim)
1024 {
1025 siga=std::sqrt(a3) ;
1026 p3 = std::max(0.,G4RandGauss::shoot(a3,siga)+0.5);
1027 }
1028 else
1029 p3 = G4float(G4Poisson(a3));
1030
1031 if(p3 > 0)
1032 {
1033 w = (Tm-e0)/Tm ;
1034 if(p3 > G4float(nmaxCont2))
1035 {
1036 dp3 = p3 ;
1037 Corrfac = dp3/G4float(nmaxCont2) ;
1038 p3 = G4float(nmaxCont2) ;
1039 }
1040 else
1041 Corrfac = 1. ;
1042
1043 for(G4int i=0; i<G4int(p3); i++) loss += 1./(1.-w*G4UniformRand()) ;
1044 loss *= e0*Corrfac ;
1045 }
1046 }
1047 }
1048
1049 else // not so small Step
1050 {
1051 // excitation type 1
1052 if(a1>alim)
1053 {
1054 siga=std::sqrt(a1) ;
1055 p1 = std::max(0.,G4RandGauss::shoot(a1,siga)+0.5);
1056 }
1057 else
1058 p1 = G4float(G4Poisson(a1));
1059
1060 // excitation type 2
1061 if(a2>alim)
1062 {
1063 siga=std::sqrt(a2) ;
1064 p2 = std::max(0.,G4RandGauss::shoot(a2,siga)+0.5);
1065 }
1066 else
1067 p2 = G4float(G4Poisson(a2));
1068
1069 loss = p1*e1Fluct+p2*e2Fluct;
1070 // smearing to avoid unphysical peaks
1071 if(p2 > 0)
1072 loss += (1.-2.*G4UniformRand())*e2Fluct;
1073 else if (loss>0.)
1074 loss += (1.-2.*G4UniformRand())*e1Fluct;
1075
1076 // ionisation .......................................
1077 if(a3 > 0.)
1078 {
1079 if(a3>alim)
1080 {
1081 siga=std::sqrt(a3) ;
1082 p3 = std::max(0.,G4RandGauss::shoot(a3,siga)+0.5);
1083 }
1084 else
1085 p3 = G4float(G4Poisson(a3));
1086
1087 lossc = 0.;
1088 if(p3 > 0)
1089 {
1090 na = 0.;
1091 alfa = 1.;
1092 if (p3 > G4float(nmaxCont2))
1093 {
1094 dp3 = p3;
1095 rfac = dp3/(G4float(nmaxCont2)+dp3);
1096 namean = p3*rfac;
1097 sa = G4float(nmaxCont1)*rfac;
1098 na = G4RandGauss::shoot(namean,sa);
1099 if (na > 0.)
1100 {
1101 alfa = w1*(G4float(nmaxCont2)+p3)/(w1*G4float(nmaxCont2)+p3);
1102 alfa1 = alfa*std::log(alfa)/(alfa-1.);
1103 ea = na*ipotFluct*alfa1;
1104 sea = ipotFluct*std::sqrt(na*(alfa-alfa1*alfa1));
1105 lossc += G4RandGauss::shoot(ea,sea);
1106 }
1107 }
1108
1109 nb = G4int(p3-na);
1110 if (nb > 0)
1111 {
1112 w2 = alfa*ipotFluct;
1113 w = (Tm-w2)/Tm;
1114 for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
1115 }
1116 }
1117 loss += lossc;
1118 }
1119 }
1120
1121 if( loss < 0.)
1122 loss = 0.;
1123
1124 return loss ;
1125}
1126
1127//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
1128
1129G4bool G4VEnergyLoss::EqualCutVectors( G4double* vec1, G4double* vec2 )
1130{
1131 if ( (vec1==0 ) || (vec2==0) ) return false;
1132
1133 G4bool flag = true;
1134
1135 for (size_t j=0; flag && j<G4Material::GetNumberOfMaterials(); j++){
1136 flag = (vec1[j] == vec2[j]);
1137 }
1138
1139 return flag;
1140}
1141
1142//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
1143
1144G4double* G4VEnergyLoss::CopyCutVectors( G4double* dest, G4double* source )
1145{
1146 if ( dest != 0) delete [] dest;
1147 dest = new G4double [G4Material::GetNumberOfMaterials()];
1148 for (size_t j=0; j<G4Material::GetNumberOfMaterials(); j++){
1149 dest[j] = source[j];
1150 }
1151 return dest;
1152}
1153
1154//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
1155
1156G4bool G4VEnergyLoss::CutsWhereModified()
1157{
1158 G4bool wasModified = false;
1159 const G4ProductionCutsTable* theCoupleTable=
1160 G4ProductionCutsTable::GetProductionCutsTable();
1161 size_t numOfCouples = theCoupleTable->GetTableSize();
1162
1163 for (size_t j=0; j<numOfCouples; j++){
1164 if (theCoupleTable->GetMaterialCutsCouple(j)->IsRecalcNeeded()) {
1165 wasModified = true;
1166 break;
1167 }
1168 }
1169 return wasModified;
1170}
1171
1172//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Note: See TracBrowser for help on using the repository browser.