61   const G4int nPerDecade     = 10; 
    67   fLowestKineticEnergy  = 
std::max(tmin, lowestTkin);
    68   fHighestKineticEnergy = tmax;
    70   if(tmax < 10*fLowestKineticEnergy) 
    72     fHighestKineticEnergy = 10*fLowestKineticEnergy;
    74   else if(tmax > highestTkin) 
    76     fHighestKineticEnergy = 
std::max(highestTkin, 10*fLowestKineticEnergy);
    78   fTotBin = (
G4int)(nPerDecade*
    79             std::log10(fHighestKineticEnergy/fLowestKineticEnergy));
    82                          fHighestKineticEnergy,
    85     G4cout << 
"### G4PAIPhotData: Nbins= " << fTotBin
    86        << 
" Tmin(MeV)= " << fLowestKineticEnergy/
MeV    87        << 
" Tmax(GeV)= " << fHighestKineticEnergy/
GeV     97   size_t n = fPAIxscBank.size();
   100     for(
size_t i=0; i<
n; ++i) 
   104     fPAIxscBank[i]->clearAndDestroy();
   105     delete fPAIxscBank[i];
   110     fPAIdEdxBank[i]->clearAndDestroy();
   111     delete fPAIdEdxBank[i];
   114       delete fdEdxTable[i];
   115       delete fdNdxCutTable[i];
   117       fdNdxCutTable[i] = 0;
   120   delete fParticleEnergyVector;
   121   fParticleEnergyVector = 0;
   135   for (jMatCC = 0; jMatCC < numOfCouples; jMatCC++ )
   139   if( jMatCC == numOfCouples && jMatCC > 0 ) jMatCC--;
   143   G4double deltaCutInKineticEnergyNow  = (*deltaCutInKineticEnergy)[jMatCC];
   144   G4double photonCutInKineticEnergyNow = (*photonCutInKineticEnergy)[jMatCC];
   146   G4cout<<
"G4PAIPhotData::Initialise: "<<
"cut = "<<cut/
keV<<
" keV; cutEl = "   147         <<deltaCutInKineticEnergyNow/
keV<<
" keV; cutPh = "   148     <<photonCutInKineticEnergyNow/
keV<<
" keV"<<
G4endl;
   154                fHighestKineticEnergy,
   159                fHighestKineticEnergy,
   163                fHighestKineticEnergy,
   167                fHighestKineticEnergy,
   171   fSandia.Initialize(const_cast<G4Material*>(mat));
   180                fHighestKineticEnergy,
   184   G4double Tmin = fSandia.GetSandiaMatTablePAI(0,0); 
   189   for (
G4int i = 0; i <= fTotBin; ++i) 
   191     G4double kinEnergy = fParticleEnergyVector->Energy(i);
   196     if ( Tmax < Tmin + deltaLow ) Tmax = Tmin + deltaLow; 
   198     fPAIxSection.Initialize( mat, Tmax, bg2, &fSandia);
   203     G4int n = fPAIxSection.GetSplineSize();
   211     for( 
G4int k = 0; k < 
n; k++ )
   213       G4double t = fPAIxSection.GetSplineEnergy(k+1);
   216                                t*fPAIxSection.GetIntegralPAIxSection(k+1));
   218                                t*fPAIxSection.GetIntegralCerenkov(k+1));
   220                                t*fPAIxSection.GetIntegralPlasmon(k+1));
   222       dEdxVector->
PutValue(k, t, fPAIxSection.GetIntegralPAIdEdx(k+1));
   226     G4double ionloss = fPAIxSection.GetMeanEnergyLoss();
   228     if(ionloss < 0.0) ionloss = 0.0; 
   230     dEdxMeanVector->
PutValue(i,ionloss);
   232     G4double dNdxCut = transferVector->
Value(deltaCutInKineticEnergyNow)/deltaCutInKineticEnergyNow;
   233     G4double dNdxCutPhoton = photonVector->
Value(photonCutInKineticEnergyNow)/photonCutInKineticEnergyNow;
   234     G4double dNdxCutPlasmon = plasmonVector->
Value(deltaCutInKineticEnergyNow)/deltaCutInKineticEnergyNow;
   239     if(dNdxCut < 0.0) { dNdxCut = 0.0; }
   240     if(dNdxCutPhoton < 0.0) { dNdxCutPhoton = 0.0; }
   241     if(dNdxCutPlasmon < 0.0) { dNdxCutPlasmon = 0.0; }
   243     dNdxCutVector->
PutValue(i, dNdxCut);
   244     dNdxCutPhotonVector->
