78 fHighestGamma(10000.),
82 fHighKinEnergy(100.*TeV),
83 fTwoln10(2.0*log(10.0)),
90 fPAItransferTable = 0;
92 fSandiaPhotoAbsCof = 0;
96 fParticleEnergyVector = 0;
97 fSandiaIntervalNumber = 0;
99 fDeltaCutInKinEnergy = 0.0;
104 if(p) { SetParticle(p); }
105 else { SetParticle(fElectron); }
107 isInitialised =
false;
115 if(fParticleEnergyVector)
delete fParticleEnergyVector;
116 if(fdEdxVector)
delete fdEdxVector ;
117 if(fLambdaVector)
delete fLambdaVector;
118 if(fdNdxCutVector)
delete fdNdxCutVector;
120 if( fPAItransferTable )
123 delete fPAItransferTable ;
128 delete fPAIdEdxTable ;
130 if(fSandiaPhotoAbsCof)
132 for(
G4int i=0;i<fSandiaIntervalNumber;i++)
134 delete[] fSandiaPhotoAbsCof[i];
136 delete[] fSandiaPhotoAbsCof;
145 if(fParticle == p) {
return; }
151 fLowKinEnergy = 0.2*MeV*fMass/proton_mass_c2;
152 fRatio = electron_mass_c2/fMass;
154 fLowestKineticEnergy = fMass*(fLowestGamma - 1.0);
155 fHighestKineticEnergy = fMass*(fHighestGamma - 1.0);
170 if(isInitialised) {
return; }
171 isInitialised =
true;
176 fHighestKineticEnergy,
186 size_t numRegions = fPAIRegionVector.size();
188 for(
size_t iReg = 0; iReg < numRegions; ++iReg)
190 const G4Region* curReg = fPAIRegionVector[iReg];
192 for(
size_t jMat = 0; jMat < numOfMat; ++jMat)
194 fMaterial = (*theMaterialTable)[jMat];
202 fMaterialCutsCoupleVector.push_back(fCutCouple);
207 fDeltaCutInKinEnergy =
213 fPAIxscBank.push_back(fPAItransferTable);
214 fPAIdEdxBank.push_back(fPAIdEdxTable);
215 fdEdxTable.push_back(fdEdxVector);
218 fdNdxCutTable.push_back(fdNdxCutVector);
219 fLambdaTable.push_back(fLambdaVector);
238 G4int numberOfElements =
239 (*theMaterialTable)[fMatIndex]->GetNumberOfElements();
241 G4int* thisMaterialZ =
new G4int[numberOfElements] ;
243 for(i=0;i<numberOfElements;i++)
246 (
G4int)(*theMaterialTable)[fMatIndex]->GetElement(i)->GetZ() ;
249 (thisMaterialZ,numberOfElements) ;
251 fSandiaIntervalNumber = thisMaterialSandiaTable.
SandiaMixing
253 (*theMaterialTable)[fMatIndex]->GetFractionVector() ,
254 numberOfElements,fSandiaIntervalNumber) ;
256 fSandiaPhotoAbsCof =
new G4double*[fSandiaIntervalNumber] ;
258 for(i=0; i<fSandiaIntervalNumber; i++)
260 fSandiaPhotoAbsCof[i] =
new G4double[5];
263 for( i = 0 ; i < fSandiaIntervalNumber ; i++ )
267 for( j = 1; j < 5 ; j++ )
270 (*theMaterialTable)[fMatIndex]->GetDensity() ;
273 delete[] thisMaterialZ;
285 G4double tau, Tmax, Tmin, Tkin, deltaLow, bg2 ;
288 fHighestKineticEnergy,
295 for (
G4int i = 0 ; i <= fTotBin ; i++)
298 tau = LowEdgeEnergy/fMass ;
301 bg2 = tau*( tau + 2. );
306 if ( Tmax < Tmin + deltaLow )
307 Tkin = Tmin + deltaLow ;
309 fPAIySection.
Initialize(fMaterial, Tkin, bg2);
320 for(
G4int k = 0 ; k < n; k++ )
331 if ( ionloss <
DBL_MIN) { ionloss = 0.0; }
334 fPAItransferTable->
insertAt(i,transferVector) ;
335 fPAIdEdxTable->
insertAt(i,dEdxVector) ;
349 fHighestKineticEnergy,
352 fHighestKineticEnergy,
356 G4cout<<
"PAIModel DeltaCutInKineticEnergyNow = "
357 <<fDeltaCutInKinEnergy/keV<<
" keV"<<
G4endl;
359 for (
G4int i = 0 ; i <= fTotBin ; i++ )
363 if(dNdxCut < 0.0) dNdxCut = 0.0;
366 if(dNdxCut > 0.0) lambda = 1.0/dNdxCut;
368 fLambdaVector->
PutValue(i, lambda) ;
369 fdNdxCutVector->
PutValue(i, dNdxCut) ;
386 iTransfer <
G4int((*fPAItransferTable)(iPlace)->GetVectorLength()) ;
389 if(transferCut <= (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
394 if ( iTransfer >=
G4int((*fPAItransferTable)(iPlace)->GetVectorLength()) )
396 iTransfer = (*fPAItransferTable)(iPlace)->GetVectorLength() - 1 ;
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;
403 x1 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
404 x2 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
407 if ( y1 == y2 ) dNdxCut = y2 ;
412 if ( std::abs(x1-x2) <= eV ) dNdxCut = y1 + (y2 - y1)*0.5 ;
413 else dNdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
416 if(dNdxCut < 0.0) dNdxCut = 0.0;
432 iTransfer <
G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) ;
435 if(transferCut <= (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
440 if ( iTransfer >=
G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) )
442 iTransfer = (*fPAIdEdxTable)(iPlace)->GetVectorLength() - 1 ;
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;
449 x1 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
450 x2 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
453 if ( y1 == y2 ) dEdxCut = y2 ;
458 if ( std::abs(x1-x2) <= eV ) dEdxCut = y1 + (y2 - y1)*0.5 ;
459 else dEdxCut = y1 + (transferCut - x1)*(y2 - y1)/(x2 - x1) ;
462 if(dEdxCut < 0.0) dEdxCut = 0.0;
479 G4double scaledTkin = kineticEnergy*massRatio;
485 for(;jMat < fMaterialCutsCoupleVector.size(); ++jMat )
487 if( matCC == fMaterialCutsCoupleVector[jMat] )
break;
494 if(jMat == fMaterialCutsCoupleVector.size())
return 0.0;
496 fPAIdEdxTable = fPAIdEdxBank[jMat];
497 fdEdxVector = fdEdxTable[jMat];
498 for(iTkin = 0 ; iTkin <= fTotBin ; iTkin++)
500 if(scaledTkin < fParticleEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
505 if(iPlace < 0) iPlace = 0;
506 else if(iPlace >= fTotBin) iPlace = fTotBin-1;
508 if( dEdx < 0.) dEdx = 0.;
522 if(tmax <= cutEnergy)
return 0.0;
524 G4double scaledTkin = kineticEnergy*massRatio;
526 G4double charge2 = charge*charge, cross, cross1, cross2;
530 for(;jMat < fMaterialCutsCoupleVector.size(); ++jMat )
532 if( matCC == fMaterialCutsCoupleVector[jMat] )
break;
534 if(jMat == fMaterialCutsCoupleVector.size())
return 0.0;
536 fPAItransferTable = fPAIxscBank[jMat];
538 for(iTkin = 0 ; iTkin <= fTotBin ; iTkin++)
540 if(scaledTkin < fParticleEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
543 if(iPlace < 0) iPlace = 0;
544 else if(iPlace >= fTotBin) iPlace = fTotBin-1;
552 cross = (cross2-cross1)*charge2;
554 if( cross <
DBL_MIN) cross = 0.0;
573 for(;jMat < fMaterialCutsCoupleVector.size(); ++jMat )
575 if( matCC == fMaterialCutsCoupleVector[jMat] )
break;
577 if(jMat == fMaterialCutsCoupleVector.size())
return;
579 fPAItransferTable = fPAIxscBank[jMat];
580 fdNdxCutVector = fdNdxCutTable[jMat];
583 if( tmin >= tmax && fVerbose > 0)
585 G4cout<<
"G4PAIModel::SampleSecondary: tmin >= tmax "<<
G4endl;
591 G4double massRatio = fMass/particleMass;
592 G4double scaledTkin = kineticEnergy*massRatio;
593 G4double totalEnergy = kineticEnergy + particleMass;
594 G4double pSquare = kineticEnergy*(totalEnergy+particleMass);
600 if( deltaTkin <= 0. && fVerbose > 0)
602 G4cout<<
"G4PAIModel::SampleSecondary e- deltaTkin = "<<deltaTkin<<
G4endl;
604 if( deltaTkin <= 0.)
return;
606 if( deltaTkin > tmax) deltaTkin = tmax;
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);
613 if( costheta > 0.99999 ) costheta = 0.99999;
615 G4double sin2 = 1. - costheta*costheta;
616 if( sin2 > 0.) sintheta = sqrt(sin2);
620 G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
624 deltaDirection.
unit();
627 kineticEnergy -= deltaTkin;
628 G4ThreeVector dir = totalMomentum*direction - deltaTotalMomentum*deltaDirection;
629 direction = dir.
unit();
639 vdp->push_back(deltaRay);
653 G4int iTkin, iTransfer, iPlace ;
656 for(iTkin=0;iTkin<=fTotBin;iTkin++)
658 if(scaledTkin < fParticleEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
662 if(iPlace < 0) iPlace = 0;
663 else if(iPlace >= fTotBin) iPlace = fTotBin-1;
664 dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
673 iTransfer <
G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
675 if(
position >= (*(*fPAItransferTable)(iPlace))(iTransfer)) break ;
681 dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
688 iTransfer <
G4int((*fPAItransferTable)(iPlace+1)->GetVectorLength()); iTransfer++ )
690 if(
position >= (*(*fPAItransferTable)(iPlace+1))(iTransfer)) break ;
699 W1 = (E2 - scaledTkin)*W ;
700 W2 = (scaledTkin - E1)*W ;
706 G4int iTrMax1, iTrMax2, iTrMax;
708 iTrMax1 =
G4int((*fPAItransferTable)(iPlace)->GetVectorLength());
709 iTrMax2 =
G4int((*fPAItransferTable)(iPlace+1)->GetVectorLength());
711 if (iTrMax1 >= iTrMax2) iTrMax = iTrMax2;
712 else iTrMax = iTrMax1;
715 for( iTransfer = 0; iTransfer < iTrMax; iTransfer++ )
718 ( (*(*fPAItransferTable)(iPlace))(iTransfer)*W1 +
719 (*(*fPAItransferTable)(iPlace+1))(iTransfer)*W2) ) break ;
725 if(transfer < 0.0 ) transfer = 0.0 ;
740 G4double x1, x2, y1, y2, energyTransfer;
744 energyTransfer = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
748 iTransferMax =
G4int((*fPAItransferTable)(iPlace)->GetVectorLength());
750 if ( iTransfer >= iTransferMax ) iTransfer = iTransferMax - 1;
752 y1 = (*(*fPAItransferTable)(iPlace))(iTransfer-1);
753 y2 = (*(*fPAItransferTable)(iPlace))(iTransfer);
755 x1 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1);
756 x2 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
758 if ( x1 == x2 ) energyTransfer = x2;
761 if ( y1 == y2 ) energyTransfer = x1 + (x2 - x1)*
G4UniformRand();
764 energyTransfer = x1 + (
position - y1)*(x2 - x1)/(y2 - y1);
768 return energyTransfer;
780 for(;jMat < fMaterialCutsCoupleVector.size(); ++jMat )
782 if( material == fMaterialCutsCoupleVector[jMat]->GetMaterial() )
break;
784 if(jMat == fMaterialCutsCoupleVector.size())
return 0.0;
786 fPAItransferTable = fPAIxscBank[jMat];
787 fdNdxCutVector = fdNdxCutTable[jMat];
789 G4int iTkin, iTransfer, iPlace;
795 G4double stepSum = 0., stepDelta, lambda, omega;
801 charge2 = charge*charge ;
802 G4double TkinScaled = Tkin*MassRatio ;
804 for(iTkin=0;iTkin<=fTotBin;iTkin++)
806 if(TkinScaled < fParticleEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
809 if(iPlace < 0) iPlace = 0;
810 else if(iPlace >= fTotBin) iPlace = fTotBin - 1;
812 dNdxCut1 = (*fdNdxCutVector)(iPlace) ;
817 meanNumber =((*(*fPAItransferTable)(iPlace))(0)-dNdxCut1)*step*charge2;
818 if(meanNumber < 0.) meanNumber = 0. ;
821 if( meanNumber > 0.) lambda = step/meanNumber;
826 stepSum += stepDelta;
827 if(stepSum >= step)
break;
832 while(numOfCollisions)
835 ((*(*fPAItransferTable)(iPlace))(0)-dNdxCut1)*
G4UniformRand() ;
838 iTransfer <
G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
840 if(
position >= (*(*fPAItransferTable)(iPlace))(iTransfer)) break ;
850 dNdxCut2 = (*fdNdxCutVector)(iPlace+1) ;
855 meanNumber =((*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2)*step*charge2;
856 if( meanNumber < 0. ) meanNumber = 0. ;
859 if( meanNumber > 0.) lambda = step/meanNumber;
864 stepSum += stepDelta;
865 if(stepSum >= step)
break;
871 while(numOfCollisions)
874 ((*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2)*
G4UniformRand();
877 iTransfer <
G4int((*fPAItransferTable)(iPlace+1)->GetVectorLength()); iTransfer++ )
879 if(
position >= (*(*fPAItransferTable)(iPlace+1))(iTransfer)) break ;
892 W1 = (E2 - TkinScaled)*W ;
893 W2 = (TkinScaled - E1)*W ;
901 meanNumber=( ((*(*fPAItransferTable)(iPlace))(0)-dNdxCut1)*W1 +
902 ((*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2)*W2 )*step*charge2;
903 if(meanNumber<0.0) meanNumber = 0.0;
906 if( meanNumber > 0.) lambda = step/meanNumber;
911 stepSum += stepDelta;
912 if(stepSum >= step)
break;
918 while(numOfCollisions)
920 position = dNdxCut1*W1 + dNdxCut2*W2 +
921 ( ( (*(*fPAItransferTable)(iPlace))(0)-dNdxCut1 )*W1 +
923 ( (*(*fPAItransferTable)(iPlace+1))(0)-dNdxCut2 )*W2 )*
G4UniformRand();
928 iTransfer <
G4int((*fPAItransferTable)(iPlace)->GetVectorLength()); iTransfer++ )
931 ( (*(*fPAItransferTable)(iPlace))(iTransfer)*W1 +
932 (*(*fPAItransferTable)(iPlace+1))(iTransfer)*W2) )
946 if(loss > Tkin) loss=Tkin;
947 if(loss < 0. ) loss = 0.;
963 G4double loss, sumLoss=0., sumLoss2=0., sigma2, meanLoss=0.;
964 for(
G4int i = 0 ; i < fMeanNumber; i++)
968 sumLoss2 += loss*loss;
970 meanLoss = sumLoss/fMeanNumber;
971 sigma2 = meanLoss*meanLoss + (sumLoss2-2*sumLoss*meanLoss)/fMeanNumber;
981 if(p == fElectron) tmax *= 0.5;
982 else if(p != fPositron) {
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);
996 fPAIRegionVector.push_back(r);
std::vector< G4Material * > G4MaterialTable
G4DLLIMPORT std::ostream G4cout
Hep3Vector & rotateUz(const Hep3Vector &)
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()
static const G4MaterialTable * GetMaterialTable()
static size_t GetNumberOfMaterials()
G4SandiaTable * GetSandiaTable() const
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
G4double GetdEdxCut(G4int iPlace, G4double transferCut)
G4double GetdNdxCut(G4int iPlace, G4double transferCut)
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy, G4double maxEnergy)
void BuildPAIonisationTable()
void DefineForRegion(const G4Region *r)
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy)
G4double GetPostStepTransfer(G4double scaledTkin)
virtual void InitialiseMe(const G4ParticleDefinition *)
G4double GetEnergyTransfer(G4int iPlace, G4double position, G4int iTransfer)
virtual G4double Dispersion(const G4Material *, const G4DynamicParticle *, G4double &, G4double &)
G4double MaxSecondaryEnergy(const G4ParticleDefinition *, G4double kinEnergy)
G4PAIModel(const G4ParticleDefinition *p=0, const G4String &nam="PAI")
void ComputeSandiaPhotoAbsCof()
virtual G4double SampleFluctuations(const G4Material *, const G4DynamicParticle *, G4double &, G4double &, G4double &)
virtual G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy)
G4double GetSplineEnergy(G4int i) const
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 GetPDGMass() const
G4double GetPDGCharge() const
const G4String & GetParticleName() const
G4double GetPDGSpin() const
void PutValue(size_t binNumber, G4double binValue, G4double dataValue)
void insertAt(size_t, G4PhysicsVector *)
virtual G4double GetLowEdgeEnergy(size_t binNumber) const
void PutValue(size_t index, G4double theValue)
static G4Positron * Positron()
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
G4double MaxSecondaryKinEnergy(const G4DynamicParticle *dynParticle)
G4ParticleChangeForLoss * GetParticleChangeForLoss()