// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // ------------------------------------------------------------------- // // GEANT4 Class // File name: G4PAIModelData.cc // // Author: V. Ivanchenko based on V.Grichine code of G4PAIModel // // Creation date: 16.08.2013 // // Modifications: // #include "G4PAIModelData.hh" #include "G4PAIModel.hh" #include "G4SystemOfUnits.hh" #include "G4PhysicalConstants.hh" #include "G4PhysicsLogVector.hh" #include "G4PhysicsFreeVector.hh" #include "G4PhysicsTable.hh" #include "G4MaterialCutsCouple.hh" #include "G4SandiaTable.hh" #include "Randomize.hh" #include "G4Poisson.hh" //////////////////////////////////////////////////////////////////////// using namespace std; G4PAIModelData::G4PAIModelData(G4double tmin, G4double tmax, G4int ver) { const G4int nPerDecade = 10; const G4double lowestTkin = 50*keV; const G4double highestTkin = 10*TeV; fPAIySection.SetVerbose(ver); fLowestKineticEnergy = std::max(tmin, lowestTkin); fHighestKineticEnergy = tmax; if(tmax < 10*fLowestKineticEnergy) { fHighestKineticEnergy = 10*fLowestKineticEnergy; } else if(tmax > highestTkin) { fHighestKineticEnergy = std::max(highestTkin, 10*fLowestKineticEnergy); } fTotBin = (G4int)(nPerDecade* std::log10(fHighestKineticEnergy/fLowestKineticEnergy)); fParticleEnergyVector = new G4PhysicsLogVector(fLowestKineticEnergy, fHighestKineticEnergy, fTotBin); if(0 < ver) { G4cout << "### G4PAIModelData: Nbins= " << fTotBin << " Tlowest(keV)= " << lowestTkin/keV << " Tmin(keV)= " << fLowestKineticEnergy/keV << " Tmax(GeV)= " << fHighestKineticEnergy/GeV << G4endl; } } //////////////////////////////////////////////////////////////////////////// G4PAIModelData::~G4PAIModelData() { std::size_t n = fPAIxscBank.size(); if(0 < n) { for(std::size_t i=0; iclearAndDestroy(); delete fPAIxscBank[i]; } if(fPAIdEdxBank[i]) { fPAIdEdxBank[i]->clearAndDestroy(); delete fPAIdEdxBank[i]; } delete fdEdxTable[i]; } } delete fParticleEnergyVector; } /////////////////////////////////////////////////////////////////////////////// void G4PAIModelData::Initialise(const G4MaterialCutsCouple* couple, G4PAIModel* model) { const G4Material* mat = couple->GetMaterial(); fSandia.Initialize(const_cast(mat)); auto PAItransferTable = new G4PhysicsTable(fTotBin+1); auto PAIdEdxTable = new G4PhysicsTable(fTotBin+1); auto dEdxMeanVector = new G4PhysicsLogVector(fLowestKineticEnergy, fHighestKineticEnergy, fTotBin); // low energy Sandia interval G4double Tmin = fSandia.GetSandiaMatTablePAI(0,0); // energy safety static const G4double deltaLow = 100.*eV; for (G4int i = 0; i <= fTotBin; ++i) { G4double kinEnergy = fParticleEnergyVector->Energy(i); G4double Tmax = model->ComputeMaxEnergy(kinEnergy); G4double tau = kinEnergy/proton_mass_c2; G4double bg2 = tau*( tau + 2. ); if (Tmax < Tmin + deltaLow ) { Tmax = Tmin + deltaLow; } fPAIySection.Initialize(mat, Tmax, bg2, &fSandia); //G4cout << i << ". TransferMax(keV)= "<< Tmax/keV // << " E(MeV)= " << kinEnergy/MeV << G4endl; G4int n = fPAIySection.GetSplineSize(); G4int kmin = 0; for(G4int k = 0; k < n; ++k) { if(fPAIySection.GetIntegralPAIySection(k+1) <= 0.0) { kmin = k; } else { break; } } n -= kmin; auto transferVector = new G4PhysicsFreeVector(n); auto dEdxVector = new G4PhysicsFreeVector(n); //G4double tr0 = 0.0; G4double tr = 0.0; for(G4int k = kmin; k < n; ++k) { G4double t = fPAIySection.GetSplineEnergy(k+1); tr = fPAIySection.GetIntegralPAIySection(k+1); //if(tr >= tr0) { tr0 = tr; } //else { G4cout << "G4PAIModelData::Initialise Warning: Ekin(MeV)= " // << t/MeV << " IntegralTransfer= " << tr // << " < " << tr0 << G4endl; } transferVector->PutValue(k, t, t*tr); dEdxVector->PutValue(k, t, fPAIySection.GetIntegralPAIdEdx(k+1)); } //G4cout << "TransferVector:" << G4endl; //G4cout << *transferVector << G4endl; //G4cout << "DEDXVector:" << G4endl; //G4cout << *dEdxVector << G4endl; G4double ionloss = std::max(fPAIySection.GetMeanEnergyLoss(), 0.0);// total dEdxMeanVector->PutValue(i,ionloss); PAItransferTable->insertAt(i,transferVector); PAIdEdxTable->insertAt(i,dEdxVector); } // end of Tkin loop` fPAIxscBank.push_back(PAItransferTable); fPAIdEdxBank.push_back(PAIdEdxTable); //G4cout << "dEdxMeanVector: " << G4endl; //G4cout << *dEdxMeanVector << G4endl; fdEdxTable.push_back(dEdxMeanVector); } ////////////////////////////////////////////////////////////////////////////// G4double G4PAIModelData::DEDXPerVolume(G4int coupleIndex, G4double scaledTkin, G4double cut) const { // VI: iPlace is the low edge index of the bin // iPlace is in interval from 0 to (N-1) std::size_t iPlace(0); G4double dEdx = fdEdxTable[coupleIndex]->Value(scaledTkin, iPlace); std::size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1; /* G4cout << "G4PAIModelData::DEDXPerVolume: coupleIdx= " << coupleIndex << " Tscaled= " << scaledTkin << " cut= " << cut << " iPlace= " << iPlace << " nPlace= " << nPlace << G4endl; */ G4bool one = true; if(scaledTkin >= fParticleEnergyVector->Energy(nPlace)) { iPlace = nPlace; } else if(scaledTkin > fParticleEnergyVector->Energy(0)) { one = false; } // VI: apply interpolation of the vector G4double del = (*(fPAIdEdxBank[coupleIndex]))(iPlace)->Value(cut); //G4cout << "dEdx= " << dEdx << " del= " << del << G4endl; if(!one) { G4double del2 = (*(fPAIdEdxBank[coupleIndex]))(iPlace+1)->Value(cut); G4double E1 = fParticleEnergyVector->Energy(iPlace); G4double E2 = fParticleEnergyVector->Energy(iPlace+1); G4double W = 1.0/(E2 - E1); G4double W1 = (E2 - scaledTkin)*W; G4double W2 = (scaledTkin - E1)*W; del *= W1; del += W2*del2; } dEdx -= del; //G4cout << "dEdx= " << dEdx << " del= " << del << G4endl; dEdx = std::max(dEdx, 0.); return dEdx; } ///////////////////////////////////////////////////////////////////////// G4double G4PAIModelData::CrossSectionPerVolume(G4int coupleIndex, G4double scaledTkin, G4double tcut, G4double tmax) const { G4double cross, cross1, cross2; // iPlace is in interval from 0 to (N-1) std::size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0); std::size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1; G4bool one = true; if(scaledTkin >= fParticleEnergyVector->Energy(nPlace)) { iPlace = nPlace; } else if(scaledTkin > fParticleEnergyVector->Energy(0)) { one = false; } G4PhysicsTable* table = fPAIxscBank[coupleIndex]; //G4cout<<"iPlace = "<FindBin(scaledTkin, 0); std::size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1; G4bool one = true; if(scaledTkin >= fParticleEnergyVector->Energy(nPlace)) { iPlace = nPlace; } else if(scaledTkin > fParticleEnergyVector->Energy(0)) { one = false; } G4double meanNumber = 0.0; G4double meanN11 = 0.0; G4double meanN12 = 0.0; G4double meanN21 = 0.0; G4double meanN22 = 0.0; G4PhysicsVector* v1 = (*(fPAIxscBank[coupleIndex]))(iPlace); G4PhysicsVector* v2 = nullptr; G4double e1 = v1->Energy(0); G4double e2 = std::min(tmax, v1->GetMaxEnergy()); if(e2 >= e1) { meanN11 = (*v1)[0]/e1; meanN12 = v1->Value(e2)/e2; meanNumber = (meanN11 - meanN12)*stepFactor; } //G4cout<<"iPlace = "< kinEnergy) { loss = kinEnergy; } else if(loss < 0.) { loss = 0.; } return loss; } /////////////////////////////////////////////////////////////////////// // // Returns post step PAI energy transfer > cut electron energy // according to passed scaled kinetic energy of particle G4double G4PAIModelData::SamplePostStepTransfer(G4int coupleIndex, G4double scaledTkin, G4double tmin, G4double tmax) const { //G4cout<<"=== G4PAIModelData::SamplePostStepTransfer idx= "<< coupleIndex // << " Tkin= " << scaledTkin << " Tmax= " << tmax << G4endl; G4double transfer = 0.0; G4double rand = G4UniformRand(); std::size_t nPlace = fParticleEnergyVector->GetVectorLength() - 1; std::size_t iPlace = fParticleEnergyVector->FindBin(scaledTkin, 0); G4bool one = true; if(scaledTkin >= fParticleEnergyVector->Energy(nPlace)) { iPlace = nPlace; } else if(scaledTkin > fParticleEnergyVector->Energy(0)) { one = false; } G4PhysicsTable* table = fPAIxscBank[coupleIndex]; G4PhysicsVector* v1 = (*table)[iPlace]; G4double emin = std::max(tmin, v1->Energy(0)); G4double emax = std::min(tmax, v1->GetMaxEnergy()); if(emax < emin) { return transfer; } G4double dNdx1 = v1->Value(emin)/emin; G4double dNdx2 = v1->Value(emax)/emax; /* G4cout << "iPlace= " << iPlace << " nPlace= " << nPlace << " emin= " << emin << " emax= " << emax << " dNdx1= " << dNdx1 << " dNdx2= " << dNdx2 << " one: " << one << G4endl; */ G4double position = dNdx2 + (dNdx1 - dNdx2)*rand; transfer = GetEnergyTransfer(coupleIndex, iPlace, position); //G4cout<<"PAImodel PostStepTransfer = "<