Files
geant4/source/processes/hadronic/models/inclxx/utils/src/G4INCLParticleTable.cc
T
2016-12-09 12:35:28 +01:00

988 lines
33 KiB
C++

//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// INCL++ intra-nuclear cascade model
// Alain Boudard, CEA-Saclay, France
// Joseph Cugnon, University of Liege, Belgium
// Jean-Christophe David, CEA-Saclay, France
// Pekka Kaitaniemi, CEA-Saclay, France, and Helsinki Institute of Physics, Finland
// Sylvie Leray, CEA-Saclay, France
// Davide Mancusi, CEA-Saclay, France
//
#define INCLXX_IN_GEANT4_MODE 1
#include "globals.hh"
#include "G4INCLParticleTable.hh"
#include "G4INCLNuclearMassTable.hh"
#include <algorithm>
// #include <cassert>
#include <cmath>
#include <cctype>
#include <sstream>
#ifdef INCLXX_IN_GEANT4_MODE
#include "G4SystemOfUnits.hh"
#endif
#ifdef INCLXX_IN_GEANT4_MODE
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#endif
namespace G4INCL {
namespace ParticleTable {
namespace {
/// \brief Static instance of the NaturalIsotopicAbundances class
const NaturalIsotopicDistributions *theNaturalIsotopicDistributions = NULL;
const G4double theINCLNucleonMass = 938.2796;
const G4double theINCLPionMass = 138.0;
const G4double theINCLEtaMass = 547.862;
const G4double theINCLOmegaMass = 782.65;
const G4double theINCLEtaPrimeMass = 957.78;
const G4double theINCLPhotonMass = 0.0;
G4ThreadLocal G4double protonMass = 0.0;
G4ThreadLocal G4double neutronMass = 0.0;
G4ThreadLocal G4double piPlusMass = 0.0;
G4ThreadLocal G4double piMinusMass = 0.0;
G4ThreadLocal G4double piZeroMass = 0.0;
G4ThreadLocal G4double etaMass = 0.0;
G4ThreadLocal G4double omegaMass = 0.0;
G4ThreadLocal G4double etaPrimeMass = 0.0;
G4ThreadLocal G4double photonMass = 0.0;
// Hard-coded values of the real particle masses (MeV/c^2)
G4ThreadLocal G4double theRealProtonMass = 938.27203;
G4ThreadLocal G4double theRealNeutronMass = 939.56536;
G4ThreadLocal G4double theRealChargedPiMass = 139.57018;
G4ThreadLocal G4double theRealPiZeroMass = 134.9766;
G4ThreadLocal G4double theRealEtaMass = 547.862;
G4ThreadLocal G4double theRealOmegaMass = 782.65;
G4ThreadLocal G4double theRealEtaPrimeMass = 957.78;
G4ThreadLocal G4double theRealPhotonMass = 0.0;
// Width (second)
const G4double theChargedPiWidth = 2.6033e-08;
const G4double thePiZeroWidth = 8.52e-17;
const G4double theEtaWidth = 5.025e-19; // 1.31 keV
const G4double theOmegaWidth = 7.7528e-23; // 8.49 MeV
const G4double theEtaPrimeWidth = 3.3243e-21; // 0.198 MeV
G4ThreadLocal G4double piPlusWidth = 0.0;
G4ThreadLocal G4double piMinusWidth = 0.0;
G4ThreadLocal G4double piZeroWidth = 0.0;
G4ThreadLocal G4double etaWidth = 0.0;
G4ThreadLocal G4double omegaWidth = 0.0;
G4ThreadLocal G4double etaPrimeWidth = 0.0;
const G4int mediumNucleiTableSize = 30;
const G4double mediumDiffuseness[mediumNucleiTableSize] =
{0.0,0.0,0.0,0.0,0.0,1.78,1.77,1.77,1.77,1.71,
1.69,1.69,1.635,1.730,1.81,1.833,1.798,
1.841,0.567,0.571, 0.560,0.549,0.550,0.551,
0.580,0.575,0.569,0.537,0.0,0.0};
const G4double mediumRadius[mediumNucleiTableSize] =
{0.0,0.0,0.0,0.0,0.0,0.334,0.327,0.479,0.631,0.838,
0.811,1.07,1.403,1.335,1.25,1.544,1.498,1.513,
2.58,2.77, 2.775,2.78,2.88,2.98,3.22,3.03,2.84,
3.14,0.0,0.0};
const G4double positionRMS[clusterTableZSize][clusterTableASize] = {
/* A= 0 1 2 3 4 5 6 7 8 9 10 11 12 */
/* Z=0 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0},
/* Z=1 */ {-1.0, -1.0, 2.10, 1.80, 1.70, 1.83, 2.60, 2.50, -1.0, -1.0, -1.0, -1.0, -1.0},
/* Z=2 */ {-1.0, -1.0, -1.0, 1.80, 1.68, 1.70, 2.60, 2.50, 2.50, 2.50, 2.50, -1.0, -1.0},
/* Z=3 */ {-1.0, -1.0, -1.0, -1.0, 1.70, 1.83, 2.56, 2.40, 2.50, 2.50, 2.50, 2.50, 2.50},
/* Z=4 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 2.60, 2.50, 2.50, 2.51, 2.50, 2.50, 2.50},
/* Z=5 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 2.50, 2.50, 2.50, 2.50, 2.45, 2.40, 2.50},
/* Z=6 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 2.50, 2.50, 2.50, 2.50, 2.47},
/* Z=7 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 2.50, 2.50, 2.50},
/* Z=8 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 2.50}
};
const G4double momentumRMS[clusterTableZSize][clusterTableASize] = {
/* A= 0 1 2 3 4 5 6 7 8 9 10 11 12 */
/* Z=0 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0},
/* Z=1 */ {-1.0, -1.0, 77.0, 110., 153., 100., 100., 100., -1.0, -1.0, -1.0, -1.0, -1.0},
/* Z=2 */ {-1.0, -1.0, -1.0, 110., 153., 100., 100., 100., 100., 100., 100., -1.0, -1.0},
/* Z=3 */ {-1.0, -1.0, -1.0, -1.0, 153., 100., 100., 100., 100., 100., 100., 100., 100.},
/* Z=4 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 100., 100., 100., 100., 100., 100., 100.},
/* Z=5 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 100., 100., 100., 100., 100., 100., 100.},
/* Z=6 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 100., 100., 100., 100., 100.},
/* Z=7 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 100., 100., 100.},
/* Z=8 */ {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 100.}
};
const G4int elementTableSize = 113; // up to Cn
/// \brief Table of chemical element names
const std::string elementTable[elementTableSize] = {
"",
"H",
"He",
"Li",
"Be",
"B",
"C",
"N",
"O",
"F",
"Ne",
"Na",
"Mg",
"Al",
"Si",
"P",
"S",
"Cl",
"Ar",
"K",
"Ca",
"Sc",
"Ti",
"V",
"Cr",
"Mn",
"Fe",
"Co",
"Ni",
"Cu",
"Zn",
"Ga",
"Ge",
"As",
"Se",
"Br",
"Kr",
"Rb",
"Sr",
"Y",
"Zr",
"Nb",
"Mo",
"Tc",
"Ru",
"Rh",
"Pd",
"Ag",
"Cd",
"In",
"Sn",
"Sb",
"Te",
"I",
"Xe",
"Cs",
"Ba",
"La",
"Ce",
"Pr",
"Nd",
"Pm",
"Sm",
"Eu",
"Gd",
"Tb",
"Dy",
"Ho",
"Er",
"Tm",
"Yb",
"Lu",
"Hf",
"Ta",
"W",
"Re",
"Os",
"Ir",
"Pt",
"Au",
"Hg",
"Tl",
"Pb",
"Bi",
"Po",
"At",
"Rn",
"Fr",
"Ra",
"Ac",
"Th",
"Pa",
"U",
"Np",
"Pu",
"Am",
"Cm",
"Bk",
"Cf",
"Es",
"Fm",
"Md",
"No",
"Lr",
"Rf",
"Db",
"Sg",
"Bh",
"Hs",
"Mt",
"Ds",
"Rg",
"Cn"
};
/// \brief Digit names to compose IUPAC element names
const std::string elementIUPACDigits = "nubtqphsoe";
#define INCL_DEFAULT_SEPARATION_ENERGY 6.83
const G4double theINCLProtonSeparationEnergy = INCL_DEFAULT_SEPARATION_ENERGY;
const G4double theINCLNeutronSeparationEnergy = INCL_DEFAULT_SEPARATION_ENERGY;
G4ThreadLocal G4double protonSeparationEnergy = INCL_DEFAULT_SEPARATION_ENERGY;
G4ThreadLocal G4double neutronSeparationEnergy = INCL_DEFAULT_SEPARATION_ENERGY;
#undef INCL_DEFAULT_SEPARATION_ENERGY
G4ThreadLocal G4double rpCorrelationCoefficient[UnknownParticle];
G4ThreadLocal G4double neutronSkin = 0.0;
G4ThreadLocal G4double neutronHalo = 0.0;
#ifdef INCLXX_IN_GEANT4_MODE
G4ThreadLocal G4IonTable *theG4IonTable;
#endif
/// \brief Default value for constant Fermi momentum
G4ThreadLocal G4double constantFermiMomentum = 0.0;
/// \brief Transform a IUPAC char to an char representing an integer digit
char iupacToInt(char c) {
return (char)(((G4int)'0')+elementIUPACDigits.find(c));
}
/// \brief Transform an integer digit (represented by a char) to a IUPAC char
char intToIUPAC(char n) { return elementIUPACDigits.at(n); }
/// \brief Get the singleton instance of the natural isotopic distributions
const NaturalIsotopicDistributions *getNaturalIsotopicDistributions() {
if(!theNaturalIsotopicDistributions)
theNaturalIsotopicDistributions = new NaturalIsotopicDistributions;
return theNaturalIsotopicDistributions;
}
} // namespace
void initialize(Config const * const theConfig /*=0*/) {
protonMass = theINCLNucleonMass;
neutronMass = theINCLNucleonMass;
piPlusMass = theINCLPionMass;
piMinusMass = theINCLPionMass;
piZeroMass = theINCLPionMass;
etaMass = theINCLEtaMass;
omegaMass = theINCLOmegaMass;
etaPrimeMass = theINCLEtaPrimeMass;
photonMass = theINCLPhotonMass;
if(theConfig && theConfig->getUseRealMasses()) {
getTableMass = getRealMass;
getTableParticleMass = getRealMass;
} else {
getTableMass = getINCLMass;
getTableParticleMass = getINCLMass;
}
#ifndef INCLXX_IN_GEANT4_MODE
std::string dataFilePath;
if(theConfig)
dataFilePath = theConfig->getINCLXXDataFilePath();
NuclearMassTable::initialize(dataFilePath, getRealMass(Proton), getRealMass(Neutron));
#endif
#ifdef INCLXX_IN_GEANT4_MODE
G4ParticleTable *theG4ParticleTable = G4ParticleTable::GetParticleTable();
theG4IonTable = theG4ParticleTable->GetIonTable();
theRealProtonMass = theG4ParticleTable->FindParticle("proton")->GetPDGMass() / MeV;
theRealNeutronMass = theG4ParticleTable->FindParticle("neutron")->GetPDGMass() / MeV;
theRealChargedPiMass = theG4ParticleTable->FindParticle("pi+")->GetPDGMass() / MeV;
theRealPiZeroMass = theG4ParticleTable->FindParticle("pi0")->GetPDGMass() / MeV;
theRealEtaMass = theG4ParticleTable->FindParticle("eta")->GetPDGMass() / MeV;
theRealOmegaMass = theG4ParticleTable->FindParticle("omega")->GetPDGMass() / MeV;
theRealEtaPrimeMass = theG4ParticleTable->FindParticle("eta_prime")->GetPDGMass() / MeV;
theRealPhotonMass = theG4ParticleTable->FindParticle("gamma")->GetPDGMass() / MeV;
#endif
minDeltaMass = theRealNeutronMass + theRealChargedPiMass + 0.5;
minDeltaMass2 = minDeltaMass*minDeltaMass;
minDeltaMassRndm = std::atan((minDeltaMass-effectiveDeltaMass)*2./effectiveDeltaWidth);
piPlusWidth = theChargedPiWidth;
piMinusWidth = theChargedPiWidth;
piZeroWidth = thePiZeroWidth;
etaWidth = theEtaWidth;
omegaWidth = theOmegaWidth;
etaPrimeWidth = theEtaPrimeWidth;
// Initialise the separation-energy function
if(!theConfig || theConfig->getSeparationEnergyType()==INCLSeparationEnergy)
getSeparationEnergy = getSeparationEnergyINCL;
else if(theConfig->getSeparationEnergyType()==RealSeparationEnergy)
getSeparationEnergy = getSeparationEnergyReal;
else if(theConfig->getSeparationEnergyType()==RealForLightSeparationEnergy)
getSeparationEnergy = getSeparationEnergyRealForLight;
else {
INCL_FATAL("Unrecognized separation-energy type in ParticleTable initialization: " << theConfig->getSeparationEnergyType() << '\n');
return;
}
// Initialise the Fermi-momentum function
if(!theConfig || theConfig->getFermiMomentumType()==ConstantFermiMomentum) {
getFermiMomentum = ParticleTable::getFermiMomentumConstant;
if(theConfig) {
const G4double aFermiMomentum = theConfig->getFermiMomentum();
if(aFermiMomentum>0.)
constantFermiMomentum = aFermiMomentum;
else
constantFermiMomentum = PhysicalConstants::Pf;
} else {
constantFermiMomentum = PhysicalConstants::Pf;
}
} else if(theConfig->getFermiMomentumType()==ConstantLightFermiMomentum)
getFermiMomentum = ParticleTable::getFermiMomentumConstantLight;
else if(theConfig->getFermiMomentumType()==MassDependentFermiMomentum)
getFermiMomentum = ParticleTable::getFermiMomentumMassDependent;
else {
INCL_FATAL("Unrecognized Fermi-momentum type in ParticleTable initialization: " << theConfig->getFermiMomentumType() << '\n');
return;
}
// Initialise the r-p correlation coefficients
std::fill(rpCorrelationCoefficient, rpCorrelationCoefficient + UnknownParticle, 1.);
if(theConfig) {
rpCorrelationCoefficient[Proton] = theConfig->getRPCorrelationCoefficient(Proton);
rpCorrelationCoefficient[Neutron] = theConfig->getRPCorrelationCoefficient(Neutron);
}
// Initialise the neutron-skin parameters
if(theConfig) {
neutronSkin = theConfig->getNeutronSkin();
neutronHalo = theConfig->getNeutronHalo();
}
}
G4int getIsospin(const ParticleType t) {
// Actually this is the 3rd component of isospin (I_z) multiplied by 2!
if(t == Proton) {
return 1;
} else if(t == Neutron) {
return -1;
} else if(t == PiPlus) {
return 2;
} else if(t == PiMinus) {
return -2;
} else if(t == PiZero) {
return 0;
} else if(t == DeltaPlusPlus) {
return 3;
} else if(t == DeltaPlus) {
return 1;
} else if(t == DeltaZero) {
return -1;
} else if(t == DeltaMinus) {
return -3;
} else if(t == Eta) {
return 0;
} else if(t == Omega) {
return 0;
} else if(t == EtaPrime) {
return 0;
} else if(t == Photon) {
return 0;
}
INCL_ERROR("Requested isospin of an unknown particle!");
return -10; // Unknown
}
std::string getShortName(const ParticleSpecies &s) {
if(s.theType==Composite)
return getShortName(s.theA,s.theZ);
else
return getShortName(s.theType);
}
std::string getName(const ParticleSpecies &s) {
if(s.theType==Composite)
return getName(s.theA,s.theZ);
else
return getName(s.theType);
}
std::string getName(const G4int A, const G4int Z) {
std::stringstream stream;
stream << getElementName(Z) << "-" << A;
return stream.str();
}
std::string getShortName(const G4int A, const G4int Z) {
std::stringstream stream;
stream << getElementName(Z);
if(A>0)
stream << A;
return stream.str();
}
std::string getName(const ParticleType p) {
if(p == G4INCL::Proton) {
return std::string("proton");
} else if(p == G4INCL::Neutron) {
return std::string("neutron");
} else if(p == G4INCL::DeltaPlusPlus) {
return std::string("delta++");
} else if(p == G4INCL::DeltaPlus) {
return std::string("delta+");
} else if(p == G4INCL::DeltaZero) {
return std::string("delta0");
} else if(p == G4INCL::DeltaMinus) {
return std::string("delta-");
} else if(p == G4INCL::PiPlus) {
return std::string("pi+");
} else if(p == G4INCL::PiZero) {
return std::string("pi0");
} else if(p == G4INCL::PiMinus) {
return std::string("pi-");
} else if(p == G4INCL::Composite) {
return std::string("composite");
} else if(p == G4INCL::Eta) {
return std::string("eta");
} else if(p == G4INCL::Omega) {
return std::string("omega");
} else if(p == G4INCL::EtaPrime) {
return std::string("etaprime");
} else if(p == G4INCL::Photon) {
return std::string("photon");
}
return std::string("unknown");
}
std::string getShortName(const ParticleType p) {
if(p == G4INCL::Proton) {
return std::string("p");
} else if(p == G4INCL::Neutron) {
return std::string("n");
} else if(p == G4INCL::DeltaPlusPlus) {
return std::string("d++");
} else if(p == G4INCL::DeltaPlus) {
return std::string("d+");
} else if(p == G4INCL::DeltaZero) {
return std::string("d0");
} else if(p == G4INCL::DeltaMinus) {
return std::string("d-");
} else if(p == G4INCL::PiPlus) {
return std::string("pi+");
} else if(p == G4INCL::PiZero) {
return std::string("pi0");
} else if(p == G4INCL::PiMinus) {
return std::string("pi-");
} else if(p == G4INCL::Composite) {
return std::string("comp");
} else if(p == G4INCL::Eta) {
return std::string("eta");
} else if(p == G4INCL::Omega) {
return std::string("omega");
} else if(p == G4INCL::EtaPrime) {
return std::string("etap");
} else if(p == G4INCL::Photon) {
return std::string("photon");
}
return std::string("unknown");
}
G4double getINCLMass(const ParticleType pt) {
if(pt == Proton) {
return protonMass;
} else if(pt == Neutron) {
return neutronMass;
} else if(pt == PiPlus) {
return piPlusMass;
} else if(pt == PiMinus) {
return piMinusMass;
} else if(pt == PiZero) {
return piZeroMass;
} else if(pt == Eta) {
return etaMass;
} else if(pt == Omega) {
return omegaMass;
} else if(pt == EtaPrime) {
return etaPrimeMass;
} else if(pt == Photon) {
return photonMass;
} else {
INCL_ERROR("getMass : Unknown particle type." << '\n');
return 0.0;
}
}
G4double getRealMass(const ParticleType t) {
switch(t) {
case Proton:
return theRealProtonMass;
break;
case Neutron:
return theRealNeutronMass;
break;
case PiPlus:
case PiMinus:
return theRealChargedPiMass;
break;
case PiZero:
return theRealPiZeroMass;
break;
case Eta:
return theRealEtaMass;
break;
case Omega:
return theRealOmegaMass;
break;
case EtaPrime:
return theRealEtaPrimeMass;
break;
case Photon:
return theRealPhotonMass;
break;
default:
INCL_ERROR("Particle::getRealMass : Unknown particle type." << '\n');
return 0.0;
break;
}
}
G4double getRealMass(const G4int A, const G4int Z) {
// assert(A>=0);
// For nuclei with Z<0 or Z>A, assume that the exotic charge state is due to pions
if(Z<0)
return A*neutronMass - Z*getRealMass(PiMinus);
else if(Z>A)
return A*protonMass + (A-Z)*getRealMass(PiPlus);
else if(Z==0)
return A*getRealMass(Neutron);
else if(A==Z)
return A*getRealMass(Proton);
else if(A>1) {
#ifndef INCLXX_IN_GEANT4_MODE
return ::G4INCL::NuclearMassTable::getMass(A,Z);
#else
return theG4IonTable->GetNucleusMass(Z,A) / MeV;
#endif
} else
return 0.;
}
G4double getINCLMass(const G4int A, const G4int Z) {
// assert(A>=0);
// For nuclei with Z<0 or Z>A, assume that the exotic charge state is due to pions
if(Z<0)
return A*neutronMass - Z*getINCLMass(PiMinus);
else if(Z>A)
return A*protonMass + (A-Z)*getINCLMass(PiPlus);
else if(A>1)
return Z*(protonMass - protonSeparationEnergy) + (A-Z)*(neutronMass - neutronSeparationEnergy);
else if(A==1 && Z==0)
return getINCLMass(Neutron);
else if(A==1 && Z==1)
return getINCLMass(Proton);
else
return 0.;
}
G4double getTableQValue(const G4int A1, const G4int Z1, const G4int A2, const G4int Z2) {
return getTableMass(A1,Z1) + getTableMass(A2,Z2) - getTableMass(A1+A2,Z1+Z2);
}
G4double getTableQValue(const G4int A1, const G4int Z1, const G4int A2, const G4int Z2, const G4int A3, const G4int Z3) {
return getTableMass(A1,Z1) + getTableMass(A2,Z2) - getTableMass(A3,Z3) - getTableMass(A1+A2-A3,Z1+Z2-Z3);
}
G4double getTableSpeciesMass(const ParticleSpecies &p) {
if(p.theType == Composite)
return (*getTableMass)(p.theA, p.theZ);
else
return (*getTableParticleMass)(p.theType);
}
G4int getMassNumber(const ParticleType t) {
switch(t) {
case Proton:
case Neutron:
case DeltaPlusPlus:
case DeltaPlus:
case DeltaZero:
case DeltaMinus:
return 1;
break;
case PiPlus:
case PiMinus:
case PiZero:
case Eta:
case Omega:
case EtaPrime:
case Photon:
return 0;
break;
default:
return 0;
break;
}
}
G4int getChargeNumber(const ParticleType t) {
switch(t) {
case DeltaPlusPlus:
return 2;
break;
case Proton:
case DeltaPlus:
case PiPlus:
return 1;
break;
case Neutron:
case DeltaZero:
case PiZero:
case Eta:
case Omega:
case EtaPrime:
case Photon:
return 0;
break;
case DeltaMinus:
case PiMinus:
return -1;
break;
default:
return 0;
break;
}
}
G4double getNuclearRadius(const ParticleType t, const G4int A, const G4int Z) {
// assert(A>=0);
if(A >= 19 || (A < 6 && A >= 2)) {
// For large (Woods-Saxon or Modified Harmonic Oscillator) or small
// (Gaussian) nuclei, the radius parameter is just the nuclear radius
return getRadiusParameter(t,A,Z);
} else if(A < clusterTableASize && Z>=0 && Z < clusterTableZSize && A >= 6) {
const G4double thisRMS = positionRMS[Z][A];
if(thisRMS>0.0)
return thisRMS;
else {
INCL_DEBUG("getNuclearRadius: Radius for nucleus A = " << A << " Z = " << Z << " is not available" << '\n'
<< "returning radius for C12");
return positionRMS[6][12];
}
} else if(A < 19) {
const G4double theRadiusParameter = getRadiusParameter(t, A, Z);
const G4double theDiffusenessParameter = getSurfaceDiffuseness(t, A, Z);
// The formula yields the nuclear RMS radius based on the parameters of
// the nuclear-density function
return 1.225*theDiffusenessParameter*
std::sqrt((2.+5.*theRadiusParameter)/(2.+3.*theRadiusParameter));
} else {
INCL_ERROR("getNuclearRadius: No radius for nucleus A = " << A << " Z = " << Z << '\n');
return 0.0;
}
}
G4double getLargestNuclearRadius(const G4int A, const G4int Z) {
return Math::max(getNuclearRadius(Proton, A, Z), getNuclearRadius(Neutron, A, Z));
}
G4double getRadiusParameter(const ParticleType t, const G4int A, const G4int Z) {
// assert(A>0);
if(A >= 28) {
// phenomenological radius fit
G4double r0 = (2.745e-4 * A + 1.063) * std::pow(A, 1.0/3.0);
if(t==Neutron)
r0 += neutronSkin;
return r0;
} else if(A < 6 && A >= 2) {
if(Z<clusterTableZSize && Z>=0) {
const G4double thisRMS = positionRMS[Z][A];
if(thisRMS>0.0)
return thisRMS;
else {
INCL_DEBUG("getRadiusParameter: Radius for nucleus A = " << A << " Z = " << Z << " is not available" << '\n'
<< "returning radius for C12");
return positionRMS[6][12];
}
} else {
INCL_DEBUG("getRadiusParameter: Radius for nucleus A = " << A << " Z = " << Z << " is not available" << '\n'
<< "returning radius for C12");
return positionRMS[6][12];
}
} else if(A < 28 && A >= 6) {
return mediumRadius[A-1];
// return 1.581*mediumDiffuseness[A-1]*(2.+5.*mediumRadius[A-1])/(2.+3.*mediumRadius[A-1]);
} else {
INCL_ERROR("getRadiusParameter: No radius for nucleus A = " << A << " Z = " << Z << '\n');
return 0.0;
}
}
G4double getMaximumNuclearRadius(const ParticleType t, const G4int A, const G4int Z) {
const G4double XFOISA = 8.0;
if(A >= 19) {
return getNuclearRadius(t,A,Z) + XFOISA * getSurfaceDiffuseness(t,A,Z);
} else if(A < 19 && A >= 6) {
return 5.5 + 0.3 * (G4double(A) - 6.0)/12.0;
} else if(A >= 2) {
return getNuclearRadius(t, A, Z) + 4.5;
} else {
INCL_ERROR("getMaximumNuclearRadius : No maximum radius for nucleus A = " << A << " Z = " << Z << '\n');
return 0.0;
}
}
G4double getSurfaceDiffuseness(const ParticleType t, const G4int A, const G4int Z) {
if(A >= 28) {
G4double a = 1.63e-4 * A + 0.510;
if(t==Neutron)
a += neutronHalo;
return a;
} else if(A < 28 && A >= 19) {
return mediumDiffuseness[A-1];
} else if(A < 19 && A >= 6) {
return mediumDiffuseness[A-1];
} else if(A < 6 && A >= 2) {
INCL_ERROR("getSurfaceDiffuseness: was called for A = " << A << " Z = " << Z << '\n');
return 0.0;
} else {
INCL_ERROR("getSurfaceDiffuseness: No diffuseness for nucleus A = " << A << " Z = " << Z << '\n');
return 0.0;
}
}
G4double getMomentumRMS(const G4int A, const G4int Z) {
// assert(Z>=0 && A>=0 && Z<=A);
return getFermiMomentum(A,Z) * Math::sqrtThreeFifths;
}
G4double getSeparationEnergyINCL(const ParticleType t, const G4int /*A*/, const G4int /*Z*/) {
if(t==Proton)
return theINCLProtonSeparationEnergy;
else if(t==Neutron)
return theINCLNeutronSeparationEnergy;
else {
INCL_ERROR("ParticleTable::getSeparationEnergyINCL : Unknown particle type." << '\n');
return 0.0;
}
}
G4double getSeparationEnergyReal(const ParticleType t, const G4int A, const G4int Z) {
// Real separation energies for all nuclei
if(t==Proton)
return (*getTableParticleMass)(Proton) + (*getTableMass)(A-1,Z-1) - (*getTableMass)(A,Z);
else if(t==Neutron)
return (*getTableParticleMass)(Neutron) + (*getTableMass)(A-1,Z) - (*getTableMass)(A,Z);
else {
INCL_ERROR("ParticleTable::getSeparationEnergyReal : Unknown particle type." << '\n');
return 0.0;
}
}
G4double getSeparationEnergyRealForLight(const ParticleType t, const G4int A, const G4int Z) {
// Real separation energies for light nuclei, fixed values for heavy nuclei
if(Z<clusterTableZSize && A<clusterTableASize)
return getSeparationEnergyReal(t, A, Z);
else
return getSeparationEnergyINCL(t, A, Z);
}
G4double getProtonSeparationEnergy() { return protonSeparationEnergy; }
G4double getNeutronSeparationEnergy() { return neutronSeparationEnergy; }
void setProtonSeparationEnergy(const G4double s) { protonSeparationEnergy = s; }
void setNeutronSeparationEnergy(const G4double s) { neutronSeparationEnergy = s; }
std::string getElementName(const G4int Z) {
if(Z<1) {
INCL_WARN("getElementName called with Z<1" << '\n');
return elementTable[0];
} else if(Z<elementTableSize)
return elementTable[Z];
else
return getIUPACElementName(Z);
}
std::string getIUPACElementName(const G4int Z) {
std::stringstream elementStream;
elementStream << Z;
std::string elementName = elementStream.str();
std::transform(elementName.begin(), elementName.end(), elementName.begin(), intToIUPAC);
elementName[0] = std::toupper(elementName.at(0));
return elementName;
}
G4int parseElement(std::string pS) {
// Normalize the element name
std::transform(pS.begin(), pS.end(), pS.begin(), ::tolower);
pS[0] = ::toupper(pS[0]);
const std::string *iter = std::find(elementTable, elementTable+elementTableSize, pS);
if(iter != elementTable+elementTableSize)
return iter - elementTable;
else
return ParticleTable::parseIUPACElement(pS);
}
G4int parseIUPACElement(std::string const &s) {
// Normalise to lower case
std::string elementName(s);
std::transform(elementName.begin(), elementName.end(), elementName.begin(), ::tolower);
// Return 0 if the element name contains anything but IUPAC digits
if(elementName.find_first_not_of(elementIUPACDigits)!=std::string::npos)
return 0;
std::transform(elementName.begin(), elementName.end(), elementName.begin(), iupacToInt);
std::stringstream elementStream(elementName);
G4int Z;
elementStream >> Z;
return Z;
}
IsotopicDistribution const &getNaturalIsotopicDistribution(const G4int Z) {
return getNaturalIsotopicDistributions()->getIsotopicDistribution(Z);
}
G4int drawRandomNaturalIsotope(const G4int Z) {
return getNaturalIsotopicDistributions()->drawRandomIsotope(Z);
}
G4double getFermiMomentumConstant(const G4int /*A*/, const G4int /*Z*/) {
return constantFermiMomentum;
}
G4double getFermiMomentumConstantLight(const G4int A, const G4int Z) {
// assert(Z>0 && A>0 && Z<=A);
if(Z<clusterTableZSize && A<clusterTableASize) {
const G4double rms = momentumRMS[Z][A];
return ((rms>0.) ? rms : momentumRMS[6][12]) * Math::sqrtFiveThirds;
} else
return getFermiMomentumConstant(A,Z);
}
G4double getFermiMomentumMassDependent(const G4int A, const G4int /*Z*/) {
// assert(A>0);
static const G4double alphaParam = 259.416; // MeV/c
static const G4double betaParam = 152.824; // MeV/c
static const G4double gammaParam = 9.5157E-2;
return alphaParam - betaParam*std::exp(-gammaParam*((G4double)A));
}
G4double getRPCorrelationCoefficient(const ParticleType t) {
// assert(t==Proton || t==Neutron);
return rpCorrelationCoefficient[t];
}
G4double getNeutronSkin() { return neutronSkin; }
G4double getNeutronHalo() { return neutronHalo; }
G4ThreadLocal G4double minDeltaMass = 0.;
G4ThreadLocal G4double minDeltaMass2 = 0.;
G4ThreadLocal G4double minDeltaMassRndm = 0.;
G4ThreadLocal NuclearMassFn getTableMass = NULL;
G4ThreadLocal ParticleMassFn getTableParticleMass = NULL;
G4ThreadLocal SeparationEnergyFn getSeparationEnergy = NULL;
G4ThreadLocal FermiMomentumFn getFermiMomentum = NULL;
ParticleType getPionType(const G4int isosp) {
// assert(isosp == -2 || isosp == 0 || isosp == 2);
if (isosp == -2) {
return PiMinus;
}
else if (isosp == 0) {
return PiZero;
}
else {
return PiPlus;
}
}
ParticleType getNucleonType(const G4int isosp) {
// assert(isosp == -1 || isosp == 1);
if (isosp == -1) {
return Neutron;
}
else {
return Proton;
}
}
ParticleType getDeltaType(const G4int isosp) {
// assert(isosp == -3 || isosp == -1 || isosp == 1 || isosp == 3);
if (isosp == -3) {
return DeltaMinus;
}
else if (isosp == -1) {
return DeltaZero;
}
else if (isosp == 1) {
return DeltaPlus;
}
else {
return DeltaPlusPlus;
}
}
G4double getWidth(const ParticleType pt) {
// assert(pt == PiPlus || pt == PiMinus || pt == PiZero || pt == Eta || pt == Omega || pt == EtaPrime);
if(pt == PiPlus) {
return piPlusWidth;
} else if(pt == PiMinus) {
return piMinusWidth;
} else if(pt == PiZero) {
return piZeroWidth;
} else if(pt == Eta) {
return etaWidth;
} else if(pt == Omega) {
return omegaWidth;
} else if(pt == EtaPrime) {
return etaPrimeWidth;
} else {
INCL_ERROR("getWidth : Unknown particle type." << '\n');
return 0.0;
}
}
} // namespace ParticleTable
} // namespace G4INCL