ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4INCLNuclearMassTable.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4INCLNuclearMassTable.cc
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 // Alain Boudard, CEA-Saclay, France
28 // Joseph Cugnon, University of Liege, Belgium
29 // Jean-Christophe David, CEA-Saclay, France
30 // Pekka Kaitaniemi, CEA-Saclay, France, and Helsinki Institute of Physics, Finland
31 // Sylvie Leray, CEA-Saclay, France
32 // Davide Mancusi, CEA-Saclay, France
33 //
34 #define INCLXX_IN_GEANT4_MODE 1
35 
36 #include "globals.hh"
37 
45 #ifndef INCLXX_IN_GEANT4_MODE
46 
48 #include "G4INCLParticleTable.hh"
49 #include "G4INCLGlobals.hh"
50 #include <algorithm>
51 #include <istream>
52 
53 namespace G4INCL {
54 
55  namespace {
56 
57  G4ThreadLocal G4double **theTable = NULL;
58  G4ThreadLocal G4int AMax = 0;
59  G4ThreadLocal G4int *ZMaxArray = NULL;
60  G4ThreadLocal G4double protonMass = 0.;
61  G4ThreadLocal G4double neutronMass = 0.;
62 
63  const G4double amu = 931.494061; // atomic mass unit in MeV/c^2
64  const G4double eMass = 0.5109988; // electron mass in MeV/c^2
65 
66  G4double getWeizsaeckerMass(const G4int A, const G4int Z) {
67  const G4int Npairing = (A-Z)%2; // pairing
68  const G4int Zpairing = Z%2;
69  const G4double fA = (G4double) A;
70  const G4double fZ = (G4double) Z;
72  - 15.67*fA // nuclear volume
73  + 17.23*Math::pow23(fA) // surface energy
74  + 93.15*((fA/2.-fZ)*(fA/2.-fZ))/fA // asymmetry
75  + 0.6984523*fZ*fZ*Math::powMinus13(fA); // coulomb
76  if( Npairing == Zpairing ) binding += (Npairing+Zpairing-1) * 12.0 / std::sqrt(fA); // pairing
77 
80  }
81 
82  void setMass(const G4int A, const G4int Z, const G4double mass) {
83  theTable[A][Z] = mass;
84  }
85 
86  class MassRecord {
87  public:
88  MassRecord() :
89  A(0),
90  Z(0),
91  excess(0.)
92  {}
93 
94  MassRecord(const G4int a, const G4int z, const G4double e) :
95  A(a),
96  Z(z),
97  excess(e)
98  {}
99 
100  friend std::istream &operator>>(std::istream &in, MassRecord &record);
101 
102  G4int A;
103  G4int Z;
104  G4double excess;
105  };
106 
107  std::istream &operator>>(std::istream &in, MassRecord &record) {
108  return (in >> record.A >> record.Z >> record.excess);
109  }
110 
111  G4bool compareA(const MassRecord &lhs, const MassRecord &rhs) {
112  return (lhs.A < rhs.A);
113  }
114 
115  }
116 
117  namespace NuclearMassTable {
118 
119  void initialize(const std::string &path, const G4double pMass, const G4double nMass) {
120  protonMass = pMass;
121  neutronMass = nMass;
122 
123  // Clear the existing tables, if any
124  deleteTable();
125 
126  // File name
127  std::string fileName(path + "/walletlifetime.dat");
128  INCL_DEBUG("Reading real nuclear masses from file " << fileName << '\n');
129 
130  // Open the file stream
131  std::ifstream massTableIn(fileName.c_str());
132  if(!massTableIn.good()) {
133  std::cerr << "Cannot open " << fileName << " data file." << '\n';
134  std::abort();
135  return;
136  }
137 
138  // read the file
139  std::vector<MassRecord> records;
140  MassRecord record;
141  while(massTableIn.good()) { /* Loop checking, 10.07.2015, D.Mancusi */
142  massTableIn >> record;
143  records.push_back(record);
144  }
145  massTableIn.close();
146  INCL_DEBUG("Read " << records.size() << " nuclear masses" << '\n');
147 
148  // determine the max A
149  AMax = std::max_element(records.begin(), records.end(), compareA)->A;
150  INCL_DEBUG("Max A in nuclear-mass table = " << AMax << '\n');
151  ZMaxArray = new G4int[AMax+1];
152  std::fill(ZMaxArray, ZMaxArray+AMax+1, 0);
153  theTable = new G4double*[AMax+1];
154  std::fill(theTable, theTable+AMax+1, static_cast<G4double*>(NULL));
155 
156  // determine the max A per Z
157  for(std::vector<MassRecord>::const_iterator i=records.begin(), e=records.end(); i!=e; ++i) {
158  ZMaxArray[i->A] = std::max(ZMaxArray[i->A], i->Z);
159  }
160 
161  // allocate the arrays
162  for(G4int A=1; A<=AMax; ++A) {
163  theTable[A] = new G4double[ZMaxArray[A]+1];
164  std::fill(theTable[A], theTable[A]+ZMaxArray[A]+1, -1.);
165  }
166 
167  // fill the actual masses
168  for(std::vector<MassRecord>::const_iterator i=records.begin(), e=records.end(); i!=e; ++i) {
169  setMass(i->A, i->Z, i->A*amu + i->excess - i->Z*eMass);
170  }
171  }
172 
173  G4double getMass(const G4int A, const G4int Z) {
174  if(A>AMax || Z>ZMaxArray[A]) {
175  INCL_DEBUG("Real mass unavailable for isotope A=" << A << ", Z=" << Z
176  << ", using Weizsaecker's formula"
177  << '\n');
178  return getWeizsaeckerMass(A,Z);
179  }
180 
181  const G4double mass = theTable[A][Z];
182  if(mass<0.) {
183  INCL_DEBUG("Real mass unavailable for isotope A=" << A << ", Z=" << Z
184  << ", using Weizsaecker's formula"
185  << '\n');
186  return getWeizsaeckerMass(A,Z);
187  } else
188  return mass;
189  }
190 
191  G4double getMass(const G4int A, const G4int Z, const G4int S){
192  if(S>=0) return getMass(A,Z);
193 
194 // assert(A >= 1);
195 // assert(Z < A);
196 // assert(S*(-1)<=A);
197 
198  const G4double mL = ParticleTable::getRealMass(Lambda); // mLambda
199  if(A == (-1)*S) return A*mL;
200 
201  if( A==2 && Z == 0) { // No stable hypernuclei with A=2
203  }
204  else if( Z == 0) { // No stable hypernuclei with Z=0
206  }
207  else if( A==2 && Z == 1) {
209  }
210 
211 
212  const G4double b7=25.; // (MeV)
213  const G4double b8=10.5; // Slope
214  const G4double a2=0.13; // BindingEnergy for d+Lambda(MeV)
215  const G4double a3=2.2; // BindingEnergy for (t/He3)+Lamb(MeV)
216  const G4double eps =0.0001; // security value (MeV)
217 
218  G4double mass = getMass(A+S, Z);
219 
220  G4double bs=0.;
221  if (A+S ==2) bs=a2; // for nnL,npL,ppL
222  else if(A+S ==3) bs=a3; // for 3nL,2npL,n2pL,3pL
223  else if(A+S >3) bs=b7*std::exp(-b8/(A+S+1.));
224  mass += (-1)*S*(mL-bs) + eps;
225 
226  return mass;
227  }
228 
229  void deleteTable() {
230  delete[] ZMaxArray;
231  ZMaxArray = NULL;
232  for(G4int A=1; A<=AMax; ++A)
233  delete[] theTable[A];
234  delete[] theTable;
235  theTable = NULL;
236  }
237  }
238 
239 }
240 
241 #endif // INCLXX_IN_GEANT4_MODE