77 fLowestKineticEnergy(10.0*
keV),
78 fHighestKineticEnergy(100.*
TeV),
82 fHighKinEnergy(100.*
TeV),
83 fLowKinEnergy(2.0*
MeV),
84 fTwoln10(2.0*log(10.0)),
93 fHighestKineticEnergy,
95 fPAItransferTable = 0;
100 fSandiaPhotoAbsCof = 0;
105 fdNdxCutPhotonVector = 0;
106 fdNdxCutPlasmonVector = 0;
108 fSandiaIntervalNumber = 0;
113 if(p) { SetParticle(p); }
114 else { SetParticle(fElectron); }
116 isInitialised =
false;
123 if(fProtonEnergyVector)
delete fProtonEnergyVector;
124 if(fdEdxVector)
delete fdEdxVector ;
125 if ( fLambdaVector)
delete fLambdaVector;
126 if ( fdNdxCutVector)
delete fdNdxCutVector;
128 if( fPAItransferTable )
131 delete fPAItransferTable ;
133 if( fPAIphotonTable )
136 delete fPAIphotonTable ;
138 if( fPAIplasmonTable )
141 delete fPAIplasmonTable ;
143 if(fSandiaPhotoAbsCof)
145 for(
G4int i=0;i<fSandiaIntervalNumber;i++)
147 delete[] fSandiaPhotoAbsCof[i];
149 delete[] fSandiaPhotoAbsCof;
173 if(isInitialised) {
return; }
174 isInitialised =
true;
176 if(!fParticle) SetParticle(p);
183 for(
size_t iReg = 0; iReg < fPAIRegionVector.size();++iReg)
185 const G4Region* curReg = fPAIRegionVector[iReg];
195 for(jMat = 0 ; jMat < numOfMat; ++jMat)
199 fMaterialCutsCoupleVector.push_back(matCouple);
202 for(iMatGlob = 0 ; iMatGlob < numberOfMat ; iMatGlob++ )
204 if( *matIter == (*theMaterialTable)[iMatGlob]) break ;
206 fMatIndex = iMatGlob;
211 fPAIxscBank.push_back(fPAItransferTable);
212 fPAIphotonBank.push_back(fPAIphotonTable);
213 fPAIplasmonBank.push_back(fPAIplasmonTable);
214 fPAIdEdxBank.push_back(fPAIdEdxTable);
215 fdEdxTable.push_back(fdEdxVector);
219 fdNdxCutTable.push_back(fdNdxCutVector);
220 fdNdxCutPhotonTable.push_back(fdNdxCutPhotonVector);
221 fdNdxCutPlasmonTable.push_back(fdNdxCutPlasmonVector);
222 fLambdaTable.push_back(fLambdaVector);
239 G4int i, j, numberOfElements ;
243 numberOfElements = (*theMaterialTable)[fMatIndex]->
244 GetNumberOfElements();
245 G4int* thisMaterialZ =
new G4int[numberOfElements] ;
247 for(i=0;i<numberOfElements;i++)
250 (
G4int)(*theMaterialTable)[fMatIndex]->GetElement(i)->GetZ() ;
253 (thisMaterialZ,numberOfElements) ;
255 fSandiaIntervalNumber = thisMaterialSandiaTable.
SandiaMixing
257 (*theMaterialTable)[fMatIndex]->GetFractionVector() ,
258 numberOfElements,fSandiaIntervalNumber) ;
260 fSandiaPhotoAbsCof =
new G4double*[fSandiaIntervalNumber] ;
262 for(i=0;i<fSandiaIntervalNumber;i++) fSandiaPhotoAbsCof[i] =
new G4double[5] ;
264 for( i = 0 ; i < fSandiaIntervalNumber ; i++ )
268 for( j = 1; j < 5 ; j++ )
270 fSandiaPhotoAbsCof[i][j] = thisMaterialSandiaTable.
271 GetPhotoAbsorpCof(i+1,j)*
272 (*theMaterialTable)[fMatIndex]->GetDensity() ;
275 delete[] thisMaterialZ ;
288 G4double tau, Tmax, Tmin, Tkin, deltaLow, bg2 ;
317 fHighestKineticEnergy,
319 Tmin = fSandiaPhotoAbsCof[0][0] ;
322 for (
G4int i = 0 ; i <= fTotBin ; i++)
329 bg2 = tau*(tau + 2. ) ;
338 if ( Tkin < Tmin + deltaLow )
340 Tkin = Tmin + deltaLow ;
346 fSandiaIntervalNumber ) ;
368 photonVector->PutValue( k ,
371 plasmonVector->PutValue( k ,
374 dEdxVector->PutValue( k ,
379 if ( ionloss <= 0.) ionloss =
DBL_MIN ;
382 fPAItransferTable->
insertAt(i,transferVector) ;
383 fPAIphotonTable->
insertAt(i,photonVector) ;
384 fPAIplasmonTable->
insertAt(i,plasmonVector) ;
385 fPAIdEdxTable->
insertAt(i,dEdxVector) ;
414 for (jMatCC = 0 ; jMatCC < numOfCouples ; jMatCC++ )
418 if( jMatCC == numOfCouples && jMatCC > 0 ) jMatCC--;
420 const vector<G4double>* deltaCutInKineticEnergy = theCoupleTable->
422 const vector<G4double>* photonCutInKineticEnergy = theCoupleTable->
425 if (fLambdaVector)
delete fLambdaVector;
426 if (fdNdxCutVector)
delete fdNdxCutVector;
427 if (fdNdxCutPhotonVector)
delete fdNdxCutPhotonVector;
428 if (fdNdxCutPlasmonVector)
delete fdNdxCutPlasmonVector;
431 fHighestKineticEnergy,
434 fHighestKineticEnergy,
437 fHighestKineticEnergy,
440 fHighestKineticEnergy,
443 G4double deltaCutInKineticEnergyNow = (*deltaCutInKineticEnergy)[jMatCC];
444 G4double photonCutInKineticEnergyNow = (*photonCutInKineticEnergy)[jMatCC];
448 G4cout<<
"PAIPhotonModel deltaCutInKineticEnergyNow = "
449 <<deltaCutInKineticEnergyNow/
keV<<
" keV"<<
G4endl;
450 G4cout<<
"PAIPhotonModel photonCutInKineticEnergyNow = "
451 <<photonCutInKineticEnergyNow/
keV<<
" keV"<<
G4endl;
453 for ( i = 0 ; i <= fTotBin ; i++ )
458 dNdxCut = dNdxPhotonCut + dNdxPlasmonCut;
461 if (lambda <= 1000*kCarTolerance) lambda = 1000*kCarTolerance;
465 fdNdxCutVector->
PutValue(i, dNdxCut);
466 fdNdxCutPhotonVector->
PutValue(i, dNdxPhotonCut);
467 fdNdxCutPlasmonVector->
PutValue(i, dNdxPlasmonCut);
484 iTransfer <
G4int((*fPAItransferTable)(iPlace)->GetVectorLength()) ;
487 if(transferCut <= (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
492 if ( iTransfer >=
G4int((*fPAItransferTable)(iPlace)->GetVectorLength()) )
494 iTransfer = (*fPAItransferTable)(iPlace)->GetVectorLength() - 1 ;
496 y1 = (*(*fPAItransferTable)(iPlace))(iTransfer-1) ;
497 y2 = (*(*fPAItransferTable)(iPlace))(iTransfer) ;
499 x1 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
500 x2 = (*fPAItransferTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
503 if ( y1 == y2 ) dNdxCut =
y2 ;
508 if ( std::abs(x1-x2) <=
eV ) dNdxCut = y1 + (y2 -
y1)*0.5 ;
509 else dNdxCut = y1 + (transferCut -
x1)*(y2 - y1)/(x2 -
x1) ;
528 iTransfer <
G4int((*fPAIphotonTable)(iPlace)->GetVectorLength()) ;
531 if(transferCut <= (*fPAIphotonTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
536 if ( iTransfer >=
G4int((*fPAIphotonTable)(iPlace)->GetVectorLength()) )
538 iTransfer = (*fPAIphotonTable)(iPlace)->GetVectorLength() - 1 ;
540 y1 = (*(*fPAIphotonTable)(iPlace))(iTransfer-1) ;
541 y2 = (*(*fPAIphotonTable)(iPlace))(iTransfer) ;
543 x1 = (*fPAIphotonTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
544 x2 = (*fPAIphotonTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
547 if ( y1 == y2 ) dNdxCut =
y2 ;
552 if ( std::abs(x1-x2) <=
eV ) dNdxCut = y1 + (y2 -
y1)*0.5 ;
553 else dNdxCut = y1 + (transferCut -
x1)*(y2 - y1)/(x2 -
x1) ;
573 iTransfer <
G4int((*fPAIplasmonTable)(iPlace)->GetVectorLength()) ;
576 if(transferCut <= (*fPAIplasmonTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
581 if ( iTransfer >=
G4int((*fPAIplasmonTable)(iPlace)->GetVectorLength()) )
583 iTransfer = (*fPAIplasmonTable)(iPlace)->GetVectorLength() - 1 ;
585 y1 = (*(*fPAIplasmonTable)(iPlace))(iTransfer-1) ;
586 y2 = (*(*fPAIplasmonTable)(iPlace))(iTransfer) ;
588 x1 = (*fPAIplasmonTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
589 x2 = (*fPAIplasmonTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
592 if ( y1 == y2 ) dNdxCut =
y2 ;
597 if ( std::abs(x1-x2) <=
eV ) dNdxCut = y1 + (y2 -
y1)*0.5 ;
598 else dNdxCut = y1 + (transferCut -
x1)*(y2 - y1)/(x2 -
x1) ;
617 iTransfer <
G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) ;
620 if(transferCut <= (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer))
625 if ( iTransfer >=
G4int((*fPAIdEdxTable)(iPlace)->GetVectorLength()) )
627 iTransfer = (*fPAIdEdxTable)(iPlace)->GetVectorLength() - 1 ;
629 y1 = (*(*fPAIdEdxTable)(iPlace))(iTransfer-1) ;
630 y2 = (*(*fPAIdEdxTable)(iPlace))(iTransfer) ;
632 x1 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1) ;
633 x2 = (*fPAIdEdxTable)(iPlace)->GetLowEdgeEnergy(iTransfer) ;
636 if ( y1 == y2 ) dEdxCut =
y2 ;
641 if ( std::abs(x1-x2) <=
eV ) dEdxCut = y1 + (y2 -
y1)*0.5 ;
642 else dEdxCut = y1 + (transferCut -
x1)*(y2 - y1)/(x2 -
x1) ;
668 for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
670 if( matCC == fMaterialCutsCoupleVector[jMat] )
break;
672 if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
674 fPAIdEdxTable = fPAIdEdxBank[jMat];
675 fdEdxVector = fdEdxTable[jMat];
676 for(iTkin = 0 ; iTkin <= fTotBin ; iTkin++)
678 if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))
break ;
681 if(iPlace < 0) iPlace = 0;
682 dEdx = charge2*( (*fdEdxVector)(iPlace) -
GetdEdxCut(iPlace,cut) ) ;
684 if( dEdx < 0.) dEdx = 0.;
699 if(cutEnergy >= tmax)
return 0.0;
703 G4double charge2 = charge*charge, cross, cross1, cross2;
704 G4double photon1, photon2, plasmon1, plasmon2;
713 for (jMatCC = 0 ; jMatCC < numOfCouples ; jMatCC++ )
717 if( jMatCC == numOfCouples && jMatCC > 0 ) jMatCC--;
719 const vector<G4double>* photonCutInKineticEnergy = theCoupleTable->
722 G4double photonCut = (*photonCutInKineticEnergy)[jMatCC] ;
724 for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
726 if( matCC == fMaterialCutsCoupleVector[jMat] )
break;
728 if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
730 fPAItransferTable = fPAIxscBank[jMat];
731 fPAIphotonTable = fPAIphotonBank[jMat];
732 fPAIplasmonTable = fPAIplasmonBank[jMat];
734 for(iTkin = 0 ; iTkin <= fTotBin ; iTkin++)
736 if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))
break ;
739 if(iPlace < 0) iPlace = 0;
749 cross1 = photon1 + plasmon1;
751 cross2 = photon2 + plasmon2;
753 cross = (cross2 - cross1)*charge2;
756 if( cross < 0. ) cross = 0.;
773 for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
775 if( matCC == fMaterialCutsCoupleVector[jMat] )
break;
777 if( jMat == fMaterialCutsCoupleVector.size() && jMat > 0 ) jMat--;
779 fPAItransferTable = fPAIxscBank[jMat];
780 fPAIphotonTable = fPAIphotonBank[jMat];
781 fPAIplasmonTable = fPAIplasmonBank[jMat];
783 fdNdxCutVector = fdNdxCutTable[jMat];
784 fdNdxCutPhotonVector = fdNdxCutPhotonTable[jMat];
785 fdNdxCutPlasmonVector = fdNdxCutPlasmonTable[jMat];
788 if( tmin >= tmax && fVerbose > 0)
790 G4cout<<
"G4PAIPhotonModel::SampleSecondary: tmin >= tmax "<<
G4endl;
796 G4double scaledTkin = kineticEnergy*fMass/particleMass;
797 G4double totalEnergy = kineticEnergy + particleMass;
798 G4double pSquare = kineticEnergy*(totalEnergy+particleMass);
801 for(iTkin=0;iTkin<=fTotBin;iTkin++)
803 if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin))
break ;
805 G4int iPlace = iTkin - 1 ;
806 if(iPlace < 0) iPlace = 0;
808 G4double dNdxPhotonCut = (*fdNdxCutPhotonVector)(iPlace) ;
809 G4double dNdxPlasmonCut = (*fdNdxCutPlasmonVector)(iPlace) ;
810 G4double dNdxCut = dNdxPhotonCut + dNdxPlasmonCut;
813 if (dNdxCut > 0.) ratio = dNdxPhotonCut/dNdxCut;
823 if( deltaTkin <= 0. )
825 G4cout<<
"G4PAIPhotonModel::SampleSecondary e- deltaTkin = "<<deltaTkin<<
G4endl;
827 if( deltaTkin <= 0.)
return;
830 G4double totalMomentum = sqrt(pSquare);
832 /(deltaTotalMomentum * totalMomentum);
834 if( costheta > 0.99999 ) costheta = 0.99999;
836 G4double sin2 = 1. - costheta*costheta;
837 if( sin2 > 0.) sintheta = sqrt(sin2);
842 G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
849 kineticEnergy -= deltaTkin;
850 G4ThreeVector dir = totalMomentum*direction - deltaTotalMomentum*deltaDirection;
851 direction = dir.
unit();
860 vdp->push_back(deltaRay);
870 if( deltaTkin <= 0. )
872 G4cout<<
"G4PAIPhotonModel::SampleSecondary gamma deltaTkin = "<<deltaTkin<<
G4endl;
874 if( deltaTkin <= 0.)
return;
877 G4double sintheta = sqrt((1.+costheta)*(1.-costheta));
881 G4double dirx = sintheta*cos(phi), diry = sintheta*sin(phi), dirz = costheta;
887 kineticEnergy -= deltaTkin;
896 vdp->push_back(photonRay);
915 G4int iTkin = iPlace+1, iTransfer;
918 dNdxCut1 = (*pVector)(iPlace) ;
927 iTransfer <
G4int((*pTable)(iPlace)->GetVectorLength()); iTransfer++ )
929 if(
position >= (*(*pTable)(iPlace))(iTransfer)) break ;
935 dNdxCut2 = (*pVector)(iPlace+1) ;
941 iTransfer <
G4int((*pTable)(iPlace+1)->GetVectorLength()); iTransfer++ )
943 if(
position >= (*(*pTable)(iPlace+1))(iTransfer)) break ;
952 W1 = (E2 - scaledTkin)*W ;
953 W2 = (scaledTkin - E1)*W ;
959 G4int iTrMax1, iTrMax2, iTrMax;
961 iTrMax1 =
G4int((*pTable)(iPlace)->GetVectorLength());
962 iTrMax2 =
G4int((*pTable)(iPlace+1)->GetVectorLength());
964 if (iTrMax1 >= iTrMax2) iTrMax = iTrMax2;
965 else iTrMax = iTrMax1;
967 for( iTransfer = 0; iTransfer < iTrMax; iTransfer++ )
970 ( (*(*pTable)(iPlace))(iTransfer)*W1 +
971 (*(*pTable)(iPlace+1))(iTransfer)*W2) ) break ;
977 if(transfer < 0.0 ) transfer = 0.0 ;
995 energyTransfer = (*pTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
999 iTransferMax =
G4int((*pTable)(iPlace)->GetVectorLength());
1001 if ( iTransfer >= iTransferMax) iTransfer = iTransferMax - 1;
1003 y1 = (*(*pTable)(iPlace))(iTransfer-1);
1004 y2 = (*(*fPAItransferTable)(iPlace))(iTransfer);
1006 x1 = (*pTable)(iPlace)->GetLowEdgeEnergy(iTransfer-1);
1007 x2 = (*pTable)(iPlace)->GetLowEdgeEnergy(iTransfer);
1009 if ( x1 == x2 ) energyTransfer =
x2;
1015 energyTransfer = x1 + (position -
y1)*(x2 - x1)/(y2 -
y1);
1019 return energyTransfer;
1036 for( jMat = 0 ;jMat < fMaterialCutsCoupleVector.size() ; ++jMat )
1038 if( material == fMaterialCutsCoupleVector[jMat]->GetMaterial() )
break;
1040 if(jMat == fMaterialCutsCoupleVector.size() && jMat > 0) jMat--;
1042 fPAItransferTable = fPAIxscBank[jMat];
1043 fPAIphotonTable = fPAIphotonBank[jMat];
1044 fPAIplasmonTable = fPAIplasmonBank[jMat];
1046 fdNdxCutVector = fdNdxCutTable[jMat];
1047 fdNdxCutPhotonVector = fdNdxCutPhotonTable[jMat];
1048 fdNdxCutPlasmonVector = fdNdxCutPlasmonTable[jMat];
1050 G4int iTkin, iPlace ;
1054 G4double loss, photonLoss, plasmonLoss, charge2 ;
1060 charge2 = charge*charge ;
1061 G4double scaledTkin = Tkin*MassRatio ;
1064 for( iTkin = 0; iTkin <= fTotBin; iTkin++)
1066 if(scaledTkin < fProtonEnergyVector->GetLowEdgeEnergy(iTkin)) break ;
1068 iPlace = iTkin - 1 ;
1069 if( iPlace < 0 ) iPlace = 0;
1072 iPlace,scaledTkin,step,cof);
1077 iPlace,scaledTkin,step,cof);
1081 loss = photonLoss + plasmonLoss;
1099 G4int iTkin = iPlace + 1, iTransfer;
1100 G4double loss = 0.,
position, E1, E2, W1, W2, W, dNdxCut1, dNdxCut2, meanNumber;
1102 G4long numOfCollisions=0;
1105 dNdxCut1 = (*pVector)(iPlace) ;
1109 if(iTkin == fTotBin)
1111 meanNumber = ((*(*pTable)(iPlace))(0) - dNdxCut1)*cof;
1112 if(meanNumber < 0.) meanNumber = 0. ;
1114 if( meanNumber > 0.) lambda = step/meanNumber;
1119 stepSum += stepDelta;
1120 if(stepSum >= step)
break;
1126 while(numOfCollisions)
1132 iTransfer <
G4int((*pTable)(iPlace)->GetVectorLength()); iTransfer++ )
1134 if(
position >= (*(*pTable)(iPlace))(iTransfer)) break ;
1142 dNdxCut2 = (*pVector)(iPlace+1) ;
1146 meanNumber = ((*(*pTable)(iPlace+1))(0) - dNdxCut2)*cof;
1147 if( meanNumber < 0. ) meanNumber = 0. ;
1149 if( meanNumber > 0.) lambda = step/meanNumber;
1154 stepSum += stepDelta;
1155 if(stepSum >= step)
break;
1161 while(numOfCollisions)
1167 iTransfer <
G4int((*pTable)(iPlace+1)->GetVectorLength()); iTransfer++ )
1169 if(
position >= (*(*pTable)(iPlace+1))(iTransfer)) break ;
1180 W1 = (E2 - scaledTkin)*W ;
1181 W2 = (scaledTkin - E1)*W ;
1188 meanNumber=( ((*(*pTable)(iPlace))(0)-dNdxCut1)*W1 +
1189 ((*(*pTable)(iPlace+1))(0)-dNdxCut2)*W2 )*cof;
1190 if(meanNumber<0.0) meanNumber = 0.0;
1192 if( meanNumber > 0.) lambda = step/meanNumber;
1197 stepSum += stepDelta;
1198 if(stepSum >= step)
break;
1204 while(numOfCollisions)
1206 position = dNdxCut1*W1 + dNdxCut2*W2 +
1207 ( ( (*(*pTable)(iPlace ))(0) - dNdxCut1)*W1 +
1209 ( (*(*pTable)(iPlace+1))(0) - dNdxCut2)*W2 )*
G4UniformRand();
1214 iTransfer <
G4int((*pTable)(iPlace)->GetVectorLength()); iTransfer++ )
1217 ( (*(*pTable)(iPlace))(iTransfer)*W1 +
1218 (*(*pTable)(iPlace+1))(iTransfer)*W2) )
1245 G4double loss, sumLoss=0., sumLoss2=0., sigma2, meanLoss=0.;
1246 for(
G4int i = 0 ; i < fMeanNumber; i++)
1250 sumLoss2 += loss*loss;
1252 meanLoss = sumLoss/fMeanNumber;
1253 sigma2 = meanLoss*meanLoss + (sumLoss2-2*sumLoss*meanLoss)/fMeanNumber;
1263 if(p == fElectron) tmax *= 0.5;
1264 else if(p != fPositron) {
1267 G4double gamma= kinEnergy/mass + 1.0;
1269 (1. + 2.0*gamma*ratio + ratio*ratio);
1278 fPAIRegionVector.push_back(r);