Import Geant4 11.3.0 source tree
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4DynamicParticleFluctuation
|
||||
//
|
||||
// Author: V. Ivanchenko
|
||||
//
|
||||
// Creation date: 23.08.2024
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "G4DynamicParticleFluctuation.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4Poisson.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4Log.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4DynamicParticleFluctuation::G4DynamicParticleFluctuation(const G4String& nam)
|
||||
: G4UniversalFluctuation(nam)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4DynamicParticleFluctuation::InitialiseLocal(const G4DynamicParticle* part)
|
||||
{
|
||||
particleMass = part->GetMass();
|
||||
const G4double q = part->GetCharge()/CLHEP::eplus;
|
||||
|
||||
// Derived quantities
|
||||
m_Inv_particleMass = 1.0 / particleMass;
|
||||
m_massrate = CLHEP::electron_mass_c2 * m_Inv_particleMass;
|
||||
chargeSquare = q*q;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DynamicParticleFluctuation::SampleFluctuations(
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dp,
|
||||
const G4double tcut,
|
||||
const G4double tmax,
|
||||
const G4double length,
|
||||
const G4double averageLoss)
|
||||
{
|
||||
// Calculate actual loss from the mean loss.
|
||||
// The model used to get the fluctuations is essentially the same
|
||||
// as in Glandz in Geant3 (Cern program library W5013, phys332).
|
||||
// L. Urban et al. NIM A362, p.416 (1995) and Geant4 Physics Reference Manual
|
||||
|
||||
// shortcut for very small loss or from a step nearly equal to the range
|
||||
// (out of validity of the model)
|
||||
//
|
||||
if (averageLoss < minLoss) { return averageLoss; }
|
||||
meanLoss = averageLoss;
|
||||
const G4double tkin = dp->GetKineticEnergy();
|
||||
//G4cout<< "Emean= "<< meanLoss<< " tmax= "<< tmax<< " L= "<<length<<G4endl;
|
||||
|
||||
CLHEP::HepRandomEngine* rndmEngineF = G4Random::getTheEngine();
|
||||
|
||||
InitialiseLocal(dp);
|
||||
const G4double gam = tkin * m_Inv_particleMass + 1.0;
|
||||
const G4double gam2 = gam*gam;
|
||||
const G4double beta = dp->GetBeta();
|
||||
const G4double beta2 = beta*beta;
|
||||
|
||||
G4double loss(0.), siga(0.);
|
||||
|
||||
const G4Material* material = couple->GetMaterial();
|
||||
|
||||
// Gaussian regime
|
||||
// for heavy particles only and conditions
|
||||
// for Gauusian fluct. has been changed
|
||||
//
|
||||
if (particleMass > CLHEP::electron_mass_c2 &&
|
||||
meanLoss >= minNumberInteractionsBohr*tcut && tmax <= 2.*tcut) {
|
||||
|
||||
siga = std::sqrt((tmax/beta2 - 0.5*tcut)*CLHEP::twopi_mc2_rcl2*
|
||||
length*chargeSquare*material->GetElectronDensity());
|
||||
const G4double sn = meanLoss/siga;
|
||||
|
||||
// thick target case
|
||||
if (sn >= 2.0) {
|
||||
|
||||
const G4double twomeanLoss = meanLoss + meanLoss;
|
||||
do {
|
||||
loss = G4RandGauss::shoot(rndmEngineF, meanLoss, siga);
|
||||
// Loop checking, 03-Aug-2015, Vladimir Ivanchenko
|
||||
} while (0.0 > loss || twomeanLoss < loss);
|
||||
|
||||
// Gamma distribution
|
||||
} else {
|
||||
|
||||
const G4double neff = sn*sn;
|
||||
loss = meanLoss*G4RandGamma::shoot(rndmEngineF, neff, 1.0)/neff;
|
||||
}
|
||||
//G4cout << "Gauss: " << loss << G4endl;
|
||||
return loss;
|
||||
}
|
||||
|
||||
auto ioni = material->GetIonisation();
|
||||
e0 = ioni->GetEnergy0fluct();
|
||||
|
||||
// very small step or low-density material
|
||||
if(tcut <= e0) { return meanLoss; }
|
||||
|
||||
ipotFluct = ioni->GetMeanExcitationEnergy();
|
||||
ipotLogFluct = ioni->GetLogMeanExcEnergy();
|
||||
|
||||
// width correction for small cuts
|
||||
const G4double scaling = std::min(1.+0.5*CLHEP::keV/tcut, 1.50);
|
||||
meanLoss /= scaling;
|
||||
|
||||
w2 = (tcut > ipotFluct) ?
|
||||
G4Log(2.*CLHEP::electron_mass_c2*beta2*gam2) - beta2 : 0.0;
|
||||
return SampleGlandz(rndmEngineF, material, tcut)*scaling;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
G4double G4DynamicParticleFluctuation::Dispersion(
|
||||
const G4Material* material,
|
||||
const G4DynamicParticle* dp,
|
||||
const G4double tcut,
|
||||
const G4double tmax,
|
||||
const G4double length)
|
||||
{
|
||||
InitialiseLocal(dp);
|
||||
const G4double beta = dp->GetBeta();
|
||||
return (tmax/(beta*beta) - 0.5*tcut) * CLHEP::twopi_mc2_rcl2 * length
|
||||
* material->GetElectronDensity() * chargeSquare;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -0,0 +1,358 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4DynamicParticleIonisation
|
||||
//
|
||||
// Author: Vladimir Ivanchenko
|
||||
//
|
||||
// Creation date: 17.08.2024
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
#include "G4DynamicParticleIonisation.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4DynamicParticleFluctuation.hh"
|
||||
#include "G4EmSecondaryParticleType.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4EmProcessSubType.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
#include "G4ProductionCutsTable.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4Log.hh"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr G4double ekinLimit = 0.2*CLHEP::MeV;
|
||||
const G4double twoln10 = 2*G4Log(10.0);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticleIonisation::G4DynamicParticleIonisation()
|
||||
: G4VContinuousDiscreteProcess("dynPartIoni")
|
||||
{
|
||||
SetVerboseLevel(1);
|
||||
SetProcessSubType(fDynamicIonisation);
|
||||
theElectron = G4Electron::Electron();
|
||||
|
||||
lManager = G4LossTableManager::Instance();
|
||||
lManager->Register(this);
|
||||
|
||||
fUrban = new G4DynamicParticleFluctuation();
|
||||
|
||||
// define these flags only once
|
||||
auto param = G4EmParameters::Instance();
|
||||
fFluct = param->LossFluctuation();
|
||||
fLinLimit = 5*param->LinearLossLimit();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticleIonisation::~G4DynamicParticleIonisation()
|
||||
{
|
||||
lManager->DeRegister(this);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void
|
||||
G4DynamicParticleIonisation::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
{
|
||||
auto theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
|
||||
fCuts = theCoupleTable->GetEnergyCutsVector(1);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DynamicParticleIonisation::PreStepInitialisation(const G4Track& track)
|
||||
{
|
||||
fCouple = track.GetMaterialCutsCouple();
|
||||
fMaterial = fCouple->GetMaterial();
|
||||
auto dpart = track.GetDynamicParticle();
|
||||
fEkinPreStep = dpart->GetKineticEnergy();
|
||||
fMass = std::max(dpart->GetMass(), CLHEP::electron_mass_c2);
|
||||
fCharge = dpart->GetCharge()/CLHEP::eplus;
|
||||
fRatio = fMass/CLHEP::proton_mass_c2;
|
||||
fLowestEkin = ekinLimit*fRatio;
|
||||
G4double tau = fEkinPreStep/fMass;
|
||||
G4double ratio = CLHEP::electron_mass_c2/fMass;
|
||||
fTmax = 2.0*CLHEP::electron_mass_c2*tau*(tau + 2.) /
|
||||
(1. + 2.0*(tau + 1.)*ratio + ratio*ratio);
|
||||
fCut = (*fCuts)[fCouple->GetIndex()];
|
||||
fCut = std::max(fCut, fMaterial->GetIonisation()->GetMeanExcitationEnergy());
|
||||
fCut = std::min(fCut, fTmax);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleIonisation::AlongStepGetPhysicalInteractionLength(
|
||||
const G4Track&, G4double, G4double, G4double&,
|
||||
G4GPILSelection* selection)
|
||||
{
|
||||
*selection = CandidateForSelection;
|
||||
|
||||
// no step limit for the time being
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleIonisation::PostStepGetPhysicalInteractionLength(
|
||||
const G4Track& track, G4double previousStepSize,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
*condition = NotForced;
|
||||
G4double x = DBL_MAX;
|
||||
G4double xsec = 0.0;
|
||||
|
||||
PreStepInitialisation(track);
|
||||
|
||||
if (fCharge != 0.0) {
|
||||
xsec = ComputeCrossSection(fEkinPreStep);
|
||||
}
|
||||
|
||||
if (xsec <= 0.0) {
|
||||
theNumberOfInteractionLengthLeft = -1.0;
|
||||
currentInteractionLength = DBL_MAX;
|
||||
|
||||
} else {
|
||||
if (theNumberOfInteractionLengthLeft < 0.0) {
|
||||
|
||||
theNumberOfInteractionLengthLeft = -G4Log( G4UniformRand() );
|
||||
theInitialNumberOfInteractionLength = theNumberOfInteractionLengthLeft;
|
||||
|
||||
} else if(currentInteractionLength < DBL_MAX) {
|
||||
|
||||
// subtract NumberOfInteractionLengthLeft using previous step
|
||||
theNumberOfInteractionLengthLeft -=
|
||||
previousStepSize/currentInteractionLength;
|
||||
|
||||
theNumberOfInteractionLengthLeft =
|
||||
std::max(theNumberOfInteractionLengthLeft, 0.0);
|
||||
}
|
||||
currentInteractionLength = 1.0/xsec;
|
||||
x = theNumberOfInteractionLengthLeft * currentInteractionLength;
|
||||
}
|
||||
#ifdef G4VERBOSE
|
||||
if (verboseLevel>2) {
|
||||
G4cout << "G4DynamicParticleIonisation::PostStepGetPhysicalInteractionLength ";
|
||||
G4cout << " Process: " << GetProcessName()
|
||||
<< " for unknown particle Mass(GeV)=" << fMass/CLHEP::GeV
|
||||
<< " charge=" << fCharge
|
||||
<< " Material " << fMaterial->GetName()
|
||||
<< " Ekin(MeV)=" << fEkinPreStep/CLHEP::MeV
|
||||
<< " MFP(cm)=" << currentInteractionLength/CLHEP::cm
|
||||
<< " ProposedLength(cm)=" << x/CLHEP::cm <<G4endl;
|
||||
}
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4VParticleChange*
|
||||
G4DynamicParticleIonisation::AlongStepDoIt(const G4Track& track,
|
||||
const G4Step& step)
|
||||
{
|
||||
fParticleChange.InitializeForAlongStep(track);
|
||||
|
||||
// no energy loss
|
||||
if (fCharge == 0.0) { return &fParticleChange; }
|
||||
|
||||
// stop low-energy object
|
||||
if (fEkinPreStep <= fLowestEkin) {
|
||||
fParticleChange.SetProposedKineticEnergy(0.0);
|
||||
fParticleChange.ProposeLocalEnergyDeposit(fEkinPreStep);
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
G4double length = step.GetStepLength();
|
||||
G4double dedxPre = ComputeDEDX(fEkinPreStep);
|
||||
G4double eloss = dedxPre*length;
|
||||
G4double ekinPostStep = fEkinPreStep - eloss;
|
||||
|
||||
// correction for large step if it is not the last step
|
||||
if (fEkinPreStep*fLinLimit < eloss && ekinPostStep > fLowestEkin) {
|
||||
G4double dedxPost = ComputeDEDX(ekinPostStep);
|
||||
eloss = (eloss + dedxPost*length)*0.5;
|
||||
}
|
||||
|
||||
// do not sample fluctuations at the last step
|
||||
if (fFluct && fEkinPreStep > eloss) {
|
||||
eloss = fUrban->SampleFluctuations(fCouple, track.GetDynamicParticle(),
|
||||
fCut, fTmax, length, eloss);
|
||||
}
|
||||
|
||||
ekinPostStep = fEkinPreStep - eloss;
|
||||
|
||||
// stop low-energy object
|
||||
if (ekinPostStep <= fLowestEkin) {
|
||||
fParticleChange.SetProposedKineticEnergy(0.0);
|
||||
fParticleChange.ProposeLocalEnergyDeposit(fEkinPreStep);
|
||||
} else {
|
||||
fParticleChange.SetProposedKineticEnergy(ekinPostStep);
|
||||
fParticleChange.ProposeLocalEnergyDeposit(eloss);
|
||||
}
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4VParticleChange*
|
||||
G4DynamicParticleIonisation::PostStepDoIt(const G4Track& track, const G4Step&)
|
||||
{
|
||||
theNumberOfInteractionLengthLeft = -1.0;
|
||||
fParticleChange.InitializeForPostStep(track);
|
||||
|
||||
auto dp = track.GetDynamicParticle();
|
||||
G4double kinEnergy = dp->GetKineticEnergy();
|
||||
const G4double totEnergy = kinEnergy + fMass;
|
||||
const G4double beta2 = kinEnergy*(kinEnergy + 2.0*fMass)/(totEnergy*totEnergy);
|
||||
|
||||
G4double deltaKinEnergy, f;
|
||||
|
||||
CLHEP::HepRandomEngine* rndmEngineMod = G4Random::getTheEngine();
|
||||
G4double rndm[2];
|
||||
|
||||
// sampling without nuclear size effect
|
||||
do {
|
||||
rndmEngineMod->flatArray(2, rndm);
|
||||
deltaKinEnergy = fCut*fTmax/(fCut*(1.0 - rndm[0]) + fTmax*rndm[0]);
|
||||
f = 1.0 - beta2*deltaKinEnergy/fTmax;
|
||||
// Loop checking, 14-Aug-2024, Vladimir Ivanchenko
|
||||
} while( rndm[1] > f);
|
||||
|
||||
G4double deltaMomentum =
|
||||
std::sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*CLHEP::electron_mass_c2));
|
||||
G4double cost = deltaKinEnergy * (totEnergy + CLHEP::electron_mass_c2) /
|
||||
(deltaMomentum * dp->GetTotalMomentum());
|
||||
cost = std::min(cost, 1.0);
|
||||
const G4double sint = std::sqrt((1.0 - cost)*(1.0 + cost));
|
||||
const G4double phi = CLHEP::twopi*rndmEngineMod->flat();
|
||||
|
||||
G4ThreeVector deltaDirection(sint*std::cos(phi), sint*std::sin(phi), cost);
|
||||
deltaDirection.rotateUz(dp->GetMomentumDirection());
|
||||
|
||||
// create G4DynamicParticle object for delta ray
|
||||
auto delta = new G4DynamicParticle(theElectron, deltaDirection, deltaKinEnergy);
|
||||
auto t = new G4Track(delta, track.GetGlobalTime(), track.GetPosition());
|
||||
t->SetTouchableHandle(track.GetTouchableHandle());
|
||||
t->SetCreatorModelID(fSecID);
|
||||
fParticleChange.AddSecondary(t);
|
||||
|
||||
// Change kinematics of primary particle
|
||||
kinEnergy -= deltaKinEnergy;
|
||||
G4ThreeVector finalP = dp->GetMomentum() - delta->GetMomentum();
|
||||
finalP = finalP.unit();
|
||||
|
||||
fParticleChange.SetProposedKineticEnergy(kinEnergy);
|
||||
fParticleChange.SetProposedMomentumDirection(finalP);
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleIonisation::ComputeDEDX(G4double ekin)
|
||||
{
|
||||
G4double tau = ekin/fMass;
|
||||
G4double gam = tau + 1.0;
|
||||
G4double bg2 = tau * (tau + 2.0);
|
||||
G4double beta2 = bg2/(gam*gam);
|
||||
G4double xc = fCut/fTmax;
|
||||
|
||||
G4double exc = fMaterial->GetIonisation()->GetMeanExcitationEnergy();
|
||||
G4double exc2 = exc*exc;
|
||||
|
||||
// general Bethe-Bloch formula
|
||||
G4double dedx = G4Log(2.0*CLHEP::electron_mass_c2*bg2*fCut/exc2) - (1.0 + xc)*beta2;
|
||||
|
||||
// density correction
|
||||
G4double x = G4Log(bg2)/twoln10;
|
||||
dedx -= fMaterial->GetIonisation()->DensityCorrection(x);
|
||||
|
||||
// now compute the total ionization loss per volume
|
||||
dedx *= CLHEP::twopi_mc2_rcl2*fCharge*fCharge*fMaterial->GetElectronDensity()/beta2;
|
||||
dedx = std::max(dedx, 0.0);
|
||||
return dedx;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleIonisation::ComputeCrossSection(G4double ekin)
|
||||
{
|
||||
G4double cross = 0.0;
|
||||
if (fCut < fTmax) {
|
||||
|
||||
G4double totEnergy = ekin + fMass;
|
||||
G4double energy2 = totEnergy*totEnergy;
|
||||
G4double beta2 = ekin*(ekin + 2.0*fMass)/energy2;
|
||||
|
||||
cross = (fTmax - fCut)/(fCut*fTmax*beta2) - G4Log(fTmax/fCut)/fTmax;
|
||||
cross *= CLHEP::twopi_mc2_rcl2*fCharge*fCharge*fMaterial->GetElectronDensity();
|
||||
}
|
||||
return cross;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleIonisation::GetMeanFreePath(const G4Track& /* track */, G4double,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
// Note: this method is not used at run-time, so its implementation is simplified.
|
||||
// It might be eventually refined later.
|
||||
*condition = NotForced;
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleIonisation::GetContinuousStepLimit(const G4Track&, G4double,
|
||||
G4double, G4double&)
|
||||
{
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DynamicParticleIonisation::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "G4DynamicParticleIonisation: dynamic ionisation" << G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -0,0 +1,176 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4DynamicParticleMSC
|
||||
//
|
||||
// Author: Vladimir Ivanchenko
|
||||
//
|
||||
// Creation date: 17.08.2024
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
#include "G4DynamicParticleMSC.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4EmProcessSubType.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4Log.hh"
|
||||
#include "G4Exp.hh"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr G4double c_highland = 13.6*CLHEP::MeV;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticleMSC::G4DynamicParticleMSC()
|
||||
: G4VContinuousDiscreteProcess("dynPartMSC")
|
||||
{
|
||||
SetVerboseLevel(1);
|
||||
SetProcessSubType(fDynamicMultipleScattering);
|
||||
lManager = G4LossTableManager::Instance();
|
||||
lManager->Register(this);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DynamicParticleMSC::~G4DynamicParticleMSC()
|
||||
{
|
||||
lManager->DeRegister(this);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DynamicParticleMSC::PreStepInitialisation(const G4Track& track)
|
||||
{
|
||||
fMaterial = track.GetMaterial();
|
||||
fZeff = fMaterial->GetIonisation()->GetZeffective();
|
||||
auto dpart = track.GetDynamicParticle();
|
||||
fEkinPreStep = dpart->GetKineticEnergy();
|
||||
fBeta = dpart->GetBeta();
|
||||
fCharge = dpart->GetCharge()/CLHEP::eplus;
|
||||
fMass = std::max(dpart->GetMass(), CLHEP::electron_mass_c2);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleMSC::AlongStepGetPhysicalInteractionLength(
|
||||
const G4Track& track, G4double, G4double, G4double&,
|
||||
G4GPILSelection* selection)
|
||||
{
|
||||
*selection = CandidateForSelection;
|
||||
PreStepInitialisation(track);
|
||||
|
||||
// no step limit for the time being
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleMSC::PostStepGetPhysicalInteractionLength(
|
||||
const G4Track&, G4double,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
*condition = NotForced;
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4VParticleChange* G4DynamicParticleMSC::AlongStepDoIt(const G4Track& track,
|
||||
const G4Step& step)
|
||||
{
|
||||
fParticleChange.InitialiseMSC(track, step);
|
||||
|
||||
// no energy loss
|
||||
if (fCharge == 0.0) { return &fParticleChange; }
|
||||
|
||||
G4double geomLength = step.GetStepLength();
|
||||
G4double y = geomLength/fMaterial->GetRadlen();
|
||||
G4double theta0 = c_highland*std::abs(fCharge)*std::sqrt(y)*
|
||||
(1.0 + 0.038*G4Log(y*fCharge*fCharge/(fBeta*fBeta)))/fBeta;
|
||||
|
||||
if (theta0 < 0.001) { return &fParticleChange; }
|
||||
G4double cost = 1.0;
|
||||
G4double r = G4UniformRand();
|
||||
if (theta0 < 1.0) {
|
||||
G4double theta2 = theta0*theta0;
|
||||
cost -= theta2*G4Log(1.0 + r*(G4Exp(2.0/theta2) - 1.0));
|
||||
} else {
|
||||
cost -= 2.0*r;
|
||||
}
|
||||
G4double phi = CLHEP::twopi*G4UniformRand();
|
||||
G4double sint = std::sqrt((1.0 - cost)*(1.0 + cost));
|
||||
fNewDir.set(sint*std::cos(phi), sint*std::sin(phi), cost);
|
||||
fNewDir.rotateUz(step.GetPostStepPoint()->GetMomentumDirection());
|
||||
|
||||
fParticleChange.ProposeMomentumDirection(fNewDir);
|
||||
fParticleChange.ProposeTrueStepLength(geomLength);
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleMSC::GetMeanFreePath(const G4Track&, G4double,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
*condition = Forced;
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DynamicParticleMSC::GetContinuousStepLimit(const G4Track& track,
|
||||
G4double previousStepSize,
|
||||
G4double currentMinimalStep,
|
||||
G4double& currentSafety)
|
||||
{
|
||||
G4GPILSelection selection = NotCandidateForSelection;
|
||||
G4double x = AlongStepGetPhysicalInteractionLength(track, previousStepSize,
|
||||
currentMinimalStep,
|
||||
currentSafety, &selection);
|
||||
return x;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DynamicParticleMSC::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "G4DynamicParticleMSC: no delta rays" << G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
Reference in New Issue
Block a user