Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4hRDEnergyLoss.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// $Id$
28//
29// -----------------------------------------------------------
30// GEANT 4 class implementation file
31//
32// History: based on object model of
33// 2nd December 1995, G.Cosmo
34// ---------- G4hEnergyLoss physics process -----------
35// by Laszlo Urban, 30 May 1997
36//
37// **************************************************************
38// It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
39// It calculates the energy loss of charged hadrons.
40// **************************************************************
41//
42// 7/10/98 bug fixes + some cleanup , L.Urban
43// 22/10/98 cleanup , L.Urban
44// 07/12/98 works for ions as well+ bug corrected, L.Urban
45// 02/02/99 several bugs fixed, L.Urban
46// 31/03/00 rename to lowenergy as G4hRDEnergyLoss.cc V.Ivanchenko
47// 05/11/00 new method to calculate particle ranges
48// 10/05/01 V.Ivanchenko Clean up againist Linux compilation with -Wall
49// 23/11/01 V.Ivanchenko Move static member-functions from header to source
50// 28/10/02 V.Ivanchenko Optimal binning for dE/dx
51// 21/01/03 V.Ivanchenko Cut per region
52// 23/01/03 V.Ivanchenko Fix in table build
53
54// 31 Jul 2008 MGP Short term supply of energy loss of hadrons through clone of
55// former G4hLowEnergyLoss (with some initial cleaning)
56// To be replaced by reworked class to deal with condensed/discrete
57// issues properly
58
59// 25 Nov 2010 MGP Added some protections for FPE (mostly division by 0)
60// The whole energy loss domain would profit from a design iteration
61
62// 20 Jun 2011 MGP Corrected some compilation warnings. The whole class will be heavily refactored anyway.
63
64// --------------------------------------------------------------
65
66#include "G4hRDEnergyLoss.hh"
68#include "G4SystemOfUnits.hh"
69#include "G4EnergyLossTables.hh"
70#include "G4Poisson.hh"
72
73
74// Initialisation of static members ******************************************
75// contributing processes : ion.loss ->NumberOfProcesses is initialized
76// to 1 . YOU DO NOT HAVE TO CHANGE this variable for a 'normal' run.
77// You have to change NumberOfProcesses
78// if you invent a new process contributing to the cont. energy loss,
79// NumberOfProcesses should be 2 in this case,
80// or for debugging purposes.
81// The NumberOfProcesses data member can be changed using the (public static)
82// functions Get/Set/Plus/MinusNumberOfProcesses (see G4hRDEnergyLoss.hh)
83
84
85// The following vectors have a fixed dimension this means that if they are
86// filled in with more than 100 elements will corrupt the memory.
87G4int G4hRDEnergyLoss::NumberOfProcesses = 1 ;
88
89G4int G4hRDEnergyLoss::CounterOfProcess = 0 ;
90G4PhysicsTable** G4hRDEnergyLoss::RecorderOfProcess =
91 new G4PhysicsTable*[100] ;
92
95 new G4PhysicsTable*[100] ;
96
99 new G4PhysicsTable*[100] ;
100
111
112G4PhysicsTable* G4hRDEnergyLoss::thepRangeCoeffATable = 0 ;
113G4PhysicsTable* G4hRDEnergyLoss::thepRangeCoeffBTable = 0 ;
114G4PhysicsTable* G4hRDEnergyLoss::thepRangeCoeffCTable = 0 ;
115G4PhysicsTable* G4hRDEnergyLoss::thepbarRangeCoeffATable = 0 ;
116G4PhysicsTable* G4hRDEnergyLoss::thepbarRangeCoeffBTable = 0 ;
117G4PhysicsTable* G4hRDEnergyLoss::thepbarRangeCoeffCTable = 0 ;
118
119G4PhysicsTable* G4hRDEnergyLoss::theDEDXTable = 0 ;
120G4PhysicsTable* G4hRDEnergyLoss::theRangeTable = 0 ;
121G4PhysicsTable* G4hRDEnergyLoss::theInverseRangeTable = 0 ;
122G4PhysicsTable* G4hRDEnergyLoss::theLabTimeTable = 0 ;
123G4PhysicsTable* G4hRDEnergyLoss::theProperTimeTable = 0 ;
124
125G4PhysicsTable* G4hRDEnergyLoss::theRangeCoeffATable = 0 ;
126G4PhysicsTable* G4hRDEnergyLoss::theRangeCoeffBTable = 0 ;
127G4PhysicsTable* G4hRDEnergyLoss::theRangeCoeffCTable = 0 ;
128
129//const G4Proton* G4hRDEnergyLoss::theProton=G4Proton::Proton() ;
130//const G4AntiProton* G4hRDEnergyLoss::theAntiProton=G4AntiProton::AntiProton() ;
131
135
136G4double G4hRDEnergyLoss::Mass,
137 G4hRDEnergyLoss::taulow,
138 G4hRDEnergyLoss::tauhigh,
139 G4hRDEnergyLoss::ltaulow,
140 G4hRDEnergyLoss::ltauhigh;
141
143G4double G4hRDEnergyLoss::finalRange = 200.*micrometer ;
144
145G4double G4hRDEnergyLoss::c1lim = dRoverRange ;
146G4double G4hRDEnergyLoss::c2lim = 2.*(1.-dRoverRange)*finalRange ;
147G4double G4hRDEnergyLoss::c3lim = -(1.-dRoverRange)*finalRange*finalRange;
148
150
153
158
159//--------------------------------------------------------------------------------
160
161// constructor and destructor
162
164 : G4VContinuousDiscreteProcess (processName),
165 MaxExcitationNumber (1.e6),
166 probLimFluct (0.01),
167 nmaxDirectFluct (100),
168 nmaxCont1(4),
169 nmaxCont2(16),
170 theLossTable(0),
171 linLossLimit(0.05),
172 MinKineticEnergy(0.0)
173{;}
174
175//--------------------------------------------------------------------------------
176
178{
179 if(theLossTable) {
181 delete theLossTable;
182 }
183}
184
185//--------------------------------------------------------------------------------
186
188{
189 return NumberOfProcesses;
190}
191
192//--------------------------------------------------------------------------------
193
195{
196 NumberOfProcesses=number;
197}
198
199//--------------------------------------------------------------------------------
200
202{
203 NumberOfProcesses++;
204}
205
206//--------------------------------------------------------------------------------
207
209{
210 NumberOfProcesses--;
211}
212
213//--------------------------------------------------------------------------------
214
216{
217 dRoverRange = value;
218}
219
220//--------------------------------------------------------------------------------
221
223{
224 rndmStepFlag = value;
225}
226
227//--------------------------------------------------------------------------------
228
230{
231 EnlossFlucFlag = value;
232}
233
234//--------------------------------------------------------------------------------
235
237{
238 dRoverRange = c1;
239 finalRange = c2;
243}
244
245//--------------------------------------------------------------------------------
246
248 const G4ParticleDefinition& aParticleType)
249{
250 // calculate data members TotBin,LOGRTable,RTable first
251
252 const G4ProductionCutsTable* theCoupleTable=
254 size_t numOfCouples = theCoupleTable->GetTableSize();
255
256 // create/fill proton or antiproton tables depending on the charge
257 Charge = aParticleType.GetPDGCharge()/eplus;
258 ParticleMass = aParticleType.GetPDGMass() ;
259
260 if (Charge>0.) {theDEDXTable= theDEDXpTable;}
261 else {theDEDXTable= theDEDXpbarTable;}
262
263 if( ((Charge>0.) && (theDEDXTable==0)) ||
264 ((Charge<0.) && (theDEDXTable==0))
265 )
266 {
267
268 // Build energy loss table as a sum of the energy loss due to the
269 // different processes.
270 if( Charge >0.)
271 {
272 RecorderOfProcess=RecorderOfpProcess;
273 CounterOfProcess=CounterOfpProcess;
274
275 if(CounterOfProcess == NumberOfProcesses)
276 {
277 if(theDEDXpTable)
279 delete theDEDXpTable; }
280 theDEDXpTable = new G4PhysicsTable(numOfCouples);
281 theDEDXTable = theDEDXpTable;
282 }
283 }
284 else
285 {
286 RecorderOfProcess=RecorderOfpbarProcess;
287 CounterOfProcess=CounterOfpbarProcess;
288
289 if(CounterOfProcess == NumberOfProcesses)
290 {
293 delete theDEDXpbarTable; }
294 theDEDXpbarTable = new G4PhysicsTable(numOfCouples);
295 theDEDXTable = theDEDXpbarTable;
296 }
297 }
298
299 if(CounterOfProcess == NumberOfProcesses)
300 {
301 // loop for materials
302 G4double LowEdgeEnergy , Value ;
303 G4bool isOutRange ;
304 G4PhysicsTable* pointer ;
305
306 for (size_t J=0; J<numOfCouples; J++)
307 {
308 // create physics vector and fill it
311
312 // loop for the kinetic energy
313 for (G4int i=0; i<TotBin; i++)
314 {
315 LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
316 Value = 0. ;
317
318 // loop for the contributing processes
319 for (G4int process=0; process < NumberOfProcesses; process++)
320 {
321 pointer= RecorderOfProcess[process];
322 Value += (*pointer)[J]->
323 GetValue(LowEdgeEnergy,isOutRange) ;
324 }
325
326 aVector->PutValue(i,Value) ;
327 }
328
329 theDEDXTable->insert(aVector) ;
330 }
331
332 // reset counter to zero ..................
333 if( Charge >0.)
335 else
337
338 // Build range table
339 BuildRangeTable( aParticleType);
340
341 // Build lab/proper time tables
342 BuildTimeTables( aParticleType) ;
343
344 // Build coeff tables for the energy loss calculation
345 BuildRangeCoeffATable( aParticleType);
346 BuildRangeCoeffBTable( aParticleType);
347 BuildRangeCoeffCTable( aParticleType);
348
349 // invert the range table
350
351 BuildInverseRangeTable(aParticleType);
352 }
353 }
354 // make the energy loss and the range table available
355
356 G4EnergyLossTables::Register(&aParticleType,
357 (Charge>0)?
359 (Charge>0)?
361 (Charge>0)?
363 (Charge>0)?
365 (Charge>0)?
368 proton_mass_c2/aParticleType.GetPDGMass(),
369 TotBin);
370
371}
372
373//--------------------------------------------------------------------------------
374
375void G4hRDEnergyLoss::BuildRangeTable(
376 const G4ParticleDefinition& aParticleType)
377// Build range table from the energy loss table
378{
379 Mass = aParticleType.GetPDGMass();
380
381 const G4ProductionCutsTable* theCoupleTable=
383 size_t numOfCouples = theCoupleTable->GetTableSize();
384
385 if( Charge >0.)
386 {
389 delete theRangepTable; }
390 theRangepTable = new G4PhysicsTable(numOfCouples);
391 theRangeTable = theRangepTable ;
392 }
393 else
394 {
397 delete theRangepbarTable; }
398 theRangepbarTable = new G4PhysicsTable(numOfCouples);
399 theRangeTable = theRangepbarTable ;
400 }
401
402 // loop for materials
403
404 for (size_t J=0; J<numOfCouples; J++)
405 {
406 G4PhysicsLogVector* aVector;
409
410 BuildRangeVector(J, aVector);
411 theRangeTable->insert(aVector);
412 }
413}
414
415//--------------------------------------------------------------------------------
416
417void G4hRDEnergyLoss::BuildTimeTables(
418 const G4ParticleDefinition& aParticleType)
419{
420
421 const G4ProductionCutsTable* theCoupleTable=
423 size_t numOfCouples = theCoupleTable->GetTableSize();
424
425 if(&aParticleType == G4Proton::Proton())
426 {
429 delete theLabTimepTable; }
430 theLabTimepTable = new G4PhysicsTable(numOfCouples);
431 theLabTimeTable = theLabTimepTable ;
432
435 delete theProperTimepTable; }
436 theProperTimepTable = new G4PhysicsTable(numOfCouples);
437 theProperTimeTable = theProperTimepTable ;
438 }
439
440 if(&aParticleType == G4AntiProton::AntiProton())
441 {
444 delete theLabTimepbarTable; }
445 theLabTimepbarTable = new G4PhysicsTable(numOfCouples);
446 theLabTimeTable = theLabTimepbarTable ;
447
450 delete theProperTimepbarTable; }
451 theProperTimepbarTable = new G4PhysicsTable(numOfCouples);
452 theProperTimeTable = theProperTimepbarTable ;
453 }
454
455 for (size_t J=0; J<numOfCouples; J++)
456 {
457 G4PhysicsLogVector* aVector;
458 G4PhysicsLogVector* bVector;
459
462
463 BuildLabTimeVector(J, aVector);
464 theLabTimeTable->insert(aVector);
465
468
469 BuildProperTimeVector(J, bVector);
470 theProperTimeTable->insert(bVector);
471 }
472}
473
474//--------------------------------------------------------------------------------
475
476void G4hRDEnergyLoss::BuildRangeVector(G4int materialIndex,
477 G4PhysicsLogVector* rangeVector)
478// create range vector for a material
479{
480 G4bool isOut;
481 G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
482 G4double energy1 = rangeVector->GetLowEdgeEnergy(0);
483 G4double dedx = physicsVector->GetValue(energy1,isOut);
484 G4double range = 0.5*energy1/dedx;
485 rangeVector->PutValue(0,range);
486 G4int n = 100;
487 G4double del = 1.0/(G4double)n ;
488
489 for (G4int j=1; j<TotBin; j++) {
490
491 G4double energy2 = rangeVector->GetLowEdgeEnergy(j);
492 G4double de = (energy2 - energy1) * del ;
493 G4double dedx1 = dedx ;
494
495 for (G4int i=1; i<n; i++) {
496 G4double energy = energy1 + i*de ;
497 G4double dedx2 = physicsVector->GetValue(energy,isOut);
498 range += 0.5*de*(1.0/dedx1 + 1.0/dedx2);
499 dedx1 = dedx2;
500 }
501 rangeVector->PutValue(j,range);
502 dedx = dedx1 ;
503 energy1 = energy2 ;
504 }
505}
506
507//--------------------------------------------------------------------------------
508
509void G4hRDEnergyLoss::BuildLabTimeVector(G4int materialIndex,
510 G4PhysicsLogVector* timeVector)
511// create lab time vector for a material
512{
513
514 G4int nbin=100;
515 G4bool isOut;
516 G4double tlim=5.*keV,parlowen=0.4,ppar=0.5-parlowen ;
517 //G4double losslim,clim,taulim,timelim,ltaulim,ltaumax,
518 G4double losslim,clim,taulim,timelim,
519 LowEdgeEnergy,tau,Value ;
520
521 G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
522
523 // low energy part first...
524 losslim = physicsVector->GetValue(tlim,isOut);
525 taulim=tlim/ParticleMass ;
526 clim=std::sqrt(ParticleMass*tlim/2.)/(c_light*losslim*ppar) ;
527 //ltaulim = std::log(taulim);
528 //ltaumax = std::log(HighestKineticEnergy/ParticleMass) ;
529
530 G4int i=-1;
531 G4double oldValue = 0. ;
532 G4double tauold ;
533 do
534 {
535 i += 1 ;
536 LowEdgeEnergy = timeVector->GetLowEdgeEnergy(i);
537 tau = LowEdgeEnergy/ParticleMass ;
538 if ( tau <= taulim )
539 {
540 Value = clim*std::exp(ppar*std::log(tau/taulim)) ;
541 }
542 else
543 {
544 timelim=clim ;
545 ltaulow = std::log(taulim);
546 ltauhigh = std::log(tau);
547 Value = timelim+LabTimeIntLog(physicsVector,nbin);
548 }
549 timeVector->PutValue(i,Value);
550 oldValue = Value ;
551 tauold = tau ;
552 } while (tau<=taulim) ;
553
554 i += 1 ;
555 for (G4int j=i; j<TotBin; j++)
556 {
557 LowEdgeEnergy = timeVector->GetLowEdgeEnergy(j);
558 tau = LowEdgeEnergy/ParticleMass ;
559 ltaulow = std::log(tauold);
560 ltauhigh = std::log(tau);
561 Value = oldValue+LabTimeIntLog(physicsVector,nbin);
562 timeVector->PutValue(j,Value);
563 oldValue = Value ;
564 tauold = tau ;
565 }
566}
567
568//--------------------------------------------------------------------------------
569
570void G4hRDEnergyLoss::BuildProperTimeVector(G4int materialIndex,
571 G4PhysicsLogVector* timeVector)
572// create proper time vector for a material
573{
574 G4int nbin=100;
575 G4bool isOut;
576 G4double tlim=5.*keV,parlowen=0.4,ppar=0.5-parlowen ;
577 //G4double losslim,clim,taulim,timelim,ltaulim,ltaumax,
578 G4double losslim,clim,taulim,timelim,
579 LowEdgeEnergy,tau,Value ;
580
581 G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
582
583 // low energy part first...
584 losslim = physicsVector->GetValue(tlim,isOut);
585 taulim=tlim/ParticleMass ;
586 clim=std::sqrt(ParticleMass*tlim/2.)/(c_light*losslim*ppar) ;
587 //ltaulim = std::log(taulim);
588 //ltaumax = std::log(HighestKineticEnergy/ParticleMass) ;
589
590 G4int i=-1;
591 G4double oldValue = 0. ;
592 G4double tauold ;
593 do
594 {
595 i += 1 ;
596 LowEdgeEnergy = timeVector->GetLowEdgeEnergy(i);
597 tau = LowEdgeEnergy/ParticleMass ;
598 if ( tau <= taulim )
599 {
600 Value = clim*std::exp(ppar*std::log(tau/taulim)) ;
601 }
602 else
603 {
604 timelim=clim ;
605 ltaulow = std::log(taulim);
606 ltauhigh = std::log(tau);
607 Value = timelim+ProperTimeIntLog(physicsVector,nbin);
608 }
609 timeVector->PutValue(i,Value);
610 oldValue = Value ;
611 tauold = tau ;
612 } while (tau<=taulim) ;
613
614 i += 1 ;
615 for (G4int j=i; j<TotBin; j++)
616 {
617 LowEdgeEnergy = timeVector->GetLowEdgeEnergy(j);
618 tau = LowEdgeEnergy/ParticleMass ;
619 ltaulow = std::log(tauold);
620 ltauhigh = std::log(tau);
621 Value = oldValue+ProperTimeIntLog(physicsVector,nbin);
622 timeVector->PutValue(j,Value);
623 oldValue = Value ;
624 tauold = tau ;
625 }
626}
627
628//--------------------------------------------------------------------------------
629
630G4double G4hRDEnergyLoss::RangeIntLin(G4PhysicsVector* physicsVector,
631 G4int nbin)
632// num. integration, linear binning
633{
634 G4double dtau,Value,taui,ti,lossi,ci;
635 G4bool isOut;
636 dtau = (tauhigh-taulow)/nbin;
637 Value = 0.;
638
639 for (G4int i=0; i<=nbin; i++)
640 {
641 taui = taulow + dtau*i ;
642 ti = Mass*taui;
643 lossi = physicsVector->GetValue(ti,isOut);
644 if(i==0)
645 ci=0.5;
646 else
647 {
648 if(i<nbin)
649 ci=1.;
650 else
651 ci=0.5;
652 }
653 Value += ci/lossi;
654 }
655 Value *= Mass*dtau;
656 return Value;
657}
658
659//--------------------------------------------------------------------------------
660
661G4double G4hRDEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
662 G4int nbin)
663// num. integration, logarithmic binning
664{
665 G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
666 G4bool isOut;
667 ltt = ltauhigh-ltaulow;
668 dltau = ltt/nbin;
669 Value = 0.;
670
671 for (G4int i=0; i<=nbin; i++)
672 {
673 ui = ltaulow+dltau*i;
674 taui = std::exp(ui);
675 ti = Mass*taui;
676 lossi = physicsVector->GetValue(ti,isOut);
677 if(i==0)
678 ci=0.5;
679 else
680 {
681 if(i<nbin)
682 ci=1.;
683 else
684 ci=0.5;
685 }
686 Value += ci*taui/lossi;
687 }
688 Value *= Mass*dltau;
689 return Value;
690}
691
692//--------------------------------------------------------------------------------
693
694G4double G4hRDEnergyLoss::LabTimeIntLog(G4PhysicsVector* physicsVector,
695 G4int nbin)
696// num. integration, logarithmic binning
697{
698 G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
699 G4bool isOut;
700 ltt = ltauhigh-ltaulow;
701 dltau = ltt/nbin;
702 Value = 0.;
703
704 for (G4int i=0; i<=nbin; i++)
705 {
706 ui = ltaulow+dltau*i;
707 taui = std::exp(ui);
708 ti = ParticleMass*taui;
709 lossi = physicsVector->GetValue(ti,isOut);
710 if(i==0)
711 ci=0.5;
712 else
713 {
714 if(i<nbin)
715 ci=1.;
716 else
717 ci=0.5;
718 }
719 Value += ci*taui*(ti+ParticleMass)/(std::sqrt(ti*(ti+2.*ParticleMass))*lossi);
720 }
721 Value *= ParticleMass*dltau/c_light;
722 return Value;
723}
724
725//--------------------------------------------------------------------------------
726
727G4double G4hRDEnergyLoss::ProperTimeIntLog(G4PhysicsVector* physicsVector,
728 G4int nbin)
729// num. integration, logarithmic binning
730{
731 G4double ltt,dltau,Value,ui,taui,ti,lossi,ci;
732 G4bool isOut;
733 ltt = ltauhigh-ltaulow;
734 dltau = ltt/nbin;
735 Value = 0.;
736
737 for (G4int i=0; i<=nbin; i++)
738 {
739 ui = ltaulow+dltau*i;
740 taui = std::exp(ui);
741 ti = ParticleMass*taui;
742 lossi = physicsVector->GetValue(ti,isOut);
743 if(i==0)
744 ci=0.5;
745 else
746 {
747 if(i<nbin)
748 ci=1.;
749 else
750 ci=0.5;
751 }
752 Value += ci*taui*ParticleMass/(std::sqrt(ti*(ti+2.*ParticleMass))*lossi);
753 }
754 Value *= ParticleMass*dltau/c_light;
755 return Value;
756}
757
758//--------------------------------------------------------------------------------
759
760void G4hRDEnergyLoss::BuildRangeCoeffATable(
761 const G4ParticleDefinition& )
762// Build tables of coefficients for the energy loss calculation
763// create table for coefficients "A"
764{
765
767
768 if(Charge>0.)
769 {
770 if(thepRangeCoeffATable)
771 { thepRangeCoeffATable->clearAndDestroy();
772 delete thepRangeCoeffATable; }
773 thepRangeCoeffATable = new G4PhysicsTable(numOfCouples);
774 theRangeCoeffATable = thepRangeCoeffATable ;
775 theRangeTable = theRangepTable ;
776 }
777 else
778 {
779 if(thepbarRangeCoeffATable)
780 { thepbarRangeCoeffATable->clearAndDestroy();
781 delete thepbarRangeCoeffATable; }
782 thepbarRangeCoeffATable = new G4PhysicsTable(numOfCouples);
783 theRangeCoeffATable = thepbarRangeCoeffATable ;
784 theRangeTable = theRangepbarTable ;
785 }
786
787 G4double R2 = RTable*RTable ;
788 G4double R1 = RTable+1.;
789 G4double w = R1*(RTable-1.)*(RTable-1.);
790 G4double w1 = RTable/w , w2 = -RTable*R1/w , w3 = R2/w ;
791 G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
792 G4bool isOut;
793
794 // loop for materials
795 for (G4int J=0; J<numOfCouples; J++)
796 {
797 G4int binmax=TotBin ;
798 G4PhysicsLinearVector* aVector =
799 new G4PhysicsLinearVector(0.,binmax, TotBin);
801 if (Ti < DBL_MIN) Ti = 1.e-8;
802 G4PhysicsVector* rangeVector= (*theRangeTable)[J];
803
804 for ( G4int i=0; i<TotBin; i++)
805 {
806 Ri = rangeVector->GetValue(Ti,isOut) ;
807 if (Ti < DBL_MIN) Ti = 1.e-8;
808 if ( i==0 )
809 Rim = 0. ;
810 else
811 {
812 // ---- MGP ---- Modified to avoid a floating point exception
813 // The correction is just a temporary patch, the whole class should be redesigned
814 // Original: Tim = Ti/RTable results in 0./0.
815 if (RTable != 0.)
816 {
817 Tim = Ti/RTable ;
818 }
819 else
820 {
821 Tim = 0.;
822 }
823 Rim = rangeVector->GetValue(Tim,isOut);
824 }
825 if ( i==(TotBin-1))
826 Rip = Ri ;
827 else
828 {
829 Tip = Ti*RTable ;
830 Rip = rangeVector->GetValue(Tip,isOut);
831 }
832 Value = (w1*Rip + w2*Ri + w3*Rim)/(Ti*Ti) ;
833
834 aVector->PutValue(i,Value);
835 Ti = RTable*Ti ;
836 }
837
838 theRangeCoeffATable->insert(aVector);
839 }
840}
841
842//--------------------------------------------------------------------------------
843
844void G4hRDEnergyLoss::BuildRangeCoeffBTable(
845 const G4ParticleDefinition& )
846// Build tables of coefficients for the energy loss calculation
847// create table for coefficients "B"
848{
849
851
852 if(Charge>0.)
853 {
854 if(thepRangeCoeffBTable)
855 { thepRangeCoeffBTable->clearAndDestroy();
856 delete thepRangeCoeffBTable; }
857 thepRangeCoeffBTable = new G4PhysicsTable(numOfCouples);
858 theRangeCoeffBTable = thepRangeCoeffBTable ;
859 theRangeTable = theRangepTable ;
860 }
861 else
862 {
863 if(thepbarRangeCoeffBTable)
864 { thepbarRangeCoeffBTable->clearAndDestroy();
865 delete thepbarRangeCoeffBTable; }
866 thepbarRangeCoeffBTable = new G4PhysicsTable(numOfCouples);
867 theRangeCoeffBTable = thepbarRangeCoeffBTable ;
868 theRangeTable = theRangepbarTable ;
869 }
870
871 G4double R2 = RTable*RTable ;
872 G4double R1 = RTable+1.;
873 G4double w = R1*(RTable-1.)*(RTable-1.);
874 if (w < DBL_MIN) w = DBL_MIN;
875 G4double w1 = -R1/w , w2 = R1*(R2+1.)/w , w3 = -R2*R1/w ;
876 G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
877 G4bool isOut;
878
879 // loop for materials
880 for (G4int J=0; J<numOfCouples; J++)
881 {
882 G4int binmax=TotBin ;
883 G4PhysicsLinearVector* aVector =
884 new G4PhysicsLinearVector(0.,binmax, TotBin);
886 if (Ti < DBL_MIN) Ti = 1.e-8;
887 G4PhysicsVector* rangeVector= (*theRangeTable)[J];
888
889 for ( G4int i=0; i<TotBin; i++)
890 {
891 Ri = rangeVector->GetValue(Ti,isOut) ;
892 if (Ti < DBL_MIN) Ti = 1.e-8;
893 if ( i==0 )
894 Rim = 0. ;
895 else
896 {
897 if (RTable < DBL_MIN) RTable = DBL_MIN;
898 Tim = Ti/RTable ;
899 Rim = rangeVector->GetValue(Tim,isOut);
900 }
901 if ( i==(TotBin-1))
902 Rip = Ri ;
903 else
904 {
905 Tip = Ti*RTable ;
906 Rip = rangeVector->GetValue(Tip,isOut);
907 }
908 if (Ti < DBL_MIN) Ti = DBL_MIN;
909 Value = (w1*Rip + w2*Ri + w3*Rim)/Ti;
910
911 aVector->PutValue(i,Value);
912 Ti = RTable*Ti ;
913 }
914 theRangeCoeffBTable->insert(aVector);
915 }
916}
917
918//--------------------------------------------------------------------------------
919
920void G4hRDEnergyLoss::BuildRangeCoeffCTable(
921 const G4ParticleDefinition& )
922// Build tables of coefficients for the energy loss calculation
923// create table for coefficients "C"
924{
925
927
928 if(Charge>0.)
929 {
930 if(thepRangeCoeffCTable)
931 { thepRangeCoeffCTable->clearAndDestroy();
932 delete thepRangeCoeffCTable; }
933 thepRangeCoeffCTable = new G4PhysicsTable(numOfCouples);
934 theRangeCoeffCTable = thepRangeCoeffCTable ;
935 theRangeTable = theRangepTable ;
936 }
937 else
938 {
939 if(thepbarRangeCoeffCTable)
940 { thepbarRangeCoeffCTable->clearAndDestroy();
941 delete thepbarRangeCoeffCTable; }
942 thepbarRangeCoeffCTable = new G4PhysicsTable(numOfCouples);
943 theRangeCoeffCTable = thepbarRangeCoeffCTable ;
944 theRangeTable = theRangepbarTable ;
945 }
946
947 G4double R2 = RTable*RTable ;
948 G4double R1 = RTable+1.;
949 G4double w = R1*(RTable-1.)*(RTable-1.);
950 G4double w1 = 1./w , w2 = -RTable*R1/w , w3 = RTable*R2/w ;
951 G4double Ti , Tim , Tip , Ri , Rim , Rip , Value ;
952 G4bool isOut;
953
954 // loop for materials
955 for (G4int J=0; J<numOfCouples; J++)
956 {
957 G4int binmax=TotBin ;
958 G4PhysicsLinearVector* aVector =
959 new G4PhysicsLinearVector(0.,binmax, TotBin);
961 G4PhysicsVector* rangeVector= (*theRangeTable)[J];
962
963 for ( G4int i=0; i<TotBin; i++)
964 {
965 Ri = rangeVector->GetValue(Ti,isOut) ;
966 if ( i==0 )
967 Rim = 0. ;
968 else
969 {
970 Tim = Ti/RTable ;
971 Rim = rangeVector->GetValue(Tim,isOut);
972 }
973 if ( i==(TotBin-1))
974 Rip = Ri ;
975 else
976 {
977 Tip = Ti*RTable ;
978 Rip = rangeVector->GetValue(Tip,isOut);
979 }
980 Value = w1*Rip + w2*Ri + w3*Rim ;
981
982 aVector->PutValue(i,Value);
983 Ti = RTable*Ti ;
984 }
985 theRangeCoeffCTable->insert(aVector);
986 }
987}
988
989//--------------------------------------------------------------------------------
990
991void G4hRDEnergyLoss::BuildInverseRangeTable(
992 const G4ParticleDefinition& aParticleType)
993// Build inverse table of the range table
994{
995 G4bool b;
996
997 const G4ProductionCutsTable* theCoupleTable=
999 size_t numOfCouples = theCoupleTable->GetTableSize();
1000
1001 if(&aParticleType == G4Proton::Proton())
1002 {
1005 delete theInverseRangepTable; }
1006 theInverseRangepTable = new G4PhysicsTable(numOfCouples);
1007 theInverseRangeTable = theInverseRangepTable ;
1008 theRangeTable = theRangepTable ;
1009 theDEDXTable = theDEDXpTable ;
1010 theRangeCoeffATable = thepRangeCoeffATable ;
1011 theRangeCoeffBTable = thepRangeCoeffBTable ;
1012 theRangeCoeffCTable = thepRangeCoeffCTable ;
1013 }
1014
1015 if(&aParticleType == G4AntiProton::AntiProton())
1016 {
1019 delete theInverseRangepbarTable; }
1020 theInverseRangepbarTable = new G4PhysicsTable(numOfCouples);
1021 theInverseRangeTable = theInverseRangepbarTable ;
1022 theRangeTable = theRangepbarTable ;
1023 theDEDXTable = theDEDXpbarTable ;
1024 theRangeCoeffATable = thepbarRangeCoeffATable ;
1025 theRangeCoeffBTable = thepbarRangeCoeffBTable ;
1026 theRangeCoeffCTable = thepbarRangeCoeffCTable ;
1027 }
1028
1029 // loop for materials
1030 for (size_t i=0; i<numOfCouples; i++)
1031 {
1032
1033 G4PhysicsVector* pv = (*theRangeTable)[i];
1034 size_t nbins = pv->GetVectorLength();
1035 G4double elow = pv->GetLowEdgeEnergy(0);
1036 G4double ehigh = pv->GetLowEdgeEnergy(nbins-1);
1037 G4double rlow = pv->GetValue(elow, b);
1038 G4double rhigh = pv->GetValue(ehigh, b);
1039
1040 if (rlow <DBL_MIN) rlow = 1.e-8;
1041 if (rhigh > 1.e16) rhigh = 1.e16;
1042 if (rhigh < 1.e-8) rhigh =1.e-8;
1043 G4double tmpTrick = rhigh/rlow;
1044
1045 //std::cout << nbins << ", elow " << elow << ", ehigh " << ehigh
1046 // << ", rlow " << rlow << ", rhigh " << rhigh << ", trick " << tmpTrick << std::endl;
1047
1048 if (tmpTrick <= 0. || tmpTrick < DBL_MIN) tmpTrick = 1.e-8;
1049 if (tmpTrick > 1.e16) tmpTrick = 1.e16;
1050
1051 rhigh *= std::exp(std::log(tmpTrick)/((G4double)(nbins-1)));
1052
1053 G4PhysicsLogVector* v = new G4PhysicsLogVector(rlow, rhigh, nbins);
1054
1055 v->PutValue(0,elow);
1056 G4double energy1 = elow;
1057 G4double range1 = rlow;
1058 G4double energy2 = elow;
1059 G4double range2 = rlow;
1060 size_t ilow = 0;
1061 size_t ihigh;
1062
1063 for (size_t j=1; j<nbins; j++) {
1064
1065 G4double range = v->GetLowEdgeEnergy(j);
1066
1067 for (ihigh=ilow+1; ihigh<nbins; ihigh++) {
1068 energy2 = pv->GetLowEdgeEnergy(ihigh);
1069 range2 = pv->GetValue(energy2, b);
1070 if(range2 >= range || ihigh == nbins-1) {
1071 ilow = ihigh - 1;
1072 energy1 = pv->GetLowEdgeEnergy(ilow);
1073 range1 = pv->GetValue(energy1, b);
1074 break;
1075 }
1076 }
1077
1078 G4double e = std::log(energy1) + std::log(energy2/energy1)*std::log(range/range1)/std::log(range2/range1);
1079
1080 v->PutValue(j,std::exp(e));
1081 }
1082 theInverseRangeTable->insert(v);
1083
1084 }
1085}
1086
1087//--------------------------------------------------------------------------------
1088
1089void G4hRDEnergyLoss::InvertRangeVector(G4int materialIndex,
1090 G4PhysicsLogVector* aVector)
1091// invert range vector for a material
1092{
1093 G4double LowEdgeRange,A,B,C,discr,KineticEnergy ;
1095 G4double rangebin = 0.0 ;
1096 G4int binnumber = -1 ;
1097 G4bool isOut ;
1098
1099
1100 //loop for range values
1101 for( G4int i=0; i<TotBin; i++)
1102 {
1103 LowEdgeRange = aVector->GetLowEdgeEnergy(i) ; //i.e. GetLowEdgeValue(i)
1104
1105 if( rangebin < LowEdgeRange )
1106 {
1107 do
1108 {
1109 binnumber += 1 ;
1110 Tbin *= RTable ;
1111 rangebin = (*theRangeTable)(materialIndex)->GetValue(Tbin,isOut) ;
1112 }
1113 while ((rangebin < LowEdgeRange) && (binnumber < TotBin )) ;
1114 }
1115
1116 if(binnumber == 0)
1117 KineticEnergy = LowestKineticEnergy ;
1118 else if(binnumber == TotBin-1)
1119 KineticEnergy = HighestKineticEnergy ;
1120 else
1121 {
1122 A = (*(*theRangeCoeffATable)(materialIndex))(binnumber-1) ;
1123 B = (*(*theRangeCoeffBTable)(materialIndex))(binnumber-1) ;
1124 C = (*(*theRangeCoeffCTable)(materialIndex))(binnumber-1) ;
1125 if(A==0.)
1126 KineticEnergy = (LowEdgeRange -C )/B ;
1127 else
1128 {
1129 discr = B*B - 4.*A*(C-LowEdgeRange);
1130 discr = discr>0. ? std::sqrt(discr) : 0.;
1131 KineticEnergy = 0.5*(discr-B)/A ;
1132 }
1133 }
1134
1135 aVector->PutValue(i,KineticEnergy) ;
1136 }
1137}
1138
1139//------------------------------------------------------------------------------
1140
1142{
1143 G4bool wasModified = false;
1144 const G4ProductionCutsTable* theCoupleTable=
1146 size_t numOfCouples = theCoupleTable->GetTableSize();
1147
1148 for (size_t j=0; j<numOfCouples; j++){
1149 if (theCoupleTable->GetMaterialCutsCouple(j)->IsRecalcNeeded()) {
1150 wasModified = true;
1151 break;
1152 }
1153 }
1154 return wasModified;
1155}
1156
1157//-----------------------------------------------------------------------
1158//--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
1159
1160//G4bool G4hRDEnergyLoss::IsApplicable(const G4ParticleDefinition&
1161// particle)
1162//{
1163// return((particle.GetPDGCharge()!= 0.) && (particle.GetLeptonNumber() == 0));
1164//}
1165
1166//G4double G4hRDEnergyLoss::GetContinuousStepLimit(
1167// const G4Track& track,
1168// G4double,
1169// G4double currentMinimumStep,
1170// G4double&)
1171//{
1172//
1173// G4double Step =
1174// GetConstraints(track.GetDynamicParticle(),track.GetMaterial()) ;
1175//
1176// if((Step>0.0)&&(Step<currentMinimumStep))
1177// currentMinimumStep = Step ;
1178//
1179// return Step ;
1180//}
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
static G4AntiProton * AntiProton()
Definition: G4AntiProton.cc:93
static void Register(const G4ParticleDefinition *p, const G4PhysicsTable *tDEDX, const G4PhysicsTable *tRange, const G4PhysicsTable *tInverseRange, const G4PhysicsTable *tLabTime, const G4PhysicsTable *tProperTime, G4double lowestKineticEnergy, G4double highestKineticEnergy, G4double massRatio, G4int NumberOfBins)
G4double GetPDGCharge() const
void clearAndDestroy()
void insert(G4PhysicsVector *)
size_t GetVectorLength() const
G4double GetValue(G4double theEnergy, G4bool &isOutRange)
virtual G4double GetLowEdgeEnergy(size_t binNumber) const
void PutValue(size_t index, G4double theValue)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
static G4ProductionCutsTable * GetProductionCutsTable()
static G4Proton * Proton()
Definition: G4Proton.cc:93
static G4PhysicsTable * theDEDXpTable
static void SetStepFunction(G4double c1, G4double c2)
static G4PhysicsTable * theInverseRangepbarTable
static G4PhysicsTable * theInverseRangepTable
static G4double pbartableElectronCutInRange
static G4PhysicsTable ** RecorderOfpbarProcess
static G4double finalRange
static G4int CounterOfpbarProcess
static G4PhysicsTable * theRangepTable
static G4PhysicsTable * theDEDXpbarTable
G4PhysicsTable * theLossTable
static G4double dRoverRange
G4hRDEnergyLoss(const G4String &)
static G4double LowestKineticEnergy
static void SetdRoverRange(G4double value)
static void PlusNumberOfProcesses()
static G4double c2lim
static void SetRndmStep(G4bool value)
static G4PhysicsTable * theLabTimepTable
static G4double Charge
static G4PhysicsTable * theProperTimepbarTable
static G4PhysicsTable * theProperTimepTable
static G4PhysicsTable ** RecorderOfpProcess
static G4PhysicsTable * theLabTimepbarTable
static G4int TotBin
static void MinusNumberOfProcesses()
static G4bool EnlossFlucFlag
G4bool CutsWhereModified()
static G4double c3lim
static G4bool rndmStepFlag
static void SetNumberOfProcesses(G4int number)
static G4double HighestKineticEnergy
static void SetEnlossFluc(G4bool value)
static G4int GetNumberOfProcesses()
static G4double ptableElectronCutInRange
static G4int CounterOfpProcess
static G4double ParticleMass
static G4PhysicsTable * theRangepbarTable
static G4double c1lim
static G4double LOGRTable
static G4double RTable
static void BuildDEDXTable(const G4ParticleDefinition &aParticleType)
#define DBL_MIN
Definition: templates.hh:75