source: trunk/source/processes/hadronic/cross_sections/src/G4CrossSectionDataStore.cc @ 1315

Last change on this file since 1315 was 1315, checked in by garnier, 14 years ago

update geant4-09-04-beta-cand-01 interfaces-V09-03-09 vis-V09-03-08

File size: 19.7 KB
Line 
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: G4CrossSectionDataStore.cc,v 1.18 2010/06/02 09:33:16 gunter Exp $
27// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
28//
29// -------------------------------------------------------------------
30//
31// GEANT4 Class file
32//
33//
34// File name:     G4CrossSectionDataStore
35//
36//
37// Modifications:
38// 23.01.2009 V.Ivanchenko add destruction of data sets
39// 29.04.2010 G.Folger     modifictaions for integer A & Z
40//
41//
42
43#include "G4CrossSectionDataStore.hh"
44#include "G4HadronicException.hh"
45#include "G4StableIsotopes.hh"
46#include "G4HadTmpUtil.hh"
47#include "Randomize.hh"
48#include "G4Nucleus.hh"
49
50G4CrossSectionDataStore::G4CrossSectionDataStore() :
51  NDataSetList(0), verboseLevel(0)
52{}
53
54G4CrossSectionDataStore::~G4CrossSectionDataStore()
55{}
56
57G4double
58G4CrossSectionDataStore::GetCrossSection(const G4DynamicParticle* aParticle,
59                                         const G4Element* anElement,
60                                         G4double aTemperature)
61{
62  if (NDataSetList == 0) 
63  {
64    throw G4HadronicException(__FILE__, __LINE__, 
65     "G4CrossSectionDataStore: no data sets registered");
66    return DBL_MIN;
67  }
68  for (G4int i = NDataSetList-1; i >= 0; i--) {
69    if (DataSetList[i]->IsApplicable(aParticle, anElement))
70      return DataSetList[i]->GetCrossSection(aParticle,anElement,aTemperature);
71  }
72  throw G4HadronicException(__FILE__, __LINE__, 
73                      "G4CrossSectionDataStore: no applicable data set found "
74                      "for particle/element");
75  return DBL_MIN;
76}
77
78G4VCrossSectionDataSet*
79G4CrossSectionDataStore::whichDataSetInCharge(const G4DynamicParticle* aParticle,
80                                              const G4Element* anElement)
81{
82  if (NDataSetList == 0) 
83  {
84    throw G4HadronicException(__FILE__, __LINE__, 
85     "G4CrossSectionDataStore: no data sets registered");
86    return 0;
87  }
88  for (G4int i = NDataSetList-1; i >= 0; i--) {
89    if (DataSetList[i]->IsApplicable(aParticle, anElement) )
90    {
91      return DataSetList[i];
92    }
93  }
94  throw G4HadronicException(__FILE__, __LINE__, 
95                      "G4CrossSectionDataStore: no applicable data set found "
96                      "for particle/element");
97  return 0;
98}
99
100
101G4double
102G4CrossSectionDataStore::GetCrossSection(const G4DynamicParticle* aParticle,
103                                         const G4Isotope* anIsotope,
104                                         G4double aTemperature)
105{
106  if (NDataSetList == 0) 
107  {
108    throw G4HadronicException(__FILE__, __LINE__, 
109     "G4CrossSectionDataStore: no data sets registered");
110    return DBL_MIN;
111  }
112  for (G4int i = NDataSetList-1; i >= 0; i--) {
113    if (DataSetList[i]->IsZAApplicable(aParticle, anIsotope->GetZ(), anIsotope->GetN()))
114      return DataSetList[i]->GetIsoCrossSection(aParticle,anIsotope,aTemperature);
115  }
116  throw G4HadronicException(__FILE__, __LINE__, 
117                      "G4CrossSectionDataStore: no applicable data set found "
118                      "for particle/element");
119  return DBL_MIN;
120}
121
122
123G4double
124G4CrossSectionDataStore::GetCrossSection(const G4DynamicParticle* aParticle,
125                                         G4double Z, G4double A,
126                                         G4double aTemperature)
127{
128  G4int iZ=G4lrint(Z);
129  G4int iA=G4lrint(A);
130  return GetCrossSection(aParticle, iZ, iA,aTemperature); 
131  }
132
133
134G4double
135G4CrossSectionDataStore::GetCrossSection(const G4DynamicParticle* aParticle,
136                                         G4int Z, G4int A,
137                                         G4double aTemperature)
138{
139  if (NDataSetList == 0) 
140  {
141    throw G4HadronicException(__FILE__, __LINE__, 
142     "G4CrossSectionDataStore: no data sets registered");
143    return DBL_MIN;
144  }
145  for (G4int i = NDataSetList-1; i >= 0; i--) {
146      if (DataSetList[i]->IsZAApplicable(aParticle, Z, A))
147      return DataSetList[i]->GetIsoZACrossSection(aParticle,Z,A,aTemperature);
148  }
149  throw G4HadronicException(__FILE__, __LINE__, 
150                      "G4CrossSectionDataStore: no applicable data set found "
151                      "for particle/element");
152  return DBL_MIN;
153}
154
155
156G4double
157G4CrossSectionDataStore::GetCrossSection(const G4DynamicParticle* aParticle,
158                                         const G4Material* aMaterial)
159{
160  G4double sigma(0);
161  G4double aTemp = aMaterial->GetTemperature();
162  G4int nElements = aMaterial->GetNumberOfElements();
163  const G4double* theAtomsPerVolumeVector = aMaterial->GetVecNbOfAtomsPerVolume();
164  G4double xSection(0);
165
166  for(G4int i=0; i<nElements; i++) {
167    xSection = GetCrossSection( aParticle, (*aMaterial->GetElementVector())[i], aTemp);
168    sigma += theAtomsPerVolumeVector[i] * xSection;
169  }
170
171  return sigma;
172}
173
174
175G4Element* G4CrossSectionDataStore::SampleZandA(const G4DynamicParticle* particle, 
176                                                const G4Material* aMaterial,
177                                                G4Nucleus& target)
178{
179  G4double aTemp = aMaterial->GetTemperature();
180  const G4int nElements = aMaterial->GetNumberOfElements();
181  const G4ElementVector* theElementVector = aMaterial->GetElementVector();
182  G4Element* anElement = (*theElementVector)[0];
183  G4VCrossSectionDataSet* inCharge;
184  G4int i;
185
186  // compounds
187  if(1 < nElements) {
188    G4double* xsec = new G4double [nElements];
189    const G4double* theAtomsPerVolumeVector = aMaterial->GetVecNbOfAtomsPerVolume();
190    G4double cross = 0.0;
191    for(i=0; i<nElements; i++) {
192      anElement= (*theElementVector)[i];
193      inCharge = whichDataSetInCharge(particle, anElement);
194      cross   += theAtomsPerVolumeVector[i]*
195        inCharge->GetCrossSection(particle, anElement, aTemp);
196      xsec[i]  = cross;
197    }
198    cross *= G4UniformRand();
199
200    for(i=0; i<nElements; i++) {
201      if( cross <=  xsec[i] ) {
202        anElement = (*theElementVector)[i];
203        break;
204      }
205    }
206    delete [] xsec;
207  }
208
209  // element have been selected
210  inCharge = whichDataSetInCharge(particle, anElement);
211  G4int ZZ = G4lrint(anElement->GetZ());
212  G4int AA;
213
214  // Collect abundance weighted cross sections and A values for each isotope
215  // in each element
216 
217  const G4int nIsoPerElement = anElement->GetNumberOfIsotopes();
218
219  // user-defined isotope abundances
220  if (0 < nIsoPerElement) { 
221    G4IsotopeVector* isoVector = anElement->GetIsotopeVector();
222    AA =(*isoVector)[0]->GetN();
223    if(1 < nIsoPerElement) {
224
225      G4double* xsec  = new G4double [nIsoPerElement];
226      G4double iso_xs = 0.0;
227      G4double cross  = 0.0;
228
229      G4double* abundVector = anElement->GetRelativeAbundanceVector();
230      G4bool elementXS = false;
231      for (i = 0; i<nIsoPerElement; i++) {
232        if (inCharge->IsZAApplicable(particle, ZZ,(*isoVector)[i]->GetN())) {
233          iso_xs = inCharge->GetIsoCrossSection(particle, (*isoVector)[i], aTemp);
234        } else if (elementXS == false) {
235          iso_xs = inCharge->GetCrossSection(particle, anElement, aTemp);
236          elementXS = true;
237        }
238
239        cross  += abundVector[i]*iso_xs;
240        xsec[i] = cross;
241      }
242      cross *= G4UniformRand();
243      for (i = 0; i<nIsoPerElement; i++) {
244        if(cross <= xsec[i]) {
245          AA = (*isoVector)[i]->GetN();
246          break;
247        }
248      }
249      delete [] xsec;
250    }
251    // natural abundances
252  } else { 
253
254    G4StableIsotopes theDefaultIsotopes; 
255//-- Int ZZ    G4int Z = G4int(ZZ + 0.5);
256    const G4int nIso = theDefaultIsotopes.GetNumberOfIsotopes(ZZ);
257    G4int index = theDefaultIsotopes.GetFirstIsotope(ZZ);
258    AA = theDefaultIsotopes.GetIsotopeNucleonCount(index);
259   
260    if(1 < nIso) {
261
262      G4double* xsec  = new G4double [nIso];
263      G4double iso_xs = 0.0;
264      G4double cross  = 0.0;
265      G4bool elementXS= false;
266
267      for (i = 0; i<nIso; i++) {
268        AA = theDefaultIsotopes.GetIsotopeNucleonCount(index+i);
269        if (inCharge->IsZAApplicable(particle, ZZ, AA )) {
270          iso_xs = inCharge->GetIsoZACrossSection(particle, ZZ, AA, aTemp);
271        } else if (elementXS == false) {
272          iso_xs = inCharge->GetCrossSection(particle, anElement, aTemp);
273          elementXS = true;
274        }
275        cross  += theDefaultIsotopes.GetAbundance(index+i)*iso_xs;
276        xsec[i] = cross;
277      }
278      cross *= G4UniformRand();
279      for (i = 0; i<nIso; i++) {
280        if(cross <= xsec[i]) {
281          AA = theDefaultIsotopes.GetIsotopeNucleonCount(index+i);
282          break;
283        }
284      }
285      delete [] xsec;
286    }
287  }
288  //G4cout << "XS: " << particle->GetDefinition()->GetParticleName()
289  //     << " e(GeV)= " << particle->GetKineticEnergy()/GeV
290  //     << " in " << aMaterial->GetName()
291  //     << " ZZ= " << ZZ << " AA= " << AA << "  " << anElement->GetName() << G4endl;
292
293  target.SetParameters(AA, ZZ);
294  return anElement;
295}
296
297/*
298G4Element* G4CrossSectionDataStore::SampleZandA(const G4DynamicParticle* particle,
299                                                const G4Material* aMaterial,
300                                                G4Nucleus& target)
301{
302  static G4StableIsotopes theDefaultIsotopes;  // natural abundances and
303                                               // stable isotopes
304  G4double aTemp = aMaterial->GetTemperature();
305  G4int nElements = aMaterial->GetNumberOfElements();
306  const G4ElementVector* theElementVector = aMaterial->GetElementVector();
307  const G4double* theAtomsPerVolumeVector = aMaterial->GetVecNbOfAtomsPerVolume();
308  std::vector<std::vector<G4double> > awicsPerElement;
309  std::vector<std::vector<G4double> > AvaluesPerElement;
310  G4Element* anElement;
311
312  // Collect abundance weighted cross sections and A values for each isotope
313  // in each element
314 
315  for (G4int i = 0; i < nElements; i++) {
316    anElement = (*theElementVector)[i];
317    G4int nIsoPerElement = anElement->GetNumberOfIsotopes();
318    std::vector<G4double> isoholder;
319    std::vector<G4double> aholder;
320    G4double iso_xs = DBL_MIN;
321
322    if (nIsoPerElement) { // user-defined isotope abundances
323      G4IsotopeVector* isoVector = anElement->GetIsotopeVector();
324      G4double* abundVector = anElement->GetRelativeAbundanceVector();
325      G4VCrossSectionDataSet* inCharge = whichDataSetInCharge(particle, anElement);
326      G4bool elementXS = false;
327      for (G4int j = 0; j < nIsoPerElement; j++) {
328        if (inCharge->IsZAApplicable(particle, (*isoVector)[j]->GetZ(),
329                                               (*isoVector)[j]->GetN() ) ) {
330          iso_xs = inCharge->GetIsoCrossSection(particle, (*isoVector)[j], aTemp);
331        } else if (elementXS == false) {
332          iso_xs = inCharge->GetCrossSection(particle, anElement, aTemp);
333          elementXS = true;
334        }
335
336        isoholder.push_back(abundVector[j]*iso_xs);
337        aholder.push_back(G4double((*isoVector)[j]->GetN()));
338      }
339
340    } else { // natural abundances
341      G4int ZZ = G4lrint(anElement->GetZ());
342      nIsoPerElement = theDefaultIsotopes.GetNumberOfIsotopes(ZZ);
343      G4int index = theDefaultIsotopes.GetFirstIsotope(ZZ);
344      G4double AA;
345      G4double abundance;
346
347      G4VCrossSectionDataSet* inCharge = whichDataSetInCharge(particle, anElement);
348      G4bool elementXS = false;
349
350      for (G4int j = 0; j < nIsoPerElement; j++) {
351        AA = G4double(theDefaultIsotopes.GetIsotopeNucleonCount(index+j));
352        aholder.push_back(AA);
353        if (inCharge->IsZAApplicable(particle, G4double(ZZ), AA) ) {
354          iso_xs = inCharge->GetIsoZACrossSection(particle, G4double(ZZ), AA, aTemp);
355        } else if (elementXS == false) {
356          iso_xs = inCharge->GetCrossSection(particle, anElement, aTemp);
357          elementXS = true;
358        }
359        abundance = theDefaultIsotopes.GetAbundance(index+j)/100.0;
360        isoholder.push_back(abundance*iso_xs);
361      }
362    }
363
364    awicsPerElement.push_back(isoholder);
365    AvaluesPerElement.push_back(aholder);
366  }
367
368  // Calculate running sums for isotope selection
369
370  G4double crossSectionTotal = 0;
371  G4double xSectionPerElement;
372  std::vector<G4double> runningSum;
373
374  for (G4int i=0; i < nElements; i++) {
375    xSectionPerElement = 0;
376    for (G4int j=0; j < G4int(awicsPerElement[i].size()); j++)
377                     xSectionPerElement += awicsPerElement[i][j];
378    runningSum.push_back(theAtomsPerVolumeVector[i]*xSectionPerElement);
379    crossSectionTotal += runningSum[i];
380  }
381
382  // Compare random number to running sum over element xc to choose Z
383
384  // Initialize Z and A to first element and first isotope in case
385  // cross section is zero
386   
387  anElement = (*theElementVector)[0];
388  G4double ZZ = anElement->GetZ();
389  G4double AA = AvaluesPerElement[0][0];
390  if (crossSectionTotal != 0.) {
391    G4double random = G4UniformRand();
392    for(G4int i=0; i < nElements; i++) {
393      if(i!=0) runningSum[i] += runningSum[i-1];
394      if(random <= runningSum[i]/crossSectionTotal) {
395        anElement = (*theElementVector)[i];
396        ZZ = anElement->GetZ();
397
398        // Compare random number to running sum over isotope xc to choose A
399
400        G4int nIso = awicsPerElement[i].size();
401        G4double* running = new G4double[nIso];
402        for (G4int j=0; j < nIso; j++) {
403          running[j] = awicsPerElement[i][j];
404          if(j!=0) running[j] += running[j-1];
405        }
406
407        G4double trial = G4UniformRand();
408        for (G4int j=0; j < nIso; j++) {
409          AA = AvaluesPerElement[i][j];
410          if (trial <= running[j]/running[nIso-1]) break;
411        }
412        delete [] running;
413        break;
414      }
415    }
416  }
417
418  //G4cout << "XS: " << particle->GetDefinition()->GetParticleName()
419  //     << " e(GeV)= " << particle->GetKineticEnergy()/GeV
420  //     << " in " << aMaterial->GetName()
421  //     << " ZZ= " << ZZ << " AA= " << AA << "  " << anElement->GetName() << G4endl;
422
423  target.SetParameters(AA, ZZ);
424  return anElement;
425}
426
427std::pair<G4double, G4double>
428G4CrossSectionDataStore::SelectRandomIsotope(const G4DynamicParticle* particle,
429                                             const G4Material* aMaterial)
430{
431  static G4StableIsotopes theDefaultIsotopes;  // natural abundances and
432                                               // stable isotopes
433  G4double aTemp = aMaterial->GetTemperature();
434  G4int nElements = aMaterial->GetNumberOfElements();
435  const G4ElementVector* theElementVector = aMaterial->GetElementVector();
436  const G4double* theAtomsPerVolumeVector = aMaterial->GetVecNbOfAtomsPerVolume();
437  std::vector<std::vector<G4double> > awicsPerElement;
438  std::vector<std::vector<G4double> > AvaluesPerElement;
439  G4Element* anElement;
440
441  // Collect abundance weighted cross sections and A values for each isotope
442  // in each element
443 
444  for (G4int i = 0; i < nElements; i++) {
445    anElement = (*theElementVector)[i];
446    G4int nIsoPerElement = anElement->GetNumberOfIsotopes();
447    std::vector<G4double> isoholder;
448    std::vector<G4double> aholder;
449    G4double iso_xs = DBL_MIN;
450
451    if (nIsoPerElement) { // user-defined isotope abundances
452      G4IsotopeVector* isoVector = anElement->GetIsotopeVector();
453      G4double* abundVector = anElement->GetRelativeAbundanceVector();
454      G4VCrossSectionDataSet* inCharge = whichDataSetInCharge(particle, anElement);
455      G4bool elementXS = false;
456      for (G4int j = 0; j < nIsoPerElement; j++) {
457        if (inCharge->IsZAApplicable(particle, (*isoVector)[j]->GetZ(),
458                                               (*isoVector)[j]->GetN() ) ) {
459          iso_xs = inCharge->GetIsoCrossSection(particle, (*isoVector)[j], aTemp);
460        } else if (elementXS == false) {
461          iso_xs = inCharge->GetCrossSection(particle, anElement, aTemp);
462          elementXS = true;
463        }
464
465        isoholder.push_back(abundVector[j]*iso_xs);
466        aholder.push_back(G4double((*isoVector)[j]->GetN()));
467      }
468
469    } else { // natural abundances
470      G4int ZZ = G4lrint(anElement->GetZ());
471      nIsoPerElement = theDefaultIsotopes.GetNumberOfIsotopes(ZZ);
472      G4int index = theDefaultIsotopes.GetFirstIsotope(ZZ);
473      G4double AA;
474      G4double abundance;
475
476      G4VCrossSectionDataSet* inCharge = whichDataSetInCharge(particle, anElement);
477      G4bool elementXS = false;
478
479      for (G4int j = 0; j < nIsoPerElement; j++) {
480        AA = G4double(theDefaultIsotopes.GetIsotopeNucleonCount(index+j));
481        aholder.push_back(AA);
482        if (inCharge->IsZAApplicable(particle, G4double(ZZ), AA) ) {
483          iso_xs = inCharge->GetIsoZACrossSection(particle, G4double(ZZ), AA, aTemp);
484        } else if (elementXS == false) {
485          iso_xs = inCharge->GetCrossSection(particle, anElement, aTemp);
486          elementXS = true;
487        }
488        abundance = theDefaultIsotopes.GetAbundance(index+j)/100.0;
489        isoholder.push_back(abundance*iso_xs);
490      }
491    }
492
493    awicsPerElement.push_back(isoholder);
494    AvaluesPerElement.push_back(aholder);
495  }
496
497  // Calculate running sums for isotope selection
498
499  G4double crossSectionTotal = 0;
500  G4double xSectionPerElement;
501  std::vector<G4double> runningSum;
502
503  for (G4int i=0; i < nElements; i++) {
504    xSectionPerElement = 0;
505    for (G4int j=0; j < G4int(awicsPerElement[i].size()); j++)
506                     xSectionPerElement += awicsPerElement[i][j];
507    runningSum.push_back(theAtomsPerVolumeVector[i]*xSectionPerElement);
508    crossSectionTotal += runningSum[i];
509  }
510
511  // Compare random number to running sum over element xc to choose Z
512
513  // Initialize Z and A to first element and first isotope in case
514  // cross section is zero
515   
516  G4double ZZ = (*theElementVector)[0]->GetZ();
517  G4double AA = AvaluesPerElement[0][0];
518  if (crossSectionTotal != 0.) {
519    G4double random = G4UniformRand();
520    for(G4int i=0; i < nElements; i++) {
521      if(i!=0) runningSum[i] += runningSum[i-1];
522      if(random <= runningSum[i]/crossSectionTotal) {
523        ZZ = ((*theElementVector)[i])->GetZ();
524
525        // Compare random number to running sum over isotope xc to choose A
526
527        G4int nIso = awicsPerElement[i].size();
528        G4double* running = new G4double[nIso];
529        for (G4int j=0; j < nIso; j++) {
530          running[j] = awicsPerElement[i][j];
531          if(j!=0) running[j] += running[j-1];
532        }
533
534        G4double trial = G4UniformRand();
535        for (G4int j=0; j < nIso; j++) {
536          AA = AvaluesPerElement[i][j];
537          if (trial <= running[j]/running[nIso-1]) break;
538        }
539        delete [] running;
540        break;
541      }
542    }
543  }
544  return std::pair<G4double, G4double>(ZZ, AA);
545}
546*/
547
548void
549G4CrossSectionDataStore::AddDataSet(G4VCrossSectionDataSet* aDataSet)
550{
551  DataSetList.push_back(aDataSet);
552  NDataSetList++;
553}
554
555void
556G4CrossSectionDataStore::
557BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
558{
559  if(NDataSetList > 0) {
560    for (G4int i=0; i<NDataSetList; i++) {
561      DataSetList[i]->BuildPhysicsTable(aParticleType);
562    } 
563  }
564}
565
566
567void
568G4CrossSectionDataStore::
569DumpPhysicsTable(const G4ParticleDefinition& aParticleType)
570{
571  if (NDataSetList == 0) {
572    G4cout << "WARNING - G4CrossSectionDataStore::DumpPhysicsTable: "
573           << " no data sets registered"<<G4endl;
574    return;
575  }
576  for (G4int i = NDataSetList-1; i >= 0; i--) {
577    DataSetList[i]->DumpPhysicsTable(aParticleType);
578  }
579}
Note: See TracBrowser for help on using the repository browser.