PutValue(i, dNdxCutPhoton);
   245     dNdxCutPlasmonVector->
PutValue(i, dNdxCutPlasmon);
   247     dEdxCutVector->
PutValue(i, dEdxCut);
   249     PAItransferTable->
insertAt(i,transferVector);
   250     PAIphotonTable->
insertAt(i,photonVector);
   251     PAIplasmonTable->
insertAt(i,plasmonVector);
   252     PAIdEdxTable->
insertAt(i,dEdxVector);
   256   fPAIxscBank.push_back(PAItransferTable);
   257   fPAIphotonBank.push_back(PAIphotonTable);
   258   fPAIplasmonBank.push_back(PAIplasmonTable);
   260   fPAIdEdxBank.push_back(PAIdEdxTable);
   261   fdEdxTable.push_back(dEdxMeanVector);
   263   fdNdxCutTable.push_back(dNdxCutVector);
   264   fdNdxCutPhotonTable.push_back(dNdxCutPhotonVector);
   265   fdNdxCutPlasmonTable.push_back(dNdxCutPlasmonVector);
   267   fdEdxCutTable.push_back(dEdxCutVector);
   277   size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0);
   278   size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1;
   281   if(scaledTkin >= fParticleEnergyVector->Energy(nPlace)) { iPlace = nPlace; }
   282   else if(scaledTkin > fParticleEnergyVector->Energy(0)) { 
   287   G4double dEdx = fdEdxTable[coupleIndex]->Value(scaledTkin);
   288   G4double del  = (*(fPAIdEdxBank[coupleIndex]))(iPlace)->Value(cut);
   290     G4double del2 = (*(fPAIdEdxBank[coupleIndex]))(iPlace+1)->Value(cut);
   291     G4double E1 = fParticleEnergyVector->Energy(iPlace); 
   292     G4double E2 = fParticleEnergyVector->Energy(iPlace+1);
   301   if( dEdx < 0.) { dEdx = 0.; }
   312   G4double cross, xscEl, xscEl2, xscPh, xscPh2;
   318   size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0);
   319   size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1;
   323   if(      scaledTkin >= fParticleEnergyVector->Energy(nPlace))  iPlace = nPlace; 
   324   else if( scaledTkin > fParticleEnergyVector->Energy(0)      )   one   = 
false; 
   327   xscEl2 = (*fdNdxCutPlasmonTable[coupleIndex])(iPlace);
   328   xscPh2 = (*fdNdxCutPhotonTable[coupleIndex])(iPlace);
   333   cross  = xscPh + xscEl;
   337     xscEl2 = (*fdNdxCutPlasmonTable[coupleIndex])(iPlace+1);
   339     G4double E1 = fParticleEnergyVector->Energy(iPlace); 
   340     G4double E2 = fParticleEnergyVector->Energy(iPlace+1);
   349     xscPh2 = (*fdNdxCutPhotonTable[coupleIndex])(iPlace+1);
   351     E1 = fParticleEnergyVector->Energy(iPlace); 
   352     E2 = fParticleEnergyVector->Energy(iPlace+1);
   355     W1 = (E2 - scaledTkin)*W;
   356     W2 = (scaledTkin - E1)*W;
   361     cross = xscEl + xscPh;
   363   if( cross < 0.0)  cross = 0.0; 
   373   G4double cross, xscEl, xscEl2, xscPh, xscPh2, plRatio;
   376   size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0);
   377   size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1;
   381   if(      scaledTkin >= fParticleEnergyVector->Energy(nPlace))  iPlace = nPlace; 
   382   else if( scaledTkin > fParticleEnergyVector->Energy(0)      )   one   = 
false; 
   385   xscEl2 = (*fdNdxCutPlasmonTable[coupleIndex])(iPlace);
   386   xscPh2 = (*fdNdxCutPhotonTable[coupleIndex])(iPlace);
   391   cross  = xscPh + xscEl;
   395     xscEl2 = (*fdNdxCutPlasmonTable[coupleIndex])(iPlace+1);
   397     G4double E1 = fParticleEnergyVector->Energy(iPlace); 
   398     G4double E2 = fParticleEnergyVector->Energy(iPlace+1);
   407     xscPh2 = (*fdNdxCutPhotonTable[coupleIndex])(iPlace+1);
   409     E1 = fParticleEnergyVector->Energy(iPlace); 
   410     E2 = fParticleEnergyVector->Energy(iPlace+1);
   413     W1 = (E2 - scaledTkin)*W;
   414     W2 = (scaledTkin - E1)*W;
   419     cross = xscEl + xscPh;
   427     plRatio = xscEl/cross;
   429     if( plRatio > 1. || plRatio < 0.) plRatio = 2.0;
   445   size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0);
   446   size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1;
   450   if     (scaledTkin >= fParticleEnergyVector->Energy(nPlace)) iPlace = nPlace; 
   451   else if(scaledTkin > fParticleEnergyVector->Energy(0))          one = 
