Import Geant4 10.5.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2018-06-29 10:58:11 +02:00
parent fe81a77428
commit 6aa23be517
1581 changed files with 124288 additions and 83758 deletions
@@ -14,6 +14,30 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
20 Mar 2018 - A.Ribon (hadr-cohe-V10-04-01)
--------------------------------------------------------
- Set to 100.0 TeV (instead of 1 TeV) the upper limit of applicability
for the model G4DiffuseElastic and G4DiffuseElasticV2
(the number of equally-sized logarithmic energy bins has been increased
from 200 to 250 to keep the same bin size (0.04) ).
The model has been validated with experimental data up to 300 GeV,
but it should not give meaningless results well above this energy.
14 Dec 2017 - A.Ribon (hadr-cohe-V10-04-00)
--------------------------------------------------------
- Re-tag of the previous tag (incorrectly named).
- Grichine's update of G4hhElastic to take into account the recent
TOTEM data for proton-proton at 13 TeV.
24 November 2017 - W. Pokorski (hadr-cohe-V10-03-07)
--------------------------------------------------------
- Added new class G4DiffuseElasticV2. The underlying physics model is
the same as in G4DiffuseElastic by V.Grichine, however, the code has been
revised, cleanup and significantly improved in a number of places.
The performance has been improved by the factor of ~2 with respect to the
original implementation. The approximation of small angles has been droped
(replaced by exact calculation) as it was not bringing any visible benefits.
19 Oct 2017 - A.Ribon (hadr-cohe-V10-03-06)
--------------------------------------------------------
- G4NuclNuclDiffuseElastic : Grichine's simplification of this class to
@@ -0,0 +1,438 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// $Id: G4DiffuseElasticV2.hh 94676 2015-12-02 09:51:20Z gunter $
//
// Author: V. Grichine (Vladimir,Grichine@cern.ch)
//
//
// G4 Model: diffuse optical elastic scattering with 4-momentum balance
//
// Class Description
// Final state production model for hadron nuclear elastic scattering;
// Class Description - End
//
//
// 24.05.07 V. Grichine, first implementation for hadron (no Coulomb) elastic scattering
// 04.09.07 V. Grichine, implementation for Coulomb elastic scattering
// 12.06.11 V. Grichine, new interface to G4hadronElastic
// 24.11.17 W. Pokorski, code cleanup and performance improvements
#ifndef G4DiffuseElasticV2_h
#define G4DiffuseElasticV2_h 1
#include <CLHEP/Units/PhysicalConstants.h>
#include "globals.hh"
#include "G4HadronElastic.hh"
#include "G4HadProjectile.hh"
#include "G4Nucleus.hh"
#include "G4Pow.hh"
#include <vector>
class G4ParticleDefinition;
class G4PhysicsTable;
class G4PhysicsLogVector;
class G4DiffuseElasticV2 : public G4HadronElastic // G4HadronicInteraction
{
public:
G4DiffuseElasticV2();
virtual ~G4DiffuseElasticV2();
virtual G4bool IsApplicable(const G4HadProjectile &/*aTrack*/,
G4Nucleus & /*targetNucleus*/);
void Initialise();
void InitialiseOnFly(G4double Z, G4double A);
void BuildAngleTable();
virtual G4double SampleInvariantT(const G4ParticleDefinition* p,
G4double plab,
G4int Z, G4int A);
G4double NeutronTuniform(G4int Z);
void SetPlabLowLimit(G4double value);
void SetHEModelLowLimit(G4double value);
void SetQModelLowLimit(G4double value);
void SetLowestEnergyLimit(G4double value);
void SetRecoilKinEnergyLimit(G4double value);
G4double SampleTableT(const G4ParticleDefinition* aParticle,
G4double p, G4double Z, G4double A);
G4double SampleThetaCMS(const G4ParticleDefinition* aParticle, G4double p, G4double A);
G4double SampleTableThetaCMS(const G4ParticleDefinition* aParticle, G4double p,
G4double Z, G4double A);
G4double GetScatteringAngle(G4int iMomentum, unsigned long iAngle, G4double position);
G4double SampleThetaLab(const G4HadProjectile* aParticle,
G4double tmass, G4double A);
G4double CalculateZommerfeld( G4double beta, G4double Z1, G4double Z2 );
G4double CalculateAm( G4double momentum, G4double n, G4double Z);
G4double CalculateNuclearRad( G4double A);
G4double ThetaCMStoThetaLab(const G4DynamicParticle* aParticle,
G4double tmass, G4double thetaCMS);
G4double ThetaLabToThetaCMS(const G4DynamicParticle* aParticle,
G4double tmass, G4double thetaLab);
G4double BesselJzero(G4double z);
G4double BesselJone(G4double z);
G4double DampFactor(G4double z);
G4double BesselOneByArg(G4double z);
G4double GetDiffElasticSumProbA(G4double alpha);
G4double GetIntegrandFunction(G4double theta);
G4double GetNuclearRadius(){return fNuclearRadius;};
private:
G4ParticleDefinition* theProton;
G4ParticleDefinition* theNeutron;
G4double lowEnergyRecoilLimit;
G4double lowEnergyLimitHE;
G4double lowEnergyLimitQ;
G4double lowestEnergyLimit;
G4double plabLowLimit;
G4int fEnergyBin;
unsigned long fAngleBin;
G4PhysicsLogVector* fEnergyVector;
std::vector<std::vector<std::vector<double>*>*> fEnergyAngleVectorBank;
std::vector<std::vector<std::vector<double>*>*> fEnergySumVectorBank;
std::vector<std::vector<double>*>* fEnergyAngleVector;
std::vector<std::vector<double>*>* fEnergySumVector;
std::vector<G4double> fElementNumberVector;
std::vector<G4String> fElementNameVector;
const G4ParticleDefinition* fParticle;
G4double fWaveVector;
G4double fAtomicWeight;
G4double fAtomicNumber;
G4double fNuclearRadius;
G4double fBeta;
G4double fZommerfeld;
G4double fAm;
G4bool fAddCoulomb;
};
inline G4bool G4DiffuseElasticV2::IsApplicable(const G4HadProjectile & projectile,
G4Nucleus & nucleus)
{
if( ( projectile.GetDefinition() == G4Proton::Proton() ||
projectile.GetDefinition() == G4Neutron::Neutron() ||
projectile.GetDefinition() == G4PionPlus::PionPlus() ||
projectile.GetDefinition() == G4PionMinus::PionMinus() ||
projectile.GetDefinition() == G4KaonPlus::KaonPlus() ||
projectile.GetDefinition() == G4KaonMinus::KaonMinus() ) &&
nucleus.GetZ_asInt() >= 2 ) return true;
else return false;
}
inline void G4DiffuseElasticV2::SetRecoilKinEnergyLimit(G4double value)
{
lowEnergyRecoilLimit = value;
}
inline void G4DiffuseElasticV2::SetPlabLowLimit(G4double value)
{
plabLowLimit = value;
}
inline void G4DiffuseElasticV2::SetHEModelLowLimit(G4double value)
{
lowEnergyLimitHE = value;
}
inline void G4DiffuseElasticV2::SetQModelLowLimit(G4double value)
{
lowEnergyLimitQ = value;
}
inline void G4DiffuseElasticV2::SetLowestEnergyLimit(G4double value)
{
lowestEnergyLimit = value;
}
/////////////////////////////////////////////////////////////
//
// Bessel J0 function based on rational approximation from
// J.F. Hart, Computer Approximations, New York, Willey 1968, p. 141
inline G4double G4DiffuseElasticV2::BesselJzero(G4double value)
{
G4double modvalue, value2, fact1, fact2, arg, shift, bessel;
modvalue = std::fabs(value);
if ( value < 8.0 && value > -8.0 )
{
value2 = value*value;
fact1 = 57568490574.0 + value2*(-13362590354.0
+ value2*( 651619640.7
+ value2*(-11214424.18
+ value2*( 77392.33017
+ value2*(-184.9052456 ) ) ) ) );
fact2 = 57568490411.0 + value2*( 1029532985.0
+ value2*( 9494680.718
+ value2*(59272.64853
+ value2*(267.8532712
+ value2*1.0 ) ) ) );
bessel = fact1/fact2;
}
else
{
arg = 8.0/modvalue;
value2 = arg*arg;
shift = modvalue-0.785398164;
fact1 = 1.0 + value2*(-0.1098628627e-2
+ value2*(0.2734510407e-4
+ value2*(-0.2073370639e-5
+ value2*0.2093887211e-6 ) ) );
fact2 = -0.1562499995e-1 + value2*(0.1430488765e-3
+ value2*(-0.6911147651e-5
+ value2*(0.7621095161e-6
- value2*0.934945152e-7 ) ) );
bessel = std::sqrt(0.636619772/modvalue)*(std::cos(shift)*fact1 - arg*std::sin(shift)*fact2 );
}
return bessel;
}
/////////////////////////////////////////////////////////////
//
// Bessel J1 function based on rational approximation from
// J.F. Hart, Computer Approximations, New York, Willey 1968, p. 141
inline G4double G4DiffuseElasticV2::BesselJone(G4double value)
{
G4double modvalue, value2, fact1, fact2, arg, shift, bessel;
modvalue = std::fabs(value);
if ( modvalue < 8.0 )
{
value2 = value*value;
fact1 = value*(72362614232.0 + value2*(-7895059235.0
+ value2*( 242396853.1
+ value2*(-2972611.439
+ value2*( 15704.48260
+ value2*(-30.16036606 ) ) ) ) ) );
fact2 = 144725228442.0 + value2*(2300535178.0
+ value2*(18583304.74
+ value2*(99447.43394
+ value2*(376.9991397
+ value2*1.0 ) ) ) );
bessel = fact1/fact2;
}
else
{
arg = 8.0/modvalue;
value2 = arg*arg;
shift = modvalue - 2.356194491;
fact1 = 1.0 + value2*( 0.183105e-2
+ value2*(-0.3516396496e-4
+ value2*(0.2457520174e-5
+ value2*(-0.240337019e-6 ) ) ) );
fact2 = 0.04687499995 + value2*(-0.2002690873e-3
+ value2*( 0.8449199096e-5
+ value2*(-0.88228987e-6
+ value2*0.105787412e-6 ) ) );
bessel = std::sqrt( 0.636619772/modvalue)*(std::cos(shift)*fact1 - arg*std::sin(shift)*fact2);
if (value < 0.0) bessel = -bessel;
}
return bessel;
}
////////////////////////////////////////////////////////////////////
//
// damp factor in diffraction x/sh(x), x was already *pi
inline G4double G4DiffuseElasticV2::DampFactor(G4double x)
{
G4double df;
G4double f2 = 2., f3 = 6., f4 = 24.; // first factorials
// x *= pi;
if( std::fabs(x) < 0.01 )
{
df = 1./(1. + x/f2 + x*x/f3 + x*x*x/f4);
}
else
{
df = x/std::sinh(x);
}
return df;
}
////////////////////////////////////////////////////////////////////
//
// return J1(x)/x with special case for small x
inline G4double G4DiffuseElasticV2::BesselOneByArg(G4double x)
{
G4double x2, result;
if( std::fabs(x) < 0.01 )
{
x *= 0.5;
x2 = x*x;
result = 2. - x2 + x2*x2/6.;
}
else
{
result = BesselJone(x)/x;
}
return result;
}
////////////////////////////////////////////////////////////////////
//
// return Zommerfeld parameter for Coulomb scattering
inline G4double G4DiffuseElasticV2::CalculateZommerfeld( G4double beta, G4double Z1, G4double Z2 )
{
fZommerfeld = CLHEP::fine_structure_const*Z1*Z2/beta;
return fZommerfeld;
}
////////////////////////////////////////////////////////////////////
//
// return Wentzel correction for Coulomb scattering
inline G4double G4DiffuseElasticV2::CalculateAm( G4double momentum, G4double n, G4double Z)
{
G4double k = momentum/CLHEP::hbarc;
G4double ch = 1.13 + 3.76*n*n;
G4double zn = 1.77*k*(1.0/G4Pow::GetInstance()->A13(Z))*CLHEP::Bohr_radius;
G4double zn2 = zn*zn;
fAm = ch/zn2;
return fAm;
}
////////////////////////////////////////////////////////////////////
//
// calculate nuclear radius for different atomic weights using different approximations
inline G4double G4DiffuseElasticV2::CalculateNuclearRad( G4double A)
{
G4double R, r0, a11, a12, a13, a2, a3;
a11 = 1.26; // 1.08, 1.16
a12 = 1.; // 1.08, 1.16
a13 = 1.12; // 1.08, 1.16
a2 = 1.1;
a3 = 1.;
// Special rms radii for light nucleii
if (A < 50.)
{
if (std::abs(A-1.) < 0.5) return 0.89*CLHEP::fermi; // p
else if(std::abs(A-2.) < 0.5) return 2.13*CLHEP::fermi; // d
else if( // std::abs(Z-1.) < 0.5 &&
std::abs(A-3.) < 0.5) return 1.80*CLHEP::fermi; // t
// else if(std::abs(Z-2.) < 0.5 && std::abs(A-3.) < 0.5) return 1.96CLHEP::fermi; // He3
else if( // std::abs(Z-2.) < 0.5 &&
std::abs(A-4.) < 0.5) return 1.68*CLHEP::fermi; // He4
else if( // std::abs(Z-3.) < 0.5
std::abs(A-7.) < 0.5 ) return 2.40*CLHEP::fermi; // Li7
else if( // std::abs(Z-4.) < 0.5
std::abs(A-9.) < 0.5) return 2.51*CLHEP::fermi; // Be9
else if( 10. < A && A <= 16. ) r0 = a11*( 1 - (1.0/G4Pow::GetInstance()->A23(A)) )*CLHEP::fermi; // 1.08CLHEP::fermi;
else if( 15. < A && A <= 20. ) r0 = a12*( 1 - (1.0/G4Pow::GetInstance()->A23(A)) )*CLHEP::fermi;
else if( 20. < A && A <= 30. ) r0 = a13*( 1 - (1.0/G4Pow::GetInstance()->A23(A)) )*CLHEP::fermi;
else r0 = a2*CLHEP::fermi;
R = r0*G4Pow::GetInstance()->A13(A);
}
else
{
r0 = a3*CLHEP::fermi;
R = r0*G4Pow::GetInstance()->powA(A, 0.27);
}
fNuclearRadius = R;
return R;
}
#endif
@@ -244,7 +244,7 @@ private:
G4int fInTkin;
G4double fOldTkin;
static const G4double theNuclNuclData[18][6];
static const G4double theNuclNuclData[19][6];
static const G4double thePiKaNuclData[8][6];
G4HadronNucleonXsc* fHadrNuclXsc;
};
@@ -368,9 +368,9 @@ inline void G4hhElastic::SetParametersCMS(G4double plab)
}
else // in approximation between array points
{
for( i = 0; i < 18; i++ ) if( sCMS <= theNuclNuclData[i][0]*CLHEP::GeV ) break;
for( i = 0; i < 19; i++ ) if( sCMS <= theNuclNuclData[i][0]*CLHEP::GeV ) break;
if( i == 0 ) i++;
if( i == 18 ) i--;
if( i == 19 ) i--;
sl = theNuclNuclData[i-1][0]*CLHEP::GeV;
sh = theNuclNuclData[i][0]*CLHEP::GeV;
@@ -11,7 +11,7 @@
#
# Generated on : 24/9/2010
#
# $Id: sources.cmake 104408 2017-05-30 07:14:50Z gcosmo $
# $Id: sources.cmake 107965 2017-12-14 13:13:33Z gcosmo $
#
#------------------------------------------------------------------------------
@@ -50,6 +50,7 @@ GEANT4_DEFINE_MODULE(NAME G4hadronic_coherent_elastic
G4ChargeExchange.hh
G4ChargeExchangeProcess.hh
G4DiffuseElastic.hh
G4DiffuseElasticV2.hh
G4ElasticHadrNucleusHE.hh
G4HadronElastic.hh
G4LEHadronProtonElastic.hh
@@ -68,6 +69,7 @@ GEANT4_DEFINE_MODULE(NAME G4hadronic_coherent_elastic
G4ChargeExchange.cc
G4ChargeExchangeProcess.cc
G4DiffuseElastic.cc
G4DiffuseElasticV2.cc
G4ElasticHadrNucleusHE.cc
G4HadronElastic.cc
G4LEHadronProtonElastic.cc
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DiffuseElastic.cc 93440 2015-10-22 14:11:41Z gcosmo $
// $Id: G4DiffuseElastic.cc 108978 2018-03-20 13:10:24Z gcosmo $
//
//
// Physics model class G4DiffuseElastic
@@ -75,7 +75,7 @@ G4DiffuseElastic::G4DiffuseElastic()
: G4HadronElastic("DiffuseElastic"), fParticle(0)
{
SetMinEnergy( 0.01*MeV ); // 0.01*GeV );
SetMaxEnergy( 1.*TeV );
SetMaxEnergy( 100.*TeV ); // 1.*TeV
verboseLevel = 0;
lowEnergyRecoilLimit = 100.*keV;
@@ -91,7 +91,8 @@ G4DiffuseElastic::G4DiffuseElastic()
thePionPlus = G4PionPlus::PionPlus();
thePionMinus = G4PionMinus::PionMinus();
fEnergyBin = 200;
fEnergyBin = 250; // Increased from 200 to 250 to keep the same bin size when extending
// the upper limit of validity of the model from 1 TeV to 100 TeV.
fAngleBin = 200;
fEnergyVector = new G4PhysicsLogVector( theMinEnergy, theMaxEnergy, fEnergyBin );
@@ -1074,7 +1075,7 @@ void G4DiffuseElastic::BuildAngleTable()
sum += delta;
angleVector->PutValue( j-1 , alpha1, sum ); // alpha2
// G4cout<<"j-1 = "<<j-1<<"; alpha2 = "<<alpha2<<"; sum = "<<sum<<G4endl;
// G4cout<<"j-1 = "<<j-1<<"; alpha2 = "<<alpha2 << " delta "<< delta <<"; sum = "<<sum<<G4endl;
}
fAngleTable->insertAt(i, angleVector);
@@ -0,0 +1,656 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// $Id: G4DiffuseElasticV2.cc 93440 2015-10-22 14:11:41Z gcosmo $
//
//
// Physics model class G4DiffuseElasticV2
//
//
// G4 Model: optical diffuse elastic scattering with 4-momentum balance
//
// 24-May-07 V. Grichine
//
// 21.10.15 V. Grichine
// Bug fixed in BuildAngleTable, improving accuracy for
// angle bins at high energies > 50 GeV for pions.
//
// 24.11.17 W. Pokorski, code cleanup and performance improvements
//
#include "G4DiffuseElasticV2.hh"
#include "G4ParticleTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4IonTable.hh"
#include "G4NucleiProperties.hh"
#include "Randomize.hh"
#include "G4Integrator.hh"
#include "globals.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4Proton.hh"
#include "G4Neutron.hh"
#include "G4Deuteron.hh"
#include "G4Alpha.hh"
#include "G4PionPlus.hh"
#include "G4PionMinus.hh"
#include "G4Element.hh"
#include "G4ElementTable.hh"
#include "G4NistManager.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsLogVector.hh"
#include "G4PhysicsFreeVector.hh"
#include "G4Exp.hh"
/////////////////////////////////////////////////////////////////////////
//
G4DiffuseElasticV2::G4DiffuseElasticV2()
: G4HadronElastic("DiffuseElasticV2"), fParticle(0)
{
SetMinEnergy( 0.01*MeV );
SetMaxEnergy( 100.*TeV );
verboseLevel = 0;
lowEnergyRecoilLimit = 100.*keV;
lowEnergyLimitQ = 0.0*GeV;
lowEnergyLimitHE = 0.0*GeV;
lowestEnergyLimit = 0.0*keV;
plabLowLimit = 20.0*MeV;
theProton = G4Proton::Proton();
theNeutron = G4Neutron::Neutron();
fEnergyBin = 250; // Increased from 200 to 250 to keep the same bin size when extending
// the upper limit of validity of the model from 1 TeV to 100 TeV.
fAngleBin = 200;
fEnergyVector = new G4PhysicsLogVector( theMinEnergy, theMaxEnergy, fEnergyBin );
fEnergyAngleVector = 0;
fEnergySumVector = 0;
fParticle = 0;
fWaveVector = 0.;
fAtomicWeight = 0.;
fAtomicNumber = 0.;
fNuclearRadius = 0.;
fBeta = 0.;
fZommerfeld = 0.;
fAm = 0.;
fAddCoulomb = false;
}
//////////////////////////////////////////////////////////////////////////////
//
// Destructor
G4DiffuseElasticV2::~G4DiffuseElasticV2()
{
if ( fEnergyVector )
{
delete fEnergyVector;
fEnergyVector = 0;
}
}
//////////////////////////////////////////////////////////////////////////////
//
// Initialisation for given particle using element table of application
void G4DiffuseElasticV2::Initialise()
{
const G4ElementTable* theElementTable = G4Element::GetElementTable();
size_t jEl, numOfEl = G4Element::GetNumberOfElements();
for( jEl = 0; jEl < numOfEl; ++jEl) // application element loop
{
fAtomicNumber = (*theElementTable)[jEl]->GetZ(); // atomic number
fAtomicWeight = G4NistManager::Instance()->GetAtomicMassAmu( static_cast< G4int >( fAtomicNumber ) );
fNuclearRadius = CalculateNuclearRad(fAtomicWeight);
if( verboseLevel > 0 )
{
G4cout<<"G4DiffuseElasticV2::Initialise() the element: "
<<(*theElementTable)[jEl]->GetName()<<G4endl;
}
fElementNumberVector.push_back(fAtomicNumber);
fElementNameVector.push_back((*theElementTable)[jEl]->GetName());
BuildAngleTable();
fEnergyAngleVectorBank.push_back(fEnergyAngleVector);
fEnergySumVectorBank.push_back(fEnergySumVector);
}
return;
}
////////////////////////////////////////////////////////////////////////////
//
// return differential elastic probability d(probability)/d(t) with
// Coulomb correction. It is called from BuildAngleTable()
G4double
G4DiffuseElasticV2::GetDiffElasticSumProbA( G4double theta )
{
G4double sigma, bzero, bzero2, bonebyarg, bonebyarg2, damp, damp2;
G4double delta, diffuse, gamma;
G4double e1, e2, bone, bone2;
// G4double wavek = momentum/hbarc; // wave vector
// G4double r0 = 1.08*fermi;
// G4double rad = r0*G4Pow::GetInstance()->A13(A);
G4double kr = fWaveVector*fNuclearRadius; // wavek*rad;
G4double kr2 = kr*kr;
G4double krt = kr*theta;
bzero = BesselJzero(krt);
bzero2 = bzero*bzero;
bone = BesselJone(krt);
bone2 = bone*bone;
bonebyarg = BesselOneByArg(krt);
bonebyarg2 = bonebyarg*bonebyarg;
if ( fParticle == theProton )
{
diffuse = 0.63*fermi;
gamma = 0.3*fermi;
delta = 0.1*fermi*fermi;
e1 = 0.3*fermi;
e2 = 0.35*fermi;
}
else if ( fParticle == theNeutron )
{
diffuse = 0.63*fermi;
gamma = 0.3*fermi;
delta = 0.1*fermi*fermi;
e1 = 0.3*fermi;
e2 = 0.35*fermi;
}
else // as proton, if were not defined
{
diffuse = 0.63*fermi;
gamma = 0.3*fermi;
delta = 0.1*fermi*fermi;
e1 = 0.3*fermi;
e2 = 0.35*fermi;
}
G4double lambda = 15; // 15 ok
// G4double kgamma = fWaveVector*gamma; // wavek*delta;
G4double kgamma = lambda*(1.-G4Exp(-fWaveVector*gamma/lambda)); // wavek*delta;
if( fAddCoulomb ) // add Coulomb correction
{
G4double sinHalfTheta = std::sin(0.5*theta);
G4double sinHalfTheta2 = sinHalfTheta*sinHalfTheta;
kgamma += 0.5*fZommerfeld/kr/(sinHalfTheta2+fAm); // correction at J0()
}
G4double kgamma2 = kgamma*kgamma;
// G4double dk2t = delta*fWaveVector*fWaveVector*theta; // delta*wavek*wavek*theta;
// G4double dk2t2 = dk2t*dk2t;
// G4double pikdt = pi*fWaveVector*diffuse*theta;// pi*wavek*diffuse*theta;
G4double pikdt = lambda*(1. - G4Exp( -pi*fWaveVector*diffuse*theta/lambda ) ); // wavek*delta;
damp = DampFactor( pikdt );
damp2 = damp*damp;
G4double mode2k2 = ( e1*e1 + e2*e2 )*fWaveVector*fWaveVector;
G4double e2dk3t = -2.*e2*delta*fWaveVector*fWaveVector*fWaveVector*theta;
sigma = kgamma2;
// sigma += dk2t2;
sigma *= bzero2;
sigma += mode2k2*bone2;
sigma += e2dk3t*bzero*bone;
// sigma += kr2*(1 + 8.*fZommerfeld*fZommerfeld/kr2)*bonebyarg2; // correction at J1()/()
sigma += kr2*bonebyarg2; // correction at J1()/()
sigma *= damp2; // *rad*rad;
return sigma;
}
////////////////////////////////////////////////////////////////////////////
//
// return differential elastic probability 2*pi*sin(theta)*d(probability)/d(omega)
G4double
G4DiffuseElasticV2::GetIntegrandFunction( G4double alpha )
{
G4double result;
result = GetDiffElasticSumProbA(alpha) * 2 * CLHEP::pi * std::sin(alpha);
return result;
}
/////////////////////////////////////////////////////////////////////////////
///////////////////// Table preparation and reading ////////////////////////
////////////////////////////////////////////////////////////////////////////
//
// Return inv momentum transfer -t > 0 from initialisation table
G4double G4DiffuseElasticV2::SampleInvariantT( const G4ParticleDefinition* aParticle, G4double p,
G4int Z, G4int A)
{
fParticle = aParticle;
G4double m1 = fParticle->GetPDGMass(), t;
G4double totElab = std::sqrt(m1*m1+p*p);
G4double mass2 = G4NucleiProperties::GetNuclearMass(A, Z);
G4LorentzVector lv1(p,0.0,0.0,totElab);
G4LorentzVector lv(0.0,0.0,0.0,mass2);
lv += lv1;
G4ThreeVector bst = lv.boostVector();
lv1.boost(-bst);
G4ThreeVector p1 = lv1.vect();
G4double momentumCMS = p1.mag();
if( aParticle == theNeutron)
{
G4double Tmax = NeutronTuniform( Z );
G4double pCMS2 = momentumCMS*momentumCMS;
G4double Tkin = std::sqrt(pCMS2+m1*m1)-m1;
if( Tkin <= Tmax )
{
t = 4.*pCMS2*G4UniformRand();
return t;
}
}
t = SampleTableT( aParticle, momentumCMS, G4double(Z), G4double(A) ); // sample theta in cms
return t;
}
///////////////////////////////////////////////////////
G4double G4DiffuseElasticV2::NeutronTuniform(G4int Z)
{
G4double elZ = G4double(Z);
elZ -= 1.;
G4double Tkin = 12.*G4Exp(-elZ/10.) + 1.;
return Tkin;
}
////////////////////////////////////////////////////////////////////////////
//
// Return inv momentum transfer -t > 0 from initialisation table
G4double G4DiffuseElasticV2::SampleTableT( const G4ParticleDefinition* aParticle, G4double p,
G4double Z, G4double A)
{
G4double alpha = SampleTableThetaCMS( aParticle, p, Z, A); // sample theta in cms
G4double t = 2*p*p*( 1 - std::cos(alpha) ); // -t !!!
return t;
}
////////////////////////////////////////////////////////////////////////////
//
// Return scattering angle2 sampled in cms according to precalculated table.
G4double
G4DiffuseElasticV2::SampleTableThetaCMS(const G4ParticleDefinition* particle,
G4double momentum, G4double Z, G4double A)
{
size_t iElement;
G4int iMomentum;
unsigned long iAngle = 0;
G4double randAngle, position, theta1, theta2, E1, E2, W1, W2, W;
G4double m1 = particle->GetPDGMass();
for(iElement = 0; iElement < fElementNumberVector.size(); iElement++)
{
if( std::fabs(Z - fElementNumberVector[iElement]) < 0.5) break;
}
if ( iElement == fElementNumberVector.size() )
{
InitialiseOnFly(Z,A); // table preparation, if needed
}
fEnergyAngleVector = fEnergyAngleVectorBank[iElement];
fEnergySumVector = fEnergySumVectorBank[iElement];
G4double kinE = std::sqrt(momentum*momentum + m1*m1) - m1;
iMomentum = fEnergyVector->FindBin(kinE,1000) + 1;
position = (*(*fEnergySumVector)[iMomentum])[0]*G4UniformRand();
for(iAngle = 0; iAngle < fAngleBin; iAngle++)
{
if (position > (*(*fEnergySumVector)[iMomentum])[iAngle]) break;
}
if (iMomentum == fEnergyBin -1 || iMomentum == 0 ) // the table edges
{
randAngle = GetScatteringAngle(iMomentum, iAngle, position);
}
else // kinE inside between energy table edges
{
theta2 = GetScatteringAngle(iMomentum, iAngle, position);
E2 = fEnergyVector->Energy(iMomentum);
iMomentum--;
theta1 = GetScatteringAngle(iMomentum, iAngle, position);
E1 = fEnergyVector->Energy(iMomentum);
W = 1.0/(E2 - E1);
W1 = (E2 - kinE)*W;
W2 = (kinE - E1)*W;
randAngle = W1*theta1 + W2*theta2;
}
if(randAngle < 0.) randAngle = 0.;
return randAngle;
}
//////////////////////////////////////////////////////////////////////////////
//
// Initialisation for given particle on fly using new element number
void G4DiffuseElasticV2::InitialiseOnFly(G4double Z, G4double A)
{
fAtomicNumber = Z; // atomic number
fAtomicWeight = G4NistManager::Instance()->GetAtomicMassAmu( static_cast< G4int >( Z ) );
fNuclearRadius = CalculateNuclearRad(fAtomicWeight);
if( verboseLevel > 0 )
{
G4cout<<"G4DiffuseElasticV2::InitialiseOnFly() the element with Z = "
<<Z<<"; and A = "<<A<<G4endl;
}
fElementNumberVector.push_back(fAtomicNumber);
BuildAngleTable();
fEnergyAngleVectorBank.push_back(fEnergyAngleVector);
fEnergySumVectorBank.push_back(fEnergySumVector);
return;
}
///////////////////////////////////////////////////////////////////////////////
//
// Build for given particle and element table of momentum, angle probability.
// For the moment in lab system.
void G4DiffuseElasticV2::BuildAngleTable()
{
G4int i, j;
G4double partMom, kinE, a = 0., z = fParticle->GetPDGCharge(), m1 = fParticle->GetPDGMass();
G4double alpha1, alpha2, alphaMax, alphaCoulomb, delta = 0., sum = 0.;
G4Integrator<G4DiffuseElasticV2,G4double(G4DiffuseElasticV2::*)(G4double)> integral;
fEnergyAngleVector = new std::vector<std::vector<double>*>;
fEnergySumVector = new std::vector<std::vector<double>*>;
for( i = 0; i < fEnergyBin; i++)
{
kinE = fEnergyVector->Energy(i);
partMom = std::sqrt( kinE*(kinE + 2*m1) );
fWaveVector = partMom/hbarc;
G4double kR = fWaveVector*fNuclearRadius;
G4double kRmax = 18.6; // 10.6; 10.6, 18, 10.174; ~ 3 maxima of J1 or 15., 25.
G4double kRcoul = 1.9; // 1.2; 1.4, 2.5; // on the first slope of J1
alphaMax = kRmax/kR;
if ( alphaMax >= CLHEP::pi ) alphaMax = CLHEP::pi; // vmg21.10.15
alphaCoulomb = kRcoul/kR;
if( z )
{
a = partMom/m1; // beta*gamma for m1
fBeta = a/std::sqrt(1+a*a);
fZommerfeld = CalculateZommerfeld( fBeta, z, fAtomicNumber);
fAm = CalculateAm( partMom, fZommerfeld, fAtomicNumber);
fAddCoulomb = true;
}
std::vector<double>* angleVector = new std::vector<double>(fAngleBin);
std::vector<double>* sumVector = new std::vector<double>(fAngleBin);
G4double delth = alphaMax/fAngleBin;
sum = 0.;
for(j = fAngleBin-1; j >= 0; j--)
{
alpha1 = delth*j;
alpha2 = alpha1 + delth;
if( fAddCoulomb && ( alpha2 < alphaCoulomb)) fAddCoulomb = false;
delta = integral.Legendre10(this, &G4DiffuseElasticV2::GetIntegrandFunction, alpha1, alpha2);
sum += delta;
(*angleVector)[j] = alpha1;
(*sumVector)[j] = sum;
}
fEnergyAngleVector->push_back(angleVector);
fEnergySumVector->push_back(sumVector);
}
return;
}
/////////////////////////////////////////////////////////////////////////////////
//
//
G4double
G4DiffuseElasticV2::GetScatteringAngle( G4int iMomentum, unsigned long iAngle, G4double position )
{
G4double x1, x2, y1, y2, randAngle = 0;
if( iAngle == 0 )
{
randAngle = (*(*fEnergyAngleVector)[iMomentum])[iAngle];
}
else
{
if ( iAngle >= (*fEnergyAngleVector)[iMomentum]->size() )
{
iAngle = (*fEnergyAngleVector)[iMomentum]->size() - 1;
}
y1 = (*(*fEnergySumVector)[iMomentum])[iAngle-1];
y2 = (*(*fEnergySumVector)[iMomentum])[iAngle];
x1 = (*(*fEnergyAngleVector)[iMomentum])[iAngle-1];
x2 = (*(*fEnergyAngleVector)[iMomentum])[iAngle];
if ( x1 == x2 ) randAngle = x2;
else
{
if ( y1 == y2 ) randAngle = x1 + ( x2 - x1 )*G4UniformRand();
else
{
randAngle = x1 + ( position - y1 )*( x2 - x1 )/( y2 - y1 );
}
}
}
return randAngle;
}
////////////////////////////////////////////////////////////////////////////
//
// Return scattering angle in lab system (target at rest) knowing theta in CMS
G4double
G4DiffuseElasticV2::ThetaCMStoThetaLab( const G4DynamicParticle* aParticle,
G4double tmass, G4double thetaCMS)
{
const G4ParticleDefinition* theParticle = aParticle->GetDefinition();
G4double m1 = theParticle->GetPDGMass();
G4LorentzVector lv1 = aParticle->Get4Momentum();
G4LorentzVector lv(0.0,0.0,0.0,tmass);
lv += lv1;
G4ThreeVector bst = lv.boostVector();
lv1.boost(-bst);
G4ThreeVector p1 = lv1.vect();
G4double ptot = p1.mag();
G4double phi = G4UniformRand()*twopi;
G4double cost = std::cos(thetaCMS);
G4double sint;
if( cost >= 1.0 )
{
cost = 1.0;
sint = 0.0;
}
else if( cost <= -1.0)
{
cost = -1.0;
sint = 0.0;
}
else
{
sint = std::sqrt((1.0-cost)*(1.0+cost));
}
if (verboseLevel>1)
{
G4cout << "cos(tcms)=" << cost << " std::sin(tcms)=" << sint << G4endl;
}
G4ThreeVector v1(sint*std::cos(phi),sint*std::sin(phi),cost);
v1 *= ptot;
G4LorentzVector nlv1(v1.x(),v1.y(),v1.z(),std::sqrt(ptot*ptot + m1*m1));
nlv1.boost(bst);
G4ThreeVector np1 = nlv1.vect();
G4double thetaLab = np1.theta();
return thetaLab;
}
////////////////////////////////////////////////////////////////////////////
//
// Return scattering angle in CMS system (target at rest) knowing theta in Lab
G4double
G4DiffuseElasticV2::ThetaLabToThetaCMS( const G4DynamicParticle* aParticle,
G4double tmass, G4double thetaLab)
{
const G4ParticleDefinition* theParticle = aParticle->GetDefinition();
G4double m1 = theParticle->GetPDGMass();
G4double plab = aParticle->GetTotalMomentum();
G4LorentzVector lv1 = aParticle->Get4Momentum();
G4LorentzVector lv(0.0,0.0,0.0,tmass);
lv += lv1;
G4ThreeVector bst = lv.boostVector();
G4double phi = G4UniformRand()*twopi;
G4double cost = std::cos(thetaLab);
G4double sint;
if( cost >= 1.0 )
{
cost = 1.0;
sint = 0.0;
}
else if( cost <= -1.0)
{
cost = -1.0;
sint = 0.0;
}
else
{
sint = std::sqrt((1.0-cost)*(1.0+cost));
}
if (verboseLevel>1)
{
G4cout << "cos(tlab)=" << cost << " std::sin(tlab)=" << sint << G4endl;
}
G4ThreeVector v1(sint*std::cos(phi),sint*std::sin(phi),cost);
v1 *= plab;
G4LorentzVector nlv1(v1.x(),v1.y(),v1.z(),std::sqrt(plab*plab + m1*m1));
nlv1.boost(-bst);
G4ThreeVector np1 = nlv1.vect();
G4double thetaCMS = np1.theta();
return thetaCMS;
}
@@ -662,7 +662,7 @@ G4hhElastic:: GetTransfer( G4int iTkin, G4int iTransfer, G4double position )
return randTransfer;
}
const G4double G4hhElastic::theNuclNuclData[18][6] =
const G4double G4hhElastic::theNuclNuclData[19][6] =
{
// sqrt(fSpp) in GeV, fRA in 1/GeV, fRB in 1/GeV, fBq, fBQ, fImCof
@@ -688,7 +688,8 @@ const G4double G4hhElastic::theNuclNuclData[18][6] =
{ 546, 7.4, 7.4, 0.013, 0.845877, 5.5 }, // pb-p 546 GeV
{ 1960, 7.8, 7.8, 0.022, 0.809062, 7.5 }, // pb-p 1960 GeV
{ 7000, 8, 8, 0.024, 0.820441, 5.5 } // pp TOTEM
{ 7000, 8, 8, 0.024, 0.820441, 5.5 }, // pp TOTEM 7 TeV
{ 13000, 8.5, 8.5, 0.03, 0.796721, 10.5 } // pp TOTEM 13 TeV
};