Geant4  10.00.p02
G4INCLNuclearDensityFactory.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 // INCL++ intra-nuclear cascade model
27 // Pekka Kaitaniemi, CEA and Helsinki Institute of Physics
28 // Davide Mancusi, CEA
29 // Alain Boudard, CEA
30 // Sylvie Leray, CEA
31 // Joseph Cugnon, University of Liege
32 //
33 #define INCLXX_IN_GEANT4_MODE 1
34 
35 #include "globals.hh"
36 
38 #include "G4INCLNDFWoodsSaxon.hh"
40 #include "G4INCLNDFGaussian.hh"
41 #include "G4INCLNDFParis.hh"
42 #include "G4INCLNDFHardSphere.hh"
43 
44 namespace G4INCL {
45 
46  namespace NuclearDensityFactory {
47 
48  namespace {
49 
50  G4ThreadLocal std::map<G4int,NuclearDensity const *> *nuclearDensityCache = NULL;
51  G4ThreadLocal std::map<G4int,InverseInterpolationTable*> *rpCorrelationTableCache = NULL;
52  G4ThreadLocal std::map<G4int,InverseInterpolationTable*> *rCDFTableCache = NULL;
53  G4ThreadLocal std::map<G4int,InverseInterpolationTable*> *pCDFTableCache = NULL;
54 
55  }
56 
57  NuclearDensity const *createDensity(const G4int A, const G4int Z) {
58  if(!nuclearDensityCache)
59  nuclearDensityCache = new std::map<G4int,NuclearDensity const *>;
60 
61  const G4int nuclideID = 1000*Z + A; // MCNP-style nuclide IDs
62  const std::map<G4int,NuclearDensity const *>::const_iterator mapEntry = nuclearDensityCache->find(nuclideID);
63  if(mapEntry == nuclearDensityCache->end()) {
64  InverseInterpolationTable *rpCorrelationTableProton = createRPCorrelationTable(Proton, A, Z);
65  InverseInterpolationTable *rpCorrelationTableNeutron = createRPCorrelationTable(Neutron, A, Z);
66  if(!rpCorrelationTableProton || !rpCorrelationTableNeutron)
67  return NULL;
68  NuclearDensity const *density = new NuclearDensity(A, Z, rpCorrelationTableProton, rpCorrelationTableNeutron);
69  (*nuclearDensityCache)[nuclideID] = density;
70  return density;
71  } else {
72  return mapEntry->second;
73  }
74  }
75 
77 // assert(t==Proton || t==Neutron);
78 
79  if(!rpCorrelationTableCache)
80  rpCorrelationTableCache = new std::map<G4int,InverseInterpolationTable*>;
81 
82  const G4int nuclideID = ((t==Proton) ? 1000 : -1000)*Z + A; // MCNP-style nuclide IDs
83  const std::map<G4int,InverseInterpolationTable*>::const_iterator mapEntry = rpCorrelationTableCache->find(nuclideID);
84  if(mapEntry == rpCorrelationTableCache->end()) {
85 
86  IFunction1D *rpCorrelationFunction;
87  if(A > 19) {
89  G4double diffuseness = ParticleTable::getSurfaceDiffuseness(t, A, Z);
90  const G4double maximumRadius = ParticleTable::getMaximumNuclearRadius(t, A, Z);
91  rpCorrelationFunction = new NuclearDensityFunctions::WoodsSaxonRP(radius, maximumRadius, diffuseness);
92  } else if(A <= 19 && A > 6) {
93  const G4double radius = ParticleTable::getRadiusParameter(t, A, Z);
94  const G4double diffuseness = ParticleTable::getSurfaceDiffuseness(t, A, Z);
95  const G4double maximumRadius = ParticleTable::getMaximumNuclearRadius(t, A, Z);
96  rpCorrelationFunction = new NuclearDensityFunctions::ModifiedHarmonicOscillatorRP(radius, maximumRadius, diffuseness);
97  } else if(A <= 6 && A > 1) { // Gaussian distribution for light nuclei
98  const G4double radius = ParticleTable::getRadiusParameter(t, A, Z);
99  const G4double maximumRadius = ParticleTable::getMaximumNuclearRadius(t, A, Z);
100  rpCorrelationFunction = new NuclearDensityFunctions::GaussianRP(maximumRadius, Math::oneOverSqrtThree * radius);
101  } else {
102  INCL_ERROR("No r-p correlation function for " << ((t==Proton) ? "protons" : "neutrons") << " in A = "
103  << A << " Z = " << Z << std::endl);
104  return NULL;
105 
106  }
107 
108  class InverseCDFOneThird : public IFunction1D {
109  public:
110  InverseCDFOneThird(IFunction1D const * const f) :
111  IFunction1D(f->getXMinimum(), f->getXMaximum()),
112  theFunction(f),
113  normalisation(1./theFunction->integrate(xMin,xMax))
114  {}
115 
116  G4double operator()(const G4double x) const {
117  return Math::pow13(normalisation * theFunction->integrate(xMin,x));
118  }
119  private:
120  IFunction1D const * const theFunction;
121  const G4double normalisation;
122  } *theInverseCDFOneThird = new InverseCDFOneThird(rpCorrelationFunction);
123 
124  InverseInterpolationTable *theTable = new InverseInterpolationTable(*theInverseCDFOneThird);
125  delete theInverseCDFOneThird;
126  delete rpCorrelationFunction;
127  INCL_DEBUG("Creating r-p correlation function for " << ((t==Proton) ? "protons" : "neutrons") << " in A=" << A << ", Z=" << Z << ":"
128  << std::endl << theTable->print() << std::endl);
129 
130  (*rpCorrelationTableCache)[nuclideID] = theTable;
131  return theTable;
132  } else {
133  return mapEntry->second;
134  }
135  }
136 
138 // assert(t==Proton || t==Neutron);
139 
140  if(!rCDFTableCache)
141  rCDFTableCache = new std::map<G4int,InverseInterpolationTable*>;
142 
143  const G4int nuclideID = ((t==Proton) ? 1000 : -1000)*Z + A; // MCNP-style nuclide IDs
144  const std::map<G4int,InverseInterpolationTable*>::const_iterator mapEntry = rCDFTableCache->find(nuclideID);
145  if(mapEntry == rCDFTableCache->end()) {
146 
147  IFunction1D *rDensityFunction;
148  if(A > 19) {
150  G4double diffuseness = ParticleTable::getSurfaceDiffuseness(t, A, Z);
151  G4double maximumRadius = ParticleTable::getMaximumNuclearRadius(t, A, Z);
152  rDensityFunction = new NuclearDensityFunctions::WoodsSaxon(radius, maximumRadius, diffuseness);
153  } else if(A <= 19 && A > 6) {
155  G4double diffuseness = ParticleTable::getSurfaceDiffuseness(t, A, Z);
156  G4double maximumRadius = ParticleTable::getMaximumNuclearRadius(t, A, Z);
157  rDensityFunction = new NuclearDensityFunctions::ModifiedHarmonicOscillator(radius, maximumRadius, diffuseness);
158  } else if(A <= 6 && A > 2) { // Gaussian distribution for light nuclei
160  G4double maximumRadius = ParticleTable::getMaximumNuclearRadius(t, A, Z);
161  rDensityFunction = new NuclearDensityFunctions::Gaussian(maximumRadius, Math::oneOverSqrtThree * radius);
162  } else if(A == 2 && Z == 1) { // density from the Paris potential for deuterons
163  rDensityFunction = new NuclearDensityFunctions::ParisR();
164  } else {
165  INCL_ERROR("No nuclear density function for target A = "
166  << A << " Z = " << Z << std::endl);
167  return NULL;
168  }
169 
170  InverseInterpolationTable *theTable = rDensityFunction->inverseCDFTable();
171  delete rDensityFunction;
172  INCL_DEBUG("Creating inverse position CDF for A=" << A << ", Z=" << Z << ":" <<
173  std::endl << theTable->print() << std::endl);
174 
175  (*rCDFTableCache)[nuclideID] = theTable;
176  return theTable;
177  } else {
178  return mapEntry->second;
179  }
180  }
181 
183 // assert(t==Proton || t==Neutron);
184 
185  if(!pCDFTableCache)
186  pCDFTableCache = new std::map<G4int,InverseInterpolationTable*>;
187 
188  const G4int nuclideID = ((t==Proton) ? 1000 : -1000)*Z + A; // MCNP-style nuclide IDs
189  const std::map<G4int,InverseInterpolationTable*>::const_iterator mapEntry = pCDFTableCache->find(nuclideID);
190  if(mapEntry == pCDFTableCache->end()) {
191  IFunction1D *pDensityFunction;
192  if(A > 19) {
193  const G4double theFermiMomentum = ParticleTable::getFermiMomentum(A, Z);
194  pDensityFunction = new NuclearDensityFunctions::HardSphere(theFermiMomentum);
195  } else if(A <= 19 && A > 2) { // Gaussian distribution for light nuclei
197  pDensityFunction = new NuclearDensityFunctions::Gaussian(5.*momentumRMS, momentumRMS);
198  } else if(A == 2 && Z == 1) { // density from the Paris potential for deuterons
199  pDensityFunction = new NuclearDensityFunctions::ParisP();
200  } else {
201  INCL_ERROR("No nuclear density function for target A = "
202  << A << " Z = " << Z << std::endl);
203  return NULL;
204  }
205 
206  InverseInterpolationTable *theTable = pDensityFunction->inverseCDFTable();
207  delete pDensityFunction;
208  INCL_DEBUG("Creating inverse momentum CDF for A=" << A << ", Z=" << Z << ":" <<
209  std::endl << theTable->print() << std::endl);
210 
211  (*pCDFTableCache)[nuclideID] = theTable;
212  return theTable;
213  } else {
214  return mapEntry->second;
215  }
216  }
217 
218  void addRPCorrelationToCache(const G4int A, const G4int Z, const ParticleType t, InverseInterpolationTable * const table) {
219 // assert(t==Proton || t==Neutron);
220 
221  if(!rpCorrelationTableCache)
222  rpCorrelationTableCache = new std::map<G4int,InverseInterpolationTable*>;
223 
224  const G4int nuclideID = ((t==Proton) ? 1000 : -1000)*Z + A; // MCNP-style nuclide IDs
225  const std::map<G4int,InverseInterpolationTable*>::const_iterator mapEntry = rpCorrelationTableCache->find(nuclideID);
226  if(mapEntry != rpCorrelationTableCache->end())
227  delete mapEntry->second;
228 
229  (*rpCorrelationTableCache)[nuclideID] = table;
230  }
231 
232  void addDensityToCache(const G4int A, const G4int Z, NuclearDensity * const density) {
233  if(!nuclearDensityCache)
234  nuclearDensityCache = new std::map<G4int,NuclearDensity const *>;
235 
236  const G4int nuclideID = 1000*Z + A; // MCNP-style nuclide IDs
237  const std::map<G4int,NuclearDensity const *>::const_iterator mapEntry = nuclearDensityCache->find(nuclideID);
238  if(mapEntry != nuclearDensityCache->end())
239  delete mapEntry->second;
240 
241  (*nuclearDensityCache)[nuclideID] = density;
242  }
243 
244  void clearCache() {
245 
246  if(nuclearDensityCache) {
247  for(std::map<G4int,NuclearDensity const *>::const_iterator i = nuclearDensityCache->begin(); i!=nuclearDensityCache->end(); ++i)
248  delete i->second;
249  nuclearDensityCache->clear();
250  delete nuclearDensityCache;
251  nuclearDensityCache = NULL;
252  }
253 
254  if(rpCorrelationTableCache) {
255  for(std::map<G4int,InverseInterpolationTable*>::const_iterator i = rpCorrelationTableCache->begin(); i!=rpCorrelationTableCache->end(); ++i)
256  delete i->second;
257  rpCorrelationTableCache->clear();
258  delete rpCorrelationTableCache;
259  rpCorrelationTableCache = NULL;
260  }
261 
262  if(rCDFTableCache) {
263  for(std::map<G4int,InverseInterpolationTable*>::const_iterator i = rCDFTableCache->begin(); i!=rCDFTableCache->end(); ++i)
264  delete i->second;
265  rCDFTableCache->clear();
266  delete rCDFTableCache;
267  rCDFTableCache = NULL;
268  }
269 
270  if(pCDFTableCache) {
271  for(std::map<G4int,InverseInterpolationTable*>::const_iterator i = pCDFTableCache->begin(); i!=pCDFTableCache->end(); ++i)
272  delete i->second;
273  pCDFTableCache->clear();
274  delete pCDFTableCache;
275  pCDFTableCache = NULL;
276  }
277  }
278 
279  } // namespace NuclearDensityFactory
280 
281 } // namespace G4INCL
Class for modified harmonic oscillator density.
InverseInterpolationTable * createPCDFTable(const ParticleType t, const G4int A, const G4int Z)
#define INCL_ERROR(x)
NDF* class for the deuteron density according to the HardSphere potential.
#define G4ThreadLocal
Definition: tls.hh:52
int G4int
Definition: G4Types.hh:78
InverseInterpolationTable * inverseCDFTable(const G4int nNodes=60) const
Return a pointer to the inverse of the CDF of this function.
G4double density
Definition: TRTMaterials.hh:39
Class for Gaussian density.
NuclearDensity const * createDensity(const G4int A, const G4int Z)
static const G4double A[nN]
const G4double oneOverSqrtThree
Class for interpolating the inverse of a 1-dimensional function.
G4double getSurfaceDiffuseness(const ParticleType t, const G4int A, const G4int Z)
G4double getRadiusParameter(const ParticleType t, const G4int A, const G4int Z)
G4double getMaximumNuclearRadius(const ParticleType t, const G4int A, const G4int Z)
void addDensityToCache(const G4int A, const G4int Z, NuclearDensity *const density)
NDF* class for the deuteron density according to the Paris potential.
1D function interface
InverseInterpolationTable * createRPCorrelationTable(const ParticleType t, const G4int A, const G4int Z)
InverseInterpolationTable * createRCDFTable(const ParticleType t, const G4int A, const G4int Z)
virtual G4double getXMinimum() const
Return the minimum allowed value of the independent variable.
G4double getMomentumRMS(const G4int A, const G4int Z)
Return the RMS of the momentum distribution (light clusters)
virtual G4double getXMaximum() const
Return the maximum allowed value of the independent variable.
double G4double
Definition: G4Types.hh:76
#define INCL_DEBUG(x)
G4double pow13(G4double x)
Class for Woods-Saxon density.
void addRPCorrelationToCache(const G4int A, const G4int Z, const ParticleType t, InverseInterpolationTable *const table)
G4ThreadLocal FermiMomentumFn getFermiMomentum