false; 
   457   dNdxCut1    = (*vcut)[iPlace];
   461   G4double meanN1 = ((*v1)[0]/e1 - dNdxCut1)*stepFactor;
   473     v2 = (*(fPAIxscBank[coupleIndex]))(iPlace+1);
   474     dNdxCut2 = (*vcut)[iPlace+1];
   477     G4double meanN2 = ((*v2)[0]/e2 - dNdxCut2)*stepFactor;
   479     E1 = fParticleEnergyVector->Energy(iPlace); 
   480     E2 = fParticleEnergyVector->Energy(iPlace+1);
   482     W1 = (E2 - scaledTkin)*W;
   483     W2 = (scaledTkin - E1)*W;
   484     meanNumber = W1*meanN1 + W2*meanN2;
   489   if( meanNumber <= 0.0) 
return 0.0; 
   495   if( 0 == numOfCollisions) 
return 0.0; 
   497   for(
G4int i=0; i< numOfCollisions; ++i) 
   500     position = dNdxCut1 + ((*v1)[0]/e1 - dNdxCut1)*rand;
   501     omega = GetEnergyTransfer(coupleIndex, iPlace, position);
   507       position = dNdxCut2 + ((*v2)[0]/e2 - dNdxCut2)*rand;
   508       G4double omega2 = GetEnergyTransfer(coupleIndex, iPlace+1, position);
   509       omega = omega*W1 + omega2*W2;
   514     if( loss > kinEnergy) { 
break; }
   520   if     ( loss > kinEnergy) loss = kinEnergy; 
   521   else if( loss < 0.)        loss = 0.;
   537   size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0);
   538   size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1;
   542   if     (scaledTkin >= fParticleEnergyVector->Energy(nPlace)) iPlace = nPlace; 
   543   else if(scaledTkin > fParticleEnergyVector->Energy(0))          one = 
false; 
   549   dNdxCut1    = (*vcut)[iPlace];
   553   G4double meanN1 = ((*v1)[0]/e1 - dNdxCut1)*stepFactor;
   565     v2 = (*(fPAIphotonBank[coupleIndex]))(iPlace+1);
   566     dNdxCut2 = (*vcut)[iPlace+1];
   569     G4double meanN2 = ((*v2)[0]/e2 - dNdxCut2)*stepFactor;
   571     E1 = fParticleEnergyVector->Energy(iPlace); 
   572     E2 = fParticleEnergyVector->Energy(iPlace+1);
   574     W1 = (E2 - scaledTkin)*W;
   575     W2 = (scaledTkin - E1)*W;
   576     meanNumber = W1*meanN1 + W2*meanN2;
   581   if( meanNumber <= 0.0) 
return 0.0; 
   587   if( 0 == numOfCollisions) 
return 0.0; 
   589   for(
G4int i=0; i< numOfCollisions; ++i) 
   592     position = dNdxCut1 + ((*v1)[0]/e1 - dNdxCut1)*rand;
   593     omega = GetEnergyPhotonTransfer(coupleIndex, iPlace, position);
   599       position = dNdxCut2 + ((*v2)[0]/e2 - dNdxCut2)*rand;
   600       G4double omega2 = GetEnergyPhotonTransfer(coupleIndex, iPlace+1, position);
   601       omega = omega*W1 + omega2*W2;
   606     if( loss > kinEnergy) { 
break; }
   612   if     ( loss > kinEnergy) loss = kinEnergy; 
   613   else if( loss < 0.)        loss = 0.;
   629   size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0);
   630   size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1;
   634   if     (scaledTkin >= fParticleEnergyVector->Energy(nPlace)) iPlace = nPlace; 
   635   else if(scaledTkin > fParticleEnergyVector->Energy(0))          one = 
false; 
   641   dNdxCut1    = (*vcut)[iPlace];
   645   G4double meanN1 = ((*v1)[0]/e1 - dNdxCut1)*stepFactor;
   657     v2 = (*(fPAIplasmonBank[coupleIndex]))(iPlace+1);
   658     dNdxCut2 = (*vcut)[iPlace+1];
   661     G4double meanN2 = ((*v2)[0]/e2 - dNdxCut2)*stepFactor;
   663     E1 = fParticleEnergyVector->Energy(iPlace); 
   664     E2 = fParticleEnergyVector->Energy(iPlace+1);
   666     W1 = (E2 - scaledTkin)*W;
   667     W2 = (scaledTkin - E1)*W;
   668     meanNumber = W1*meanN1 + W2*meanN2;
   673   if( meanNumber <= 0.0) 
