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