Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4LossTableBuilder.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// GEANT4 Class file
29//
30//
31// File name: G4LossTableBuilder
32//
33// Author: Vladimir Ivanchenko
34//
35// Creation date: 03.01.2002
36//
37// Modifications:
38//
39// 23-01-03 V.Ivanchenko Cut per region
40// 21-07-04 V.Ivanchenko Fix problem of range for dedx=0
41// 08-11-04 Migration to new interface of Store/Retrieve tables (V.Ivanchenko)
42// 07-12-04 Fix of BuildDEDX table (V.Ivanchenko)
43// 27-03-06 Add bool options isIonisation (V.Ivanchenko)
44// 16-01-07 Fill new (not old) DEDX table (V.Ivanchenko)
45// 12-02-07 Use G4LPhysicsFreeVector for the inverse range table (V.Ivanchenko)
46// 24-06-09 Removed hidden bin in G4PhysicsVector (V.Ivanchenko)
47//
48// Class Description:
49//
50// -------------------------------------------------------------------
51//
52//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
53//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
54
55#include "G4LossTableBuilder.hh"
56#include "G4SystemOfUnits.hh"
57#include "G4PhysicsTable.hh"
58#include "G4PhysicsLogVector.hh"
63#include "G4Material.hh"
64#include "G4VEmModel.hh"
66#include "G4LossTableManager.hh"
67#include "G4EmParameters.hh"
68
69std::vector<G4double>* G4LossTableBuilder::theDensityFactor = nullptr;
70std::vector<G4int>* G4LossTableBuilder::theDensityIdx = nullptr;
71std::vector<G4bool>* G4LossTableBuilder::theFlag = nullptr;
72#ifdef G4MULTITHREADED
73 G4Mutex G4LossTableBuilder::ltbMutex = G4MUTEX_INITIALIZER;
74#endif
75
76//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
77
79{
80 theParameters = G4EmParameters::Instance();
81 splineFlag = true;
82 isInitialized = false;
83 if(isMaster || !theFlag) {
84#ifdef G4MULTITHREADED
85 G4MUTEXLOCK(&ltbMutex);
86 if(isMaster || !theFlag) {
87#endif
88 isMaster = true;
89 theDensityFactor = new std::vector<G4double>;
90 theDensityIdx = new std::vector<G4int>;
91 theFlag = new std::vector<G4bool>;
92 } else {
93 isMaster = false;
94#ifdef G4MULTITHREADED
95 }
96 G4MUTEXUNLOCK(&ltbMutex);
97#endif
98 }
99}
100
101//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
102
104{
105 if(isMaster) {
106 delete theDensityFactor;
107 delete theDensityIdx;
108 delete theFlag;
109 theDensityFactor = nullptr;
110 theDensityIdx = nullptr;
111 theFlag = nullptr;
112 }
113}
114
115//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
116
117const std::vector<G4int>* G4LossTableBuilder::GetCoupleIndexes() const
118{
119 return theDensityIdx;
120}
121
122//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
123
124const std::vector<G4double>* G4LossTableBuilder::GetDensityFactors() const
125{
126 return theDensityFactor;
127}
128
129//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
130
132{
133 if(theFlag->empty()) { InitialiseBaseMaterials(); }
134 return (idx < theFlag->size()) ? (*theFlag)[idx] : false;
135}
136
137//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
138
139void
141 const std::vector<G4PhysicsTable*>& list)
142{
143 InitialiseBaseMaterials(dedxTable);
144 size_t n_processes = list.size();
145 //G4cout << "Nproc= " << n_processes << " Ncoup= "
146 //<< dedxTable->size() << G4endl;
147 if(1 >= n_processes) { return; }
148
149 size_t nCouples = dedxTable->size();
150 if(0 >= nCouples) { return; }
151
152 for (size_t i=0; i<nCouples; ++i) {
153 G4PhysicsLogVector* pv0 = static_cast<G4PhysicsLogVector*>((*(list[0]))[i]);
154 if(pv0) {
155 size_t npoints = pv0->GetVectorLength();
157 pv->SetSpline(splineFlag);
158 for (size_t j=0; j<npoints; ++j) {
159 G4double dedx = 0.0;
160 for (size_t k=0; k<n_processes; ++k) {
161 G4PhysicsVector* pv1 = (*(list[k]))[i];
162 dedx += (*pv1)[j];
163 }
164 pv->PutValue(j, dedx);
165 }
166 if(splineFlag) { pv->FillSecondDerivatives(); }
168 }
169 }
170}
171
172//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
173
175 G4PhysicsTable* rangeTable,
176 G4bool useBM)
177// Build range table from the energy loss table
178{
179 size_t nCouples = dedxTable->size();
180 if(0 >= nCouples) { return; }
181
182 size_t n = 100;
183 G4double del = 1.0/(G4double)n;
184
185 for (size_t i=0; i<nCouples; ++i) {
186 G4PhysicsLogVector* pv = static_cast<G4PhysicsLogVector*>((*dedxTable)[i]);
187 if((pv == nullptr) || (useBM && !(*theFlag)[i])) { continue; }
188 size_t npoints = pv->GetVectorLength();
189 size_t bin0 = 0;
190 G4double elow = pv->Energy(0);
191 G4double ehigh = pv->Energy(npoints-1);
192 G4double dedx1 = (*pv)[0];
193
194 //G4cout << "i= " << i << "npoints= " << npoints << " dedx1= "
195 //<< dedx1 << G4endl;
196
197 // protection for specific cases dedx=0
198 if(dedx1 == 0.0) {
199 for (size_t k=1; k<npoints; ++k) {
200 ++bin0;
201 elow = pv->Energy(k);
202 dedx1 = (*pv)[k];
203 if(dedx1 > 0.0) { break; }
204 }
205 npoints -= bin0;
206 }
207 //G4cout<<"New Range vector" << G4endl;
208 //G4cout<<"nbins= "<<npoints-1<<" elow= "<<elow<<" ehigh= "<<ehigh
209 // <<" bin0= " << bin0 <<G4endl;
210
211 // initialisation of a new vector
212 if(npoints < 2) { npoints = 2; }
213
214 delete (*rangeTable)[i];
216 if(0 == bin0) { v = new G4PhysicsLogVector(*pv); }
217 else { v = new G4PhysicsLogVector(elow, ehigh, npoints-1); }
218
219 // dedx is exact zero cannot build range table
220 if(2 == npoints) {
221 v->PutValue(0,1000.);
222 v->PutValue(1,2000.);
224 return;
225 }
226 v->SetSpline(splineFlag);
227
228 // assumed dedx proportional to beta
229 G4double energy1 = v->Energy(0);
230 G4double range = 2.*energy1/dedx1;
231 //G4cout << "range0= " << range << G4endl;
232 v->PutValue(0,range);
233
234 for (size_t j=1; j<npoints; ++j) {
235
236 G4double energy2 = v->Energy(j);
237 G4double de = (energy2 - energy1) * del;
238 G4double energy = energy2 + de*0.5;
239 G4double sum = 0.0;
240 //G4cout << "j= " << j << " e1= " << energy1 << " e2= " << energy2
241 // << " n= " << n << G4endl;
242 for (size_t k=0; k<n; ++k) {
243 energy -= de;
244 dedx1 = pv->Value(energy);
245 if(dedx1 > 0.0) { sum += de/dedx1; }
246 }
247 range += sum;
248 v->PutValue(j,range);
249 energy1 = energy2;
250 }
251 if(splineFlag) { v->FillSecondDerivatives(); }
253 }
254}
255
256//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
257
258void
260 G4PhysicsTable* invRangeTable,
261 G4bool useBM)
262// Build inverse range table from the energy loss table
263{
264 size_t nCouples = rangeTable->size();
265 if(0 >= nCouples) { return; }
266
267 for (size_t i=0; i<nCouples; ++i) {
268 G4PhysicsVector* pv = (*rangeTable)[i];
269 if((pv == nullptr) || (useBM && !(*theFlag)[i])) { continue; }
270 size_t npoints = pv->GetVectorLength();
271 G4double rlow = (*pv)[0];
272 G4double rhigh = (*pv)[npoints-1];
273
274 delete (*invRangeTable)[i];
275 G4LPhysicsFreeVector* v = new G4LPhysicsFreeVector(npoints,rlow,rhigh);
276 v->SetSpline(splineFlag);
277
278 for (size_t j=0; j<npoints; ++j) {
279 G4double e = pv->Energy(j);
280 G4double r = (*pv)[j];
281 v->PutValues(j,r,e);
282 }
283 if(splineFlag) { v->FillSecondDerivatives(); }
284
285 G4PhysicsTableHelper::SetPhysicsVector(invRangeTable, i, v);
286 }
287}
288
289//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
290
292{
293 if(!isMaster) { return; }
294 const G4ProductionCutsTable* theCoupleTable=
296 size_t nCouples = theCoupleTable->GetTableSize();
297 size_t nFlags = theFlag->size();
298 if(isInitialized && nFlags == nCouples) { return; }
299
300 isInitialized = true;
301 if(0 == nFlags) {
302 theDensityFactor->reserve(nCouples);
303 theDensityIdx->reserve(nCouples);
304 theFlag->reserve(nCouples);
305 }
306 for(size_t i=0; i<nFlags; ++i) {
307 (*theFlag)[i] = (table) ? table->GetFlag(i) : true;
308 }
309 for(size_t i=nFlags; i<nCouples; ++i) {
310 G4bool yes = (table) ? table->GetFlag(i) : true;
311 theDensityFactor->push_back(1.0);
312 theDensityIdx->push_back(i);
313 theFlag->push_back(yes);
314 }
315 // use base materials
316 for(size_t i=0; i<nCouples; ++i) {
317 // base material is needed only for a couple which is not
318 // initialised and for which tables will be computed
319 auto couple = theCoupleTable->GetMaterialCutsCouple(i);
320 auto pcuts = couple->GetProductionCuts();
321 auto mat = couple->GetMaterial();
322 auto bmat = mat->GetBaseMaterial();
323
324 // base material exists - find it and check if it can be reused
325 if(bmat) {
326 for(size_t j=0; j<nCouples; ++j) {
327 if(j == i) { continue; }
328 auto bcouple = theCoupleTable->GetMaterialCutsCouple(j);
329
330 if(bcouple->GetMaterial() == bmat &&
331 bcouple->GetProductionCuts() == pcuts) {
332
333 // based couple exist in the same region
334 (*theDensityFactor)[i] = mat->GetDensity()/bmat->GetDensity();
335 (*theDensityIdx)[i] = j;
336 (*theFlag)[i] = false;
337
338 // ensure that there will no double initialisation
339 (*theDensityFactor)[j] = 1.0;
340 (*theDensityIdx)[j] = j;
341 (*theFlag)[j] = true;
342 break;
343 }
344 }
345 }
346 }
347 /*
348 for(size_t i=0; i<nCouples; ++i) {
349 G4cout << "CoupleIdx= " << i << " Flag= " << theFlag[i]
350 << " TableFlag= " << table->GetFlag(i) << " "
351 << theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial()->GetName()
352 << G4endl;
353 }
354 */
355}
356
357//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
358
361 G4VEmModel* model,
362 const G4ParticleDefinition* part,
363 G4double emin, G4double emax,
364 G4bool spline)
365{
366 // check input
368 if(!table) { return table; }
369 if(emin >= emax) {
370 table->clearAndDestroy();
371 delete table;
372 table = nullptr;
373 return table;
374 }
376 G4int nbins = theParameters->NumberOfBinsPerDecade();
377 G4bool useMB = model->UseBaseMaterials();
378
379 // Access to materials
380 const G4ProductionCutsTable* theCoupleTable=
382 size_t numOfCouples = theCoupleTable->GetTableSize();
383
384 G4PhysicsLogVector* aVector = nullptr;
385
386 for(size_t i=0; i<numOfCouples; ++i) {
387 if ((useMB && GetFlag(i)) || (!useMB && table->GetFlag(i))) {
388
389 // create physics vector and fill it
390 auto couple = theCoupleTable->GetMaterialCutsCouple(i);
391 delete (*table)[i];
392
393 // if start from zero then change the scale
394
395 const G4Material* mat = couple->GetMaterial();
396
397 G4double tmin = std::max(emin,model->MinPrimaryEnergy(mat,part));
398 if(0.0 >= tmin) { tmin = CLHEP::eV; }
399 G4int n = nbins;
400
401 if(tmin >= emax) {
402 aVector = nullptr;
403 } else {
404 n *= (G4int)(std::log10(emax/tmin) + 0.5);
405 n = std::max(n, 3);
406 aVector = new G4PhysicsLogVector(tmin, emax, n);
407 }
408
409 if(aVector) {
410 aVector->SetSpline(spline);
411 //G4cout << part->GetParticleName() << " in " << mat->GetName()
412 // << " tmin= " << tmin << G4endl;
413 for(G4int j=0; j<=n; ++j) {
414 aVector->PutValue(j, model->Value(couple, part,
415 aVector->Energy(j)));
416 }
417 if(spline) { aVector->FillSecondDerivatives(); }
418 }
420 }
421 }
422 /*
423 G4cout << "G4LossTableBuilder::BuildTableForModel done for "
424 << part->GetParticleName() << " and "<< model->GetName()
425 << " " << table << G4endl;
426 */
427 return table;
428}
429
430//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
431
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:85
#define G4MUTEXLOCK(mutex)
Definition: G4Threading.hh:251
#define G4MUTEXUNLOCK(mutex)
Definition: G4Threading.hh:254
std::mutex G4Mutex
Definition: G4Threading.hh:81
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
static G4EmParameters * Instance()
G4int NumberOfBinsPerDecade() const
void PutValues(std::size_t index, G4double e, G4double dataValue)
void BuildInverseRangeTable(const G4PhysicsTable *rangeTable, G4PhysicsTable *invRangeTable, G4bool useBM=false)
void BuildRangeTable(const G4PhysicsTable *dedxTable, G4PhysicsTable *rangeTable, G4bool useBM=false)
void BuildDEDXTable(G4PhysicsTable *dedxTable, const std::vector< G4PhysicsTable * > &)
const std::vector< G4double > * GetDensityFactors() const
const std::vector< G4int > * GetCoupleIndexes() const
void InitialiseBaseMaterials(const G4PhysicsTable *table=nullptr)
G4PhysicsTable * BuildTableForModel(G4PhysicsTable *table, G4VEmModel *model, const G4ParticleDefinition *, G4double emin, G4double emax, G4bool spline)
G4bool GetFlag(size_t idx)
G4LossTableBuilder(G4bool master=true)
G4ProductionCuts * GetProductionCuts() const
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
Definition: G4Material.cc:651
static G4PhysicsTable * PreparePhysicsTable(G4PhysicsTable *physTable)
static void SetPhysicsVector(G4PhysicsTable *physTable, std::size_t idx, G4PhysicsVector *vec)
void clearAndDestroy()
G4bool GetFlag(std::size_t i) const
G4double Energy(std::size_t index) const
G4double Value(G4double theEnergy, std::size_t &lastidx) const
void PutValue(std::size_t index, G4double theValue)
void FillSecondDerivatives()
void SetSpline(G4bool)
std::size_t GetVectorLength() const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
virtual G4double MinPrimaryEnergy(const G4Material *, const G4ParticleDefinition *, G4double cut=0.0)
Definition: G4VEmModel.cc:424
virtual G4double Value(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy)
Definition: G4VEmModel.cc:415
G4bool UseBaseMaterials() const
Definition: G4VEmModel.hh:750