return 0.0; 
   679   if( 0 == numOfCollisions) 
return 0.0; 
   681   for(
G4int i=0; i< numOfCollisions; ++i) 
   684     position = dNdxCut1 + ((*v1)[0]/e1 - dNdxCut1)*rand;
   685     omega = GetEnergyPlasmonTransfer(coupleIndex, iPlace, position);
   691       position = dNdxCut2 + ((*v2)[0]/e2 - dNdxCut2)*rand;
   692       G4double omega2 = GetEnergyPlasmonTransfer(coupleIndex, iPlace+1, position);
   693       omega = omega*W1 + omega2*W2;
   698     if( loss > kinEnergy) { 
break; }
   704   if     ( loss > kinEnergy) loss = kinEnergy; 
   705   else if( loss < 0.)        loss = 0.;
   722   size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1;
   730   if( scaledTkin >= fParticleEnergyVector->GetMaxEnergy()) 
   732     position = (*cutv)[nPlace]*rand;
   733     transfer = GetEnergyTransfer(coupleIndex, nPlace, position);
   735   else if( scaledTkin <= fParticleEnergyVector->Energy(0) )
   737     position = (*cutv)[0]*rand;
   738     transfer = GetEnergyTransfer(coupleIndex, 0, position);
   742     size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0);
   744     dNdxCut1 = (*cutv)[iPlace];  
   745     dNdxCut2 = (*cutv)[iPlace+1];  
   747     E1 = fParticleEnergyVector->Energy(iPlace); 
   748     E2 = fParticleEnergyVector->Energy(iPlace+1);
   750     W1 = (E2 - scaledTkin)*W;
   751     W2 = (scaledTkin - E1)*W;
   756     position = dNdxCut1*rand;
   757     G4double tr1 = GetEnergyTransfer(coupleIndex, iPlace, position);
   759     position = dNdxCut2*rand;
   760     G4double tr2 = GetEnergyTransfer(coupleIndex, iPlace+1, position);
   762     transfer = tr1*W1 + tr2*W2;
   765   if(transfer < 0.0 ) { transfer = 0.0; }
   778   size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1;
   787   if( scaledTkin >= fParticleEnergyVector->GetMaxEnergy()) 
   789     position = (*cutv)[nPlace]*rand;
   790     transfer = GetEnergyPhotonTransfer(coupleIndex, nPlace, position);
   792   else if( scaledTkin <= fParticleEnergyVector->Energy(0) )
   794     position = (*cutv)[0]*rand;
   795     transfer = GetEnergyPhotonTransfer(coupleIndex, 0, position);
   799     size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0);
   801     dNdxCut1 = (*cutv)[iPlace];  
   802     dNdxCut2 = (*cutv)[iPlace+1];  
   804     E1 = fParticleEnergyVector->Energy(iPlace); 
   805     E2 = fParticleEnergyVector->Energy(iPlace+1);
   807     W1 = (E2 - scaledTkin)*W;
   808     W2 = (scaledTkin - E1)*W;
   813     position = dNdxCut1*rand;
   815     G4double tr1 = GetEnergyPhotonTransfer(coupleIndex, iPlace, position);
   817     position = dNdxCut2*rand;
   818     G4double tr2 = GetEnergyPhotonTransfer(coupleIndex, iPlace+1, position);
   820     transfer = tr1*W1 + tr2*W2;
   823   if(transfer < 0.0 ) { transfer = 0.0; }
   836   size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1;
   844   if( scaledTkin >= fParticleEnergyVector->GetMaxEnergy()) 
   846     position = (*cutv)[nPlace]*rand;
   847     transfer = GetEnergyPlasmonTransfer(coupleIndex, nPlace, position);
   849   else if( scaledTkin <= fParticleEnergyVector->Energy(0) )
   851     position = (*cutv)[0]*rand;
   852     transfer = GetEnergyPlasmonTransfer(coupleIndex, 0, position);
   856     size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0);
   858     dNdxCut1 = (*cutv)[iPlace];  
   859     dNdxCut2 = (*cutv)[iPlace+1];  
   861     E1 = fParticleEnergyVector->Energy(iPlace); 
   862     E2 = fParticleEnergyVector->Energy(iPlace+1);
   864     W1 = (E2 - scaledTkin)*W;
   865     W2 = (scaledTkin - E1)*W;
   870     position = dNdxCut1*rand;
   871     G4double tr1 = GetEnergyPlasmonTransfer(coupleIndex, iPlace, position);
   873     position = dNdxCut2*rand;
   874     G4double tr2 = GetEnergyPlasmonTransfer(coupleIndex, iPlace+1, position);
   876     transfer = tr1*W1 + tr2*W2;
   880   if(transfer < 0.0 )  transfer = 0.0;
   895   if(position*v->
Energy(0) >= (*v)[0]) { 
return v->
Energy(0); }
   902   for(iTransfer=1; iTransfer<=iTransferMax; ++iTransfer) {
   904     y2 = (*v)[iTransfer]/
x2;
   905     if(position >= 
y2) { 
break; }
   909   y1 = (*v)[iTransfer-1]/
x1;
   919     const G4int nbins = 5;
   922         for(
G4int i=1; i<=nbins; ++i) {
   925           if(position >= 
y2) { 
break; }
   936   return energyTransfer;
   946   if(position*v->
Energy(0) >= (*v)[0])  
return v->
Energy(0); 
   953   for(iTransfer=1; iTransfer<=iTransferMax; ++iTransfer) 
   956     y2 = (*v)[iTransfer]/
x2;
   957     if(position >= 
y2)  
break; 
   960   y1 = (*v)[iTransfer-1]/
x1;
   977     const G4int nbins = 5;
   981         for(
G4int i=1; i<=nbins; ++i) 
   985           if(position >= 
y2) { 
break; }
   997   return energyTransfer;
  1008   if( position*v->
Energy(0) >= (*v)[0] )  
return v->
Energy(0); 
  1015   for(iTransfer = 1; iTransfer <= iTransferMax; ++iTransfer) 
  1018     y2 = (*v)[iTransfer]/
x2;
  1019     if(position >= 
y2)  
break; 
  1022   y1 = (*v)[iTransfer-1]/
x1;
  1027   energyTransfer = 
x1;
  1039     const G4int nbins = 5;
  1043         for( 
G4int i = 1; i <= nbins; ++i ) 
  1048           if(position >= 
y2)  
break; 
  1061   return energyTransfer;
 
G4double SamplePostStepTransfer(G4int coupleIndex, G4double scaledTkin) const
 
G4long G4Poisson(G4double mean)
 
G4double SamplePostStepPhotonTransfer(G4int coupleIndex, G4double scaledTkin) const
 
void PutValue(size_t binNumber, G4double binValue, G4double dataValue)
 
const G4Material * GetMaterial() const
 
G4PAIPhotData(G4double tmin, G4double tmax, G4int verbose)
 
G4double GetPlasmonRatio(G4int coupleIndex, G4double scaledTkin) const
 
const std::vector< G4double > * GetEnergyCutsVector(size_t pcIdx) const
 
void Initialise(const G4MaterialCutsCouple *, G4double cut, G4PAIPhotModel *)
 
G4double SampleAlongStepPlasmonTransfer(G4int coupleIndex, G4double kinEnergy, G4double scaledTkin, G4double stepFactor) const
 
G4GLOB_DLL std::ostream G4cout
 
G4double GetEnergyPhotonTransfer(G4int coupleIndex, size_t iPlace, G4double position) const
 
G4double ComputeMaxEnergy(G4double scaledEnergy)
 
void PutValue(size_t index, G4double theValue)
 
size_t GetVectorLength() const
 
G4double Value(G4double theEnergy, size_t &lastidx) const
 
G4double GetEnergyPlasmonTransfer(G4int coupleIndex, size_t iPlace, G4double position) const
 
G4double SampleAlongStepPhotonTransfer(G4int coupleIndex, G4double kinEnergy, G4double scaledTkin, G4double stepFactor) const
 
static G4ProductionCutsTable * GetProductionCutsTable()
 
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
 
G4double SamplePostStepPlasmonTransfer(G4int coupleIndex, G4double scaledTkin) const
 
G4double CrossSectionPerVolume(G4int coupleIndex, G4double scaledTkin, G4double tcut, G4double tmax) const
 
void insertAt(size_t, G4PhysicsVector *)
 
size_t GetTableSize() const
 
G4double GetEnergyTransfer(G4int coupleIndex, size_t iPlace, G4double position) const
 
G4double Energy(size_t index) const
 
G4double DEDXPerVolume(G4int coupleIndex, G4double scaledTkin, G4double cut) const
 
G4double SampleAlongStepTransfer(G4int coupleIndex, G4double kinEnergy, G4double scaledTkin, G4double stepFactor) const