Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4PAIModel.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// $Id$
27//
28// -------------------------------------------------------------------
29//
30// GEANT4 Class
31// File name: G4PAIModel.cc
32//
33// Author: Vladimir.Grichine@cern.ch on base of Vladimir Ivanchenko model interface
34//
35// Creation date: 05.10.2003
36//
37// Modifications:
38//
39// 17.08.04 V.Grichine, bug fixed for Tkin<=0 in SampleSecondary
40// 16.08.04 V.Grichine, bug fixed in massRatio for DEDX, CrossSection, SampleSecondary
41// 08.04.05 Major optimisation of internal interfaces (V.Ivantchenko)
42// 26.07.09 Fixed logic to work with several materials (V.Ivantchenko)
43// 21.11.10 V. Grichine verbose flag for protons and G4PAYySection to check sandia table
44//
45
46#include "G4PAIModel.hh"
47
49#include "G4SystemOfUnits.hh"
50#include "G4Region.hh"
51#include "G4PhysicsLogVector.hh"
53#include "G4PhysicsTable.hh"
56#include "G4MaterialTable.hh"
57#include "G4SandiaTable.hh"
58#include "G4OrderedTable.hh"
59
60#include "Randomize.hh"
61#include "G4Electron.hh"
62#include "G4Positron.hh"
63#include "G4Poisson.hh"
64#include "G4Step.hh"
65#include "G4Material.hh"
66#include "G4DynamicParticle.hh"
69
70////////////////////////////////////////////////////////////////////////
71
72using namespace std;
73
76 fVerbose(0),
77 fLowestGamma(1.005),
78 fHighestGamma(10000.),
79 fTotBin(200),
80 fMeanNumber(20),
81 fParticle(0),
82 fHighKinEnergy(100.*TeV),
83 fTwoln10(2.0*log(10.0)),
84 fBg2lim(0.0169),
85 fTaulim(8.4146e-3)
86{
87 fElectron = G4Electron::Electron();
88 fPositron = G4Positron::Positron();
89
90 fPAItransferTable = 0;
91 fPAIdEdxTable = 0;
92 fSandiaPhotoAbsCof = 0;
93 fdEdxVector = 0;
94 fLambdaVector = 0;
95 fdNdxCutVector = 0;
96 fParticleEnergyVector = 0;
97 fSandiaIntervalNumber = 0;
98 fMatIndex = 0;
99 fDeltaCutInKinEnergy = 0.0;
100 fParticleChange = 0;
101 fMaterial = 0;
102 fCutCouple = 0;
103
104 if(p) { SetParticle(p); }
105 else { SetParticle(fElectron); }
106
107 isInitialised = false;
108}
109
110////////////////////////////////////////////////////////////////////////////
111
113{
114 // G4cout << "PAI: start destruction" << G4endl;
115 if(fParticleEnergyVector) delete fParticleEnergyVector;
116 if(fdEdxVector) delete fdEdxVector ;
117 if(fLambdaVector) delete fLambdaVector;
118 if(fdNdxCutVector) delete fdNdxCutVector;
119
120 if( fPAItransferTable )
121 {
122 fPAItransferTable->clearAndDestroy();
123 delete fPAItransferTable ;
124 }
125 if( fPAIdEdxTable )
126 {
127 fPAIdEdxTable->clearAndDestroy();
128 delete fPAIdEdxTable ;
129 }
130 if(fSandiaPhotoAbsCof)
131 {
132 for(G4int i=0;i<fSandiaIntervalNumber;i++)
133 {
134 delete[] fSandiaPhotoAbsCof[i];
135 }
136 delete[] fSandiaPhotoAbsCof;
137 }
138 //G4cout << "PAI: end destruction" << G4endl;
139}
140
141///////////////////////////////////////////////////////////////////////////////
142
143void G4PAIModel::SetParticle(const G4ParticleDefinition* p)
144{
145 if(fParticle == p) { return; }
146 fParticle = p;
147 fMass = fParticle->GetPDGMass();
148 fSpin = fParticle->GetPDGSpin();
149 G4double q = fParticle->GetPDGCharge()/eplus;
150 fChargeSquare = q*q;
151 fLowKinEnergy = 0.2*MeV*fMass/proton_mass_c2;
152 fRatio = electron_mass_c2/fMass;
153 fQc = fMass/fRatio;
154 fLowestKineticEnergy = fMass*(fLowestGamma - 1.0);
155 fHighestKineticEnergy = fMass*(fHighestGamma - 1.0);
156}
157
158////////////////////////////////////////////////////////////////////////////
159
161 const G4DataVector&)
162{
163 if( fVerbose > 0 && p->GetParticleName()=="proton")
164 {
165 G4cout<<"G4PAIModel::Initialise for "<<p->GetParticleName()<<G4endl;
166 fPAIySection.SetVerbose(1);
167 }
168 else fPAIySection.SetVerbose(0);
169
170 if(isInitialised) { return; }
171 isInitialised = true;
172
173 SetParticle(p);
174
175 fParticleEnergyVector = new G4PhysicsLogVector(fLowestKineticEnergy,
176 fHighestKineticEnergy,
177 fTotBin);
178
179 fParticleChange = GetParticleChangeForLoss();
180
181 // Prepare initialization
182 const G4ProductionCutsTable* theCoupleTable =
184 const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
185 size_t numOfMat = G4Material::GetNumberOfMaterials();
186 size_t numRegions = fPAIRegionVector.size();
187
188 for(size_t iReg = 0; iReg < numRegions; ++iReg) // region loop
189 {
190 const G4Region* curReg = fPAIRegionVector[iReg];
191
192 for(size_t jMat = 0; jMat < numOfMat; ++jMat) // region material loop
193 {
194 fMaterial = (*theMaterialTable)[jMat];
195 fCutCouple = theCoupleTable->GetMaterialCutsCouple( fMaterial,
196 curReg->GetProductionCuts() );
197 //G4cout << "Reg <" <<curReg->GetName() << "> mat <"
198 // << fMaterial->GetName() << "> fCouple= "
199 // << fCutCouple<<" " << p->GetParticleName() <<G4endl;
200 if( fCutCouple )
201 {
202 fMaterialCutsCoupleVector.push_back(fCutCouple);
203
204 fPAItransferTable = new G4PhysicsTable(fTotBin+1);
205 fPAIdEdxTable = new G4PhysicsTable(fTotBin+1);
206
207 fDeltaCutInKinEnergy =
208 (*theCoupleTable->GetEnergyCutsVector(1))[fCutCouple->GetIndex()];
209
210 //ComputeSandiaPhotoAbsCof();
212
213 fPAIxscBank.push_back(fPAItransferTable);
214 fPAIdEdxBank.push_back(fPAIdEdxTable);
215 fdEdxTable.push_back(fdEdxVector);
216
218 fdNdxCutTable.push_back(fdNdxCutVector);
219 fLambdaTable.push_back(fLambdaVector);
220 }
221 }
222 }
223}
224
225//////////////////////////////////////////////////////////////////
226
228{}
229
230//////////////////////////////////////////////////////////////////
231
233{
234 G4int i, j;
235 const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
236
237 G4SandiaTable thisMaterialSandiaTable(fMatIndex) ;
238 G4int numberOfElements =
239 (*theMaterialTable)[fMatIndex]->GetNumberOfElements();
240
241 G4int* thisMaterialZ = new G4int[numberOfElements] ;
242
243 for(i=0;i<numberOfElements;i++)
244 {
245 thisMaterialZ[i] =
246 (G4int)(*theMaterialTable)[fMatIndex]->GetElement(i)->GetZ() ;
247 }
248 fSandiaIntervalNumber = thisMaterialSandiaTable.SandiaIntervals
249 (thisMaterialZ,numberOfElements) ;
250
251 fSandiaIntervalNumber = thisMaterialSandiaTable.SandiaMixing
252 ( thisMaterialZ ,
253 (*theMaterialTable)[fMatIndex]->GetFractionVector() ,
254 numberOfElements,fSandiaIntervalNumber) ;
255
256 fSandiaPhotoAbsCof = new G4double*[fSandiaIntervalNumber] ;
257
258 for(i=0; i<fSandiaIntervalNumber; i++)
259 {
260 fSandiaPhotoAbsCof[i] = new G4double[5];
261 }
262
263 for( i = 0 ; i < fSandiaIntervalNumber ; i++ )
264 {
265 fSandiaPhotoAbsCof[i][0] = thisMaterialSandiaTable.GetPhotoAbsorpCof(i+1,0);
266
267 for( j = 1; j < 5 ; j++ )
268 {
269 fSandiaPhotoAbsCof[i][j] = thisMaterialSandiaTable.GetPhotoAbsorpCof(i+1,j)*
270 (*theMaterialTable)[fMatIndex]->GetDensity() ;
271 }
272 }
273 delete[] thisMaterialZ;
274}
275
276////////////////////////////////////////////////////////////////////////////
277//
278// Build tables for the ionization energy loss
279// the tables are built for MATERIALS
280// *********
281
283{
284 G4double LowEdgeEnergy , ionloss ;
285 G4double tau, Tmax, Tmin, Tkin, deltaLow, /*gamma,*/ bg2 ;
286
287 fdEdxVector = new G4PhysicsLogVector( fLowestKineticEnergy,
288 fHighestKineticEnergy,
289 fTotBin);
290 G4SandiaTable* sandia = fMaterial->GetSandiaTable();
291
292 Tmin = sandia->GetSandiaCofForMaterialPAI(0,0)*keV;
293 deltaLow = 100.*eV; // 0.5*eV ;
294
295 for (G4int i = 0 ; i <= fTotBin ; i++) //The loop for the kinetic energy
296 {
297 LowEdgeEnergy = fParticleEnergyVector->GetLowEdgeEnergy(i) ;
298 tau = LowEdgeEnergy/fMass ;
299 //gamma = tau +1. ;
300 // G4cout<<"gamma = "<<gamma<<endl ;
301 bg2 = tau*( tau + 2. );
302 Tmax = MaxSecondaryEnergy(fParticle, LowEdgeEnergy);
303 // Tmax = std::min(fDeltaCutInKinEnergy, Tmax);
304 Tkin = Tmax ;
305
306 if ( Tmax < Tmin + deltaLow ) // low energy safety
307 Tkin = Tmin + deltaLow ;
308
309 fPAIySection.Initialize(fMaterial, Tkin, bg2);
310
311 // G4cout<<"ionloss = "<<ionloss*cm/keV<<" keV/cm"<<endl ;
312 // G4cout<<"n1 = "<<protonPAI.GetIntegralPAIxSection(1)*cm<<" 1/cm"<<endl ;
313 // G4cout<<"protonPAI.GetSplineSize() = "<<
314 // protonPAI.GetSplineSize()<<G4endl<<G4endl ;
315
316 G4int n = fPAIySection.GetSplineSize();
317 G4PhysicsFreeVector* transferVector = new G4PhysicsFreeVector(n) ;
318 G4PhysicsFreeVector* dEdxVector = new G4PhysicsFreeVector(n);
319
320 for( G4int k = 0 ; k < n; k++ )
321 {
322 transferVector->PutValue( k ,
323 fPAIySection.GetSplineEnergy(k+1),
324 fPAIySection.GetIntegralPAIySection(k+1) ) ;
325 dEdxVector->PutValue( k ,
326 fPAIySection.GetSplineEnergy(k+1),
327 fPAIySection.GetIntegralPAIdEdx(k+1) ) ;
328 }
329 ionloss = fPAIySection.GetMeanEnergyLoss() ; // total <dE/dx>
330
331 if ( ionloss < DBL_MIN) { ionloss = 0.0; }
332 fdEdxVector->PutValue(i,ionloss) ;
333
334 fPAItransferTable->insertAt(i,transferVector) ;
335 fPAIdEdxTable->insertAt(i,dEdxVector) ;
336
337 } // end of Tkin loop
338}
339
340///////////////////////////////////////////////////////////////////////
341//
342// Build mean free path tables for the delta ray production process
343// tables are built for MATERIALS
344//
345
347{
348 fLambdaVector = new G4PhysicsLogVector( fLowestKineticEnergy,
349 fHighestKineticEnergy,
350 fTotBin ) ;
351 fdNdxCutVector = new G4PhysicsLogVector( fLowestKineticEnergy,
352 fHighestKineticEnergy,
353 fTotBin ) ;
354 if(fVerbose > 1)
355 {
356 G4cout<<"PAIModel DeltaCutInKineticEnergyNow = "
357 <<fDeltaCutInKinEnergy/keV<<" keV"<<G4endl;
358 }
359 for (G4int i = 0 ; i <= fTotBin ; i++ )
360 {
361 G4double dNdxCut = GetdNdxCut(i,fDeltaCutInKinEnergy) ;
362 //G4cout << "i= " << i << " x= " << dNdxCut << G4endl;
363 if(dNdxCut < 0.0) dNdxCut = 0.0;
364 // G4double lambda = dNdxCut <= DBL_MIN ? DBL_MAX: 1.0/dNdxCut ;
365 G4double lambda = DBL_MAX;
366 if(dNdxCut > 0.0) lambda = 1.0/dNdxCut;
367
368 fLambdaVector->PutValue(i, lambda) ;
369 fdNdxCutVector->PutValue(i, dNdxCut) ;
370 }
371}
372
373///////////////////////////////////////////////////////////////////////
374//
375// Returns integral PAI cross section for energy transfers >= transferCut
376
379{
380 G4int iTransfer;
381 G4double x1, x2, y1, y2, dNdxCut;
382 // G4cout<<"iPlace = "<<iPlace<<"; "<<"transferCut = "<<transferCut<<G4endl;
383 // G4cout<<"size = "<<G4int((*fPAItransferTable)(iPlace)->GetVectorLength())
384 // <<G4endl;
385 for( iTransfer = 0 ;
386 iTransfer < G4int((*fPAItransferTable)(iPlace)->GetVectorLength()) ;
387 iTransfer++)
388 {
389 if(transferCut <= (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
390 {
391 break ;
392 }
393 }
394 if ( iTransfer >= G4int((*fPAItransferTable)(iPlace)->GetVectorLength()) )
395 {
396 iTransfer = (*fPAItransferTable)(iPlace)->GetVectorLength() - 1 ;
397 }
398 y1 = (*(*fPAItransferTable)(iPlace))(iTransfer-1) ;
399 y2 = (*(*fPAItransferTable)(iPlace))(iTransfer) ;
400 if(y1 < 0.0) y1 = 0.0;
401 if(y2 < 0.0) y2 = 0.0;
402 // G4cout<<"y1 = "<<y1<<"; "<<"y2 = "<<y2<<G4endl;
403 x1 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
404 x2 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
405 // G4cout<<"x1 = "<<x1<<"; "<<"x2 = "<<x2<<G4endl;
406
407 if ( y1 == y2 ) dNdxCut = y2 ;
408 else
409 {
410 // if ( x1 == x2 ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
411 // if ( std::abs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*G4UniformRand() ;
412 if ( std::abs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*0.5 ;
413 else dNdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
414 }
415 // G4cout<<""<<dNdxCut<<G4endl;
416 if(dNdxCut < 0.0) dNdxCut = 0.0;
417 return dNdxCut ;
418}
419///////////////////////////////////////////////////////////////////////
420//
421// Returns integral dEdx for energy transfers >= transferCut
422
425{
426 G4int iTransfer;
427 G4double x1, x2, y1, y2, dEdxCut;
428 //G4cout<<"iPlace = "<<iPlace<<"; "<<"transferCut = "<<transferCut<<G4endl;
429 // G4cout<<"size = "<<G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength())
430 // <<G4endl;
431 for( iTransfer = 0 ;
432 iTransfer < G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) ;
433 iTransfer++)
434 {
435 if(transferCut <= (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
436 {
437 break ;
438 }
439 }
440 if ( iTransfer >= G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) )
441 {
442 iTransfer = (*fPAIdEdxTable)(iPlace)->GetVectorLength() - 1 ;
443 }
444 y1 = (*(*fPAIdEdxTable)(iPlace))(iTransfer-1) ;
445 y2 = (*(*fPAIdEdxTable)(iPlace))(iTransfer) ;
446 if(y1 < 0.0) y1 = 0.0;
447 if(y2 < 0.0) y2 = 0.0;
448 //G4cout<<"y1 = "<<y1<<"; "<<"y2 = "<<y2<<G4endl;
449 x1 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
450 x2 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
451 //G4cout<<"x1 = "<<x1<<"; "<<"x2 = "<<x2<<G4endl;
452
453 if ( y1 == y2 ) dEdxCut = y2 ;
454 else
455 {
456 // if ( x1 == x2 ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
457 // if ( std::abs(x1-x2) <= eV ) dEdxCut = y1 + (y2 - y1)*G4UniformRand() ;
458 if ( std::abs(x1-x2) <= eV ) dEdxCut = y1 + (y2 - y1)*0.5 ;
459 else dEdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
460 }
461 //G4cout<<""<<dEdxCut<<G4endl;
462 if(dEdxCut < 0.0) dEdxCut = 0.0;
463 return dEdxCut ;
464}
465
466//////////////////////////////////////////////////////////////////////////////
467
469 const G4ParticleDefinition* p,
470 G4double kineticEnergy,
471 G4double cutEnergy)
472{
473 G4int iTkin,iPlace;
474
475 //G4double cut = std::min(MaxSecondaryEnergy(p, kineticEnergy), cutEnergy);
476 G4double cut = cutEnergy;
477
478 G4double massRatio = fMass/p->GetPDGMass();
479 G4double scaledTkin = kineticEnergy*massRatio;
480 G4double charge = p->GetPDGCharge();
481 G4double charge2 = charge*charge;
482 const G4MaterialCutsCouple* matCC = CurrentCouple();
483
484 size_t jMat = 0;
485 for(;jMat < fMaterialCutsCoupleVector.size(); ++jMat )
486 {
487 if( matCC == fMaterialCutsCoupleVector[jMat] ) break;
488 }
489 //G4cout << "jMat= " << jMat
490 // << " jMax= " << fMaterialCutsCoupleVector.size()
491 // << " matCC: " << matCC;
492 //if(matCC) G4cout << " mat: " << matCC->GetMaterial()->GetName();
493 // G4cout << G4endl;
494 if(jMat == fMaterialCutsCoupleVector.size()) return 0.0;
495
496 fPAIdEdxTable = fPAIdEdxBank[jMat];
497 fdEdxVector = fdEdxTable[jMat];
498 for(iTkin = 0 ; iTkin <= fTotBin ; iTkin++)
499 {
500 if(scaledTkin < fParticleEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
501 }
502 //G4cout << "E= " << scaledTkin << " iTkin= " << iTkin
503 // << " " << fdEdxVector->GetVectorLength()<<G4endl;
504 iPlace = iTkin - 1;
505 if(iPlace < 0) iPlace = 0;
506 else if(iPlace >= fTotBin) iPlace = fTotBin-1;
507 G4double dEdx = charge2*( (*fdEdxVector)(iPlace) - GetdEdxCut(iPlace,cut) );
508 if( dEdx < 0.) dEdx = 0.;
509 return dEdx;
510}
511
512/////////////////////////////////////////////////////////////////////////
513
515 const G4ParticleDefinition* p,
516 G4double kineticEnergy,
517 G4double cutEnergy,
518 G4double maxEnergy )
519{
520 G4int iTkin,iPlace;
521 G4double tmax = std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
522 if(tmax <= cutEnergy) return 0.0;
523 G4double massRatio = fMass/p->GetPDGMass();
524 G4double scaledTkin = kineticEnergy*massRatio;
525 G4double charge = p->GetPDGCharge();
526 G4double charge2 = charge*charge, cross, cross1, cross2;
527 const G4MaterialCutsCouple* matCC = CurrentCouple();
528
529 size_t jMat = 0;
530 for(;jMat < fMaterialCutsCoupleVector.size(); ++jMat )
531 {
532 if( matCC == fMaterialCutsCoupleVector[jMat] ) break;
533 }
534 if(jMat == fMaterialCutsCoupleVector.size()) return 0.0;
535
536 fPAItransferTable = fPAIxscBank[jMat];
537
538 for(iTkin = 0 ; iTkin <= fTotBin ; iTkin++)
539 {
540 if(scaledTkin < fParticleEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
541 }
542 iPlace = iTkin - 1;
543 if(iPlace < 0) iPlace = 0;
544 else if(iPlace >= fTotBin) iPlace = fTotBin-1;
545
546 //G4cout<<"iPlace = "<<iPlace<<"; tmax = "
547 // <<tmax<<"; cutEnergy = "<<cutEnergy<<G4endl;
548 cross1 = GetdNdxCut(iPlace,tmax) ;
549 //G4cout<<"cross1 = "<<cross1<<G4endl;
550 cross2 = GetdNdxCut(iPlace,cutEnergy) ;
551 //G4cout<<"cross2 = "<<cross2<<G4endl;
552 cross = (cross2-cross1)*charge2;
553 //G4cout<<"cross = "<<cross<<G4endl;
554 if( cross < DBL_MIN) cross = 0.0;
555 // if( cross2 < DBL_MIN) cross2 = DBL_MIN;
556
557 // return cross2;
558 return cross;
559}
560
561///////////////////////////////////////////////////////////////////////////
562//
563// It is analog of PostStepDoIt in terms of secondary electron.
564//
565
566void G4PAIModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
567 const G4MaterialCutsCouple* matCC,
568 const G4DynamicParticle* dp,
569 G4double tmin,
570 G4double maxEnergy)
571{
572 size_t jMat = 0;
573 for(;jMat < fMaterialCutsCoupleVector.size(); ++jMat )
574 {
575 if( matCC == fMaterialCutsCoupleVector[jMat] ) break;
576 }
577 if(jMat == fMaterialCutsCoupleVector.size()) return;
578
579 fPAItransferTable = fPAIxscBank[jMat];
580 fdNdxCutVector = fdNdxCutTable[jMat];
581
582 G4double tmax = std::min(MaxSecondaryKinEnergy(dp), maxEnergy);
583 if( tmin >= tmax && fVerbose > 0)
584 {
585 G4cout<<"G4PAIModel::SampleSecondary: tmin >= tmax "<<G4endl;
586 }
587 G4ThreeVector direction= dp->GetMomentumDirection();
588 G4double particleMass = dp->GetMass();
589 G4double kineticEnergy = dp->GetKineticEnergy();
590
591 G4double massRatio = fMass/particleMass;
592 G4double scaledTkin = kineticEnergy*massRatio;
593 G4double totalEnergy = kineticEnergy + particleMass;
594 G4double pSquare = kineticEnergy*(totalEnergy+particleMass);
595
596 G4double deltaTkin = GetPostStepTransfer(scaledTkin);
597
598 // G4cout<<"G4PAIModel::SampleSecondaries; deltaKIn = "<<deltaTkin/keV<<" keV "<<G4endl;
599
600 if( deltaTkin <= 0. && fVerbose > 0)
601 {
602 G4cout<<"G4PAIModel::SampleSecondary e- deltaTkin = "<<deltaTkin<<G4endl;
603 }
604 if( deltaTkin <= 0.) return;
605
606 if( deltaTkin > tmax) deltaTkin = tmax;
607
608 G4double deltaTotalMomentum = sqrt(deltaTkin*(deltaTkin + 2. * electron_mass_c2 ));
609 G4double totalMomentum = sqrt(pSquare);
610 G4double costheta = deltaTkin*(totalEnergy + electron_mass_c2)
611 /(deltaTotalMomentum * totalMomentum);
612
613 if( costheta > 0.99999 ) costheta = 0.99999;
614 G4double sintheta = 0.0;
615 G4double sin2 = 1. - costheta*costheta;
616 if( sin2 > 0.) sintheta = sqrt(sin2);
617
618 // direction of the delta electron
619 G4double phi = twopi*G4UniformRand();
620 G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
621
622 G4ThreeVector deltaDirection(dirx,diry,dirz);
623 deltaDirection.rotateUz(direction);
624 deltaDirection.unit();
625
626 // primary change
627 kineticEnergy -= deltaTkin;
628 G4ThreeVector dir = totalMomentum*direction - deltaTotalMomentum*deltaDirection;
629 direction = dir.unit();
630 fParticleChange->SetProposedKineticEnergy(kineticEnergy);
631 fParticleChange->SetProposedMomentumDirection(direction);
632
633 // create G4DynamicParticle object for e- delta ray
634 G4DynamicParticle* deltaRay = new G4DynamicParticle;
636 deltaRay->SetKineticEnergy( deltaTkin ); // !!! trick for last steps /2.0 ???
637 deltaRay->SetMomentumDirection(deltaDirection);
638
639 vdp->push_back(deltaRay);
640}
641
642
643///////////////////////////////////////////////////////////////////////
644//
645// Returns post step PAI energy transfer > cut electron energy according to passed
646// scaled kinetic energy of particle
647
650{
651 // G4cout<<"G4PAIModel::GetPostStepTransfer"<<G4endl ;
652
653 G4int iTkin, iTransfer, iPlace ;
654 G4double transfer = 0.0, position, dNdxCut1, dNdxCut2, E1, E2, W1, W2, W ;
655
656 for(iTkin=0;iTkin<=fTotBin;iTkin++)
657 {
658 if(scaledTkin < fParticleEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
659 }
660 iPlace = iTkin - 1 ;
661 // G4cout<<"from search, iPlace = "<<iPlace<<G4endl ;
662 if(iPlace < 0) iPlace = 0;
663 else if(iPlace >= fTotBin) iPlace = fTotBin-1;
664 dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
665 // G4cout<<"dNdxCut1 = "<<dNdxCut1<<G4endl ;
666
667
668 if(iTkin == fTotBin) // Fermi plato, try from left
669 {
670 position = dNdxCut1*G4UniformRand() ;
671
672 for( iTransfer = 0;
673 iTransfer < G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
674 {
675 if(position >= (*(*fPAItransferTable)(iPlace))(iTransfer)) break ;
676 }
677 transfer = GetEnergyTransfer(iPlace,position,iTransfer);
678 }
679 else
680 {
681 dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
682 // G4cout<<"dNdxCut2 = "<<dNdxCut2<<G4endl ;
683 if(iTkin == 0) // Tkin is too small, trying from right only
684 {
685 position = dNdxCut2*G4UniformRand() ;
686
687 for( iTransfer = 0;
688 iTransfer < G4int((*fPAItransferTable)(iPlace+1)->GetVectorLength()); iTransfer++ )
689 {
690 if(position >= (*(*fPAItransferTable)(iPlace+1))(iTransfer)) break ;
691 }
692 transfer = GetEnergyTransfer(iPlace+1,position,iTransfer);
693 }
694 else // general case: Tkin between two vectors of the material
695 {
696 E1 = fParticleEnergyVector->GetLowEdgeEnergy(iTkin - 1) ;
697 E2 = fParticleEnergyVector->GetLowEdgeEnergy(iTkin) ;
698 W = 1.0/(E2 - E1) ;
699 W1 = (E2 - scaledTkin)*W ;
700 W2 = (scaledTkin - E1)*W ;
701
702 position = ( dNdxCut1*W1 + dNdxCut2*W2 )*G4UniformRand() ;
703
704 // G4cout<<position<<"\t" ;
705
706 G4int iTrMax1, iTrMax2, iTrMax;
707
708 iTrMax1 = G4int((*fPAItransferTable)(iPlace)->GetVectorLength());
709 iTrMax2 = G4int((*fPAItransferTable)(iPlace+1)->GetVectorLength());
710
711 if (iTrMax1 >= iTrMax2) iTrMax = iTrMax2;
712 else iTrMax = iTrMax1;
713
714
715 for( iTransfer = 0; iTransfer < iTrMax; iTransfer++ )
716 {
717 if( position >=
718 ( (*(*fPAItransferTable)(iPlace))(iTransfer)*W1 +
719 (*(*fPAItransferTable)(iPlace+1))(iTransfer)*W2) ) break ;
720 }
721 transfer = GetEnergyTransfer(iPlace,position,iTransfer);
722 }
723 }
724 // G4cout<<"PAImodel PostStepTransfer = "<<transfer/keV<<" keV"<<G4endl ;
725 if(transfer < 0.0 ) transfer = 0.0 ;
726 // if(transfer < DBL_MIN ) transfer = DBL_MIN;
727
728 return transfer ;
729}
730
731///////////////////////////////////////////////////////////////////////
732//
733// Returns random PAI energy transfer according to passed
734// indexes of particle kinetic
735
738{
739 G4int iTransferMax;
740 G4double x1, x2, y1, y2, energyTransfer;
741
742 if(iTransfer == 0)
743 {
744 energyTransfer = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
745 }
746 else
747 {
748 iTransferMax = G4int((*fPAItransferTable)(iPlace)->GetVectorLength());
749
750 if ( iTransfer >= iTransferMax ) iTransfer = iTransferMax - 1;
751
752 y1 = (*(*fPAItransferTable)(iPlace))(iTransfer-1);
753 y2 = (*(*fPAItransferTable)(iPlace))(iTransfer);
754
755 x1 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1);
756 x2 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
757
758 if ( x1 == x2 ) energyTransfer = x2;
759 else
760 {
761 if ( y1 == y2 ) energyTransfer = x1 + (x2 - x1)*G4UniformRand();
762 else
763 {
764 energyTransfer = x1 + (position - y1)*(x2 - x1)/(y2 - y1);
765 }
766 }
767 }
768 return energyTransfer;
769}
770
771///////////////////////////////////////////////////////////////////////
772
774 const G4DynamicParticle* aParticle,
775 G4double&,
776 G4double& step,
777 G4double&)
778{
779 size_t jMat = 0;
780 for(;jMat < fMaterialCutsCoupleVector.size(); ++jMat )
781 {
782 if( material == fMaterialCutsCoupleVector[jMat]->GetMaterial() ) break;
783 }
784 if(jMat == fMaterialCutsCoupleVector.size()) return 0.0;
785
786 fPAItransferTable = fPAIxscBank[jMat];
787 fdNdxCutVector = fdNdxCutTable[jMat];
788
789 G4int iTkin, iTransfer, iPlace;
790 G4long numOfCollisions=0;
791
792 //G4cout<<"G4PAIModel::SampleFluctuations"<<G4endl ;
793 //G4cout<<"in: "<<fMaterialCutsCoupleVector[jMat]->GetMaterial()->GetName()<<G4endl;
794 G4double loss = 0.0, charge2 ;
795 G4double stepSum = 0., stepDelta, lambda, omega;
796 G4double position, E1, E2, W1, W2, W, dNdxCut1, dNdxCut2, meanNumber;
797 G4bool numb = true;
798 G4double Tkin = aParticle->GetKineticEnergy() ;
799 G4double MassRatio = fMass/aParticle->GetDefinition()->GetPDGMass() ;
800 G4double charge = aParticle->GetDefinition()->GetPDGCharge() ;
801 charge2 = charge*charge ;
802 G4double TkinScaled = Tkin*MassRatio ;
803
804 for(iTkin=0;iTkin<=fTotBin;iTkin++)
805 {
806 if(TkinScaled < fParticleEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
807 }
808 iPlace = iTkin - 1 ;
809 if(iPlace < 0) iPlace = 0;
810 else if(iPlace >= fTotBin) iPlace = fTotBin - 1;
811 //G4cout<<"from search, iPlace = "<<iPlace<<G4endl ;
812 dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
813 //G4cout<<"dNdxCut1 = "<<dNdxCut1<<G4endl ;
814
815 if(iTkin == fTotBin) // Fermi plato, try from left
816 {
817 meanNumber =((*(*fPAItransferTable)(iPlace))(0)-dNdxCut1)*step*charge2;
818 if(meanNumber < 0.) meanNumber = 0. ;
819 // numOfCollisions = RandPoisson::shoot(meanNumber) ;
820 // numOfCollisions = G4Poisson(meanNumber) ;
821 if( meanNumber > 0.) lambda = step/meanNumber;
822 else lambda = DBL_MAX;
823 while(numb)
824 {
825 stepDelta = CLHEP::RandExponential::shoot(lambda);
826 stepSum += stepDelta;
827 if(stepSum >= step) break;
828 numOfCollisions++;
829 }
830 //G4cout<<"##1 numOfCollisions = "<<numOfCollisions<<G4endl ;
831
832 while(numOfCollisions)
833 {
834 position = dNdxCut1+
835 ((*(*fPAItransferTable)(iPlace))(0)-dNdxCut1)*G4UniformRand() ;
836
837 for( iTransfer = 0;
838 iTransfer < G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
839 {
840 if(position >= (*(*fPAItransferTable)(iPlace))(iTransfer)) break ;
841 }
842 omega = GetEnergyTransfer(iPlace,position,iTransfer);
843 //G4cout<<"G4PAIModel::SampleFluctuations, omega = "<<omega/keV<<" keV; "<<"\t";
844 loss += omega;
845 numOfCollisions-- ;
846 }
847 }
848 else
849 {
850 dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
851 //G4cout<<"dNdxCut2 = "<<dNdxCut2<< " iTkin= "<<iTkin<<" iPlace= "<<iPlace<<G4endl;
852
853 if(iTkin == 0) // Tkin is too small, trying from right only
854 {
855 meanNumber =((*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2)*step*charge2;
856 if( meanNumber < 0. ) meanNumber = 0. ;
857 // numOfCollisions = CLHEP::RandPoisson::shoot(meanNumber) ;
858 // numOfCollisions = G4Poisson(meanNumber) ;
859 if( meanNumber > 0.) lambda = step/meanNumber;
860 else lambda = DBL_MAX;
861 while(numb)
862 {
863 stepDelta = CLHEP::RandExponential::shoot(lambda);
864 stepSum += stepDelta;
865 if(stepSum >= step) break;
866 numOfCollisions++;
867 }
868
869 //G4cout<<"##2 numOfCollisions = "<<numOfCollisions<<G4endl ;
870
871 while(numOfCollisions)
872 {
873 position = dNdxCut2+
874 ((*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2)*G4UniformRand();
875
876 for( iTransfer = 0;
877 iTransfer < G4int((*fPAItransferTable)(iPlace+1)->GetVectorLength()); iTransfer++ )
878 {
879 if(position >= (*(*fPAItransferTable)(iPlace+1))(iTransfer)) break ;
880 }
881 omega = GetEnergyTransfer(iPlace,position,iTransfer);
882 //G4cout<<omega/keV<<"\t";
883 loss += omega;
884 numOfCollisions-- ;
885 }
886 }
887 else // general case: Tkin between two vectors of the material
888 {
889 E1 = fParticleEnergyVector->GetLowEdgeEnergy(iTkin - 1) ;
890 E2 = fParticleEnergyVector->GetLowEdgeEnergy(iTkin) ;
891 W = 1.0/(E2 - E1) ;
892 W1 = (E2 - TkinScaled)*W ;
893 W2 = (TkinScaled - E1)*W ;
894
895 //G4cout << fPAItransferTable->size() << G4endl;
896 //G4cout<<"(*(*fPAItransferTable)(iPlace))(0) = "<<
897 // (*(*fPAItransferTable)(iPlace))(0)<<G4endl ;
898 //G4cout<<"(*(*fPAItransferTable)(iPlace+1))(0) = "<<
899 // (*(*fPAItransferTable)(iPlace+1))(0)<<G4endl ;
900
901 meanNumber=( ((*(*fPAItransferTable)(iPlace))(0)-dNdxCut1)*W1 +
902 ((*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2)*W2 )*step*charge2;
903 if(meanNumber<0.0) meanNumber = 0.0;
904 // numOfCollisions = RandPoisson::shoot(meanNumber) ;
905 // numOfCollisions = G4Poisson(meanNumber) ;
906 if( meanNumber > 0.) lambda = step/meanNumber;
907 else lambda = DBL_MAX;
908 while(numb)
909 {
910 stepDelta = CLHEP::RandExponential::shoot(lambda);
911 stepSum += stepDelta;
912 if(stepSum >= step) break;
913 numOfCollisions++;
914 }
915
916 //G4cout<<"##3 numOfCollisions = "<<numOfCollisions<<endl ;
917
918 while(numOfCollisions)
919 {
920 position = dNdxCut1*W1 + dNdxCut2*W2 +
921 ( ( (*(*fPAItransferTable)(iPlace))(0)-dNdxCut1 )*W1 +
922 dNdxCut2+
923 ( (*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2 )*W2 )*G4UniformRand();
924
925 // G4cout<<position<<"\t" ;
926
927 for( iTransfer = 0;
928 iTransfer < G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
929 {
930 if( position >=
931 ( (*(*fPAItransferTable)(iPlace))(iTransfer)*W1 +
932 (*(*fPAItransferTable)(iPlace+1))(iTransfer)*W2) )
933 {
934 break ;
935 }
936 }
937 omega = GetEnergyTransfer(iPlace,position,iTransfer);
938 // G4cout<<omega/keV<<"\t";
939 loss += omega;
940 numOfCollisions-- ;
941 }
942 }
943 }
944 //G4cout<<"PAIModel AlongStepLoss = "<<loss/keV<<" keV, on step = "
945 // <<step/mm<<" mm"<<G4endl ;
946 if(loss > Tkin) loss=Tkin;
947 if(loss < 0. ) loss = 0.;
948 return loss ;
949
950}
951
952//////////////////////////////////////////////////////////////////////
953//
954// Returns the statistical estimation of the energy loss distribution variance
955//
956
957
959 const G4DynamicParticle* aParticle,
960 G4double& tmax,
961 G4double& step )
962{
963 G4double loss, sumLoss=0., sumLoss2=0., sigma2, meanLoss=0.;
964 for(G4int i = 0 ; i < fMeanNumber; i++)
965 {
966 loss = SampleFluctuations(material,aParticle,tmax,step,meanLoss);
967 sumLoss += loss;
968 sumLoss2 += loss*loss;
969 }
970 meanLoss = sumLoss/fMeanNumber;
971 sigma2 = meanLoss*meanLoss + (sumLoss2-2*sumLoss*meanLoss)/fMeanNumber;
972 return sigma2;
973}
974
975/////////////////////////////////////////////////////////////////////
976
978 G4double kinEnergy)
979{
980 G4double tmax = kinEnergy;
981 if(p == fElectron) tmax *= 0.5;
982 else if(p != fPositron) {
983 G4double mass = p->GetPDGMass();
984 G4double ratio= electron_mass_c2/mass;
985 G4double gamma= kinEnergy/mass + 1.0;
986 tmax = 2.0*electron_mass_c2*(gamma*gamma - 1.) /
987 (1. + 2.0*gamma*ratio + ratio*ratio);
988 }
989 return tmax;
990}
991
992///////////////////////////////////////////////////////////////
993
995{
996 fPAIRegionVector.push_back(r);
997}
998
999//
1000//
1001/////////////////////////////////////////////////
1002
1003
1004
1005
1006
1007
std::vector< G4Material * > G4MaterialTable
double G4double
Definition: G4Types.hh:64
long G4long
Definition: G4Types.hh:68
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
Hep3Vector unit() const
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:72
G4double GetMass() const
void SetMomentumDirection(const G4ThreeVector &aDirection)
const G4ThreeVector & GetMomentumDirection() const
void SetDefinition(const G4ParticleDefinition *aParticleDefinition)
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
void SetKineticEnergy(G4double aEnergy)
static G4Electron * Electron()
Definition: G4Electron.cc:94
static const G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:562
static size_t GetNumberOfMaterials()
Definition: G4Material.cc:569
G4SandiaTable * GetSandiaTable() const
Definition: G4Material.hh:228
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
Definition: G4PAIModel.cc:160
G4double GetdEdxCut(G4int iPlace, G4double transferCut)
Definition: G4PAIModel.cc:424
G4double GetdNdxCut(G4int iPlace, G4double transferCut)
Definition: G4PAIModel.cc:378
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy, G4double maxEnergy)
Definition: G4PAIModel.cc:514
virtual ~G4PAIModel()
Definition: G4PAIModel.cc:112
void BuildPAIonisationTable()
Definition: G4PAIModel.cc:282
void DefineForRegion(const G4Region *r)
Definition: G4PAIModel.cc:994
void BuildLambdaVector()
Definition: G4PAIModel.cc:346
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy)
Definition: G4PAIModel.cc:566
G4double GetPostStepTransfer(G4double scaledTkin)
Definition: G4PAIModel.cc:649
virtual void InitialiseMe(const G4ParticleDefinition *)
Definition: G4PAIModel.cc:227
G4double GetEnergyTransfer(G4int iPlace, G4double position, G4int iTransfer)
Definition: G4PAIModel.cc:737
virtual G4double Dispersion(const G4Material *, const G4DynamicParticle *, G4double &, G4double &)
Definition: G4PAIModel.cc:958
G4double MaxSecondaryEnergy(const G4ParticleDefinition *, G4double kinEnergy)
Definition: G4PAIModel.cc:977
G4PAIModel(const G4ParticleDefinition *p=0, const G4String &nam="PAI")
Definition: G4PAIModel.cc:74
void ComputeSandiaPhotoAbsCof()
Definition: G4PAIModel.cc:232
virtual G4double SampleFluctuations(const G4Material *, const G4DynamicParticle *, G4double &, G4double &, G4double &)
Definition: G4PAIModel.cc:773
virtual G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy)
Definition: G4PAIModel.cc:468
G4double GetSplineEnergy(G4int i) const
void SetVerbose(G4int v)
G4double GetIntegralPAIdEdx(G4int i) const
G4double GetMeanEnergyLoss() const
G4double GetIntegralPAIySection(G4int i) const
void Initialize(const G4Material *material, G4double maxEnergyTransfer, G4double betaGammaSq)
G4int GetSplineSize() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void SetProposedMomentumDirection(const G4ThreeVector &dir)
G4double GetPDGCharge() const
const G4String & GetParticleName() const
void PutValue(size_t binNumber, G4double binValue, G4double dataValue)
void insertAt(size_t, G4PhysicsVector *)
void clearAndDestroy()
virtual G4double GetLowEdgeEnergy(size_t binNumber) const
void PutValue(size_t index, G4double theValue)
static G4Positron * Positron()
Definition: G4Positron.cc:94
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
const std::vector< G4double > * GetEnergyCutsVector(size_t pcIdx) const
static G4ProductionCutsTable * GetProductionCutsTable()
G4ProductionCuts * GetProductionCuts() const
G4double GetSandiaCofForMaterialPAI(G4int, G4int)
G4int SandiaMixing(G4int Z[], const G4double *fractionW, G4int el, G4int mi)
G4int SandiaIntervals(G4int Z[], G4int el)
G4double GetPhotoAbsorpCof(G4int i, G4int j) const
const G4MaterialCutsCouple * CurrentCouple() const
Definition: G4VEmModel.hh:377
G4double MaxSecondaryKinEnergy(const G4DynamicParticle *dynParticle)
Definition: G4VEmModel.hh:399
G4ParticleChangeForLoss * GetParticleChangeForLoss()
Definition: G4VEmModel.cc:95
#define DBL_MIN
Definition: templates.hh:75
#define DBL_MAX
Definition: templates.hh:83