Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/standard/src/G4PAIModel.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 //
 27 // -------------------------------------------------------------------
 28 //
 29 // GEANT4 Class
 30 // File name:     G4PAIModel.cc
 31 //
 32 // Author: Vladimir.Grichine@cern.ch on base of V.Ivanchenko model interface
 33 //
 34 // Creation date: 05.10.2003
 35 //
 36 // Modifications:
 37 //
 38 // 17.08.04 V.Grichine, bug fixed for Tkin<=0 in SampleSecondary
 39 // 16.08.04 V.Grichine, bug fixed in massRatio for DEDX, CrossSection, 
 40 //          SampleSecondary
 41 // 08.04.05 Major optimisation of internal interfaces (V.Ivantchenko)
 42 // 26.07.09 Fixed logic to work with several materials (V.Ivantchenko)
 43 // 21.11.10 V. Grichine verbose flag for protons and G4PAYySection to 
 44 //          check sandia table 
 45 // 12.06.13 V. Grichine Bug fixed in SampleSecondaries for scaled Tkin 
 46 //          (fMass -> proton_mass_c2)
 47 // 19.08.13 V.Ivanchenko extract data handling to G4PAIModelData class 
 48 //          added sharing of internal data between threads (MT migration)
 49 //
 50 
 51 #include "G4PAIModel.hh"
 52 
 53 #include "G4SystemOfUnits.hh"
 54 #include "G4PhysicalConstants.hh"
 55 #include "G4Region.hh"
 56 #include "G4MaterialCutsCouple.hh"
 57 #include "G4MaterialTable.hh"
 58 #include "G4RegionStore.hh"
 59 
 60 #include "Randomize.hh"
 61 #include "G4Electron.hh"
 62 #include "G4Positron.hh"
 63 #include "G4Poisson.hh"
 64 #include "G4Step.hh"
 65 #include "G4Material.hh"
 66 #include "G4DynamicParticle.hh"
 67 #include "G4ParticleDefinition.hh"
 68 #include "G4ParticleChangeForLoss.hh"
 69 #include "G4PAIModelData.hh"
 70 #include "G4DeltaAngle.hh"
 71 
 72 ////////////////////////////////////////////////////////////////////////
 73 
 74 using namespace std;
 75 
 76 G4PAIModel::G4PAIModel(const G4ParticleDefinition* p, const G4String& nam)
 77   : G4VEmModel(nam),G4VEmFluctuationModel(nam),
 78     fVerbose(0),
 79     fModelData(nullptr),
 80     fParticle(nullptr)
 81 {  
 82   fElectron = G4Electron::Electron();
 83   fPositron = G4Positron::Positron();
 84 
 85   fParticleChange = nullptr;
 86 
 87   if(p) { SetParticle(p); }
 88   else  { SetParticle(fElectron); }
 89 
 90   // default generator
 91   SetAngularDistribution(new G4DeltaAngle());
 92   fLowestTcut = 12.5*CLHEP::eV;
 93 }
 94 
 95 ////////////////////////////////////////////////////////////////////////////
 96 
 97 G4PAIModel::~G4PAIModel()
 98 {
 99   if(IsMaster()) { delete fModelData; }
100 }
101 
102 ////////////////////////////////////////////////////////////////////////////
103 
104 void G4PAIModel::Initialise(const G4ParticleDefinition* p,
105           const G4DataVector& cuts)
106 {
107   if(fVerbose > 1) {
108     G4cout<<"G4PAIModel::Initialise for "<<p->GetParticleName()<<G4endl;
109   }
110   SetParticle(p);
111   fParticleChange = GetParticleChangeForLoss();
112 
113   if(IsMaster()) { 
114 
115     delete fModelData;      
116     fMaterialCutsCoupleVector.clear(); 
117     if(fVerbose > 1) {
118       G4cout << "G4PAIModel instantiates data for  " << p->GetParticleName()
119        << G4endl;
120     }  
121     G4double tmin = LowEnergyLimit()*fRatio;
122     G4double tmax = HighEnergyLimit()*fRatio;
123     fModelData = new G4PAIModelData(tmin, tmax, fVerbose);
124   
125     // Prepare initialization
126     const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
127     std::size_t numOfMat   = G4Material::GetNumberOfMaterials();
128     std::size_t numRegions = fPAIRegionVector.size();
129 
130     // protect for unit tests
131     if(0 == numRegions) {
132       G4Exception("G4PAIModel::Initialise()","em0106",JustWarning,
133                   "no G4Regions are registered for the PAI model - World is used");
134       fPAIRegionVector.push_back(G4RegionStore::GetInstance()
135          ->GetRegion("DefaultRegionForTheWorld", false));
136       numRegions = 1;
137     }
138 
139     if(fVerbose > 1) {
140       G4cout << "G4PAIModel is defined for " << numRegions << " regions "   
141        << "; number of materials " << numOfMat << G4endl;
142     } 
143     for(std::size_t iReg = 0; iReg<numRegions; ++iReg) {
144       const G4Region* curReg = fPAIRegionVector[iReg];
145       G4Region* reg = const_cast<G4Region*>(curReg);
146 
147       for(std::size_t jMat = 0; jMat<numOfMat; ++jMat) {
148   G4Material* mat = (*theMaterialTable)[jMat];
149   const G4MaterialCutsCouple* cutCouple = reg->FindCouple(mat);
150   std::size_t n = fMaterialCutsCoupleVector.size();
151   if(nullptr != cutCouple) {
152     if(fVerbose > 1) {
153       G4cout << "Region <" << curReg->GetName() << ">  mat <" 
154        << mat->GetName() << ">  CoupleIndex= " 
155        << cutCouple->GetIndex()
156        << "  " << p->GetParticleName()
157        << " cutsize= " << cuts.size() << G4endl;
158     }
159     // check if this couple is not already initialized
160     G4bool isnew = true;
161     if(0 < n) {
162       for(std::size_t i=0; i<n; ++i) {
163         G4cout << i << G4endl;
164         if(cutCouple == fMaterialCutsCoupleVector[i]) {
165     isnew = false;
166     break;
167         }
168       }
169     }
170     // initialise data banks
171     // G4cout << "   isNew: " << isnew << "  " << cutCouple << G4endl;
172     if(isnew) { 
173       fMaterialCutsCoupleVector.push_back(cutCouple); 
174       fModelData->Initialise(cutCouple, this);
175     }
176   }
177       }
178     }
179     InitialiseElementSelectors(p, cuts);
180   }
181 }
182 
183 /////////////////////////////////////////////////////////////////////////
184 
185 void G4PAIModel::InitialiseLocal(const G4ParticleDefinition*,
186          G4VEmModel* masterModel)
187 {
188   fModelData = static_cast<G4PAIModel*>(masterModel)->GetPAIModelData();
189   fMaterialCutsCoupleVector = 
190     static_cast<G4PAIModel*>(masterModel)->GetVectorOfCouples();
191   SetElementSelectors(masterModel->GetElementSelectors());
192 }
193 
194 //////////////////////////////////////////////////////////////////////////////
195 
196 G4double G4PAIModel::MinEnergyCut(const G4ParticleDefinition*,
197           const G4MaterialCutsCouple*)
198 {
199   return fLowestTcut;
200 }
201 
202 //////////////////////////////////////////////////////////////////////////////
203 
204 G4double G4PAIModel::ComputeDEDXPerVolume(const G4Material*,
205             const G4ParticleDefinition* p,
206             G4double kineticEnergy,
207             G4double cutEnergy)
208 {  
209   G4int coupleIndex = FindCoupleIndex(CurrentCouple());
210   if(0 > coupleIndex) { return 0.0; }
211 
212   G4double cut = std::min(MaxSecondaryEnergy(p, kineticEnergy), cutEnergy);
213   G4double scaledTkin = kineticEnergy*fRatio;
214   G4double dedx = fChargeSquare*fModelData->DEDXPerVolume(coupleIndex, scaledTkin, cut);
215   return dedx;
216 }
217 
218 /////////////////////////////////////////////////////////////////////////
219 
220 G4double G4PAIModel::CrossSectionPerVolume( const G4Material*,
221               const G4ParticleDefinition* p,
222               G4double kineticEnergy,
223               G4double cutEnergy,
224               G4double maxEnergy  ) 
225 {
226   G4int coupleIndex = FindCoupleIndex(CurrentCouple());
227   if(0 > coupleIndex) { return 0.0; }
228 
229   G4double tmax = std::min(MaxSecondaryEnergy(p, kineticEnergy), maxEnergy);
230   if(tmax <= cutEnergy) { return 0.0; }
231 
232   G4double scaledTkin = kineticEnergy*fRatio;
233   G4double xs = fChargeSquare*fModelData->CrossSectionPerVolume(coupleIndex,
234                                           scaledTkin, cutEnergy, tmax);
235   return xs;
236 }
237 
238 ///////////////////////////////////////////////////////////////////////////
239 //
240 // It is analog of PostStepDoIt in terms of secondary electron.
241 //
242  
243 void G4PAIModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
244            const G4MaterialCutsCouple* matCC,
245            const G4DynamicParticle* dp,
246            G4double tmin,
247            G4double maxEnergy)
248 {
249   G4int coupleIndex = FindCoupleIndex(matCC);
250 
251   //G4cout << "G4PAIModel::SampleSecondaries: coupleIndex= "<<coupleIndex<<G4endl;
252   if(0 > coupleIndex) { return; }
253 
254   SetParticle(dp->GetDefinition());
255   G4double kineticEnergy = dp->GetKineticEnergy();
256 
257   G4double tmax = MaxSecondaryEnergy(fParticle, kineticEnergy);
258   if(maxEnergy < tmax) { tmax = maxEnergy; }
259   if(tmin >= tmax) { return; }
260 
261   G4ThreeVector direction= dp->GetMomentumDirection();
262   G4double scaledTkin    = kineticEnergy*fRatio;
263   G4double totalEnergy   = kineticEnergy + fMass;
264   G4double totalMomentum = sqrt(kineticEnergy*(totalEnergy+fMass));
265 
266   G4double deltaTkin = 
267     fModelData->SamplePostStepTransfer(coupleIndex, scaledTkin, tmin, tmax);
268 
269   //G4cout<<"G4PAIModel::SampleSecondaries; deltaKIn = "<<deltaTkin/keV
270   //  <<" keV "<< " Escaled(MeV)= " << scaledTkin << G4endl;
271 
272   if( !(deltaTkin <= 0.) && !(deltaTkin > 0)) {
273     G4cout<<"G4PAIModel::SampleSecondaries; deltaKIn = "<<deltaTkin/keV
274     <<" keV "<< " Escaled(MeV)= " << scaledTkin << G4endl;
275     return;
276   }
277   if( deltaTkin <= 0.) { return; }
278 
279   if( deltaTkin > tmax) { deltaTkin = tmax; }
280 
281   const G4Element* anElement = SelectTargetAtom(matCC, fParticle, kineticEnergy,
282                                                 dp->GetLogKineticEnergy());
283 
284   G4int Z = anElement->GetZasInt();
285  
286   auto deltaRay = new G4DynamicParticle(fElectron,
287       GetAngularDistribution()->SampleDirection(dp, deltaTkin,
288                   Z, matCC->GetMaterial()),
289                   deltaTkin);
290 
291   // primary change
292   kineticEnergy -= deltaTkin;
293   G4ThreeVector dir = totalMomentum*direction - deltaRay->GetMomentum();
294   direction = dir.unit();
295   fParticleChange->SetProposedKineticEnergy(kineticEnergy);
296   fParticleChange->SetProposedMomentumDirection(direction);
297 
298   vdp->push_back(deltaRay);
299 }
300 
301 ///////////////////////////////////////////////////////////////////////
302 
303 G4double G4PAIModel::SampleFluctuations(const G4MaterialCutsCouple* matCC,
304                                         const G4DynamicParticle* aParticle,
305                                         const G4double tcut,
306           const G4double, 
307                                         const G4double step,
308           const G4double eloss)
309 {
310   G4int coupleIndex = FindCoupleIndex(matCC);
311   if(0 > coupleIndex) { return eloss; }
312 
313   SetParticle(aParticle->GetDefinition());
314 
315   /*
316   G4cout << "G4PAIModel::SampleFluctuations step(mm)= "<< step/mm
317    << "  Eloss(keV)= " << eloss/keV  << " in " 
318    << matCC->Getmaterial()->GetName() << G4endl;
319   */
320 
321   G4double Tkin       = aParticle->GetKineticEnergy();
322   G4double scaledTkin = Tkin*fRatio;
323 
324   G4double loss = fModelData->SampleAlongStepTransfer(coupleIndex, Tkin,
325                   scaledTkin, tcut,
326                   step*fChargeSquare);
327   
328   // G4cout<<"PAIModel AlongStepLoss = "<<loss/keV<<" keV, on step = "
329   //<<step/mm<<" mm"<<G4endl; 
330   return loss;
331 
332 }
333 
334 //////////////////////////////////////////////////////////////////////
335 //
336 // Returns the statistical estimation of the energy loss distribution variance
337 //
338 
339 
340 G4double G4PAIModel::Dispersion( const G4Material* material, 
341                                  const G4DynamicParticle* aParticle,
342          const G4double tcut,
343          const G4double tmax,
344                const G4double step )
345 {
346   G4double particleMass  = aParticle->GetMass();
347   G4double electronDensity = material->GetElectronDensity();
348   G4double kineticEnergy = aParticle->GetKineticEnergy();
349   G4double q = aParticle->GetCharge()/eplus;
350   G4double etot = kineticEnergy + particleMass;
351   G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*particleMass)/(etot*etot);
352   G4double siga  = (tmax/beta2 - 0.5*tcut) * twopi_mc2_rcl2 * step
353                  * electronDensity * q * q;
354 
355   return siga;
356 }
357 
358 /////////////////////////////////////////////////////////////////////
359 
360 G4double G4PAIModel::MaxSecondaryEnergy( const G4ParticleDefinition* p,
361            G4double kinEnergy) 
362 {
363   SetParticle(p);
364   G4double tmax = kinEnergy;
365   if(p == fElectron) { tmax *= 0.5; }
366   else if(p != fPositron) { 
367     G4double ratio= electron_mass_c2/fMass;
368     G4double gamma= kinEnergy/fMass + 1.0;
369     tmax = 2.0*electron_mass_c2*(gamma*gamma - 1.) /
370                   (1. + 2.0*gamma*ratio + ratio*ratio);
371   }
372   return tmax;
373 }
374 
375 ///////////////////////////////////////////////////////////////
376 
377 void G4PAIModel::DefineForRegion(const G4Region* r) 
378 {
379   fPAIRegionVector.push_back(r);
380 }
381 
382 ///////////////////////////////////////////////////////////////
383 
384