source: trunk/source/processes/electromagnetic/standard/src/G4PAIModel.cc@ 1036

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

update to geant4.9.2

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