Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4PAIModel.cc
Go to the documentation of this file.
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: [email protected] 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"
55#include "G4Region.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"
69#include "G4PAIModelData.hh"
70#include "G4DeltaAngle.hh"
71
72////////////////////////////////////////////////////////////////////////
73
74using namespace std;
75
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
92 fLowestTcut = 12.5*CLHEP::eV;
93}
94
95////////////////////////////////////////////////////////////////////////////
96
98{
99 if(IsMaster()) { delete fModelData; }
100}
101
102////////////////////////////////////////////////////////////////////////////
103
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 }
180 }
181}
182
183/////////////////////////////////////////////////////////////////////////
184
186 G4VEmModel* masterModel)
187{
188 fModelData = static_cast<G4PAIModel*>(masterModel)->GetPAIModelData();
189 fMaterialCutsCoupleVector =
190 static_cast<G4PAIModel*>(masterModel)->GetVectorOfCouples();
192}
193
194//////////////////////////////////////////////////////////////////////////////
195
198{
199 return fLowestTcut;
200}
201
202//////////////////////////////////////////////////////////////////////////////
203
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
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
243void 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
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
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
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
378{
379 fPAIRegionVector.push_back(r);
380}
381
382///////////////////////////////////////////////////////////////
383
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::vector< G4Material * > G4MaterialTable
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
Hep3Vector unit() const
G4double GetMass() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetCharge() const
G4double GetLogKineticEnergy() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4Electron * Electron()
Definition G4Electron.cc:91
G4int GetZasInt() const
Definition G4Element.hh:120
const G4Material * GetMaterial() const
static std::size_t GetNumberOfMaterials()
G4double GetElectronDensity() const
static G4MaterialTable * GetMaterialTable()
const G4String & GetName() const
G4double DEDXPerVolume(G4int coupleIndex, G4double scaledTkin, G4double cut) const
void Initialise(const G4MaterialCutsCouple *, G4PAIModel *)
G4double SamplePostStepTransfer(G4int coupleIndex, G4double scaledTkin, G4double tmin, G4double tmax) const
G4double SampleAlongStepTransfer(G4int coupleIndex, G4double kinEnergy, G4double scaledTkin, G4double tmax, G4double stepFactor) const
G4double CrossSectionPerVolume(G4int coupleIndex, G4double scaledTkin, G4double tcut, G4double tmax) const
void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *masterModel) final
G4PAIModelData * GetPAIModelData()
const std::vector< const G4MaterialCutsCouple * > & GetVectorOfCouples()
G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy) final
void DefineForRegion(const G4Region *r) final
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) final
G4double SampleFluctuations(const G4MaterialCutsCouple *, const G4DynamicParticle *, const G4double, const G4double, const G4double, const G4double) final
void Initialise(const G4ParticleDefinition *, const G4DataVector &) final
G4double Dispersion(const G4Material *, const G4DynamicParticle *, const G4double, const G4double, const G4double) final
G4double MaxSecondaryEnergy(const G4ParticleDefinition *, G4double kinEnergy) final
G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy, G4double maxEnergy) final
G4double MinEnergyCut(const G4ParticleDefinition *, const G4MaterialCutsCouple *couple) final
G4PAIModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="PAI")
Definition G4PAIModel.cc:76
~G4PAIModel() final
Definition G4PAIModel.cc:97
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void SetProposedMomentumDirection(const G4ThreeVector &dir)
const G4String & GetParticleName() const
static G4Positron * Positron()
Definition G4Positron.cc:90
static G4RegionStore * GetInstance()
G4MaterialCutsCouple * FindCouple(G4Material *mat)
const G4String & GetName() const
void SetElementSelectors(std::vector< G4EmElementSelector * > *)
G4VEmAngularDistribution * GetAngularDistribution()
G4double LowEnergyLimit() const
std::vector< G4EmElementSelector * > * GetElementSelectors()
G4bool IsMaster() const
G4double HighEnergyLimit() const
void SetAngularDistribution(G4VEmAngularDistribution *)
const G4MaterialCutsCouple * CurrentCouple() const
const G4Element * SelectTargetAtom(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double logKineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
void InitialiseElementSelectors(const G4ParticleDefinition *, const G4DataVector &)
G4ParticleChangeForLoss * GetParticleChangeForLoss()