Import Geant4 11.3.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2024-06-28 13:08:51 +02:00
parent f7b23877ed
commit e58e650b32
5232 changed files with 239416 additions and 244360 deletions
@@ -83,14 +83,10 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
G4bool G4eeToTwoGammaModel::fSampleAtomicPDF = false;
G4eeToTwoGammaModel::G4eeToTwoGammaModel(const G4ParticleDefinition*,
const G4String& nam)
: G4VEmModel(nam),
pi_rcl2(pi*classic_electr_radius*classic_electr_radius)
pi_rcl2(CLHEP::pi*CLHEP::classic_electr_radius*CLHEP::classic_electr_radius)
{
theGamma = G4Gamma::Gamma();
fParticleChange = nullptr;
@@ -105,27 +101,7 @@ G4eeToTwoGammaModel::~G4eeToTwoGammaModel() = default;
void G4eeToTwoGammaModel::Initialise(const G4ParticleDefinition*,
const G4DataVector&)
{
if(IsMaster()) {
G4int verbose = G4EmParameters::Instance()->Verbose();
// redo initialisation for each new run
fSampleAtomicPDF = false;
const auto& materialTable = G4Material::GetMaterialTable();
for (const auto& material: *materialTable) {
const G4double meanEnergyPerIonPair = material->GetIonisation()->GetMeanEnergyPerIonPair();
if (meanEnergyPerIonPair > 0.) {
fSampleAtomicPDF = true;
if(verbose > 0) {
G4cout << "### G4eeToTwoGammaModel: for " << material->GetName() << " mean energy per ion pair is "
<< meanEnergyPerIonPair/CLHEP::eV << " eV" << G4endl;
}
}
}
}
// If no materials have meanEnergyPerIonPair set. This is probably the usual
// case, since most applications are not senstive to the slight
// non-collinearity of gammas in eeToTwoGamma. Do not issue any warning.
if(fParticleChange) { return; }
if (nullptr != fParticleChange) { return; }
fParticleChange = GetParticleChangeForGamma();
}
@@ -137,13 +113,13 @@ G4eeToTwoGammaModel::ComputeCrossSectionPerElectron(G4double kineticEnergy)
// Calculates the cross section per electron of annihilation into two photons
// from the Heilter formula.
G4double ekin = std::max(eV,kineticEnergy);
G4double ekin = std::max(CLHEP::eV, kineticEnergy);
G4double tau = ekin/electron_mass_c2;
G4double tau = ekin/CLHEP::electron_mass_c2;
G4double gam = tau + 1.0;
G4double gamma2= gam*gam;
G4double bg2 = tau * (tau+2.0);
G4double bg = sqrt(bg2);
G4double bg = std::sqrt(bg2);
G4double cross = pi_rcl2*((gamma2+4*gam+1.)*G4Log(gam+bg) - (gam+3.)*bg)
/ (bg2*(gam+1.));
@@ -178,183 +154,46 @@ G4double G4eeToTwoGammaModel::CrossSectionPerVolume(
// Polarisation of gamma according to M.H.L.Pryce and J.C.Ward,
// Nature 4065 (1947) 435.
void G4eeToTwoGammaModel::SampleSecondaries(vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple* pCutsCouple,
void G4eeToTwoGammaModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple*,
const G4DynamicParticle* dp,
G4double,
G4double)
{
G4double posiKinEnergy = dp->GetKineticEnergy();
G4DynamicParticle *aGamma1, *aGamma2;
CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine();
// Case at rest
if(posiKinEnergy == 0.0) {
const G4double eGamma = electron_mass_c2;
// In rest frame of positronium gammas are back to back
const G4ThreeVector& dir1 = G4RandomDirection();
const G4ThreeVector& dir2 = -dir1;
aGamma1 = new G4DynamicParticle(G4Gamma::Gamma(),dir1,eGamma);
aGamma2 = new G4DynamicParticle(G4Gamma::Gamma(),dir2,eGamma);
// In rest frame the gammas are polarised perpendicular to each other - see
// Pryce and Ward, Nature No 4065 (1947) p.435.
// Snyder et al, Physical Review 73 (1948) p.440.
G4ThreeVector pol1 = (G4RandomDirection().cross(dir1)).unit();
G4ThreeVector pol2 = (pol1.cross(dir2)).unit();
// But the positronium is moving...
// A positron in matter slows down and combines with an atomic electron to
// make a neutral “atom” called positronium, about half the size of a normal
// atom. I expect that when the energy of the positron is small enough,
// less than the binding energy of positronium (6.8 eV), it is
// energetically favourable for an electron from the outer orbitals of a
// nearby atom or molecule to transfer and bind to the positron, as in an
// ionic bond, leaving behind a mildly ionised nearby atom/molecule. I
// would expect the positronium to come away with a kinetic energy of a
// few eV on average. In its para (spin 0) state it annihilates into two
// photons, which in the rest frame of the positronium are collinear
// (back-to-back) due to momentum conservation. Because of the motion of the
// positronium, photons will be not quite back-to-back in the laboratory.
// The positroniuim acquires an energy of order its binding energy and
// doesn't have time to thermalise. Nevertheless, here we approximate its
// energy distribution by a Maxwell-Boltzman with mean energy <KE>. In terms
// of a more familiar concept of temperature, and the law of equipartition
// of energy of translational motion, <KE>=3kT/2. Each component of velocity
// has a distribution exp(-mv^2/2kT), which is a Gaussian of mean zero
// and variance kT/m=2<KE>/3m, where m is the positronium mass.
// We take <KE> = material->GetIonisation()->GetMeanEnergyPerIonPair().
if(fSampleAtomicPDF) {
const G4Material* material = pCutsCouple->GetMaterial();
const G4double meanEnergyPerIonPair = material->GetIonisation()->GetMeanEnergyPerIonPair();
const G4double& meanKE = meanEnergyPerIonPair; // Just an alias
if (meanKE > 0.) { // Positronium haas motion
// Mass of positronium
const G4double mass = 2.*electron_mass_c2;
// Mean <KE>=3kT/2, as described above
// const G4double T = 2.*meanKE/(3.*k_Boltzmann);
// Component velocities: Gaussian, variance kT/m=2<KE>/3m.
const G4double sigmav = std::sqrt(2.*meanKE/(3.*mass));
// This is in units where c=1
const G4double vx = G4RandGauss::shoot(0.,sigmav);
const G4double vy = G4RandGauss::shoot(0.,sigmav);
const G4double vz = G4RandGauss::shoot(0.,sigmav);
const G4ThreeVector v(vx,vy,vz); // In unit where c=1
const G4ThreeVector& beta = v; // so beta=v/c=v
aGamma1->Set4Momentum(aGamma1->Get4Momentum().boost(beta));
aGamma2->Set4Momentum(aGamma2->Get4Momentum().boost(beta));
// Rotate polarisation vectors
const G4ThreeVector& newDir1 = aGamma1->GetMomentumDirection();
const G4ThreeVector& newDir2 = aGamma2->GetMomentumDirection();
const G4ThreeVector& axis1 = dir1.cross(newDir1); // No need to be unit
const G4ThreeVector& axis2 = dir2.cross(newDir2); // No need to be unit
const G4double& angle1 = std::acos(dir1*newDir1);
const G4double& angle2 = std::acos(dir2*newDir2);
if (axis1 != G4ThreeVector()) pol1.rotate(axis1,angle1);
if (axis2 != G4ThreeVector()) pol2.rotate(axis2,angle2);
}
}
aGamma1->SetPolarization(pol1.x(),pol1.y(),pol1.z());
aGamma2->SetPolarization(pol2.x(),pol2.y(),pol2.z());
} else { // Positron interacts in flight
G4ThreeVector posiDirection = dp->GetMomentumDirection();
G4double tau = posiKinEnergy/electron_mass_c2;
G4double gam = tau + 1.0;
G4double tau2 = tau + 2.0;
G4double sqgrate = sqrt(tau/tau2)*0.5;
G4double sqg2m1 = sqrt(tau*tau2);
// limits of the energy sampling
G4double epsilmin = 0.5 - sqgrate;
G4double epsilmax = 0.5 + sqgrate;
G4double epsilqot = epsilmax/epsilmin;
//
// sample the energy rate of the created gammas
//
G4double epsil, greject;
do {
epsil = epsilmin*G4Exp(G4Log(epsilqot)*rndmEngine->flat());
greject = 1. - epsil + (2.*gam*epsil-1.)/(epsil*tau2*tau2);
// Loop checking, 03-Aug-2015, Vladimir Ivanchenko
} while( greject < rndmEngine->flat());
//
// scattered Gamma angles. ( Z - axis along the parent positron)
//
G4double cost = (epsil*tau2-1.)/(epsil*sqg2m1);
if(std::abs(cost) > 1.0) {
G4cout << "### G4eeToTwoGammaModel WARNING cost= " << cost
<< " positron Ekin(MeV)= " << posiKinEnergy
<< " gamma epsil= " << epsil
<< G4endl;
if(cost > 1.0) cost = 1.0;
else cost = -1.0;
}
G4double sint = sqrt((1.+cost)*(1.-cost));
G4double phi = twopi * rndmEngine->flat();
//
// kinematic of the created pair
//
G4double totalEnergy = posiKinEnergy + 2.0*electron_mass_c2;
G4double phot1Energy = epsil*totalEnergy;
G4ThreeVector phot1Direction(sint*cos(phi), sint*sin(phi), cost);
phot1Direction.rotateUz(posiDirection);
aGamma1 = new G4DynamicParticle (theGamma,phot1Direction, phot1Energy);
phi = twopi * rndmEngine->flat();
G4double cosphi = cos(phi);
G4double sinphi = sin(phi);
G4ThreeVector pol(cosphi, sinphi, 0.0);
pol.rotateUz(phot1Direction);
aGamma1->SetPolarization(pol.x(),pol.y(),pol.z());
G4double phot2Energy =(1.-epsil)*totalEnergy;
G4double posiP= sqrt(posiKinEnergy*(posiKinEnergy+2.*electron_mass_c2));
G4ThreeVector dir = posiDirection*posiP - phot1Direction*phot1Energy;
G4ThreeVector phot2Direction = dir.unit();
// create G4DynamicParticle object for the particle2
aGamma2 = new G4DynamicParticle (theGamma, phot2Direction, phot2Energy);
//!!! likely problematic direction to be checked
pol.set(-sinphi, cosphi, 0.0);
pol.rotateUz(phot1Direction);
cost = pol*phot2Direction;
pol -= cost*phot2Direction;
pol = pol.unit();
aGamma2->SetPolarization(pol.x(),pol.y(),pol.z());
/*
G4cout << "Annihilation on fly: e0= " << posiKinEnergy
<< " m= " << electron_mass_c2
<< " e1= " << phot1Energy
<< " e2= " << phot2Energy << " dir= " << dir
<< " -> " << phot1Direction << " "
<< phot2Direction << G4endl;
*/
}
vdp->push_back(aGamma1);
vdp->push_back(aGamma2);
// kill primary positron
fParticleChange->SetProposedKineticEnergy(0.0);
fParticleChange->ProposeTrackStatus(fStopAndKill);
// Case at rest not considered anymore inside this model
G4LorentzVector lv(dp->GetMomentum(),
dp->GetKineticEnergy() + 2*CLHEP::electron_mass_c2);
G4double eGammaCMS = 0.5 * lv.mag();
G4ThreeVector dir1 = G4RandomDirection();
G4double phi = CLHEP::twopi * G4UniformRand();
G4double cosphi = std::cos(phi);
G4double sinphi = std::sin(phi);
G4ThreeVector pol1(cosphi, sinphi, 0.0);
pol1.rotateUz(dir1);
G4LorentzVector lv1(eGammaCMS*dir1, eGammaCMS);
G4ThreeVector pol2(-sinphi, cosphi, 0.0);
pol2.rotateUz(dir1);
// transformation to lab system
lv1.boost(lv.boostVector());
lv -= lv1;
//!!! boost of polarisation vector is not yet implemented
// use constructors optimal for massless particle
auto aGamma1 = new G4DynamicParticle(G4Gamma::Gamma(), lv1.vect());
aGamma1->SetPolarization(pol1);
auto aGamma2 = new G4DynamicParticle(G4Gamma::Gamma(), lv.vect());
aGamma2->SetPolarization(pol2);
vdp->push_back(aGamma1);
vdp->push_back(aGamma2);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....