Import Geant4 11.0.0.beta source tree
This commit is contained in:
+57
-71
@@ -23,104 +23,90 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4AdjointAlongStepWeightCorrection.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4VParticleChange.hh"
|
||||
|
||||
#include "G4AdjointCSManager.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4VParticleChange.hh"
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
G4AdjointAlongStepWeightCorrection::G4AdjointAlongStepWeightCorrection(const G4String& name,
|
||||
G4ProcessType type): G4VContinuousProcess(name, type)
|
||||
{fParticleChange = new G4ParticleChange();
|
||||
currentMaterialIndex=0;
|
||||
preStepKinEnergy=1.;
|
||||
currentCouple=0;
|
||||
G4AdjointAlongStepWeightCorrection::G4AdjointAlongStepWeightCorrection(
|
||||
const G4String& name, G4ProcessType type)
|
||||
: G4VContinuousProcess(name, type)
|
||||
{
|
||||
fParticleChange = new G4ParticleChange();
|
||||
fCSManager = G4AdjointCSManager::GetAdjointCSManager();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
G4AdjointAlongStepWeightCorrection::~G4AdjointAlongStepWeightCorrection()
|
||||
{delete fParticleChange;
|
||||
}
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointAlongStepWeightCorrection::PreparePhysicsTable(
|
||||
const G4ParticleDefinition& )
|
||||
{
|
||||
;
|
||||
delete fParticleChange;
|
||||
}
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void G4AdjointAlongStepWeightCorrection::BuildPhysicsTable(const G4ParticleDefinition& )
|
||||
{;
|
||||
}
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4VParticleChange* G4AdjointAlongStepWeightCorrection::AlongStepDoIt(const G4Track& track,
|
||||
const G4Step& step)
|
||||
void G4AdjointAlongStepWeightCorrection::ProcessDescription(
|
||||
std::ostream& out) const
|
||||
{
|
||||
out <<
|
||||
"Continuous processes act on adjoint particles to continuously correct their "
|
||||
"weight during the adjoint reverse tracking. This process is needed when "
|
||||
"the adjoint cross sections are not scaled such that the total adjoint cross "
|
||||
"section matches the total forward cross section. By default the mode where "
|
||||
"the total adjoint cross section is equal to the total forward cross section "
|
||||
"is used and therefore this along step weightcorrection factor is 1. However "
|
||||
"in some cases (some energy ranges) the total forward cross section or the "
|
||||
"total adjoint cross section can be zero. In this case the along step weight "
|
||||
"correction is needed and is given by exp(-(Sigma_tot_adj-Sigma_tot_fwd).dx)"
|
||||
"\n";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
G4VParticleChange* G4AdjointAlongStepWeightCorrection::AlongStepDoIt(
|
||||
const G4Track& track, const G4Step& step)
|
||||
{
|
||||
|
||||
fParticleChange->Initialize(track);
|
||||
|
||||
|
||||
// Get the actual (true) Step length
|
||||
//----------------------------------
|
||||
G4double length = step.GetStepLength();
|
||||
|
||||
|
||||
G4double Tkin = step.GetPostStepPoint()->GetKineticEnergy();
|
||||
G4ParticleDefinition* thePartDef= const_cast<G4ParticleDefinition*> (track.GetDynamicParticle()->GetDefinition());
|
||||
G4double weight_correction=G4AdjointCSManager::GetAdjointCSManager()->GetContinuousWeightCorrection(thePartDef,
|
||||
preStepKinEnergy,Tkin, currentCouple,length);
|
||||
|
||||
|
||||
|
||||
G4ParticleDefinition* thePartDef = const_cast<G4ParticleDefinition*>(
|
||||
track.GetDynamicParticle()->GetDefinition());
|
||||
G4double weight_correction = fCSManager->GetContinuousWeightCorrection(
|
||||
thePartDef, fPreStepKinEnergy, Tkin, fCurrentCouple, length);
|
||||
|
||||
//Caution!!!
|
||||
// It is important to select the weight of the post_step_point
|
||||
// as the current weight and not the weight of the track, as t
|
||||
// the weight of the track is changed after having applied all
|
||||
// the along_step_do_it.
|
||||
// Caution!!!
|
||||
// It is important to select the weight of the post_step_point as the current
|
||||
// weight and not the weight of the track, as the weight of the track is
|
||||
// changed after having applied all the along_step_do_it.
|
||||
G4double new_weight =
|
||||
weight_correction * step.GetPostStepPoint()->GetWeight();
|
||||
|
||||
// G4double new_weight=weight_correction*track.GetWeight(); //old
|
||||
G4double new_weight=weight_correction*step.GetPostStepPoint()->GetWeight();
|
||||
|
||||
|
||||
|
||||
//if (weight_correction >2.) new_weight=1.e-300;
|
||||
|
||||
|
||||
//The following test check for zero weight.
|
||||
//This happens after weight correction of gamma for photo electric effect.
|
||||
//When the new weight is 0 it will be later on consider as nan by G4.
|
||||
//Therefore we do put a lower limit of 1.e-300. for new_weight
|
||||
//Correction by L.Desorgher on 15 July 2009
|
||||
if (new_weight==0 || (new_weight<=0 && new_weight>0)){
|
||||
//G4cout<<new_weight<<'\t'<<weight_correction<<'\t'<<track.GetWeight()<<G4endl;
|
||||
new_weight=1.e-300;
|
||||
// The following test check for zero weight.
|
||||
// This happens after weight correction of gamma for photo electric effect.
|
||||
// When the new weight is 0 it will be later on considered as NaN by G4.
|
||||
// Therefore we put a lower limit of 1.e-300. for new_weight
|
||||
if(new_weight == 0. || (new_weight <= 0. && new_weight > 0.))
|
||||
{
|
||||
new_weight = 1.e-300;
|
||||
}
|
||||
|
||||
//G4cout<<new_weight<<'\t'<<weight_correction<<'\t'<<track.GetWeight()<<G4endl;
|
||||
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
|
||||
|
||||
return fParticleChange;
|
||||
}
|
||||
|
||||
}
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointAlongStepWeightCorrection::GetContinuousStepLimit(const G4Track& track,
|
||||
G4double , G4double , G4double& )
|
||||
{
|
||||
G4double x = DBL_MAX;
|
||||
G4double G4AdjointAlongStepWeightCorrection::GetContinuousStepLimit(
|
||||
const G4Track& track, G4double, G4double, G4double&)
|
||||
{
|
||||
DefineMaterial(track.GetMaterialCutsCouple());
|
||||
preStepKinEnergy = track.GetKineticEnergy();
|
||||
return x;
|
||||
fPreStepKinEnergy = track.GetKineticEnergy();
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
@@ -23,414 +23,319 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4AdjointBremsstrahlungModel.hh"
|
||||
|
||||
#include "G4AdjointCSManager.hh"
|
||||
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
#include "G4Integrator.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4AdjointElectron.hh"
|
||||
#include "G4AdjointGamma.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Timer.hh"
|
||||
#include "G4EmModelManager.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SeltzerBergerModel.hh"
|
||||
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointBremsstrahlungModel::G4AdjointBremsstrahlungModel(G4VEmModel* aModel):
|
||||
G4VEmAdjointModel("AdjointeBremModel")
|
||||
{
|
||||
SetUseMatrix(false);
|
||||
SetUseMatrixPerElement(false);
|
||||
|
||||
theDirectStdBremModel = aModel;
|
||||
theDirectEMModel=theDirectStdBremModel;
|
||||
theEmModelManagerForFwdModels = new G4EmModelManager();
|
||||
isDirectModelInitialised = false;
|
||||
G4VEmFluctuationModel* f=0;
|
||||
G4Region* r=0;
|
||||
theEmModelManagerForFwdModels->AddEmModel(1, theDirectStdBremModel, f, r);
|
||||
|
||||
SetApplyCutInRange(true);
|
||||
highKinEnergy= 1.*GeV;
|
||||
lowKinEnergy = 1.0*keV;
|
||||
|
||||
lastCZ =0.;
|
||||
|
||||
|
||||
theAdjEquivOfDirectPrimPartDef =G4AdjointElectron::AdjointElectron();
|
||||
theAdjEquivOfDirectSecondPartDef=G4AdjointGamma::AdjointGamma();
|
||||
theDirectPrimaryPartDef=G4Electron::Electron();
|
||||
second_part_of_same_type=false;
|
||||
|
||||
|
||||
CS_biasing_factor =1.;
|
||||
|
||||
|
||||
G4AdjointBremsstrahlungModel::G4AdjointBremsstrahlungModel(G4VEmModel* aModel)
|
||||
: G4VEmAdjointModel("AdjointeBremModel")
|
||||
{
|
||||
fDirectModel = aModel;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointBremsstrahlungModel::G4AdjointBremsstrahlungModel():
|
||||
G4VEmAdjointModel("AdjointeBremModel")
|
||||
G4AdjointBremsstrahlungModel::G4AdjointBremsstrahlungModel()
|
||||
: G4VEmAdjointModel("AdjointeBremModel")
|
||||
{
|
||||
fDirectModel = new G4SeltzerBergerModel();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointBremsstrahlungModel::Initialize()
|
||||
{
|
||||
SetUseMatrix(false);
|
||||
SetUseMatrixPerElement(false);
|
||||
|
||||
theDirectStdBremModel = new G4SeltzerBergerModel();
|
||||
theDirectEMModel=theDirectStdBremModel;
|
||||
theEmModelManagerForFwdModels = new G4EmModelManager();
|
||||
isDirectModelInitialised = false;
|
||||
G4VEmFluctuationModel* f=0;
|
||||
G4Region* r=0;
|
||||
theEmModelManagerForFwdModels->AddEmModel(1, theDirectStdBremModel, f, r);
|
||||
// theDirectPenelopeBremModel =0;
|
||||
fEmModelManagerForFwdModels = new G4EmModelManager();
|
||||
fEmModelManagerForFwdModels->AddEmModel(1, fDirectModel, nullptr, nullptr);
|
||||
SetApplyCutInRange(true);
|
||||
highKinEnergy= 1.*GeV;
|
||||
lowKinEnergy = 1.0*keV;
|
||||
lastCZ =0.;
|
||||
theAdjEquivOfDirectPrimPartDef =G4AdjointElectron::AdjointElectron();
|
||||
theAdjEquivOfDirectSecondPartDef=G4AdjointGamma::AdjointGamma();
|
||||
theDirectPrimaryPartDef=G4Electron::Electron();
|
||||
second_part_of_same_type=false;
|
||||
|
||||
fElectron = G4Electron::Electron();
|
||||
fGamma = G4Gamma::Gamma();
|
||||
|
||||
fAdjEquivDirectPrimPart = G4AdjointElectron::AdjointElectron();
|
||||
fAdjEquivDirectSecondPart = G4AdjointGamma::AdjointGamma();
|
||||
fDirectPrimaryPart = fElectron;
|
||||
fSecondPartSameType = false;
|
||||
|
||||
fCSManager = G4AdjointCSManager::GetAdjointCSManager();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointBremsstrahlungModel::~G4AdjointBremsstrahlungModel()
|
||||
{if (theDirectStdBremModel) delete theDirectStdBremModel;
|
||||
if (theEmModelManagerForFwdModels) delete theEmModelManagerForFwdModels;
|
||||
{
|
||||
if(fEmModelManagerForFwdModels)
|
||||
delete fEmModelManagerForFwdModels;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointBremsstrahlungModel::SampleSecondaries(const G4Track& aTrack,
|
||||
G4bool IsScatProjToProjCase,
|
||||
G4ParticleChange* fParticleChange)
|
||||
void G4AdjointBremsstrahlungModel::SampleSecondaries(
|
||||
const G4Track& aTrack, G4bool isScatProjToProj,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
if (!UseMatrix) return RapidSampleSecondaries(aTrack,IsScatProjToProjCase,fParticleChange);
|
||||
if(!fUseMatrix)
|
||||
return RapidSampleSecondaries(aTrack, isScatProjToProj, fParticleChange);
|
||||
|
||||
const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
|
||||
DefineCurrentMaterial(aTrack.GetMaterialCutsCouple());
|
||||
|
||||
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimTotalEnergy = theAdjointPrimary->GetTotalEnergy();
|
||||
|
||||
if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
|
||||
return;
|
||||
}
|
||||
|
||||
G4double projectileKinEnergy = SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy,
|
||||
IsScatProjToProjCase);
|
||||
//Weight correction
|
||||
//-----------------------
|
||||
CorrectPostStepWeight(fParticleChange,
|
||||
aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy,
|
||||
projectileKinEnergy,
|
||||
IsScatProjToProjCase);
|
||||
|
||||
|
||||
//Kinematic
|
||||
//---------
|
||||
G4double projectileM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0+projectileKinEnergy;
|
||||
G4double projectileP2 = projectileTotalEnergy*projectileTotalEnergy - projectileM0*projectileM0;
|
||||
G4double projectileP = std::sqrt(projectileP2);
|
||||
|
||||
|
||||
//Angle of the gamma direction with the projectile taken from G4eBremsstrahlungModel
|
||||
//------------------------------------------------
|
||||
const G4DynamicParticle* theAdjointPrimary = aTrack.GetDynamicParticle();
|
||||
DefineCurrentMaterial(aTrack.GetMaterialCutsCouple());
|
||||
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimTotalEnergy = theAdjointPrimary->GetTotalEnergy();
|
||||
|
||||
if(adjointPrimKinEnergy > GetHighEnergyLimit() * 0.999)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
G4double projectileKinEnergy =
|
||||
SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy, isScatProjToProj);
|
||||
|
||||
// Weight correction
|
||||
CorrectPostStepWeight(fParticleChange, aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy, projectileKinEnergy,
|
||||
isScatProjToProj);
|
||||
|
||||
// Kinematic
|
||||
G4double projectileM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0 + projectileKinEnergy;
|
||||
G4double projectileP2 =
|
||||
projectileTotalEnergy * projectileTotalEnergy - projectileM0 * projectileM0;
|
||||
G4double projectileP = std::sqrt(projectileP2);
|
||||
|
||||
// Angle of the gamma direction with the projectile taken from
|
||||
// G4eBremsstrahlungModel
|
||||
G4double u;
|
||||
const G4double a1 = 0.625 , a2 = 3.*a1 , d = 27. ;
|
||||
if(0.25 > G4UniformRand())
|
||||
u = -std::log(G4UniformRand() * G4UniformRand()) / 0.625;
|
||||
else
|
||||
u = -std::log(G4UniformRand() * G4UniformRand()) / 1.875;
|
||||
|
||||
if (9./(9.+d) > G4UniformRand()) u = - std::log(G4UniformRand()*G4UniformRand())/a1;
|
||||
else u = - std::log(G4UniformRand()*G4UniformRand())/a2;
|
||||
G4double theta = u * electron_mass_c2 / projectileTotalEnergy;
|
||||
G4double sint = std::sin(theta);
|
||||
G4double cost = std::cos(theta);
|
||||
|
||||
G4double theta = u*electron_mass_c2/projectileTotalEnergy;
|
||||
G4double phi = twopi * G4UniformRand();
|
||||
|
||||
G4double sint = std::sin(theta);
|
||||
G4double cost = std::cos(theta);
|
||||
|
||||
G4double phi = twopi * G4UniformRand() ;
|
||||
|
||||
G4ThreeVector projectileMomentum;
|
||||
projectileMomentum=G4ThreeVector(std::cos(phi)*sint,std::sin(phi)*sint,cost)*projectileP; //gamma frame
|
||||
if (IsScatProjToProjCase) {//the adjoint primary is the scattered e-
|
||||
G4ThreeVector gammaMomentum = (projectileTotalEnergy-adjointPrimTotalEnergy)*G4ThreeVector(0.,0.,1.);
|
||||
G4ThreeVector dirProd=projectileMomentum-gammaMomentum;
|
||||
G4double cost1 = std::cos(dirProd.angle(projectileMomentum));
|
||||
G4double sint1 = std::sqrt(1.-cost1*cost1);
|
||||
projectileMomentum=G4ThreeVector(std::cos(phi)*sint1,std::sin(phi)*sint1,cost1)*projectileP;
|
||||
|
||||
G4ThreeVector projectileMomentum =
|
||||
G4ThreeVector(std::cos(phi) * sint, std::sin(phi) * sint, cost) *
|
||||
projectileP; // gamma frame
|
||||
if(isScatProjToProj)
|
||||
{ // the adjoint primary is the scattered e-
|
||||
G4ThreeVector gammaMomentum =
|
||||
(projectileTotalEnergy - adjointPrimTotalEnergy) *
|
||||
G4ThreeVector(0., 0., 1.);
|
||||
G4ThreeVector dirProd = projectileMomentum - gammaMomentum;
|
||||
G4double cost1 = std::cos(dirProd.angle(projectileMomentum));
|
||||
G4double sint1 = std::sqrt(1. - cost1 * cost1);
|
||||
projectileMomentum =
|
||||
G4ThreeVector(std::cos(phi) * sint1, std::sin(phi) * sint1, cost1) *
|
||||
projectileP;
|
||||
}
|
||||
|
||||
|
||||
projectileMomentum.rotateUz(theAdjointPrimary->GetMomentumDirection());
|
||||
|
||||
|
||||
|
||||
if (!IsScatProjToProjCase ){ //kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,projectileMomentum));
|
||||
|
||||
if(!isScatProjToProj)
|
||||
{ // kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(
|
||||
new G4DynamicParticle(fAdjEquivDirectPrimPart, projectileMomentum));
|
||||
}
|
||||
else {
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointBremsstrahlungModel::RapidSampleSecondaries(const G4Track& aTrack,
|
||||
G4bool IsScatProjToProjCase,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
void G4AdjointBremsstrahlungModel::RapidSampleSecondaries(
|
||||
const G4Track& aTrack, G4bool isScatProjToProj,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
const G4DynamicParticle* theAdjointPrimary = aTrack.GetDynamicParticle();
|
||||
DefineCurrentMaterial(aTrack.GetMaterialCutsCouple());
|
||||
|
||||
const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
|
||||
DefineCurrentMaterial(aTrack.GetMaterialCutsCouple());
|
||||
|
||||
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimTotalEnergy = theAdjointPrimary->GetTotalEnergy();
|
||||
|
||||
if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
|
||||
return;
|
||||
}
|
||||
|
||||
G4double projectileKinEnergy =0.;
|
||||
G4double gammaEnergy=0.;
|
||||
G4double diffCSUsed=0.;
|
||||
if (!IsScatProjToProjCase){
|
||||
gammaEnergy=adjointPrimKinEnergy;
|
||||
G4double Emax = GetSecondAdjEnergyMaxForProdToProjCase(adjointPrimKinEnergy);
|
||||
G4double Emin= GetSecondAdjEnergyMinForProdToProjCase(adjointPrimKinEnergy);;
|
||||
if (Emin>=Emax) return;
|
||||
projectileKinEnergy=Emin*std::pow(Emax/Emin,G4UniformRand());
|
||||
diffCSUsed=CS_biasing_factor*lastCZ/projectileKinEnergy;
|
||||
|
||||
}
|
||||
else { G4double Emax = GetSecondAdjEnergyMaxForScatProjToProjCase(adjointPrimKinEnergy);
|
||||
G4double Emin = GetSecondAdjEnergyMinForScatProjToProjCase(adjointPrimKinEnergy,currentTcutForDirectSecond);
|
||||
if (Emin>=Emax) return;
|
||||
G4double f1=(Emin-adjointPrimKinEnergy)/Emin;
|
||||
G4double f2=(Emax-adjointPrimKinEnergy)/Emax/f1;
|
||||
projectileKinEnergy=adjointPrimKinEnergy/(1.-f1*std::pow(f2,G4UniformRand()));
|
||||
gammaEnergy=projectileKinEnergy-adjointPrimKinEnergy;
|
||||
diffCSUsed=lastCZ*adjointPrimKinEnergy/projectileKinEnergy/gammaEnergy;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Weight correction
|
||||
//-----------------------
|
||||
//First w_corr is set to the ratio between adjoint total CS and fwd total CS
|
||||
//if this has to be done in the model
|
||||
//For the case of forced interaction this will be done in the PostStepDoIt of the
|
||||
//forced interaction
|
||||
//It is important to set the weight before the vreation of the secondary
|
||||
//
|
||||
G4double w_corr=additional_weight_correction_factor_for_post_step_outside_model;
|
||||
if (correct_weight_for_post_step_in_model) {
|
||||
w_corr=G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection();
|
||||
}
|
||||
//G4cout<<"Correction factor start in brem model "<<w_corr<<std::endl;
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimTotalEnergy = theAdjointPrimary->GetTotalEnergy();
|
||||
|
||||
if(adjointPrimKinEnergy > GetHighEnergyLimit() * 0.999)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Then another correction is needed due to the fact that a biaised differential CS has been used rather than the one consistent with the direct model
|
||||
//Here we consider the true diffCS as the one obtained by the numericla differentiation over Tcut of the direct CS, corrected by the Migdal term.
|
||||
//Basically any other differential CS diffCS could be used here (example Penelope).
|
||||
G4double projectileKinEnergy = 0.;
|
||||
G4double gammaEnergy = 0.;
|
||||
G4double diffCSUsed = 0.;
|
||||
if(!isScatProjToProj)
|
||||
{
|
||||
gammaEnergy = adjointPrimKinEnergy;
|
||||
G4double Emax = GetSecondAdjEnergyMaxForProdToProj(adjointPrimKinEnergy);
|
||||
G4double Emin = GetSecondAdjEnergyMinForProdToProj(adjointPrimKinEnergy);
|
||||
if(Emin >= Emax)
|
||||
return;
|
||||
projectileKinEnergy = Emin * std::pow(Emax / Emin, G4UniformRand());
|
||||
diffCSUsed = fCsBiasingFactor * fLastCZ / projectileKinEnergy;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double Emax =
|
||||
GetSecondAdjEnergyMaxForScatProjToProj(adjointPrimKinEnergy);
|
||||
G4double Emin =
|
||||
GetSecondAdjEnergyMinForScatProjToProj(adjointPrimKinEnergy, fTcutSecond);
|
||||
if(Emin >= Emax)
|
||||
return;
|
||||
G4double f1 = (Emin - adjointPrimKinEnergy) / Emin;
|
||||
G4double f2 = (Emax - adjointPrimKinEnergy) / Emax / f1;
|
||||
projectileKinEnergy =
|
||||
adjointPrimKinEnergy / (1. - f1 * std::pow(f2, G4UniformRand()));
|
||||
gammaEnergy = projectileKinEnergy - adjointPrimKinEnergy;
|
||||
diffCSUsed =
|
||||
fLastCZ * adjointPrimKinEnergy / projectileKinEnergy / gammaEnergy;
|
||||
}
|
||||
|
||||
G4double diffCS = DiffCrossSectionPerVolumePrimToSecond(currentMaterial, projectileKinEnergy, gammaEnergy);
|
||||
/*G4cout<<"diffCS "<<diffCS <<std::endl;
|
||||
G4cout<<"diffCS_Used "<<diffCSUsed <<std::endl;*/
|
||||
w_corr*=diffCS/diffCSUsed;
|
||||
// Weight correction:
|
||||
// First w_corr is set to the ratio between adjoint total CS and fwd total CS
|
||||
// if this has to be done in the model.
|
||||
// For the case of forced interaction this will be done in the PostStepDoIt of
|
||||
// the forced interaction. It is important to set the weight before the
|
||||
// creation of the secondary
|
||||
G4double w_corr = fOutsideWeightFactor;
|
||||
if(fInModelWeightCorr)
|
||||
{
|
||||
w_corr = fCSManager->GetPostStepWeightCorrection();
|
||||
}
|
||||
|
||||
// Then another correction is needed due to the fact that a biaised
|
||||
// differential CS has been used rather than the one consistent with the
|
||||
// direct model Here we consider the true diffCS as the one obtained by the
|
||||
// numerical differentiation over Tcut of the direct CS, corrected by the
|
||||
// Migdal term. Basically any other differential CS could be used here
|
||||
// (example Penelope).
|
||||
G4double diffCS = DiffCrossSectionPerVolumePrimToSecond(
|
||||
fCurrentMaterial, projectileKinEnergy, gammaEnergy);
|
||||
w_corr *= diffCS / diffCSUsed;
|
||||
|
||||
G4double new_weight = aTrack.GetWeight()*w_corr;
|
||||
/*G4cout<<"New weight brem "<<new_weight<<std::endl;
|
||||
G4cout<<"Weight correction brem "<<w_corr<<std::endl;*/
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
|
||||
//Kinematic
|
||||
//---------
|
||||
G4double projectileM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0+projectileKinEnergy;
|
||||
G4double projectileP2 = projectileTotalEnergy*projectileTotalEnergy - projectileM0*projectileM0;
|
||||
G4double projectileP = std::sqrt(projectileP2);
|
||||
|
||||
G4double new_weight = aTrack.GetWeight() * w_corr;
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
|
||||
//Use the angular model of the forward model to generate the gamma direction
|
||||
//---------------------------------------------------------------------------
|
||||
//Dum dynamic particle to use the model
|
||||
G4DynamicParticle * aDynPart = new G4DynamicParticle(G4Electron::Electron(),G4ThreeVector(0.,0.,1.)*projectileP);
|
||||
// Kinematic
|
||||
G4double projectileM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0 + projectileKinEnergy;
|
||||
G4double projectileP2 =
|
||||
projectileTotalEnergy * projectileTotalEnergy - projectileM0 * projectileM0;
|
||||
G4double projectileP = std::sqrt(projectileP2);
|
||||
|
||||
//Get the element from the direct model
|
||||
const G4Element* elm = theDirectEMModel->SelectRandomAtom(currentCouple,G4Electron::Electron(),
|
||||
projectileKinEnergy,currentTcutForDirectSecond);
|
||||
G4int Z=elm->GetZasInt();
|
||||
G4double energy = aDynPart->GetTotalEnergy()-gammaEnergy;
|
||||
G4ThreeVector projectileMomentum =
|
||||
theDirectEMModel->GetAngularDistribution()->SampleDirection(aDynPart,energy,Z,currentMaterial)*projectileP;
|
||||
// Use the angular model of the forward model to generate the gamma direction
|
||||
// Dummy dynamic particle to use the model
|
||||
G4DynamicParticle* aDynPart =
|
||||
new G4DynamicParticle(fElectron, G4ThreeVector(0., 0., 1.) * projectileP);
|
||||
|
||||
// Get the element from the direct model
|
||||
const G4Element* elm = fDirectModel->SelectRandomAtom(
|
||||
fCurrentCouple, fElectron, projectileKinEnergy, fTcutSecond);
|
||||
G4int Z = elm->GetZasInt();
|
||||
G4double energy = aDynPart->GetTotalEnergy() - gammaEnergy;
|
||||
G4ThreeVector projectileMomentum =
|
||||
fDirectModel->GetAngularDistribution()->SampleDirection(aDynPart, energy, Z,
|
||||
fCurrentMaterial) * projectileP;
|
||||
G4double phi = projectileMomentum.getPhi();
|
||||
|
||||
/*
|
||||
//Angle of the gamma direction with the projectile taken from G4eBremsstrahlungModel
|
||||
//------------------------------------------------
|
||||
G4double u;
|
||||
const G4double a1 = 0.625 , a2 = 3.*a1 , d = 27. ;
|
||||
|
||||
if (9./(9.+d) > G4UniformRand()) u = - std::log(G4UniformRand()*G4UniformRand())/a1;
|
||||
else u = - std::log(G4UniformRand()*G4UniformRand())/a2;
|
||||
|
||||
G4double theta = u*electron_mass_c2/projectileTotalEnergy;
|
||||
|
||||
G4double sint = std::sin(theta);
|
||||
G4double cost = std::cos(theta);
|
||||
|
||||
G4double phi = twopi * G4UniformRand() ;
|
||||
G4ThreeVector projectileMomentum;
|
||||
projectileMomentum=G4ThreeVector(std::cos(phi)*sint,std::sin(phi)*sint,cost)*projectileP; //gamma frame
|
||||
*/
|
||||
if (IsScatProjToProjCase) {//the adjoint primary is the scattered e-
|
||||
G4ThreeVector gammaMomentum = (projectileTotalEnergy-adjointPrimTotalEnergy)*G4ThreeVector(0.,0.,1.);
|
||||
G4ThreeVector dirProd=projectileMomentum-gammaMomentum;
|
||||
G4double cost1 = std::cos(dirProd.angle(projectileMomentum));
|
||||
G4double sint1 = std::sqrt(1.-cost1*cost1);
|
||||
projectileMomentum=G4ThreeVector(std::cos(phi)*sint1,std::sin(phi)*sint1,cost1)*projectileP;
|
||||
if(isScatProjToProj)
|
||||
{ // the adjoint primary is the scattered e-
|
||||
G4ThreeVector gammaMomentum =
|
||||
(projectileTotalEnergy - adjointPrimTotalEnergy) *
|
||||
G4ThreeVector(0., 0., 1.);
|
||||
G4ThreeVector dirProd = projectileMomentum - gammaMomentum;
|
||||
G4double cost1 = std::cos(dirProd.angle(projectileMomentum));
|
||||
G4double sint1 = std::sqrt(1. - cost1 * cost1);
|
||||
projectileMomentum =
|
||||
G4ThreeVector(std::cos(phi) * sint1, std::sin(phi) * sint1, cost1) *
|
||||
projectileP;
|
||||
}
|
||||
|
||||
projectileMomentum.rotateUz(theAdjointPrimary->GetMomentumDirection());
|
||||
|
||||
if (!IsScatProjToProjCase ){ //kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,projectileMomentum));
|
||||
}
|
||||
else {
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointBremsstrahlungModel::DiffCrossSectionPerVolumePrimToSecond(const G4Material* aMaterial,
|
||||
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
|
||||
G4double kinEnergyProd // kinetic energy of the secondary particle
|
||||
)
|
||||
{if (!isDirectModelInitialised) {
|
||||
theEmModelManagerForFwdModels->Initialise(G4Electron::Electron(),G4Gamma::Gamma(),1.,0);
|
||||
isDirectModelInitialised =true;
|
||||
}
|
||||
/*
|
||||
return DiffCrossSectionPerVolumePrimToSecondApproximated2(aMaterial,
|
||||
kinEnergyProj,
|
||||
kinEnergyProd);
|
||||
*/
|
||||
return G4VEmAdjointModel::DiffCrossSectionPerVolumePrimToSecond(aMaterial,
|
||||
kinEnergyProj,
|
||||
kinEnergyProd);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointBremsstrahlungModel::DiffCrossSectionPerVolumePrimToSecondApproximated1(
|
||||
const G4Material* aMaterial,
|
||||
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
|
||||
G4double kinEnergyProd // kinetic energy of the secondary particle
|
||||
)
|
||||
{
|
||||
G4double dCrossEprod=0.;
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProjCase(kinEnergyProd);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProjCase(kinEnergyProd);
|
||||
|
||||
|
||||
//In this approximation we consider that the secondary gammas are sampled with 1/Egamma energy distribution
|
||||
//This is what is applied in the discrete standard model before the rejection test that make a correction
|
||||
//The application of the same rejection function is not possible here.
|
||||
//The differentiation of the CS over Ecut does not produce neither a good differential CS. That is due to the
|
||||
// fact that in the discrete model the differential CS and the integrated CS are both fitted but separatly and
|
||||
// therefore do not allow a correct numerical differentiation of the integrated CS to get the differential one.
|
||||
// In the future we plan to use the brem secondary spectra from the G4Penelope implementation
|
||||
|
||||
if (kinEnergyProj>Emin_proj && kinEnergyProj<=Emax_proj){
|
||||
G4double sigma=theDirectEMModel->CrossSectionPerVolume(aMaterial,theDirectPrimaryPartDef,kinEnergyProj,1.*keV);
|
||||
dCrossEprod=sigma/kinEnergyProd/std::log(kinEnergyProj/keV);
|
||||
}
|
||||
return dCrossEprod;
|
||||
|
||||
if(!isScatProjToProj)
|
||||
{ // kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(
|
||||
new G4DynamicParticle(fAdjEquivDirectPrimPart, projectileMomentum));
|
||||
}
|
||||
else
|
||||
{
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointBremsstrahlungModel::DiffCrossSectionPerVolumePrimToSecondApproximated2(
|
||||
const G4Material* material,
|
||||
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
|
||||
G4double kinEnergyProd // kinetic energy of the secondary particle
|
||||
)
|
||||
G4double G4AdjointBremsstrahlungModel::DiffCrossSectionPerVolumePrimToSecond(
|
||||
const G4Material* aMaterial,
|
||||
G4double kinEnergyProj, // kin energy of primary before interaction
|
||||
G4double kinEnergyProd // kinetic energy of the secondary particle
|
||||
)
|
||||
{
|
||||
//In this approximation we derive the direct cross section over Tcut=gamma energy, en after apply the Migdla correction factor
|
||||
//used in the direct model
|
||||
|
||||
G4double dCrossEprod=0.;
|
||||
|
||||
const G4ElementVector* theElementVector = material->GetElementVector();
|
||||
const double* theAtomNumDensityVector = material->GetAtomicNumDensityVector();
|
||||
G4double dum=0.;
|
||||
G4double E1=kinEnergyProd,E2=kinEnergyProd*1.001;
|
||||
G4double dE=E2-E1;
|
||||
for (size_t i=0; i<material->GetNumberOfElements(); i++) {
|
||||
G4double C1=theDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,(*theElementVector)[i]->GetZ(),dum ,E1);
|
||||
G4double C2=theDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,(*theElementVector)[i]->GetZ(),dum,E2);
|
||||
dCrossEprod += theAtomNumDensityVector[i] * (C1-C2)/dE;
|
||||
}
|
||||
|
||||
return dCrossEprod;
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointBremsstrahlungModel::AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
|
||||
G4double primEnergy,
|
||||
G4bool IsScatProjToProjCase)
|
||||
{ if (!isDirectModelInitialised) {
|
||||
theEmModelManagerForFwdModels->Initialise(G4Electron::Electron(),G4Gamma::Gamma(),1.,0);
|
||||
isDirectModelInitialised =true;
|
||||
if(!fIsDirectModelInitialised)
|
||||
{
|
||||
fEmModelManagerForFwdModels->Initialise(fElectron, fGamma, 1., 0);
|
||||
fIsDirectModelInitialised = true;
|
||||
}
|
||||
if (UseMatrix) return G4VEmAdjointModel::AdjointCrossSection(aCouple,primEnergy,IsScatProjToProjCase);
|
||||
return G4VEmAdjointModel::DiffCrossSectionPerVolumePrimToSecond(
|
||||
aMaterial, kinEnergyProj, kinEnergyProd);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4double G4AdjointBremsstrahlungModel::AdjointCrossSection(
|
||||
const G4MaterialCutsCouple* aCouple, G4double primEnergy,
|
||||
G4bool isScatProjToProj)
|
||||
{
|
||||
static constexpr G4double maxEnergy = 100. * MeV / 2.718281828459045;
|
||||
// 2.78.. == std::exp(1.)
|
||||
if(!fIsDirectModelInitialised)
|
||||
{
|
||||
fEmModelManagerForFwdModels->Initialise(fElectron, fGamma, 1., 0);
|
||||
fIsDirectModelInitialised = true;
|
||||
}
|
||||
if(fUseMatrix)
|
||||
return G4VEmAdjointModel::AdjointCrossSection(aCouple, primEnergy,
|
||||
isScatProjToProj);
|
||||
DefineCurrentMaterial(aCouple);
|
||||
G4double Cross=0.;
|
||||
lastCZ=theDirectEMModel->CrossSectionPerVolume(aCouple->GetMaterial(),theDirectPrimaryPartDef,100.*MeV,100.*MeV/std::exp(1.));//this give the constant above
|
||||
|
||||
if (!IsScatProjToProjCase ){
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProjCase(primEnergy);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProjCase(primEnergy);
|
||||
if (Emax_proj>Emin_proj && primEnergy > currentTcutForDirectSecond) Cross= CS_biasing_factor*lastCZ*std::log(Emax_proj/Emin_proj);
|
||||
}
|
||||
else {
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForScatProjToProjCase(primEnergy);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForScatProjToProjCase(primEnergy,currentTcutForDirectSecond);
|
||||
if (Emax_proj>Emin_proj) Cross= lastCZ*std::log((Emax_proj-primEnergy)*Emin_proj/Emax_proj/(Emin_proj-primEnergy));
|
||||
|
||||
}
|
||||
return Cross;
|
||||
}
|
||||
G4double Cross = 0.;
|
||||
// this gives the constant above
|
||||
fLastCZ = fDirectModel->CrossSectionPerVolume(
|
||||
aCouple->GetMaterial(), fDirectPrimaryPart, 100. * MeV, maxEnergy);
|
||||
|
||||
G4double G4AdjointBremsstrahlungModel::GetAdjointCrossSection(const G4MaterialCutsCouple* aCouple,
|
||||
G4double primEnergy,
|
||||
G4bool IsScatProjToProjCase)
|
||||
{
|
||||
return AdjointCrossSection(aCouple, primEnergy,IsScatProjToProjCase);
|
||||
lastCZ=theDirectEMModel->CrossSectionPerVolume(aCouple->GetMaterial(),theDirectPrimaryPartDef,100.*MeV,100.*MeV/std::exp(1.));//this give the constant above
|
||||
return G4VEmAdjointModel::GetAdjointCrossSection(aCouple, primEnergy,IsScatProjToProjCase);
|
||||
|
||||
if(!isScatProjToProj)
|
||||
{
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProj(primEnergy);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProj(primEnergy);
|
||||
if(Emax_proj > Emin_proj && primEnergy > fTcutSecond)
|
||||
Cross = fCsBiasingFactor * fLastCZ * std::log(Emax_proj / Emin_proj);
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForScatProjToProj(primEnergy);
|
||||
G4double Emin_proj =
|
||||
GetSecondAdjEnergyMinForScatProjToProj(primEnergy, fTcutSecond);
|
||||
if(Emax_proj > Emin_proj)
|
||||
Cross = fLastCZ * std::log((Emax_proj - primEnergy) * Emin_proj /
|
||||
Emax_proj / (Emin_proj - primEnergy));
|
||||
}
|
||||
return Cross;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,177 +23,198 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4AdjointCSMatrix.hh"
|
||||
|
||||
#include "G4AdjointInterpolator.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
|
||||
#include "G4AdjointCSMatrix.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4AdjointInterpolator.hh"
|
||||
///////////////////////////////////////////////////////
|
||||
G4AdjointCSMatrix::G4AdjointCSMatrix(G4bool aBool) { fScatProjToProj = aBool; }
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointCSMatrix::G4AdjointCSMatrix(G4bool aBool){
|
||||
theLogPrimEnergyVector.clear();
|
||||
theLogCrossSectionVector.clear();
|
||||
theLogSecondEnergyMatrix.clear();
|
||||
theLogProbMatrix.clear();
|
||||
theLogProbMatrixIndex.clear();
|
||||
log0Vector.clear();
|
||||
nb_of_PrimEnergy=0;
|
||||
is_scat_proj_to_proj_case =aBool;
|
||||
dlog =0;
|
||||
G4AdjointCSMatrix::~G4AdjointCSMatrix()
|
||||
{
|
||||
fLogPrimEnergyVector.clear();
|
||||
fLogCrossSectionVector.clear();
|
||||
|
||||
for (auto p : fLogSecondEnergyMatrix) {
|
||||
p->clear();
|
||||
delete p;
|
||||
p = nullptr;
|
||||
}
|
||||
fLogSecondEnergyMatrix.clear();
|
||||
|
||||
for (auto p : fLogProbMatrix) {
|
||||
p->clear();
|
||||
delete p;
|
||||
p = nullptr;
|
||||
}
|
||||
fLogProbMatrix.clear();
|
||||
|
||||
for (auto p : fLogProbMatrixIndex) {
|
||||
if (p) {
|
||||
p->clear();
|
||||
delete p;
|
||||
p = nullptr;
|
||||
}
|
||||
}
|
||||
fLogProbMatrixIndex.clear();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointCSMatrix::~G4AdjointCSMatrix(){
|
||||
theLogPrimEnergyVector.clear();
|
||||
theLogCrossSectionVector.clear();
|
||||
theLogSecondEnergyMatrix.clear();
|
||||
theLogProbMatrix.clear();
|
||||
}
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointCSMatrix::Clear()
|
||||
{
|
||||
theLogPrimEnergyVector.clear();
|
||||
theLogCrossSectionVector.clear();
|
||||
theLogSecondEnergyMatrix.clear();
|
||||
theLogProbMatrix.clear();
|
||||
theLogProbMatrixIndex.clear();
|
||||
log0Vector.clear();
|
||||
nb_of_PrimEnergy=0;
|
||||
fLogPrimEnergyVector.clear();
|
||||
fLogCrossSectionVector.clear();
|
||||
fLogSecondEnergyMatrix.clear();
|
||||
fLogProbMatrix.clear();
|
||||
fLogProbMatrixIndex.clear();
|
||||
fLog0Vector.clear();
|
||||
fNbPrimEnergy = 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointCSMatrix::AddData(G4double aLogPrimEnergy,G4double aLogCS, std::vector< double>* aLogSecondEnergyVector,
|
||||
std::vector< double>* aLogProbVector,size_t n_pro_decade){
|
||||
|
||||
G4AdjointInterpolator* theInterpolator=G4AdjointInterpolator::GetInstance();
|
||||
|
||||
//At this time we consider that the energy is increasing monotically
|
||||
theLogPrimEnergyVector.push_back(aLogPrimEnergy);
|
||||
theLogCrossSectionVector.push_back(aLogCS);
|
||||
theLogSecondEnergyMatrix.push_back(aLogSecondEnergyVector);
|
||||
theLogProbMatrix.push_back(aLogProbVector);
|
||||
|
||||
std::vector< size_t>* aLogProbVectorIndex = 0;
|
||||
dlog =0;
|
||||
|
||||
if (n_pro_decade > 0 && aLogProbVector->size()>0) {
|
||||
aLogProbVectorIndex = new std::vector< size_t>();
|
||||
dlog=std::log(10.)/n_pro_decade;
|
||||
G4double log_val = int(std::min((*aLogProbVector)[0],aLogProbVector->back())/dlog)*dlog;
|
||||
log0Vector.push_back(log_val);
|
||||
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
while(log_val<0.) {
|
||||
aLogProbVectorIndex->push_back(theInterpolator->FindPosition(log_val,(*aLogProbVector)));
|
||||
log_val+=dlog;
|
||||
}
|
||||
}
|
||||
else {
|
||||
log0Vector.push_back(0.);
|
||||
}
|
||||
theLogProbMatrixIndex.push_back(aLogProbVectorIndex);
|
||||
|
||||
|
||||
nb_of_PrimEnergy++;
|
||||
|
||||
|
||||
void G4AdjointCSMatrix::AddData(G4double aLogPrimEnergy, G4double aLogCS,
|
||||
std::vector<double>* aLogSecondEnergyVector,
|
||||
std::vector<double>* aLogProbVector,
|
||||
size_t n_pro_decade)
|
||||
{
|
||||
G4AdjointInterpolator* theInterpolator = G4AdjointInterpolator::GetInstance();
|
||||
|
||||
// At this time we consider that the energy is increasing monotically
|
||||
fLogPrimEnergyVector.push_back(aLogPrimEnergy);
|
||||
fLogCrossSectionVector.push_back(aLogCS);
|
||||
fLogSecondEnergyMatrix.push_back(aLogSecondEnergyVector);
|
||||
fLogProbMatrix.push_back(aLogProbVector);
|
||||
|
||||
std::vector<size_t>* aLogProbVectorIndex = nullptr;
|
||||
|
||||
if(n_pro_decade > 0 && !aLogProbVector->empty())
|
||||
{
|
||||
aLogProbVectorIndex = new std::vector<size_t>();
|
||||
G4double dlog = std::log(10.) / n_pro_decade;
|
||||
G4double log_val =
|
||||
int(std::min((*aLogProbVector)[0], aLogProbVector->back()) / dlog) * dlog;
|
||||
fLog0Vector.push_back(log_val);
|
||||
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
while(log_val < 0.)
|
||||
{
|
||||
aLogProbVectorIndex->push_back(
|
||||
theInterpolator->FindPosition(log_val, (*aLogProbVector)));
|
||||
log_val += dlog;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fLog0Vector.push_back(0.);
|
||||
}
|
||||
fLogProbMatrixIndex.push_back(aLogProbVectorIndex);
|
||||
|
||||
++fNbPrimEnergy;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4bool G4AdjointCSMatrix::GetData(unsigned int i, G4double& aLogPrimEnergy,G4double& aLogCS,G4double& log0, std::vector< double>*& aLogSecondEnergyVector,
|
||||
std::vector< double>*& aLogProbVector, std::vector< size_t>*& aLogProbVectorIndex)
|
||||
{ if (i>= nb_of_PrimEnergy) return false;
|
||||
//G4cout<<"Test Get Data "<<G4endl;
|
||||
aLogPrimEnergy = theLogPrimEnergyVector[i];
|
||||
aLogCS = theLogCrossSectionVector[i];
|
||||
aLogSecondEnergyVector = theLogSecondEnergyMatrix[i];
|
||||
aLogProbVector = theLogProbMatrix[i];
|
||||
aLogProbVectorIndex = theLogProbMatrixIndex[i];
|
||||
log0=log0Vector[i];
|
||||
return true;
|
||||
|
||||
G4bool G4AdjointCSMatrix::GetData(unsigned int i, G4double& aLogPrimEnergy,
|
||||
G4double& aLogCS, G4double& log0,
|
||||
std::vector<double>*& aLogSecondEnergyVector,
|
||||
std::vector<double>*& aLogProbVector,
|
||||
std::vector<size_t>*& aLogProbVectorIndex)
|
||||
{
|
||||
if(i >= fNbPrimEnergy)
|
||||
return false;
|
||||
aLogPrimEnergy = fLogPrimEnergyVector[i];
|
||||
aLogCS = fLogCrossSectionVector[i];
|
||||
aLogSecondEnergyVector = fLogSecondEnergyMatrix[i];
|
||||
aLogProbVector = fLogProbMatrix[i];
|
||||
aLogProbVectorIndex = fLogProbMatrixIndex[i];
|
||||
log0 = fLog0Vector[i];
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointCSMatrix::Write(G4String file_name)
|
||||
{ std::fstream FileOutput(file_name, std::ios::out);
|
||||
FileOutput<<std::setiosflags(std::ios::scientific);
|
||||
FileOutput<<std::setprecision(6);
|
||||
FileOutput<<theLogPrimEnergyVector.size()<<G4endl;
|
||||
for (size_t i=0;i<theLogPrimEnergyVector.size();i++){
|
||||
FileOutput<<std::exp(theLogPrimEnergyVector[i])/MeV<<'\t'<<std::exp(theLogCrossSectionVector[i])<<G4endl;
|
||||
size_t j1=0;
|
||||
FileOutput<<theLogSecondEnergyMatrix[i]->size()<<G4endl;
|
||||
for (size_t j=0;j<theLogSecondEnergyMatrix[i]->size();j++){
|
||||
FileOutput<<std::exp((*theLogSecondEnergyMatrix[i])[j]);
|
||||
j1++;
|
||||
if (j1<10) FileOutput<<'\t';
|
||||
else {
|
||||
FileOutput<<G4endl;
|
||||
j1=0;
|
||||
}
|
||||
}
|
||||
if (j1>0) FileOutput<<G4endl;
|
||||
j1=0;
|
||||
FileOutput<<theLogProbMatrix[i]->size()<<G4endl;
|
||||
for (size_t j=0;j<theLogProbMatrix[i]->size();j++){
|
||||
FileOutput<<std::exp((*theLogProbMatrix[i])[j]);
|
||||
j1++;
|
||||
if (j1<10) FileOutput<<'\t';
|
||||
else {
|
||||
FileOutput<<G4endl;
|
||||
j1=0;
|
||||
}
|
||||
}
|
||||
if (j1>0) FileOutput<<G4endl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
std::fstream FileOutput(file_name, std::ios::out);
|
||||
FileOutput << std::setiosflags(std::ios::scientific);
|
||||
FileOutput << std::setprecision(6);
|
||||
FileOutput << fLogPrimEnergyVector.size() << G4endl;
|
||||
for(size_t i = 0; i < fLogPrimEnergyVector.size(); ++i)
|
||||
{
|
||||
FileOutput << std::exp(fLogPrimEnergyVector[i]) / MeV << '\t'
|
||||
<< std::exp(fLogCrossSectionVector[i]) << G4endl;
|
||||
size_t j1 = 0;
|
||||
FileOutput << fLogSecondEnergyMatrix[i]->size() << G4endl;
|
||||
for(size_t j = 0; j < fLogSecondEnergyMatrix[i]->size(); ++j)
|
||||
{
|
||||
FileOutput << std::exp((*fLogSecondEnergyMatrix[i])[j]);
|
||||
++j1;
|
||||
if(j1 < 10)
|
||||
FileOutput << '\t';
|
||||
else
|
||||
{
|
||||
FileOutput << G4endl;
|
||||
j1 = 0;
|
||||
}
|
||||
}
|
||||
if(j1 > 0)
|
||||
FileOutput << G4endl;
|
||||
j1 = 0;
|
||||
FileOutput << fLogProbMatrix[i]->size() << G4endl;
|
||||
for(size_t j = 0; j < fLogProbMatrix[i]->size(); ++j)
|
||||
{
|
||||
FileOutput << std::exp((*fLogProbMatrix[i])[j]);
|
||||
++j1;
|
||||
if(j1 < 10)
|
||||
FileOutput << '\t';
|
||||
else
|
||||
{
|
||||
FileOutput << G4endl;
|
||||
j1 = 0;
|
||||
}
|
||||
}
|
||||
if(j1 > 0)
|
||||
FileOutput << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointCSMatrix::Read(G4String file_name)
|
||||
{ std::fstream FileOutput(file_name, std::ios::in);
|
||||
size_t n1,n2;
|
||||
|
||||
|
||||
theLogPrimEnergyVector.clear();
|
||||
theLogCrossSectionVector.clear();
|
||||
theLogSecondEnergyMatrix.clear();
|
||||
theLogProbMatrix.clear();
|
||||
FileOutput>>n1;
|
||||
for (size_t i=0; i<n1;i++){
|
||||
G4double E,CS;
|
||||
FileOutput>>E>>CS;
|
||||
theLogPrimEnergyVector.push_back(E);
|
||||
theLogCrossSectionVector.push_back(CS);
|
||||
FileOutput>>n2;
|
||||
theLogSecondEnergyMatrix.push_back(new std::vector<G4double>());
|
||||
theLogProbMatrix.push_back(new std::vector<G4double>());
|
||||
|
||||
for (size_t j=0; j<n2;j++){
|
||||
G4double E1;
|
||||
FileOutput>>E1;
|
||||
theLogSecondEnergyMatrix[i]->push_back(E1);
|
||||
}
|
||||
FileOutput>>n2;
|
||||
for (size_t j=0; j<n2;j++){
|
||||
G4double prob;
|
||||
FileOutput>>prob;
|
||||
theLogProbMatrix[i]->push_back(prob);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
std::fstream FileOutput(file_name, std::ios::in);
|
||||
size_t n1, n2;
|
||||
|
||||
fLogPrimEnergyVector.clear();
|
||||
fLogCrossSectionVector.clear();
|
||||
fLogSecondEnergyMatrix.clear();
|
||||
fLogProbMatrix.clear();
|
||||
FileOutput >> n1;
|
||||
for(size_t i = 0; i < n1; ++i)
|
||||
{
|
||||
G4double E, CS;
|
||||
FileOutput >> E >> CS;
|
||||
fLogPrimEnergyVector.push_back(E);
|
||||
fLogCrossSectionVector.push_back(CS);
|
||||
FileOutput >> n2;
|
||||
fLogSecondEnergyMatrix.push_back(new std::vector<G4double>());
|
||||
fLogProbMatrix.push_back(new std::vector<G4double>());
|
||||
|
||||
for(size_t j = 0; j < n2; ++j)
|
||||
{
|
||||
G4double E1;
|
||||
FileOutput >> E1;
|
||||
fLogSecondEnergyMatrix[i]->push_back(E1);
|
||||
}
|
||||
FileOutput >> n2;
|
||||
for(size_t j = 0; j < n2; ++j)
|
||||
{
|
||||
G4double prob;
|
||||
FileOutput >> prob;
|
||||
fLogProbMatrix[i]->push_back(prob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,395 +24,339 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
#include "G4AdjointComptonModel.hh"
|
||||
#include "G4AdjointCSManager.hh"
|
||||
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4Integrator.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4AdjointComptonModel.hh"
|
||||
|
||||
#include "G4AdjointCSManager.hh"
|
||||
#include "G4AdjointElectron.hh"
|
||||
#include "G4AdjointGamma.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4KleinNishinaCompton.hh"
|
||||
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
#include "G4VEmProcess.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointComptonModel::G4AdjointComptonModel():
|
||||
G4VEmAdjointModel("AdjointCompton")
|
||||
|
||||
{ SetApplyCutInRange(false);
|
||||
G4AdjointComptonModel::G4AdjointComptonModel()
|
||||
: G4VEmAdjointModel("AdjointCompton")
|
||||
{
|
||||
SetApplyCutInRange(false);
|
||||
SetUseMatrix(false);
|
||||
SetUseMatrixPerElement(true);
|
||||
SetUseOnlyOneMatrixForAllElements(true);
|
||||
theAdjEquivOfDirectPrimPartDef =G4AdjointGamma::AdjointGamma();
|
||||
theAdjEquivOfDirectSecondPartDef=G4AdjointElectron::AdjointElectron();
|
||||
theDirectPrimaryPartDef=G4Gamma::Gamma();
|
||||
second_part_of_same_type=false;
|
||||
theDirectEMModel=new G4KleinNishinaCompton(G4Gamma::Gamma(),"ComptonDirectModel");
|
||||
G4direct_CS = 0.;
|
||||
fAdjEquivDirectPrimPart = G4AdjointGamma::AdjointGamma();
|
||||
fAdjEquivDirectSecondPart = G4AdjointElectron::AdjointElectron();
|
||||
fDirectPrimaryPart = G4Gamma::Gamma();
|
||||
fSecondPartSameType = false;
|
||||
fDirectModel =
|
||||
new G4KleinNishinaCompton(G4Gamma::Gamma(), "ComptonDirectModel");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointComptonModel::~G4AdjointComptonModel()
|
||||
{;}
|
||||
G4AdjointComptonModel::~G4AdjointComptonModel() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointComptonModel::SampleSecondaries(const G4Track& aTrack,
|
||||
G4bool IsScatProjToProjCase,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
if (!UseMatrix) return RapidSampleSecondaries(aTrack,IsScatProjToProjCase,fParticleChange);
|
||||
|
||||
//A recall of the compton scattering law is
|
||||
//Egamma2=Egamma1/(1+(Egamma1/E0_electron)(1.-cos_th))
|
||||
//Therefore Egamma2_max= Egamma2(cos_th=1) = Egamma1
|
||||
//Therefore Egamma2_min= Egamma2(cos_th=-1) = Egamma1/(1+2.(Egamma1/E0_electron))
|
||||
|
||||
|
||||
const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
|
||||
G4bool isScatProjToProj,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
if(!fUseMatrix)
|
||||
return RapidSampleSecondaries(aTrack, isScatProjToProj, fParticleChange);
|
||||
|
||||
// A recall of the compton scattering law:
|
||||
// Egamma2=Egamma1/(1+(Egamma1/E0_electron)(1.-cos_th))
|
||||
// Therefore Egamma2_max= Egamma2(cos_th=1) = Egamma1
|
||||
// and Egamma2_min= Egamma2(cos_th=-1) =
|
||||
// Egamma1/(1+2.(Egamma1/E0_electron))
|
||||
const G4DynamicParticle* theAdjointPrimary = aTrack.GetDynamicParticle();
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
|
||||
return;
|
||||
if(adjointPrimKinEnergy > GetHighEnergyLimit() * 0.999)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//Sample secondary energy
|
||||
//-----------------------
|
||||
G4double gammaE1;
|
||||
gammaE1 = SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy,
|
||||
IsScatProjToProjCase);
|
||||
|
||||
|
||||
//gammaE2
|
||||
//-----------
|
||||
|
||||
G4double gammaE2 = adjointPrimKinEnergy;
|
||||
if (!IsScatProjToProjCase) gammaE2 = gammaE1 - adjointPrimKinEnergy;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Cos th
|
||||
//-------
|
||||
// G4cout<<"Compton scattering "<<gammaE1<<'\t'<<gammaE2<<G4endl;
|
||||
G4double cos_th = 1.+ electron_mass_c2*(1./gammaE1 -1./gammaE2);
|
||||
if (!IsScatProjToProjCase) {
|
||||
G4double p_elec=theAdjointPrimary->GetTotalMomentum();
|
||||
cos_th = (gammaE1 - gammaE2*cos_th)/p_elec;
|
||||
}
|
||||
G4double sin_th = 0.;
|
||||
if (std::abs(cos_th)>1){
|
||||
//G4cout<<"Problem in compton scattering with cos_th "<<cos_th<<G4endl;
|
||||
if (cos_th>0) {
|
||||
cos_th=1.;
|
||||
}
|
||||
else cos_th=-1.;
|
||||
sin_th=0.;
|
||||
}
|
||||
else sin_th = std::sqrt(1.-cos_th*cos_th);
|
||||
|
||||
|
||||
|
||||
|
||||
//gamma0 momentum
|
||||
//--------------------
|
||||
// Sample secondary energy
|
||||
G4double gammaE1;
|
||||
gammaE1 =
|
||||
SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy, isScatProjToProj);
|
||||
|
||||
|
||||
G4ThreeVector dir_parallel=theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi =G4UniformRand()*2.*3.1415926;
|
||||
G4ThreeVector gammaMomentum1 = gammaE1*G4ThreeVector(std::cos(phi)*sin_th,std::sin(phi)*sin_th,cos_th);
|
||||
gammaMomentum1.rotateUz(dir_parallel);
|
||||
// G4cout<<gamma0Energy<<'\t'<<gamma0Momentum<<G4endl;
|
||||
|
||||
|
||||
//It is important to correct the weight of particles before adding the secondary
|
||||
//------------------------------------------------------------------------------
|
||||
CorrectPostStepWeight(fParticleChange,
|
||||
aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy,
|
||||
gammaE1,
|
||||
IsScatProjToProjCase);
|
||||
|
||||
if (!IsScatProjToProjCase){ //kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,gammaMomentum1));
|
||||
//G4cout<<"gamma0Momentum "<<gamma0Momentum<<G4endl;
|
||||
}
|
||||
else {
|
||||
fParticleChange->ProposeEnergy(gammaE1);
|
||||
fParticleChange->ProposeMomentumDirection(gammaMomentum1.unit());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointComptonModel::RapidSampleSecondaries(const G4Track& aTrack,
|
||||
G4bool IsScatProjToProjCase,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
// gammaE2
|
||||
G4double gammaE2 = adjointPrimKinEnergy;
|
||||
if(!isScatProjToProj)
|
||||
gammaE2 = gammaE1 - adjointPrimKinEnergy;
|
||||
|
||||
const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
|
||||
DefineCurrentMaterial(aTrack.GetMaterialCutsCouple());
|
||||
|
||||
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
|
||||
|
||||
if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
G4double diffCSUsed=0.1*currentMaterial->GetElectronDensity()*twopi_mc2_rcl2;
|
||||
G4double gammaE1=0.;
|
||||
G4double gammaE2=0.;
|
||||
if (!IsScatProjToProjCase){
|
||||
|
||||
G4double Emax = GetSecondAdjEnergyMaxForProdToProjCase(adjointPrimKinEnergy);
|
||||
G4double Emin= GetSecondAdjEnergyMinForProdToProjCase(adjointPrimKinEnergy);;
|
||||
if (Emin>=Emax) return;
|
||||
G4double f1=(Emin-adjointPrimKinEnergy)/Emin;
|
||||
G4double f2=(Emax-adjointPrimKinEnergy)/Emax/f1;
|
||||
gammaE1=adjointPrimKinEnergy/(1.-f1*std::pow(f2,G4UniformRand()));;
|
||||
gammaE2=gammaE1-adjointPrimKinEnergy;
|
||||
diffCSUsed= diffCSUsed*(1.+2.*std::log(1.+electron_mass_c2/adjointPrimKinEnergy))*adjointPrimKinEnergy/gammaE1/gammaE2;
|
||||
|
||||
|
||||
}
|
||||
else { G4double Emax = GetSecondAdjEnergyMaxForScatProjToProjCase(adjointPrimKinEnergy);
|
||||
G4double Emin = GetSecondAdjEnergyMinForScatProjToProjCase(adjointPrimKinEnergy,currentTcutForDirectSecond);
|
||||
if (Emin>=Emax) return;
|
||||
gammaE2 =adjointPrimKinEnergy;
|
||||
gammaE1=Emin*std::pow(Emax/Emin,G4UniformRand());
|
||||
diffCSUsed= diffCSUsed/gammaE1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Weight correction
|
||||
//-----------------------
|
||||
//First w_corr is set to the ratio between adjoint total CS and fwd total CS
|
||||
G4double w_corr=additional_weight_correction_factor_for_post_step_outside_model;
|
||||
if (correct_weight_for_post_step_in_model) {
|
||||
w_corr=G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection();
|
||||
// Cos th
|
||||
G4double cos_th = 1. + electron_mass_c2 * (1. / gammaE1 - 1. / gammaE2);
|
||||
if(!isScatProjToProj)
|
||||
{
|
||||
cos_th =
|
||||
(gammaE1 - gammaE2 * cos_th) / theAdjointPrimary->GetTotalMomentum();
|
||||
}
|
||||
//Then another correction is needed due to the fact that a biaised differential CS has been used rather than the
|
||||
//one consistent with the direct model
|
||||
|
||||
|
||||
G4double diffCS = DiffCrossSectionPerAtomPrimToScatPrim(gammaE1, gammaE2,1,0.);
|
||||
if (diffCS >0) diffCS /=G4direct_CS; // here we have the normalised diffCS
|
||||
//An we remultiply by the lambda of the forward process
|
||||
diffCS*=theDirectEMProcess->GetLambda(gammaE1,currentCouple);
|
||||
//diffCS*=theDirectEMModel->CrossSectionPerVolume(currentMaterial,G4Gamma::Gamma(),gammaE1,0.,2.*gammaE1);
|
||||
//G4cout<<"diffCS/diffCSUsed "<<diffCS/diffCSUsed<<'\t'<<gammaE1<<'\t'<<gammaE2<<G4endl;
|
||||
|
||||
w_corr*=diffCS/diffCSUsed;
|
||||
|
||||
G4double new_weight = aTrack.GetWeight()*w_corr;
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
|
||||
|
||||
|
||||
//Cos th
|
||||
//-------
|
||||
G4double sin_th = 0.;
|
||||
if(std::abs(cos_th) > 1.)
|
||||
{
|
||||
if(cos_th > 0.)
|
||||
{
|
||||
cos_th = 1.;
|
||||
}
|
||||
else
|
||||
cos_th = -1.;
|
||||
sin_th = 0.;
|
||||
}
|
||||
else
|
||||
sin_th = std::sqrt(1. - cos_th * cos_th);
|
||||
|
||||
G4double cos_th = 1.+ electron_mass_c2*(1./gammaE1 -1./gammaE2);
|
||||
if (!IsScatProjToProjCase) {
|
||||
G4double p_elec=theAdjointPrimary->GetTotalMomentum();
|
||||
cos_th = (gammaE1 - gammaE2*cos_th)/p_elec;
|
||||
}
|
||||
G4double sin_th = 0.;
|
||||
if (std::abs(cos_th)>1){
|
||||
//G4cout<<"Problem in compton scattering with cos_th "<<cos_th<<G4endl;
|
||||
if (cos_th>0) {
|
||||
cos_th=1.;
|
||||
}
|
||||
else cos_th=-1.;
|
||||
sin_th=0.;
|
||||
}
|
||||
else sin_th = std::sqrt(1.-cos_th*cos_th);
|
||||
// gamma0 momentum
|
||||
G4ThreeVector dir_parallel = theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi = G4UniformRand() * twopi;
|
||||
G4ThreeVector gammaMomentum1 =
|
||||
gammaE1 *
|
||||
G4ThreeVector(std::cos(phi) * sin_th, std::sin(phi) * sin_th, cos_th);
|
||||
gammaMomentum1.rotateUz(dir_parallel);
|
||||
|
||||
|
||||
|
||||
|
||||
//gamma0 momentum
|
||||
//--------------------
|
||||
// correct the weight of particles before adding the secondary
|
||||
CorrectPostStepWeight(fParticleChange, aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy, gammaE1, isScatProjToProj);
|
||||
|
||||
|
||||
G4ThreeVector dir_parallel=theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi =G4UniformRand()*2.*3.1415926;
|
||||
G4ThreeVector gammaMomentum1 = gammaE1*G4ThreeVector(std::cos(phi)*sin_th,std::sin(phi)*sin_th,cos_th);
|
||||
gammaMomentum1.rotateUz(dir_parallel);
|
||||
|
||||
|
||||
if(!isScatProjToProj)
|
||||
{ // kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(
|
||||
new G4DynamicParticle(fAdjEquivDirectPrimPart, gammaMomentum1));
|
||||
}
|
||||
else
|
||||
{
|
||||
fParticleChange->ProposeEnergy(gammaE1);
|
||||
fParticleChange->ProposeMomentumDirection(gammaMomentum1.unit());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!IsScatProjToProjCase){ //kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,gammaMomentum1));
|
||||
//G4cout<<"gamma0Momentum "<<gamma0Momentum<<G4endl;
|
||||
}
|
||||
else {
|
||||
fParticleChange->ProposeEnergy(gammaE1);
|
||||
fParticleChange->ProposeMomentumDirection(gammaMomentum1.unit());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//The implementation here is correct for energy loss process, for the photoelectric and compton scattering the method should be redefine
|
||||
void G4AdjointComptonModel::RapidSampleSecondaries(
|
||||
const G4Track& aTrack, G4bool isScatProjToProj,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
const G4DynamicParticle* theAdjointPrimary = aTrack.GetDynamicParticle();
|
||||
DefineCurrentMaterial(aTrack.GetMaterialCutsCouple());
|
||||
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
|
||||
if(adjointPrimKinEnergy > GetHighEnergyLimit() * 0.999)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
G4double diffCSUsed =
|
||||
0.1 * fCurrentMaterial->GetElectronDensity() * twopi_mc2_rcl2;
|
||||
G4double gammaE1 = 0.;
|
||||
G4double gammaE2 = 0.;
|
||||
if(!isScatProjToProj)
|
||||
{
|
||||
G4double Emax = GetSecondAdjEnergyMaxForProdToProj(adjointPrimKinEnergy);
|
||||
G4double Emin = GetSecondAdjEnergyMinForProdToProj(adjointPrimKinEnergy);
|
||||
if(Emin >= Emax)
|
||||
return;
|
||||
G4double f1 = (Emin - adjointPrimKinEnergy) / Emin;
|
||||
G4double f2 = (Emax - adjointPrimKinEnergy) / Emax / f1;
|
||||
gammaE1 = adjointPrimKinEnergy / (1. - f1 * std::pow(f2, G4UniformRand()));
|
||||
gammaE2 = gammaE1 - adjointPrimKinEnergy;
|
||||
diffCSUsed =
|
||||
diffCSUsed *
|
||||
(1. + 2. * std::log(1. + electron_mass_c2 / adjointPrimKinEnergy)) *
|
||||
adjointPrimKinEnergy / gammaE1 / gammaE2;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double Emax =
|
||||
GetSecondAdjEnergyMaxForScatProjToProj(adjointPrimKinEnergy);
|
||||
G4double Emin =
|
||||
GetSecondAdjEnergyMinForScatProjToProj(adjointPrimKinEnergy, fTcutSecond);
|
||||
if(Emin >= Emax)
|
||||
return;
|
||||
gammaE2 = adjointPrimKinEnergy;
|
||||
gammaE1 = Emin * std::pow(Emax / Emin, G4UniformRand());
|
||||
diffCSUsed = diffCSUsed / gammaE1;
|
||||
}
|
||||
|
||||
// Weight correction
|
||||
// First w_corr is set to the ratio between adjoint total CS and fwd total CS
|
||||
G4double w_corr = fOutsideWeightFactor;
|
||||
if(fInModelWeightCorr)
|
||||
{
|
||||
w_corr =
|
||||
G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection();
|
||||
}
|
||||
// Then another correction is needed because a biased differential CS has
|
||||
// been used rather than the one consistent with the direct model
|
||||
|
||||
G4double diffCS =
|
||||
DiffCrossSectionPerAtomPrimToScatPrim(gammaE1, gammaE2, 1, 0.);
|
||||
if(diffCS > 0.)
|
||||
diffCS /= fDirectCS; // here we have the normalised diffCS
|
||||
// And we remultiply by the lambda of the forward process
|
||||
diffCS *= fDirectProcess->GetLambda(gammaE1, fCurrentCouple);
|
||||
|
||||
w_corr *= diffCS / diffCSUsed;
|
||||
|
||||
G4double new_weight = aTrack.GetWeight() * w_corr;
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
|
||||
G4double cos_th = 1. + electron_mass_c2 * (1. / gammaE1 - 1. / gammaE2);
|
||||
if(!isScatProjToProj)
|
||||
{
|
||||
G4double p_elec = theAdjointPrimary->GetTotalMomentum();
|
||||
cos_th = (gammaE1 - gammaE2 * cos_th) / p_elec;
|
||||
}
|
||||
G4double sin_th = 0.;
|
||||
if(std::abs(cos_th) > 1.)
|
||||
{
|
||||
if(cos_th > 0.)
|
||||
{
|
||||
cos_th = 1.;
|
||||
}
|
||||
else
|
||||
cos_th = -1.;
|
||||
}
|
||||
else
|
||||
sin_th = std::sqrt(1. - cos_th * cos_th);
|
||||
|
||||
// gamma0 momentum
|
||||
G4ThreeVector dir_parallel = theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi = G4UniformRand() * twopi;
|
||||
G4ThreeVector gammaMomentum1 =
|
||||
gammaE1 *
|
||||
G4ThreeVector(std::cos(phi) * sin_th, std::sin(phi) * sin_th, cos_th);
|
||||
gammaMomentum1.rotateUz(dir_parallel);
|
||||
|
||||
if(!isScatProjToProj)
|
||||
{ // kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(
|
||||
new G4DynamicParticle(fAdjEquivDirectPrimPart, gammaMomentum1));
|
||||
}
|
||||
else
|
||||
{
|
||||
fParticleChange->ProposeEnergy(gammaE1);
|
||||
fParticleChange->ProposeMomentumDirection(gammaMomentum1.unit());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The implementation here is correct for energy loss process, for the
|
||||
// photoelectric and compton scattering the method should be redefined
|
||||
G4double G4AdjointComptonModel::DiffCrossSectionPerAtomPrimToSecond(
|
||||
G4double gamEnergy0,
|
||||
G4double kinEnergyElec,
|
||||
G4double Z,
|
||||
G4double A)
|
||||
{
|
||||
G4double gamEnergy1 = gamEnergy0 - kinEnergyElec;
|
||||
G4double dSigmadEprod=0.;
|
||||
if (gamEnergy1>0.) dSigmadEprod=DiffCrossSectionPerAtomPrimToScatPrim(gamEnergy0,gamEnergy1,Z,A);
|
||||
return dSigmadEprod;
|
||||
G4double gamEnergy0, G4double kinEnergyElec, G4double Z, G4double A)
|
||||
{
|
||||
G4double gamEnergy1 = gamEnergy0 - kinEnergyElec;
|
||||
G4double dSigmadEprod = 0.;
|
||||
if(gamEnergy1 > 0.)
|
||||
dSigmadEprod =
|
||||
DiffCrossSectionPerAtomPrimToScatPrim(gamEnergy0, gamEnergy1, Z, A);
|
||||
return dSigmadEprod;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointComptonModel::DiffCrossSectionPerAtomPrimToScatPrim(
|
||||
G4double gamEnergy0,
|
||||
G4double gamEnergy1,
|
||||
G4double Z,
|
||||
G4double )
|
||||
{ //Based on Klein Nishina formula
|
||||
// In the forward case (see G4KleinNishinaCompton) the cross section is parametrised
|
||||
// but the secondaries are sampled from the
|
||||
// Klein Nishida differential cross section
|
||||
// The used diffrential cross section here is therefore the cross section multiplied by the normalised
|
||||
//differential Klein Nishida cross section
|
||||
|
||||
|
||||
//Klein Nishida Cross Section
|
||||
//-----------------------------
|
||||
G4double epsilon = gamEnergy0 / electron_mass_c2 ;
|
||||
G4double one_plus_two_epsi =1.+2.*epsilon;
|
||||
G4double gamEnergy1_max = gamEnergy0;
|
||||
G4double gamEnergy1_min = gamEnergy0/one_plus_two_epsi;
|
||||
if (gamEnergy1 >gamEnergy1_max || gamEnergy1<gamEnergy1_min) {
|
||||
/*G4cout<<"the differential CS is null"<<G4endl;
|
||||
G4cout<<gamEnergy0<<G4endl;
|
||||
G4cout<<gamEnergy1<<G4endl;
|
||||
G4cout<<gamEnergy1_min<<G4endl;*/
|
||||
return 0.;
|
||||
}
|
||||
|
||||
|
||||
G4double epsi2 = epsilon *epsilon ;
|
||||
G4double one_plus_two_epsi_2=one_plus_two_epsi*one_plus_two_epsi;
|
||||
|
||||
|
||||
G4double CS=std::log(one_plus_two_epsi)*(1.- 2.*(1.+epsilon)/epsi2);
|
||||
CS+=4./epsilon +0.5*(1.-1./one_plus_two_epsi_2);
|
||||
CS/=epsilon;
|
||||
//Note that the pi*re2*Z factor is neglected because it is suppresed when computing dCS_dE1/CS;
|
||||
// in the differential cross section
|
||||
|
||||
|
||||
//Klein Nishida Differential Cross Section
|
||||
//-----------------------------------------
|
||||
G4double epsilon1 = gamEnergy1 / electron_mass_c2 ;
|
||||
G4double v= epsilon1/epsilon;
|
||||
G4double term1 =1.+ 1./epsilon -1/epsilon1;
|
||||
G4double dCS_dE1= 1./v +v + term1*term1 -1.;
|
||||
dCS_dE1 *=1./epsilon/gamEnergy0;
|
||||
|
||||
|
||||
//Normalised to the CS used in G4
|
||||
//-------------------------------
|
||||
|
||||
G4direct_CS = theDirectEMModel->ComputeCrossSectionPerAtom(G4Gamma::Gamma(),
|
||||
gamEnergy0,
|
||||
Z, 0., 0.,0.);
|
||||
|
||||
dCS_dE1 *= G4direct_CS/CS;
|
||||
/* G4cout<<"the differential CS is not null"<<G4endl;
|
||||
G4cout<<gamEnergy0<<G4endl;
|
||||
G4cout<<gamEnergy1<<G4endl;*/
|
||||
|
||||
return dCS_dE1;
|
||||
G4double gamEnergy0, G4double gamEnergy1, G4double Z, G4double)
|
||||
{
|
||||
// Based on Klein Nishina formula
|
||||
// In the forward case (see G4KleinNishinaCompton) the cross section is
|
||||
// parametrised but the secondaries are sampled from the Klein Nishina
|
||||
// differential cross section. The differential cross section used here
|
||||
// is therefore the cross section multiplied by the normalised
|
||||
// differential Klein Nishina cross section
|
||||
|
||||
// Klein Nishina Cross Section
|
||||
G4double epsilon = gamEnergy0 / electron_mass_c2;
|
||||
G4double one_plus_two_epsi = 1. + 2. * epsilon;
|
||||
if(gamEnergy1 > gamEnergy0 || gamEnergy1 < gamEnergy0 / one_plus_two_epsi)
|
||||
{
|
||||
return 0.;
|
||||
}
|
||||
|
||||
G4double CS = std::log(one_plus_two_epsi) *
|
||||
(1. - 2. * (1. + epsilon) / (epsilon * epsilon));
|
||||
CS +=
|
||||
4. / epsilon + 0.5 * (1. - 1. / (one_plus_two_epsi * one_plus_two_epsi));
|
||||
CS /= epsilon;
|
||||
// Note that the pi*re2*Z factor is neglected because it is suppressed when
|
||||
// computing dCS_dE1/CS in the differential cross section
|
||||
|
||||
// Klein Nishina Differential Cross Section
|
||||
G4double epsilon1 = gamEnergy1 / electron_mass_c2;
|
||||
G4double v = epsilon1 / epsilon;
|
||||
G4double term1 = 1. + 1. / epsilon - 1. / epsilon1;
|
||||
G4double dCS_dE1 = 1. / v + v + term1 * term1 - 1.;
|
||||
dCS_dE1 *= 1. / epsilon / gamEnergy0;
|
||||
|
||||
// Normalised to the CS used in G4
|
||||
fDirectCS = fDirectModel->ComputeCrossSectionPerAtom(
|
||||
G4Gamma::Gamma(), gamEnergy0, Z, 0., 0., 0.);
|
||||
|
||||
dCS_dE1 *= fDirectCS / CS;
|
||||
|
||||
return dCS_dE1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointComptonModel::GetSecondAdjEnergyMaxForScatProjToProjCase(G4double PrimAdjEnergy)
|
||||
{ G4double inv_e_max = 1./PrimAdjEnergy - 2./electron_mass_c2;
|
||||
G4double e_max = HighEnergyLimit;
|
||||
if (inv_e_max > 0. ) e_max=std::min(1./inv_e_max,HighEnergyLimit);
|
||||
return e_max;
|
||||
G4double G4AdjointComptonModel::GetSecondAdjEnergyMaxForScatProjToProj(
|
||||
G4double primAdjEnergy)
|
||||
{
|
||||
G4double inv_e_max = 1. / primAdjEnergy - 2. / electron_mass_c2;
|
||||
G4double e_max = GetHighEnergyLimit();
|
||||
if(inv_e_max > 0.)
|
||||
e_max = std::min(1. / inv_e_max, e_max);
|
||||
return e_max;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointComptonModel::GetSecondAdjEnergyMinForProdToProjCase(G4double PrimAdjEnergy)
|
||||
{ G4double half_e=PrimAdjEnergy/2.;
|
||||
G4double term=std::sqrt(half_e*(electron_mass_c2+half_e));
|
||||
G4double emin=half_e+term;
|
||||
return emin;
|
||||
G4double G4AdjointComptonModel::GetSecondAdjEnergyMinForProdToProj(
|
||||
G4double primAdjEnergy)
|
||||
{
|
||||
G4double half_e = primAdjEnergy / 2.;
|
||||
return half_e + std::sqrt(half_e * (electron_mass_c2 + half_e));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointComptonModel::AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
|
||||
G4double primEnergy,
|
||||
G4bool IsScatProjToProjCase)
|
||||
{
|
||||
if (UseMatrix) return G4VEmAdjointModel::AdjointCrossSection(aCouple,primEnergy,IsScatProjToProjCase);
|
||||
G4double G4AdjointComptonModel::AdjointCrossSection(
|
||||
const G4MaterialCutsCouple* aCouple, G4double primEnergy,
|
||||
G4bool isScatProjToProj)
|
||||
{
|
||||
if(fUseMatrix)
|
||||
return G4VEmAdjointModel::AdjointCrossSection(aCouple, primEnergy,
|
||||
isScatProjToProj);
|
||||
DefineCurrentMaterial(aCouple);
|
||||
|
||||
|
||||
float Cross=0.;
|
||||
float Emax_proj =0.;
|
||||
float Emin_proj =0.;
|
||||
if (!IsScatProjToProjCase ){
|
||||
Emax_proj = GetSecondAdjEnergyMaxForProdToProjCase(primEnergy);
|
||||
Emin_proj = GetSecondAdjEnergyMinForProdToProjCase(primEnergy);
|
||||
if (Emax_proj>Emin_proj ){
|
||||
Cross= 0.1*std::log((Emax_proj-float (primEnergy))*Emin_proj/Emax_proj/(Emin_proj-primEnergy))
|
||||
*(1.+2.*std::log(float(1.+electron_mass_c2/primEnergy)));
|
||||
}
|
||||
|
||||
G4float Cross = 0.;
|
||||
G4float Emax_proj = 0.;
|
||||
G4float Emin_proj = 0.;
|
||||
if(!isScatProjToProj)
|
||||
{
|
||||
Emax_proj = GetSecondAdjEnergyMaxForProdToProj(primEnergy);
|
||||
Emin_proj = GetSecondAdjEnergyMinForProdToProj(primEnergy);
|
||||
if(Emax_proj > Emin_proj)
|
||||
{
|
||||
Cross = 0.1 *
|
||||
std::log((Emax_proj - G4float(primEnergy)) * Emin_proj /
|
||||
Emax_proj / (Emin_proj - primEnergy)) *
|
||||
(1. + 2. * std::log(G4float(1. + electron_mass_c2 / primEnergy)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Emax_proj = GetSecondAdjEnergyMaxForScatProjToProjCase(primEnergy);
|
||||
Emin_proj = GetSecondAdjEnergyMinForScatProjToProjCase(primEnergy,0.);
|
||||
if (Emax_proj>Emin_proj) {
|
||||
Cross = 0.1*std::log(Emax_proj/Emin_proj);
|
||||
//+0.5*primEnergy*primEnergy(1./(Emin_proj*Emin_proj) - 1./(Emax_proj*Emax_proj)); neglected at the moment
|
||||
}
|
||||
|
||||
|
||||
else
|
||||
{
|
||||
Emax_proj = GetSecondAdjEnergyMaxForScatProjToProj(primEnergy);
|
||||
Emin_proj = GetSecondAdjEnergyMinForScatProjToProj(primEnergy, 0.);
|
||||
if(Emax_proj > Emin_proj)
|
||||
{
|
||||
Cross = 0.1 * std::log(Emax_proj / Emin_proj);
|
||||
}
|
||||
}
|
||||
|
||||
Cross*=currentMaterial->GetElectronDensity()*twopi_mc2_rcl2;
|
||||
lastCS=Cross;
|
||||
return double(Cross);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointComptonModel::GetAdjointCrossSection(const G4MaterialCutsCouple* aCouple,
|
||||
G4double primEnergy,
|
||||
G4bool IsScatProjToProjCase)
|
||||
{ return AdjointCrossSection(aCouple, primEnergy,IsScatProjToProjCase);
|
||||
//return G4VEmAdjointModel::GetAdjointCrossSection(aCouple, primEnergy,IsScatProjToProjCase);
|
||||
|
||||
Cross *= fCurrentMaterial->GetElectronDensity() * twopi_mc2_rcl2;
|
||||
fLastCS = Cross;
|
||||
return double(Cross);
|
||||
}
|
||||
|
||||
+237
-230
@@ -23,264 +23,271 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4AdjointForcedInteractionForGamma.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
#include "G4AdjointCSManager.hh"
|
||||
#include "G4AdjointCSMatrix.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
#include "G4AdjointGamma.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4AdjointGamma.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
|
||||
|
||||
G4AdjointForcedInteractionForGamma::
|
||||
G4AdjointForcedInteractionForGamma(G4String process_name):
|
||||
G4VContinuousDiscreteProcess(process_name),theAdjointComptonModel(0),theAdjointBremModel(0)
|
||||
{ theAdjointCSManager = G4AdjointCSManager::GetAdjointCSManager();
|
||||
fParticleChange=new G4ParticleChange();
|
||||
lastAdjCS=0.;
|
||||
trackid = nstep = 0;
|
||||
is_free_flight_gamma = false;
|
||||
copy_gamma_for_forced_interaction = false;
|
||||
last_free_flight_trackid=1000;
|
||||
|
||||
theAdjointComptonModel =0;
|
||||
theAdjointBremModel=0;
|
||||
|
||||
acc_track_length=0.;
|
||||
acc_nb_adj_interaction_length=0.;
|
||||
acc_nb_fwd_interaction_length=0.;
|
||||
total_acc_nb_adj_interaction_length=0.;
|
||||
total_acc_nb_fwd_interaction_length=0.;
|
||||
continue_gamma_as_new_free_flight =false;
|
||||
|
||||
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointForcedInteractionForGamma::
|
||||
~G4AdjointForcedInteractionForGamma()
|
||||
{ if (fParticleChange) delete fParticleChange;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointForcedInteractionForGamma::PreparePhysicsTable(const G4ParticleDefinition&)
|
||||
{;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointForcedInteractionForGamma::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
G4AdjointForcedInteractionForGamma::G4AdjointForcedInteractionForGamma(
|
||||
G4String process_name)
|
||||
: G4VContinuousDiscreteProcess(process_name)
|
||||
, fAdjointComptonModel(nullptr)
|
||||
, fAdjointBremModel(nullptr)
|
||||
{
|
||||
theAdjointCSManager->BuildCrossSectionMatrices(); //do not worry it will be done just once
|
||||
theAdjointCSManager->BuildTotalSigmaTables();
|
||||
fCSManager = G4AdjointCSManager::GetAdjointCSManager();
|
||||
fParticleChange = new G4ParticleChange();
|
||||
}
|
||||
//Note on weight correction for forced interaction
|
||||
//For the forced interaction applied here we do use a truncated exponential law for the probability of survival
|
||||
//over a fixed total length. This is done by using a linear transformation of the non biased probability survival
|
||||
//In mathematic this writes
|
||||
//P'(x)=C1P(x)+C2
|
||||
//With P(x)=exp(-sum(sigma_ixi)) x and L can cross different volumes with different cross section sigma.
|
||||
//For forced interaction we get the following limit conditions
|
||||
//P'(L)=0 P'(0)=1 (L can be used over different volumes)
|
||||
//From simple solving of linear equation we get
|
||||
//C1=1/(1-P(L)) et C2=-P(L)/(1-P(L))
|
||||
//P'(x)=(P(x)-P(L))/(1-P(L))
|
||||
//For the probability over a step x1 to x2
|
||||
//P'(x1->x2)=P'(x2)/P'(x1)
|
||||
//The effective cross section is defined -d(P'(x))/dx/P'(x)
|
||||
//We get therefore
|
||||
//sigma_eff=C1sigmaP(x)/(C1P(x)+C2)=sigmaP(x)/(P(x)+C2/C1)=sigmaP(x)/(P(x)-P(L))=sigma/(1-P(L)/P(x))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4VParticleChange* G4AdjointForcedInteractionForGamma::PostStepDoIt(const G4Track& track, const G4Step& )
|
||||
{ fParticleChange->Initialize(track);
|
||||
//For the free flight gamma no interaction occur but a gamma with same property is
|
||||
//produces for further forced interaction
|
||||
//It is done at the very beginning of the track such that the weight can be the same
|
||||
if (copy_gamma_for_forced_interaction) {
|
||||
G4ThreeVector theGammaMomentum = track.GetMomentum();
|
||||
fParticleChange->AddSecondary(new G4DynamicParticle(G4AdjointGamma::AdjointGamma(),theGammaMomentum));
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
G4AdjointForcedInteractionForGamma::~G4AdjointForcedInteractionForGamma()
|
||||
{
|
||||
if(fParticleChange)
|
||||
delete fParticleChange;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointForcedInteractionForGamma::ProcessDescription(
|
||||
std::ostream& out) const
|
||||
{
|
||||
out << "Forced interaction for gamma.\n";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointForcedInteractionForGamma::BuildPhysicsTable(
|
||||
const G4ParticleDefinition&)
|
||||
{
|
||||
fCSManager->BuildCrossSectionMatrices(); // it will be done just once
|
||||
fCSManager->BuildTotalSigmaTables();
|
||||
}
|
||||
|
||||
// Note on weight correction for forced interaction.
|
||||
// For the forced interaction applied here we use a truncated exponential law
|
||||
// for the probability of survival over a fixed total length. This is done by
|
||||
// using a linear transformation of the non-biased probability survival. In
|
||||
// math this is written P'(x)=C1P(x)+C2 , with P(x)=exp(-sum(sigma_ixi)) . x and
|
||||
// L can cross different volumes with different cross section sigma. For forced
|
||||
// interaction, we get the limit conditions:
|
||||
// P'(L)=0 and P'(0)=1 (L can be used over different volumes)
|
||||
// From simple solving of linear equations we
|
||||
// get C1=1/(1-P(L)) and C2=-P(L)/(1-P(L))
|
||||
// P'(x)=(P(x)-P(L))/(1-P(L))
|
||||
// For the probability over a step x1 to x2, P'(x1->x2)=P'(x2)/P'(x1).
|
||||
// The effective cross
|
||||
// section is defined -d(P'(x))/dx/P'(x).
|
||||
// We get therefore
|
||||
// sigma_eff = C1sigmaP(x)/(C1P(x)+C2) = sigmaP(x)/(P(x)+C2/C1)
|
||||
// = sigmaP(x)/(P(x)-P(L)) = sigma/(1-P(L)/P(x))
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
G4VParticleChange* G4AdjointForcedInteractionForGamma::PostStepDoIt(
|
||||
const G4Track& track, const G4Step&)
|
||||
{
|
||||
fParticleChange->Initialize(track);
|
||||
// For the free flight gamma no interaction occurs but a gamma with same
|
||||
// properties is produced for further forced interaction. It is done at the
|
||||
// very beginning of the track so that the weight can be the same
|
||||
if(fCopyGammaForForced)
|
||||
{
|
||||
G4ThreeVector theGammaMomentum = track.GetMomentum();
|
||||
fParticleChange->AddSecondary(
|
||||
new G4DynamicParticle(G4AdjointGamma::AdjointGamma(), theGammaMomentum));
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
}
|
||||
else { //Occurrence of forced interaction
|
||||
else
|
||||
{ // Occurrence of forced interaction
|
||||
// Selection of the model to be called
|
||||
G4VEmAdjointModel* theSelectedModel = nullptr;
|
||||
G4bool is_scat_proj_to_proj_case = false;
|
||||
if(!fAdjointComptonModel && !fAdjointBremModel)
|
||||
return fParticleChange;
|
||||
if(!fAdjointComptonModel)
|
||||
{
|
||||
theSelectedModel = fAdjointBremModel;
|
||||
is_scat_proj_to_proj_case = false;
|
||||
// This is needed because the results of it will be used in the post step
|
||||
// do it weight correction inside the model
|
||||
fAdjointBremModel->AdjointCrossSection(track.GetMaterialCutsCouple(),
|
||||
track.GetKineticEnergy(), false);
|
||||
}
|
||||
else if(!fAdjointBremModel)
|
||||
{
|
||||
theSelectedModel = fAdjointComptonModel;
|
||||
is_scat_proj_to_proj_case = true;
|
||||
}
|
||||
else
|
||||
{ // Choose the model according to cross sections
|
||||
G4double bremAdjCS = fAdjointBremModel->AdjointCrossSection(
|
||||
track.GetMaterialCutsCouple(), track.GetKineticEnergy(), false);
|
||||
if(G4UniformRand() * fLastAdjCS < bremAdjCS)
|
||||
{
|
||||
theSelectedModel = fAdjointBremModel;
|
||||
is_scat_proj_to_proj_case = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
theSelectedModel = fAdjointComptonModel;
|
||||
is_scat_proj_to_proj_case = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Selection of the model to be called
|
||||
G4VEmAdjointModel* theSelectedModel =0;
|
||||
G4bool is_scat_proj_to_proj_case=false;
|
||||
if (!theAdjointComptonModel && !theAdjointBremModel) return fParticleChange;
|
||||
if (!theAdjointComptonModel) {
|
||||
theSelectedModel = theAdjointBremModel;
|
||||
is_scat_proj_to_proj_case=false;
|
||||
//This is needed because the results of it will be used in the post step do it weight correction inside the model
|
||||
theAdjointBremModel->AdjointCrossSection(
|
||||
track.GetMaterialCutsCouple(),track.GetKineticEnergy(), false);
|
||||
// Compute the weight correction factor
|
||||
G4double invEffectiveAdjointCS =
|
||||
(1. - std::exp(fNbAdjIntLength - fTotNbAdjIntLength)) / fLastAdjCS;
|
||||
|
||||
}
|
||||
else if (!theAdjointBremModel) {
|
||||
theSelectedModel = theAdjointComptonModel;
|
||||
is_scat_proj_to_proj_case=true;
|
||||
}
|
||||
else { //Choose the model according to cross sections
|
||||
// Call the selected model without correction of the weight in the model
|
||||
theSelectedModel->SetCorrectWeightForPostStepInModel(false);
|
||||
theSelectedModel
|
||||
->SetAdditionalWeightCorrectionFactorForPostStepOutsideModel(
|
||||
fLastAdjCS * invEffectiveAdjointCS);
|
||||
theSelectedModel->SampleSecondaries(track, is_scat_proj_to_proj_case,
|
||||
fParticleChange);
|
||||
theSelectedModel->SetCorrectWeightForPostStepInModel(true);
|
||||
|
||||
G4double bremAdjCS = theAdjointBremModel->AdjointCrossSection(
|
||||
track.GetMaterialCutsCouple(),track.GetKineticEnergy(), false);
|
||||
if (G4UniformRand()*lastAdjCS<bremAdjCS) {
|
||||
theSelectedModel = theAdjointBremModel;
|
||||
is_scat_proj_to_proj_case=false;
|
||||
}
|
||||
else {
|
||||
theSelectedModel = theAdjointComptonModel;
|
||||
is_scat_proj_to_proj_case=true;
|
||||
}
|
||||
}
|
||||
|
||||
//Compute the weight correction factor
|
||||
G4double one_over_effectiveAdjointCS= (1.-std::exp(acc_nb_adj_interaction_length-total_acc_nb_adj_interaction_length))/lastAdjCS;
|
||||
G4double weight_correction_factor = lastAdjCS*one_over_effectiveAdjointCS;
|
||||
//G4cout<<"Weight correction factor start "<<weight_correction_factor<<std::endl;
|
||||
//Call the selected model without correction of the weight in the model
|
||||
theSelectedModel->SetCorrectWeightForPostStepInModel(false);
|
||||
theSelectedModel->SetAdditionalWeightCorrectionFactorForPostStepOutsideModel(weight_correction_factor);
|
||||
theSelectedModel->SampleSecondaries(track,is_scat_proj_to_proj_case,fParticleChange);
|
||||
theSelectedModel->SetCorrectWeightForPostStepInModel(true);
|
||||
|
||||
continue_gamma_as_new_free_flight =true;
|
||||
fContinueGammaAsNewFreeFlight = true;
|
||||
}
|
||||
return fParticleChange;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4VParticleChange* G4AdjointForcedInteractionForGamma::AlongStepDoIt(const G4Track& track, const G4Step& )
|
||||
{ fParticleChange->Initialize(track);
|
||||
//Compute nb of interactions length over step length
|
||||
G4VParticleChange* G4AdjointForcedInteractionForGamma::AlongStepDoIt(
|
||||
const G4Track& track, const G4Step&)
|
||||
{
|
||||
fParticleChange->Initialize(track);
|
||||
// Compute nb of interactions length over step length
|
||||
G4ThreeVector position = track.GetPosition();
|
||||
G4double stepLength = track.GetStep()->GetStepLength();
|
||||
G4double ekin = track.GetKineticEnergy();
|
||||
G4double nb_fwd_interaction_length_over_step=0.;
|
||||
G4double nb_adj_interaction_length_over_step=0.;
|
||||
lastAdjCS = G4AdjointCSManager::GetAdjointCSManager()->GetTotalAdjointCS(track.GetDefinition(), ekin, track.GetMaterialCutsCouple());
|
||||
lastFwdCS = G4AdjointCSManager::GetAdjointCSManager()->GetTotalForwardCS(G4AdjointGamma::AdjointGamma(),
|
||||
ekin,track.GetMaterialCutsCouple());
|
||||
nb_fwd_interaction_length_over_step = stepLength*lastFwdCS;
|
||||
nb_adj_interaction_length_over_step = stepLength*lastAdjCS;
|
||||
G4double fwd_survival_probability=std::exp(-nb_fwd_interaction_length_over_step);
|
||||
G4double mc_induced_survival_probability=1.;
|
||||
G4double stepLength = track.GetStep()->GetStepLength();
|
||||
G4double ekin = track.GetKineticEnergy();
|
||||
fLastAdjCS = fCSManager->GetTotalAdjointCS(track.GetDefinition(), ekin,
|
||||
track.GetMaterialCutsCouple());
|
||||
G4double nb_fwd_interaction_length_over_step =
|
||||
stepLength * fCSManager->GetTotalForwardCS(G4AdjointGamma::AdjointGamma(),
|
||||
ekin,
|
||||
track.GetMaterialCutsCouple());
|
||||
|
||||
if (is_free_flight_gamma) { //for free_flight survival probability stays 1
|
||||
//Accumulate the number of interaction lengths during free flight of gamma
|
||||
total_acc_nb_fwd_interaction_length+=nb_fwd_interaction_length_over_step;
|
||||
total_acc_nb_adj_interaction_length+=nb_adj_interaction_length_over_step;
|
||||
acc_track_length+=stepLength;
|
||||
G4double nb_adj_interaction_length_over_step = stepLength * fLastAdjCS;
|
||||
G4double fwd_survival_probability =
|
||||
std::exp(-nb_fwd_interaction_length_over_step);
|
||||
G4double mc_induced_survival_probability = 1.;
|
||||
|
||||
if(fFreeFlightGamma)
|
||||
{ // for free_flight survival probability stays 1
|
||||
// Accumulate the number of interaction lengths during free flight of gamma
|
||||
fTotNbAdjIntLength += nb_adj_interaction_length_over_step;
|
||||
fAccTrackLength += stepLength;
|
||||
}
|
||||
else {
|
||||
G4double previous_acc_nb_adj_interaction_length =acc_nb_adj_interaction_length;
|
||||
acc_nb_fwd_interaction_length+=nb_fwd_interaction_length_over_step;
|
||||
acc_nb_adj_interaction_length+=nb_adj_interaction_length_over_step;
|
||||
theNumberOfInteractionLengthLeft-=nb_adj_interaction_length_over_step;
|
||||
else
|
||||
{
|
||||
G4double previous_acc_nb_adj_interaction_length = fNbAdjIntLength;
|
||||
fNbAdjIntLength += nb_adj_interaction_length_over_step;
|
||||
theNumberOfInteractionLengthLeft -= nb_adj_interaction_length_over_step;
|
||||
|
||||
//Following condition to remove very rare FPE issue
|
||||
//if (total_acc_nb_adj_interaction_length <= 1.e-50 && theNumberOfInteractionLengthLeft<=1.e-50) { //condition added to avoid FPE issue
|
||||
// VI 06.11.2017 - new condition
|
||||
if (std::abs(total_acc_nb_adj_interaction_length - previous_acc_nb_adj_interaction_length) <= 1.e-15) {
|
||||
mc_induced_survival_probability = 1.e50;
|
||||
/*
|
||||
G4cout << "FPE protection: " << total_acc_nb_adj_interaction_length << " "
|
||||
<< previous_acc_nb_adj_interaction_length << " "
|
||||
<< acc_nb_fwd_interaction_length << " "
|
||||
<< acc_nb_adj_interaction_length << " "
|
||||
<< theNumberOfInteractionLengthLeft
|
||||
<< G4endl;
|
||||
*/
|
||||
}
|
||||
else {
|
||||
mc_induced_survival_probability= std::exp(-acc_nb_adj_interaction_length)-std::exp(-total_acc_nb_adj_interaction_length);
|
||||
mc_induced_survival_probability=mc_induced_survival_probability/(std::exp(-previous_acc_nb_adj_interaction_length)-std::exp(-total_acc_nb_adj_interaction_length));
|
||||
}
|
||||
// protection against rare race condition
|
||||
if(std::abs(fTotNbAdjIntLength - previous_acc_nb_adj_interaction_length) <=
|
||||
1.e-15)
|
||||
{
|
||||
mc_induced_survival_probability = 1.e50;
|
||||
}
|
||||
else
|
||||
{
|
||||
mc_induced_survival_probability =
|
||||
std::exp(-fNbAdjIntLength) - std::exp(-fTotNbAdjIntLength);
|
||||
mc_induced_survival_probability /=
|
||||
(std::exp(-previous_acc_nb_adj_interaction_length) -
|
||||
std::exp(-fTotNbAdjIntLength));
|
||||
}
|
||||
}
|
||||
G4double weight_correction = fwd_survival_probability/mc_induced_survival_probability;
|
||||
G4double weight_correction =
|
||||
fwd_survival_probability / mc_induced_survival_probability;
|
||||
|
||||
//weight_correction = 1.;
|
||||
//Caution!!!
|
||||
// It is important to select the weight of the post_step_point
|
||||
// as the current weight and not the weight of the track, as t
|
||||
// the weight of the track is changed after having applied all
|
||||
// the along_step_do_it.
|
||||
G4double new_weight=weight_correction*track.GetStep()->GetPostStepPoint()->GetWeight();
|
||||
/*
|
||||
G4cout<<"New weight "<<new_weight<<std::endl;
|
||||
G4cout<<"Weight correction "<<weight_correction<<std::endl;
|
||||
*/
|
||||
// Caution!!!
|
||||
// It is important to select the weight of the post_step_point as the
|
||||
// current weight and not the weight of the track, as the weight of the track
|
||||
// is changed after having applied all the along_step_do_it.
|
||||
G4double new_weight =
|
||||
weight_correction * track.GetStep()->GetPostStepPoint()->GetWeight();
|
||||
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
|
||||
return fParticleChange;
|
||||
return fParticleChange;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointForcedInteractionForGamma::PostStepGetPhysicalInteractionLength(
|
||||
const G4Track& track,
|
||||
G4double ,
|
||||
G4ForceCondition* condition)
|
||||
{ G4int step_id = track.GetCurrentStepNumber();
|
||||
*condition = NotForced;
|
||||
copy_gamma_for_forced_interaction = false;
|
||||
G4int track_id=track.GetTrackID();
|
||||
is_free_flight_gamma = (track_id != last_free_flight_trackid+1 || continue_gamma_as_new_free_flight);
|
||||
if (is_free_flight_gamma) {
|
||||
if (step_id == 1 || continue_gamma_as_new_free_flight) {
|
||||
*condition=Forced;
|
||||
//A gamma with same conditions will be generate at next post_step do it for the forced interaction
|
||||
copy_gamma_for_forced_interaction = true;
|
||||
last_free_flight_trackid = track_id;
|
||||
acc_track_length=0.;
|
||||
total_acc_nb_adj_interaction_length=0.;
|
||||
total_acc_nb_fwd_interaction_length=0.;
|
||||
continue_gamma_as_new_free_flight=false;
|
||||
return 1.e-90;
|
||||
G4double
|
||||
G4AdjointForcedInteractionForGamma::PostStepGetPhysicalInteractionLength(
|
||||
const G4Track& track, G4double, G4ForceCondition* condition)
|
||||
{
|
||||
static G4int lastFreeFlightTrackId = 1000;
|
||||
G4int step_id = track.GetCurrentStepNumber();
|
||||
*condition = NotForced;
|
||||
fCopyGammaForForced = false;
|
||||
G4int track_id = track.GetTrackID();
|
||||
fFreeFlightGamma =
|
||||
(track_id != lastFreeFlightTrackId + 1 || fContinueGammaAsNewFreeFlight);
|
||||
if(fFreeFlightGamma)
|
||||
{
|
||||
if(step_id == 1 || fContinueGammaAsNewFreeFlight)
|
||||
{
|
||||
*condition = Forced;
|
||||
// A gamma with same conditions will be generate at next post_step do it
|
||||
// for the forced interaction
|
||||
fCopyGammaForForced = true;
|
||||
lastFreeFlightTrackId = track_id;
|
||||
fAccTrackLength = 0.;
|
||||
fTotNbAdjIntLength = 0.;
|
||||
fContinueGammaAsNewFreeFlight = false;
|
||||
return 1.e-90;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DBL_MAX;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//Computation of accumulated length for
|
||||
return DBL_MAX;
|
||||
else
|
||||
{ // compute the interaction length for forced interaction
|
||||
if(step_id == 1)
|
||||
{
|
||||
G4double min_val = std::exp(-fTotNbAdjIntLength);
|
||||
theNumberOfInteractionLengthLeft =
|
||||
-std::log(min_val + G4UniformRand() * (1. - min_val));
|
||||
theInitialNumberOfInteractionLength = theNumberOfInteractionLengthLeft;
|
||||
fNbAdjIntLength = 0.;
|
||||
}
|
||||
G4VPhysicalVolume* thePostPhysVolume =
|
||||
track.GetStep()->GetPreStepPoint()->GetPhysicalVolume();
|
||||
G4double ekin = track.GetKineticEnergy();
|
||||
G4double postCS = 0.;
|
||||
if(thePostPhysVolume)
|
||||
{
|
||||
postCS = fCSManager->GetTotalAdjointCS(
|
||||
G4AdjointGamma::AdjointGamma(), ekin,
|
||||
thePostPhysVolume->GetLogicalVolume()->GetMaterialCutsCouple());
|
||||
}
|
||||
if(postCS > 0.)
|
||||
return theNumberOfInteractionLengthLeft / postCS;
|
||||
else
|
||||
return DBL_MAX;
|
||||
}
|
||||
}
|
||||
else { //compute the interaction length for forced interaction
|
||||
if (step_id ==1) {
|
||||
G4double min_val= std::exp(-total_acc_nb_adj_interaction_length);
|
||||
theNumberOfInteractionLengthLeft = -std::log( min_val+G4UniformRand()*(1.-min_val));
|
||||
theInitialNumberOfInteractionLength = theNumberOfInteractionLengthLeft;
|
||||
acc_nb_adj_interaction_length=0.;
|
||||
acc_nb_fwd_interaction_length=0.;
|
||||
}
|
||||
G4VPhysicalVolume* thePostPhysVolume = track.GetStep()->GetPreStepPoint()->GetPhysicalVolume();
|
||||
G4double ekin =track.GetKineticEnergy();
|
||||
G4double postCS=0.;
|
||||
if (thePostPhysVolume){
|
||||
postCS = G4AdjointCSManager::GetAdjointCSManager()->GetTotalAdjointCS(G4AdjointGamma::AdjointGamma(),
|
||||
ekin,thePostPhysVolume->GetLogicalVolume()->GetMaterialCutsCouple());
|
||||
}
|
||||
if (postCS>0.) return theNumberOfInteractionLengthLeft/postCS;
|
||||
else return DBL_MAX;
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointForcedInteractionForGamma::GetContinuousStepLimit(const G4Track& ,
|
||||
G4double ,
|
||||
G4double ,
|
||||
G4double& )
|
||||
{return DBL_MAX;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//Not used in this process but should be implemented as virtual method
|
||||
G4double G4AdjointForcedInteractionForGamma::GetMeanFreePath(const G4Track& ,
|
||||
G4double ,
|
||||
G4ForceCondition*)
|
||||
{ return 0.;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4double G4AdjointForcedInteractionForGamma::GetContinuousStepLimit(
|
||||
const G4Track&, G4double, G4double, G4double&)
|
||||
{
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Not used in this process but should be implemented as virtual method
|
||||
G4double G4AdjointForcedInteractionForGamma::GetMeanFreePath(const G4Track&,
|
||||
G4double,
|
||||
G4ForceCondition*)
|
||||
{
|
||||
return 0.;
|
||||
}
|
||||
|
||||
@@ -23,211 +23,185 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
#include "G4AdjointCSMatrix.hh"
|
||||
|
||||
#include "G4AdjointInterpolator.hh"
|
||||
|
||||
G4ThreadLocal G4AdjointInterpolator* G4AdjointInterpolator::theInstance = 0;
|
||||
G4ThreadLocal G4AdjointInterpolator* G4AdjointInterpolator::fInstance = nullptr;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointInterpolator* G4AdjointInterpolator::GetAdjointInterpolator()
|
||||
{
|
||||
return GetInstance();
|
||||
return GetInstance();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointInterpolator* G4AdjointInterpolator::GetInstance()
|
||||
{
|
||||
if(!theInstance)
|
||||
if(!fInstance)
|
||||
{
|
||||
theInstance = new G4AdjointInterpolator;
|
||||
fInstance = new G4AdjointInterpolator;
|
||||
}
|
||||
return theInstance;
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointInterpolator::G4AdjointInterpolator()
|
||||
{
|
||||
}
|
||||
G4AdjointInterpolator::G4AdjointInterpolator() {}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointInterpolator::~G4AdjointInterpolator()
|
||||
{
|
||||
}
|
||||
G4AdjointInterpolator::~G4AdjointInterpolator() {}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointInterpolator::LinearInterpolation(G4double& x,G4double& x1,G4double& x2,G4double& y1,G4double& y2)
|
||||
G4double G4AdjointInterpolator::LinearInterpolation(G4double& x, G4double& x1,
|
||||
G4double& x2, G4double& y1,
|
||||
G4double& y2)
|
||||
{
|
||||
G4double res = y1+ (x-x1)*(y2-y1)/(x2-x1);
|
||||
//G4cout<<"Linear "<<res<<G4endl;
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointInterpolator::LogarithmicInterpolation(G4double& x,G4double& x1,G4double& x2,G4double& y1,G4double& y2)
|
||||
{
|
||||
if (y1<=0 || y2<=0 || x1<=0) return LinearInterpolation(x,x1,x2,y1,y2);
|
||||
G4double B=std::log(y2/y1)/std::log(x2/x1);
|
||||
//G4cout<<"x1,x2,y1,y2 "<<x1<<'\t'<<x2<<'\t'<<y1<<'\t'<<y2<<'\t'<<G4endl;
|
||||
G4double A=y1/std::pow(x1,B);
|
||||
G4double res=A*std::pow(x,B);
|
||||
// G4cout<<"Log "<<res<<G4endl;
|
||||
G4double res = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointInterpolator::ExponentialInterpolation(G4double& x,G4double& x1,G4double& x2,G4double& y1,G4double& y2)
|
||||
G4double G4AdjointInterpolator::LogarithmicInterpolation(
|
||||
G4double& x, G4double& x1, G4double& x2, G4double& y1, G4double& y2)
|
||||
{
|
||||
G4double B=(std::log(y2)-std::log(y1));
|
||||
B=B/(x2-x1);
|
||||
G4double A=y1*std::exp(-B*x1);
|
||||
G4double res=A*std::exp(B*x);
|
||||
if(y1 <= 0. || y2 <= 0. || x1 <= 0.)
|
||||
return LinearInterpolation(x, x1, x2, y1, y2);
|
||||
G4double B = std::log(y2 / y1) / std::log(x2 / x1);
|
||||
G4double A = y1 / std::pow(x1, B);
|
||||
G4double res = A * std::pow(x, B);
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointInterpolator::Interpolation(G4double& x,G4double& x1,G4double& x2,G4double& y1,G4double& y2,G4String InterPolMethod)
|
||||
G4double G4AdjointInterpolator::ExponentialInterpolation(
|
||||
G4double& x, G4double& x1, G4double& x2, G4double& y1, G4double& y2)
|
||||
{
|
||||
if (InterPolMethod == "Log" ){
|
||||
return LogarithmicInterpolation(x,x1,x2,y1,y2);
|
||||
G4double B = (std::log(y2) - std::log(y1)) / (x2 - x1);
|
||||
G4double A = y1 * std::exp(-B * x1);
|
||||
G4double res = A * std::exp(B * x);
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
G4double G4AdjointInterpolator::Interpolation(G4double& x, G4double& x1,
|
||||
G4double& x2, G4double& y1,
|
||||
G4double& y2,
|
||||
G4String InterPolMethod)
|
||||
{
|
||||
if(InterPolMethod == "Log")
|
||||
{
|
||||
return LogarithmicInterpolation(x, x1, x2, y1, y2);
|
||||
}
|
||||
else if (InterPolMethod == "Lin" ){
|
||||
return LinearInterpolation(x,x1,x2,y1,y2);
|
||||
else if(InterPolMethod == "Lin")
|
||||
{
|
||||
return LinearInterpolation(x, x1, x2, y1, y2);
|
||||
}
|
||||
else if (InterPolMethod == "Exp" ){
|
||||
return ExponentialInterpolation(x,x1,x2,y1,y2);
|
||||
else if(InterPolMethod == "Exp")
|
||||
{
|
||||
return ExponentialInterpolation(x, x1, x2, y1, y2);
|
||||
}
|
||||
else {
|
||||
//G4cout<<"The interpolation method that you invoked does not exist!"<<G4endl;
|
||||
return -1111111111.;
|
||||
else
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
ed << "The interpolation method that you invoked does not exist!\n";
|
||||
G4Exception("G4AdjointInterpolator::Interpolation", "adoint001",
|
||||
FatalException, ed);
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
size_t G4AdjointInterpolator::FindPosition(G4double& x,std::vector<G4double>& x_vec,size_t , size_t ) //only valid if x_vec is monotically increasing
|
||||
// only valid if x_vec is monotically increasing
|
||||
size_t G4AdjointInterpolator::FindPosition(G4double& x,
|
||||
std::vector<G4double>& x_vec, size_t,
|
||||
size_t)
|
||||
{
|
||||
//most rapid nethod could be used probably
|
||||
//It is important to put std::vector<G4double>& such that the vector itself is used and not a copy
|
||||
|
||||
|
||||
// most rapid method could be used probably
|
||||
|
||||
size_t ndim = x_vec.size();
|
||||
size_t ind1 = 0;
|
||||
size_t ind2 = ndim - 1;
|
||||
/* if (ind_max >= ind_min){
|
||||
ind1=ind_min;
|
||||
ind2=ind_max;
|
||||
|
||||
|
||||
|
||||
if(ndim > 1)
|
||||
{
|
||||
if(x_vec[0] < x_vec[1])
|
||||
{ // increasing
|
||||
do
|
||||
{
|
||||
size_t midBin = (ind1 + ind2) / 2;
|
||||
if(x < x_vec[midBin])
|
||||
ind2 = midBin;
|
||||
else
|
||||
ind1 = midBin;
|
||||
} while(ind2 - ind1 > 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
size_t midBin = (ind1 + ind2) / 2;
|
||||
if(x < x_vec[midBin])
|
||||
ind1 = midBin;
|
||||
else
|
||||
ind2 = midBin;
|
||||
} while(ind2 - ind1 > 1);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if (ndim >1) {
|
||||
|
||||
if (x_vec[0] < x_vec[1] ) { //increasing
|
||||
do {
|
||||
size_t midBin = (ind1 + ind2)/2;
|
||||
if (x < x_vec[midBin])
|
||||
ind2 = midBin;
|
||||
else
|
||||
ind1 = midBin;
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
} while (ind2 - ind1 > 1);
|
||||
}
|
||||
else {
|
||||
do {
|
||||
size_t midBin = (ind1 + ind2)/2;
|
||||
if (x < x_vec[midBin])
|
||||
ind1 = midBin;
|
||||
else
|
||||
ind2 = midBin;
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
} while (ind2 - ind1 > 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return ind1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
size_t G4AdjointInterpolator::FindPositionForLogVector(G4double& log_x,std::vector<G4double>& log_x_vec) //only valid if x_vec is monotically increasing
|
||||
// only valid if x_vec is monotically increasing
|
||||
size_t G4AdjointInterpolator::FindPositionForLogVector(
|
||||
G4double& log_x, std::vector<G4double>& log_x_vec)
|
||||
{
|
||||
//most rapid nethod could be used probably
|
||||
//It is important to put std::vector<G4double>& such that the vector itself is used and not a copy
|
||||
// most rapid method could be used probably
|
||||
return FindPosition(log_x, log_x_vec);
|
||||
/*
|
||||
if (log_x_vec.size()>3){
|
||||
size_t ind=0;
|
||||
G4double log_x1=log_x_vec[1];
|
||||
G4double d_log =log_x_vec[2]-log_x1;
|
||||
G4double dind=(log_x-log_x1)/d_log +1.;
|
||||
if (dind <1.) ind=0;
|
||||
else if (dind >= double(log_x_vec.size())-2.) ind =log_x_vec.size()-2;
|
||||
else ind =size_t(dind);
|
||||
return ind;
|
||||
|
||||
}
|
||||
else return FindPosition(log_x, log_x_vec);
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointInterpolator::Interpolate(G4double& x,std::vector<G4double>& x_vec,std::vector<G4double>& y_vec,G4String InterPolMethod)
|
||||
G4double G4AdjointInterpolator::Interpolate(G4double& x,
|
||||
std::vector<G4double>& x_vec,
|
||||
std::vector<G4double>& y_vec,
|
||||
G4String InterPolMethod)
|
||||
{
|
||||
size_t i=FindPosition(x,x_vec);
|
||||
//G4cout<<i<<G4endl;
|
||||
//G4cout<<x<<G4endl;
|
||||
//G4cout<<x_vec[i]<<G4endl;
|
||||
return Interpolation( x,x_vec[i],x_vec[i+1],y_vec[i],y_vec[i+1],InterPolMethod);
|
||||
size_t i = FindPosition(x, x_vec);
|
||||
return Interpolation(x, x_vec[i], x_vec[i + 1], y_vec[i], y_vec[i + 1],
|
||||
InterPolMethod);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointInterpolator::InterpolateWithIndexVector(G4double& x,std::vector<G4double>& x_vec,std::vector<G4double>& y_vec,
|
||||
std::vector<size_t>& index_vec,G4double x0, G4double dx) //only linear interpolation possible
|
||||
G4double G4AdjointInterpolator::InterpolateWithIndexVector(
|
||||
G4double& x, std::vector<G4double>& x_vec, std::vector<G4double>& y_vec,
|
||||
std::vector<size_t>& index_vec, G4double x0,
|
||||
G4double dx) // only linear interpolation possible
|
||||
{
|
||||
size_t ind=0;
|
||||
if (x>x0) ind=int((x-x0)/dx);
|
||||
if (ind >= index_vec.size()-1) ind= index_vec.size()-2;
|
||||
size_t ind = 0;
|
||||
if(x > x0)
|
||||
ind = int((x - x0) / dx);
|
||||
if(ind >= index_vec.size() - 1)
|
||||
ind = index_vec.size() - 2;
|
||||
size_t ind1 = index_vec[ind];
|
||||
size_t ind2 = index_vec[ind+1];
|
||||
if (ind1 >ind2) {
|
||||
size_t ind11=ind1;
|
||||
ind1=ind2;
|
||||
ind2=ind11;
|
||||
|
||||
size_t ind2 = index_vec[ind + 1];
|
||||
if(ind1 > ind2)
|
||||
{
|
||||
size_t ind11 = ind1;
|
||||
ind1 = ind2;
|
||||
ind2 = ind11;
|
||||
}
|
||||
ind=FindPosition(x,x_vec,ind1,ind2);
|
||||
return Interpolation( x,x_vec[ind],x_vec[ind+1],y_vec[ind],y_vec[ind+1],"Lin");
|
||||
}
|
||||
ind = FindPosition(x, x_vec, ind1, ind2);
|
||||
return Interpolation(x, x_vec[ind], x_vec[ind + 1], y_vec[ind],
|
||||
y_vec[ind + 1], "Lin");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointInterpolator::InterpolateForLogVector(G4double& log_x,std::vector<G4double>& log_x_vec,std::vector<G4double>& log_y_vec)
|
||||
G4double G4AdjointInterpolator::InterpolateForLogVector(
|
||||
G4double& log_x, std::vector<G4double>& log_x_vec,
|
||||
std::vector<G4double>& log_y_vec)
|
||||
{
|
||||
//size_t i=0;
|
||||
size_t i=FindPositionForLogVector(log_x,log_x_vec);
|
||||
/*G4cout<<"In interpolate "<<G4endl;
|
||||
G4cout<<i<<G4endl;
|
||||
G4cout<<log_x<<G4endl;
|
||||
G4cout<<log_x_vec[i]<<G4endl;
|
||||
G4cout<<log_x_vec[i+1]<<G4endl;
|
||||
G4cout<<log_y_vec[i]<<G4endl;
|
||||
G4cout<<log_y_vec[i+1]<<G4endl;*/
|
||||
|
||||
G4double log_y=LinearInterpolation(log_x,log_x_vec[i],log_x_vec[i+1],log_y_vec[i],log_y_vec[i+1]);
|
||||
size_t i = FindPositionForLogVector(log_x, log_x_vec);
|
||||
|
||||
G4double log_y = LinearInterpolation(log_x, log_x_vec[i], log_x_vec[i + 1],
|
||||
log_y_vec[i], log_y_vec[i + 1]);
|
||||
return log_y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,341 +23,317 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
#include "G4AdjointIonIonisationModel.hh"
|
||||
#include "G4AdjointCSManager.hh"
|
||||
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4Integrator.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4AdjointIonIonisationModel.hh"
|
||||
|
||||
#include "G4AdjointCSManager.hh"
|
||||
#include "G4AdjointElectron.hh"
|
||||
#include "G4AdjointProton.hh"
|
||||
#include "G4AdjointInterpolator.hh"
|
||||
#include "G4BetheBlochModel.hh"
|
||||
#include "G4BraggIonModel.hh"
|
||||
#include "G4Proton.hh"
|
||||
#include "G4GenericIon.hh"
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointIonIonisationModel::G4AdjointIonIonisationModel():
|
||||
G4VEmAdjointModel("Adjoint_IonIonisation")
|
||||
{
|
||||
|
||||
|
||||
UseMatrix =true;
|
||||
UseMatrixPerElement = true;
|
||||
ApplyCutInRange = true;
|
||||
UseOnlyOneMatrixForAllElements = true;
|
||||
CS_biasing_factor =1.;
|
||||
second_part_of_same_type =false;
|
||||
use_only_bragg = false; // for the Ion ionisation using the parametrised table model the cross sections and the sample of secondaries is done
|
||||
// as in the BraggIonModel, Therefore the use of this flag;
|
||||
|
||||
//The direct EM Model is taken has BetheBloch it is only used for the computation
|
||||
// of the differential cross section.
|
||||
//The Bragg model could be used as an alternative as it offers the same differential cross section
|
||||
|
||||
theBetheBlochDirectEMModel = new G4BetheBlochModel(G4GenericIon::GenericIon());
|
||||
theBraggIonDirectEMModel = new G4BraggIonModel(G4GenericIon::GenericIon());
|
||||
theAdjEquivOfDirectSecondPartDef=G4AdjointElectron::AdjointElectron();
|
||||
theDirectPrimaryPartDef =0;
|
||||
theAdjEquivOfDirectPrimPartDef =0;
|
||||
/* theDirectPrimaryPartDef =fwd_ion;
|
||||
theAdjEquivOfDirectPrimPartDef =adj_ion;
|
||||
|
||||
DefineProjectileProperty();*/
|
||||
|
||||
|
||||
G4AdjointIonIonisationModel::G4AdjointIonIonisationModel()
|
||||
: G4VEmAdjointModel("Adjoint_IonIonisation")
|
||||
{
|
||||
fUseMatrix = true;
|
||||
fUseMatrixPerElement = true;
|
||||
fApplyCutInRange = true;
|
||||
fOneMatrixForAllElements = true;
|
||||
fSecondPartSameType = false;
|
||||
|
||||
// The direct EM Model is taken as BetheBloch. It is only used for the
|
||||
// computation of the differential cross section.
|
||||
// The Bragg model could be used as an alternative as it offers the same
|
||||
// differential cross section
|
||||
|
||||
fBetheBlochDirectEMModel = new G4BetheBlochModel(G4GenericIon::GenericIon());
|
||||
fBraggIonDirectEMModel = new G4BraggIonModel(G4GenericIon::GenericIon());
|
||||
fAdjEquivDirectSecondPart = G4AdjointElectron::AdjointElectron();
|
||||
fDirectPrimaryPart = nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointIonIonisationModel::~G4AdjointIonIonisationModel()
|
||||
{;}
|
||||
G4AdjointIonIonisationModel::~G4AdjointIonIonisationModel() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointIonIonisationModel::SampleSecondaries(const G4Track& aTrack,
|
||||
G4bool IsScatProjToProjCase,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
|
||||
|
||||
//Elastic inverse scattering
|
||||
//---------------------------------------------------------
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimP =theAdjointPrimary->GetTotalMomentum();
|
||||
void G4AdjointIonIonisationModel::SampleSecondaries(
|
||||
const G4Track& aTrack, G4bool isScatProjToProj,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
const G4DynamicParticle* theAdjointPrimary = aTrack.GetDynamicParticle();
|
||||
|
||||
if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
|
||||
return;
|
||||
}
|
||||
|
||||
//Sample secondary energy
|
||||
//-----------------------
|
||||
G4double projectileKinEnergy = SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy, IsScatProjToProjCase);
|
||||
CorrectPostStepWeight(fParticleChange,
|
||||
aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy,
|
||||
projectileKinEnergy,
|
||||
IsScatProjToProjCase); //Caution !!!this weight correction should be always applied
|
||||
// Elastic inverse scattering
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimP = theAdjointPrimary->GetTotalMomentum();
|
||||
|
||||
|
||||
//Kinematic:
|
||||
//we consider a two body elastic scattering for the forward processes where the projectile knock on an e- at rest and gives
|
||||
// him part of its energy
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
G4double projectileM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0+projectileKinEnergy;
|
||||
G4double projectileP2 = projectileTotalEnergy*projectileTotalEnergy - projectileM0*projectileM0;
|
||||
|
||||
|
||||
|
||||
//Companion
|
||||
//-----------
|
||||
G4double companionM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
if (IsScatProjToProjCase) {
|
||||
companionM0=theAdjEquivOfDirectSecondPartDef->GetPDGMass();
|
||||
}
|
||||
G4double companionTotalEnergy =companionM0+ projectileKinEnergy-adjointPrimKinEnergy;
|
||||
G4double companionP2 = companionTotalEnergy*companionTotalEnergy - companionM0*companionM0;
|
||||
|
||||
|
||||
//Projectile momentum
|
||||
//--------------------
|
||||
G4double P_parallel = (adjointPrimP*adjointPrimP + projectileP2 - companionP2)/(2.*adjointPrimP);
|
||||
G4double P_perp = std::sqrt( projectileP2 - P_parallel*P_parallel);
|
||||
G4ThreeVector dir_parallel=theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi =G4UniformRand()*2.*3.1415926;
|
||||
G4ThreeVector projectileMomentum = G4ThreeVector(P_perp*std::cos(phi),P_perp*std::sin(phi),P_parallel);
|
||||
projectileMomentum.rotateUz(dir_parallel);
|
||||
|
||||
|
||||
|
||||
if (!IsScatProjToProjCase ){ //kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,projectileMomentum));
|
||||
//G4cout<<"projectileMomentum "<<projectileMomentum<<G4endl;
|
||||
}
|
||||
else {
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointIonIonisationModel::DiffCrossSectionPerAtomPrimToSecond(
|
||||
G4double kinEnergyProj,
|
||||
G4double kinEnergyProd,
|
||||
G4double Z,
|
||||
G4double A)
|
||||
{//Probably that here the Bragg Model should be also used for kinEnergyProj/nuc<2MeV
|
||||
|
||||
|
||||
|
||||
G4double dSigmadEprod=0;
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProjCase(kinEnergyProd);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProjCase(kinEnergyProd);
|
||||
|
||||
G4double kinEnergyProjScaled = massRatio*kinEnergyProj;
|
||||
|
||||
|
||||
if (kinEnergyProj>Emin_proj && kinEnergyProj<=Emax_proj){ //the produced particle should have a kinetic energy smaller than the projectile
|
||||
G4double Tmax=kinEnergyProj;
|
||||
|
||||
G4double E1=kinEnergyProd;
|
||||
G4double E2=kinEnergyProd*1.000001;
|
||||
G4double dE=(E2-E1);
|
||||
G4double sigma1,sigma2;
|
||||
theDirectEMModel =theBraggIonDirectEMModel;
|
||||
if (kinEnergyProjScaled >2.*MeV && !use_only_bragg) theDirectEMModel = theBetheBlochDirectEMModel; //Bethe Bloch Model
|
||||
sigma1=theDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E1,1.e20);
|
||||
sigma2=theDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E2,1.e20);
|
||||
|
||||
dSigmadEprod=(sigma1-sigma2)/dE;
|
||||
|
||||
//G4double chargeSqRatio = currentModel->GetChargeSquareRatio(theDirectPrimaryPartDef,currentMaterial,E);
|
||||
|
||||
|
||||
|
||||
if (dSigmadEprod>1.) {
|
||||
G4cout<<"sigma1 "<<kinEnergyProj/MeV<<'\t'<<kinEnergyProd/MeV<<'\t'<<sigma1<<G4endl;
|
||||
G4cout<<"sigma2 "<<kinEnergyProj/MeV<<'\t'<<kinEnergyProd/MeV<<'\t'<<sigma2<<G4endl;
|
||||
G4cout<<"dsigma "<<kinEnergyProj/MeV<<'\t'<<kinEnergyProd/MeV<<'\t'<<dSigmadEprod<<G4endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (theDirectEMModel == theBetheBlochDirectEMModel ){
|
||||
//correction of differential cross section at high energy to correct for the suppression of particle at secondary at high
|
||||
//energy used in the Bethe Bloch Model. This correction consist to multiply by g the probability function used
|
||||
//to test the rejection of a secondary
|
||||
//-------------------------
|
||||
|
||||
//Source code taken from G4BetheBlochModel::SampleSecondaries
|
||||
|
||||
G4double deltaKinEnergy = kinEnergyProd;
|
||||
|
||||
//Part of the taken code
|
||||
//----------------------
|
||||
|
||||
|
||||
|
||||
// projectile formfactor - suppresion of high energy
|
||||
// delta-electron production at high energy
|
||||
|
||||
|
||||
G4double x = formfact*deltaKinEnergy;
|
||||
if(x > 1.e-6) {
|
||||
G4double totEnergy = kinEnergyProj + mass;
|
||||
G4double etot2 = totEnergy*totEnergy;
|
||||
G4double beta2 = kinEnergyProj*(kinEnergyProj + 2.0*mass)/etot2;
|
||||
G4double f;
|
||||
G4double f1 = 0.0;
|
||||
f = 1.0 - beta2*deltaKinEnergy/Tmax;
|
||||
if( 0.5 == spin ) {
|
||||
f1 = 0.5*deltaKinEnergy*deltaKinEnergy/etot2;
|
||||
f += f1;
|
||||
}
|
||||
G4double x1 = 1.0 + x;
|
||||
G4double gg = 1.0/(x1*x1);
|
||||
if( 0.5 == spin ) {
|
||||
G4double x2 = 0.5*electron_mass_c2*deltaKinEnergy/(mass*mass);
|
||||
gg *= (1.0 + magMoment2*(x2 - f1/f)/(1.0 + x2));
|
||||
}
|
||||
if(gg > 1.0) {
|
||||
G4cout << "### G4BetheBlochModel in Adjoint Sim WARNING: gg= " << gg
|
||||
<< G4endl;
|
||||
gg=1.;
|
||||
}
|
||||
//G4cout<<"gg"<<gg<<G4endl;
|
||||
dSigmadEprod*=gg;
|
||||
}
|
||||
}
|
||||
|
||||
if(adjointPrimKinEnergy > GetHighEnergyLimit() * 0.999)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return dSigmadEprod;
|
||||
// Sample secondary energy
|
||||
G4double projectileKinEnergy =
|
||||
SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy, isScatProjToProj);
|
||||
// Caution !!!this weight correction should be always applied
|
||||
CorrectPostStepWeight(fParticleChange, aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy, projectileKinEnergy,
|
||||
isScatProjToProj);
|
||||
|
||||
// Kinematics:
|
||||
// we consider a two body elastic scattering for the forward processes where
|
||||
// the projectile knock on an e- at rest and gives it part of its energy
|
||||
G4double projectileM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0 + projectileKinEnergy;
|
||||
G4double projectileP2 =
|
||||
projectileTotalEnergy * projectileTotalEnergy - projectileM0 * projectileM0;
|
||||
|
||||
// Companion
|
||||
G4double companionM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
if(isScatProjToProj)
|
||||
{
|
||||
companionM0 = fAdjEquivDirectSecondPart->GetPDGMass();
|
||||
}
|
||||
G4double companionTotalEnergy =
|
||||
companionM0 + projectileKinEnergy - adjointPrimKinEnergy;
|
||||
G4double companionP2 =
|
||||
companionTotalEnergy * companionTotalEnergy - companionM0 * companionM0;
|
||||
|
||||
// Projectile momentum
|
||||
G4double P_parallel =
|
||||
(adjointPrimP * adjointPrimP + projectileP2 - companionP2) /
|
||||
(2. * adjointPrimP);
|
||||
G4double P_perp = std::sqrt(projectileP2 - P_parallel * P_parallel);
|
||||
G4ThreeVector dir_parallel = theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi = G4UniformRand() * twopi;
|
||||
G4ThreeVector projectileMomentum =
|
||||
G4ThreeVector(P_perp * std::cos(phi), P_perp * std::sin(phi), P_parallel);
|
||||
projectileMomentum.rotateUz(dir_parallel);
|
||||
|
||||
if(!isScatProjToProj)
|
||||
{ // kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(
|
||||
new G4DynamicParticle(fAdjEquivDirectPrimPart, projectileMomentum));
|
||||
}
|
||||
else
|
||||
{
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointIonIonisationModel::SetIon(G4ParticleDefinition* adj_ion, G4ParticleDefinition* fwd_ion)
|
||||
{ theDirectPrimaryPartDef =fwd_ion;
|
||||
theAdjEquivOfDirectPrimPartDef =adj_ion;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4double G4AdjointIonIonisationModel::DiffCrossSectionPerAtomPrimToSecond(
|
||||
G4double kinEnergyProj, G4double kinEnergyProd, G4double Z, G4double A)
|
||||
{
|
||||
// Probably that here the Bragg Model should be also used for
|
||||
// kinEnergyProj/nuc<2MeV
|
||||
G4double dSigmadEprod = 0.;
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProj(kinEnergyProd);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProj(kinEnergyProd);
|
||||
|
||||
G4double kinEnergyProjScaled = fMassRatio * kinEnergyProj;
|
||||
|
||||
// the produced particle should have a kinetic energy smaller than the
|
||||
// projectile
|
||||
if(kinEnergyProj > Emin_proj && kinEnergyProj <= Emax_proj)
|
||||
{
|
||||
G4double Tmax = kinEnergyProj;
|
||||
|
||||
G4double E1 = kinEnergyProd;
|
||||
G4double E2 = kinEnergyProd * 1.000001;
|
||||
G4double dE = (E2 - E1);
|
||||
G4double sigma1, sigma2;
|
||||
fDirectModel = fBraggIonDirectEMModel;
|
||||
if(kinEnergyProjScaled > 2. * MeV && !fUseOnlyBragg)
|
||||
fDirectModel = fBetheBlochDirectEMModel;
|
||||
sigma1 = fDirectModel->ComputeCrossSectionPerAtom(
|
||||
fDirectPrimaryPart, kinEnergyProj, Z, A, E1, 1.e20);
|
||||
sigma2 = fDirectModel->ComputeCrossSectionPerAtom(
|
||||
fDirectPrimaryPart, kinEnergyProj, Z, A, E2, 1.e20);
|
||||
|
||||
dSigmadEprod = (sigma1 - sigma2) / dE;
|
||||
|
||||
if(dSigmadEprod > 1.)
|
||||
{
|
||||
G4cout << "sigma1 " << kinEnergyProj / MeV << '\t' << kinEnergyProd / MeV
|
||||
<< '\t' << sigma1 << G4endl;
|
||||
G4cout << "sigma2 " << kinEnergyProj / MeV << '\t' << kinEnergyProd / MeV
|
||||
<< '\t' << sigma2 << G4endl;
|
||||
G4cout << "dsigma " << kinEnergyProj / MeV << '\t' << kinEnergyProd / MeV
|
||||
<< '\t' << dSigmadEprod << G4endl;
|
||||
}
|
||||
|
||||
if(fDirectModel == fBetheBlochDirectEMModel)
|
||||
{
|
||||
// correction of differential cross section at high energy to correct for
|
||||
// the suppression of particle at secondary at high energy used in the
|
||||
// Bethe Bloch Model. This correction consist to multiply by g the
|
||||
// probability function used to test the rejection of a secondary Source
|
||||
// code taken from G4BetheBlochModel::SampleSecondaries
|
||||
|
||||
G4double deltaKinEnergy = kinEnergyProd;
|
||||
|
||||
G4double x = fFormFact * deltaKinEnergy;
|
||||
if(x > 1.e-6)
|
||||
{
|
||||
G4double totEnergy = kinEnergyProj + fMass;
|
||||
G4double etot2 = totEnergy * totEnergy;
|
||||
G4double beta2 = kinEnergyProj * (kinEnergyProj + 2.0 * fMass) / etot2;
|
||||
G4double f1 = 0.0;
|
||||
G4double f = 1.0 - beta2 * deltaKinEnergy / Tmax;
|
||||
if(0.5 == fSpin)
|
||||
{
|
||||
f1 = 0.5 * deltaKinEnergy * deltaKinEnergy / etot2;
|
||||
f += f1;
|
||||
}
|
||||
G4double x1 = 1.0 + x;
|
||||
G4double gg = 1.0 / (x1 * x1);
|
||||
if(0.5 == fSpin)
|
||||
{
|
||||
G4double x2 =
|
||||
0.5 * electron_mass_c2 * deltaKinEnergy / (fMass * fMass);
|
||||
gg *= (1.0 + fMagMoment2 * (x2 - f1 / f) / (1.0 + x2));
|
||||
}
|
||||
if(gg > 1.0)
|
||||
{
|
||||
G4cout << "### G4BetheBlochModel in Adjoint Sim WARNING: gg= " << gg
|
||||
<< G4endl;
|
||||
gg = 1.;
|
||||
}
|
||||
dSigmadEprod *= gg;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dSigmadEprod;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointIonIonisationModel::SetIon(G4ParticleDefinition* adj_ion,
|
||||
G4ParticleDefinition* fwd_ion)
|
||||
{
|
||||
fDirectPrimaryPart = fwd_ion;
|
||||
fAdjEquivDirectPrimPart = adj_ion;
|
||||
|
||||
DefineProjectileProperty();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointIonIonisationModel::CorrectPostStepWeight(G4ParticleChange* fParticleChange, G4double old_weight,
|
||||
G4double adjointPrimKinEnergy, G4double projectileKinEnergy,G4bool )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointIonIonisationModel::CorrectPostStepWeight(
|
||||
G4ParticleChange* fParticleChange, G4double old_weight,
|
||||
G4double adjointPrimKinEnergy, G4double projectileKinEnergy, G4bool)
|
||||
{
|
||||
//It is needed because the direct cross section used to compute the differential cross section is not the one used in
|
||||
// the direct model where the GenericIon stuff is considered with correction of effective charge. In the direct model the samnepl of secondaries does
|
||||
// not reflect the integral cross section. The integral fwd cross section that we used to compute the differential CS
|
||||
// match the sample of secondaries in the forward case despite the fact that its is not the same total CS than in the FWD case. For this reasion an extra
|
||||
// weight correction is needed at the end.
|
||||
|
||||
// It is needed because the direct cross section used to compute the
|
||||
// differential cross section is not the one used in
|
||||
// the direct model where the GenericIon stuff is considered with correction
|
||||
// of effective charge. In the direct model the samnepl of secondaries does
|
||||
// not reflect the integral cross section. The integral fwd cross section that
|
||||
// we used to compute the differential CS match the sample of secondaries in
|
||||
// the forward case despite the fact that its is not the same total CS than in
|
||||
// the FWD case. For this reason an extra weight correction is needed at the
|
||||
// end.
|
||||
|
||||
G4double new_weight=old_weight;
|
||||
|
||||
//the correction of CS due to the problem explained above
|
||||
G4double kinEnergyProjScaled = massRatio*projectileKinEnergy;
|
||||
theDirectEMModel =theBraggIonDirectEMModel;
|
||||
if (kinEnergyProjScaled >2.*MeV && !use_only_bragg) theDirectEMModel = theBetheBlochDirectEMModel; //Bethe Bloch Model
|
||||
G4double UsedFwdCS=theDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,projectileKinEnergy,1,1 ,currentTcutForDirectSecond,1.e20);
|
||||
G4double chargeSqRatio =1.;
|
||||
if (chargeSquare>1.) chargeSqRatio = theDirectEMModel->GetChargeSquareRatio(theDirectPrimaryPartDef,currentMaterial,projectileKinEnergy);
|
||||
G4double CorrectFwdCS = chargeSqRatio*theDirectEMModel->ComputeCrossSectionPerAtom(G4GenericIon::GenericIon(),kinEnergyProjScaled,1,1 ,currentTcutForDirectSecond,1.e20);
|
||||
if (UsedFwdCS >0) new_weight*= CorrectFwdCS/UsedFwdCS;//May be some check is needed if UsedFwdCS ==0 probably that then we should avoid a secondary to be produced,
|
||||
|
||||
|
||||
//additional CS crorrection needed for cross section biasing in general.
|
||||
//May be wrong for ions!!! Most of the time not used!
|
||||
G4double w_corr =1./CS_biasing_factor;
|
||||
w_corr*=G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection();
|
||||
new_weight*=w_corr;
|
||||
|
||||
new_weight*=projectileKinEnergy/adjointPrimKinEnergy;
|
||||
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
G4double new_weight = old_weight;
|
||||
|
||||
// the correction of CS due to the problem explained above
|
||||
G4double kinEnergyProjScaled = fMassRatio * projectileKinEnergy;
|
||||
fDirectModel = fBraggIonDirectEMModel;
|
||||
if(kinEnergyProjScaled > 2. * MeV && !fUseOnlyBragg)
|
||||
fDirectModel = fBetheBlochDirectEMModel;
|
||||
G4double UsedFwdCS = fDirectModel->ComputeCrossSectionPerAtom(
|
||||
fDirectPrimaryPart, projectileKinEnergy, 1, 1, fTcutSecond, 1.e20);
|
||||
G4double chargeSqRatio = 1.;
|
||||
if(fChargeSquare > 1.)
|
||||
chargeSqRatio = fDirectModel->GetChargeSquareRatio(
|
||||
fDirectPrimaryPart, fCurrentMaterial, projectileKinEnergy);
|
||||
G4double CorrectFwdCS =
|
||||
chargeSqRatio * fDirectModel->ComputeCrossSectionPerAtom(
|
||||
G4GenericIon::GenericIon(), kinEnergyProjScaled, 1, 1,
|
||||
fTcutSecond, 1.e20);
|
||||
// May be some check is needed if UsedFwdCS ==0 probably that then we should
|
||||
// avoid a secondary to be produced,
|
||||
if(UsedFwdCS > 0.)
|
||||
new_weight *= CorrectFwdCS / UsedFwdCS;
|
||||
|
||||
// additional CS correction needed for cross section biasing in general.
|
||||
// May be wrong for ions. Most of the time not used.
|
||||
new_weight *=
|
||||
G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection() /
|
||||
fCsBiasingFactor;
|
||||
|
||||
new_weight *= projectileKinEnergy / adjointPrimKinEnergy;
|
||||
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointIonIonisationModel::DefineProjectileProperty()
|
||||
{
|
||||
//Slightly modified code taken from G4BetheBlochModel::SetParticle
|
||||
//------------------------------------------------
|
||||
G4String pname = theDirectPrimaryPartDef->GetParticleName();
|
||||
if (theDirectPrimaryPartDef->GetParticleType() == "nucleus" &&
|
||||
pname != "deuteron" && pname != "triton") {
|
||||
isIon = true;
|
||||
{
|
||||
// Slightly modified code taken from G4BetheBlochModel::SetParticle
|
||||
G4String pname = fDirectPrimaryPart->GetParticleName();
|
||||
|
||||
fMass = fDirectPrimaryPart->GetPDGMass();
|
||||
fMassRatio = G4GenericIon::GenericIon()->GetPDGMass() / fMass;
|
||||
fSpin = fDirectPrimaryPart->GetPDGSpin();
|
||||
G4double q = fDirectPrimaryPart->GetPDGCharge() / eplus;
|
||||
fChargeSquare = q * q;
|
||||
fRatio = electron_mass_c2 / fMass;
|
||||
fOnePlusRatio2 = (1. + fRatio) * (1. + fRatio);
|
||||
fOneMinusRatio2 = (1. - fRatio) * (1. - fRatio);
|
||||
G4double magmom = fDirectPrimaryPart->GetPDGMagneticMoment() * fMass /
|
||||
(0.5 * eplus * hbar_Planck * c_squared);
|
||||
fMagMoment2 = magmom * magmom - 1.0;
|
||||
if(fDirectPrimaryPart->GetLeptonNumber() == 0)
|
||||
{
|
||||
G4double x = 0.8426 * GeV;
|
||||
if(fSpin == 0.0 && fMass < GeV)
|
||||
{
|
||||
x = 0.736 * GeV;
|
||||
}
|
||||
|
||||
mass = theDirectPrimaryPartDef->GetPDGMass();
|
||||
massRatio= G4GenericIon::GenericIon()->GetPDGMass()/mass;
|
||||
mass_ratio_projectile = massRatio;
|
||||
spin = theDirectPrimaryPartDef->GetPDGSpin();
|
||||
G4double q = theDirectPrimaryPartDef->GetPDGCharge()/eplus;
|
||||
chargeSquare = q*q;
|
||||
ratio = electron_mass_c2/mass;
|
||||
ratio2 = ratio*ratio;
|
||||
one_plus_ratio_2=(1+ratio)*(1+ratio);
|
||||
one_minus_ratio_2=(1-ratio)*(1-ratio);
|
||||
G4double magmom = theDirectPrimaryPartDef->GetPDGMagneticMoment()
|
||||
*mass/(0.5*eplus*hbar_Planck*c_squared);
|
||||
magMoment2 = magmom*magmom - 1.0;
|
||||
formfact = 0.0;
|
||||
if(theDirectPrimaryPartDef->GetLeptonNumber() == 0) {
|
||||
G4double x = 0.8426*GeV;
|
||||
if(spin == 0.0 && mass < GeV) {x = 0.736*GeV;}
|
||||
else if(mass > GeV) {
|
||||
x /= G4NistManager::Instance()->GetZ13(mass/proton_mass_c2);
|
||||
// tlimit = 51.2*GeV*A13[iz]*A13[iz];
|
||||
}
|
||||
formfact = 2.0*electron_mass_c2/(x*x);
|
||||
tlimit = 2.0/formfact;
|
||||
}
|
||||
else if(fMass > GeV)
|
||||
{
|
||||
x /= G4NistManager::Instance()->GetZ13(fMass / proton_mass_c2);
|
||||
}
|
||||
fFormFact = 2.0 * electron_mass_c2 / (x * x);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
G4double G4AdjointIonIonisationModel::GetSecondAdjEnergyMaxForScatProjToProj(
|
||||
G4double primAdjEnergy)
|
||||
{
|
||||
return primAdjEnergy * fOnePlusRatio2 /
|
||||
(fOneMinusRatio2 - 2. * fRatio * primAdjEnergy / fMass);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointIonIonisationModel::GetSecondAdjEnergyMaxForScatProjToProjCase(G4double PrimAdjEnergy)
|
||||
{
|
||||
G4double Tmax=PrimAdjEnergy*one_plus_ratio_2/(one_minus_ratio_2-2.*ratio*PrimAdjEnergy/mass);
|
||||
return Tmax;
|
||||
G4double G4AdjointIonIonisationModel::GetSecondAdjEnergyMinForScatProjToProj(
|
||||
G4double primAdjEnergy, G4double tcut)
|
||||
{
|
||||
return primAdjEnergy + tcut;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointIonIonisationModel::GetSecondAdjEnergyMinForScatProjToProjCase(G4double PrimAdjEnergy,G4double Tcut)
|
||||
{ return PrimAdjEnergy+Tcut;
|
||||
G4double G4AdjointIonIonisationModel::GetSecondAdjEnergyMaxForProdToProj(
|
||||
G4double)
|
||||
{
|
||||
return GetHighEnergyLimit();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointIonIonisationModel::GetSecondAdjEnergyMaxForProdToProjCase(G4double )
|
||||
{ return HighEnergyLimit;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointIonIonisationModel::GetSecondAdjEnergyMinForProdToProjCase(G4double PrimAdjEnergy)
|
||||
{ G4double Tmin= (2*PrimAdjEnergy-4*mass + std::sqrt(4.*PrimAdjEnergy*PrimAdjEnergy +16.*mass*mass + 8.*PrimAdjEnergy*mass*(1/ratio +ratio)))/4.;
|
||||
return Tmin;
|
||||
G4double G4AdjointIonIonisationModel::GetSecondAdjEnergyMinForProdToProj(
|
||||
G4double primAdjEnergy)
|
||||
{
|
||||
return (2. * primAdjEnergy - 4. * fMass +
|
||||
std::sqrt(4. * primAdjEnergy * primAdjEnergy + 16. * fMass * fMass +
|
||||
8. * primAdjEnergy * fMass * (1. / fRatio + fRatio))) /
|
||||
4.;
|
||||
}
|
||||
|
||||
@@ -23,250 +23,213 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4AdjointPhotoElectricModel.hh"
|
||||
|
||||
#include "G4AdjointCSManager.hh"
|
||||
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4Integrator.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4AdjointElectron.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4AdjointGamma.hh"
|
||||
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4PEEffectFluoModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointPhotoElectricModel::G4AdjointPhotoElectricModel():
|
||||
G4VEmAdjointModel("AdjointPEEffect")
|
||||
G4AdjointPhotoElectricModel::G4AdjointPhotoElectricModel()
|
||||
: G4VEmAdjointModel("AdjointPEEffect")
|
||||
|
||||
{ SetUseMatrix(false);
|
||||
{
|
||||
SetUseMatrix(false);
|
||||
SetApplyCutInRange(false);
|
||||
|
||||
//Initialization
|
||||
current_eEnergy =0.;
|
||||
totAdjointCS=0.;
|
||||
factorCSBiasing =1.;
|
||||
post_step_AdjointCS =0.;
|
||||
pre_step_AdjointCS =0.;
|
||||
totBiasedAdjointCS =0.;
|
||||
|
||||
index_element=0;
|
||||
|
||||
theAdjEquivOfDirectPrimPartDef =G4AdjointGamma::AdjointGamma();
|
||||
theAdjEquivOfDirectSecondPartDef=G4AdjointElectron::AdjointElectron();
|
||||
theDirectPrimaryPartDef=G4Gamma::Gamma();
|
||||
second_part_of_same_type=false;
|
||||
theDirectPEEffectModel = new G4PEEffectFluoModel();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointPhotoElectricModel::~G4AdjointPhotoElectricModel()
|
||||
{;}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointPhotoElectricModel::SampleSecondaries(const G4Track& aTrack,
|
||||
G4bool IsScatProjToProjCase,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{ if (IsScatProjToProjCase) return ;
|
||||
|
||||
//Compute the totAdjointCS vectors if not already done for the current couple and electron energy
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
const G4MaterialCutsCouple* aCouple = aTrack.GetMaterialCutsCouple();
|
||||
const G4DynamicParticle* aDynPart = aTrack.GetDynamicParticle() ;
|
||||
G4double electronEnergy = aDynPart->GetKineticEnergy();
|
||||
G4ThreeVector electronDirection= aDynPart->GetMomentumDirection() ;
|
||||
pre_step_AdjointCS = totAdjointCS; //The last computed CS was at pre step point
|
||||
post_step_AdjointCS = AdjointCrossSection(aCouple, electronEnergy,IsScatProjToProjCase);
|
||||
post_step_AdjointCS = totAdjointCS;
|
||||
|
||||
|
||||
|
||||
|
||||
//Sample element
|
||||
//-------------
|
||||
const G4ElementVector* theElementVector = currentMaterial->GetElementVector();
|
||||
size_t nelm = currentMaterial->GetNumberOfElements();
|
||||
G4double rand_CS= G4UniformRand()*xsec[nelm-1];
|
||||
for (index_element=0; index_element<nelm-1; index_element++){
|
||||
if (rand_CS<xsec[index_element]) break;
|
||||
}
|
||||
|
||||
//Sample shell and binding energy
|
||||
//-------------
|
||||
G4int nShells = (*theElementVector)[index_element]->GetNbOfAtomicShells();
|
||||
rand_CS= shell_prob[index_element][nShells-1]*G4UniformRand();
|
||||
G4int i = 0;
|
||||
for (i=0; i<nShells-1; i++){
|
||||
if (rand_CS<shell_prob[index_element][i]) break;
|
||||
}
|
||||
G4double gammaEnergy= electronEnergy+(*theElementVector)[index_element]->GetAtomicShell(i);
|
||||
|
||||
//Sample cos theta
|
||||
//Copy of the G4PEEfectFluoModel cos theta sampling method ElecCosThetaDistribution.
|
||||
//This method cannot be used directly from G4PEEfectFluoModel because it is a friend method. I should ask Vladimir to change that
|
||||
//------------------------------------------------------------------------------------------------
|
||||
//G4double cos_theta = theDirectPEEffectModel->ElecCosThetaDistribution(electronEnergy);
|
||||
|
||||
G4double cos_theta = 1.;
|
||||
G4double gamma = 1. + electronEnergy/electron_mass_c2;
|
||||
if (gamma <= 5.) {
|
||||
G4double beta = std::sqrt(gamma*gamma-1.)/gamma;
|
||||
G4double b = 0.5*gamma*(gamma-1.)*(gamma-2);
|
||||
|
||||
G4double rndm,term,greject,grejsup;
|
||||
if (gamma < 2.) grejsup = gamma*gamma*(1.+b-beta*b);
|
||||
else grejsup = gamma*gamma*(1.+b+beta*b);
|
||||
|
||||
do { rndm = 1.-2*G4UniformRand();
|
||||
cos_theta = (rndm+beta)/(rndm*beta+1.);
|
||||
term = 1.-beta*cos_theta;
|
||||
greject = (1.-cos_theta*cos_theta)*(1.+b*term)/(term*term);
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
} while(greject < G4UniformRand()*grejsup);
|
||||
}
|
||||
|
||||
// direction of the adjoint gamma electron
|
||||
//---------------------------------------
|
||||
|
||||
|
||||
G4double sin_theta = std::sqrt(1.-cos_theta*cos_theta);
|
||||
G4double Phi = twopi * G4UniformRand();
|
||||
G4double dirx = sin_theta*std::cos(Phi),diry = sin_theta*std::sin(Phi),dirz = cos_theta;
|
||||
G4ThreeVector adjoint_gammaDirection(dirx,diry,dirz);
|
||||
adjoint_gammaDirection.rotateUz(electronDirection);
|
||||
|
||||
|
||||
|
||||
//Weight correction
|
||||
//-----------------------
|
||||
CorrectPostStepWeight(fParticleChange, aTrack.GetWeight(), electronEnergy,gammaEnergy,IsScatProjToProjCase);
|
||||
|
||||
|
||||
|
||||
//Create secondary and modify fParticleChange
|
||||
//--------------------------------------------
|
||||
G4DynamicParticle* anAdjointGamma = new G4DynamicParticle (
|
||||
G4AdjointGamma::AdjointGamma(),adjoint_gammaDirection, gammaEnergy);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(anAdjointGamma);
|
||||
|
||||
|
||||
|
||||
|
||||
fAdjEquivDirectPrimPart = G4AdjointGamma::AdjointGamma();
|
||||
fAdjEquivDirectSecondPart = G4AdjointElectron::AdjointElectron();
|
||||
fDirectPrimaryPart = G4Gamma::Gamma();
|
||||
fSecondPartSameType = false;
|
||||
fDirectModel = new G4PEEffectFluoModel();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointPhotoElectricModel::CorrectPostStepWeight(G4ParticleChange* fParticleChange,
|
||||
G4double old_weight,
|
||||
G4double adjointPrimKinEnergy,
|
||||
G4double projectileKinEnergy ,
|
||||
G4bool )
|
||||
G4AdjointPhotoElectricModel::~G4AdjointPhotoElectricModel() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointPhotoElectricModel::SampleSecondaries(
|
||||
const G4Track& aTrack, G4bool isScatProjToProj,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
G4double new_weight=old_weight;
|
||||
if(isScatProjToProj)
|
||||
return;
|
||||
|
||||
G4double w_corr =G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection()/factorCSBiasing;
|
||||
w_corr*=post_step_AdjointCS/pre_step_AdjointCS;
|
||||
// Compute the fTotAdjointCS vectors if not already done for the current
|
||||
// couple and electron energy
|
||||
const G4DynamicParticle* aDynPart = aTrack.GetDynamicParticle();
|
||||
G4double electronEnergy = aDynPart->GetKineticEnergy();
|
||||
G4ThreeVector electronDirection = aDynPart->GetMomentumDirection();
|
||||
fPreStepAdjointCS =
|
||||
fTotAdjointCS; // The last computed CS was at pre step point
|
||||
AdjointCrossSection(aTrack.GetMaterialCutsCouple(), electronEnergy,
|
||||
isScatProjToProj);
|
||||
fPostStepAdjointCS = fTotAdjointCS;
|
||||
|
||||
// Sample element
|
||||
const G4ElementVector* theElementVector =
|
||||
fCurrentMaterial->GetElementVector();
|
||||
size_t nelm = fCurrentMaterial->GetNumberOfElements();
|
||||
G4double rand_CS = G4UniformRand() * fXsec[nelm - 1];
|
||||
for(fIndexElement = 0; fIndexElement < nelm - 1; ++fIndexElement)
|
||||
{
|
||||
if(rand_CS < fXsec[fIndexElement])
|
||||
break;
|
||||
}
|
||||
|
||||
new_weight*=w_corr;
|
||||
new_weight*=projectileKinEnergy/adjointPrimKinEnergy;
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
}
|
||||
// Sample shell and binding energy
|
||||
G4int nShells = (*theElementVector)[fIndexElement]->GetNbOfAtomicShells();
|
||||
rand_CS = fShellProb[fIndexElement][nShells - 1] * G4UniformRand();
|
||||
G4int i;
|
||||
for(i = 0; i < nShells - 1; ++i)
|
||||
{
|
||||
if(rand_CS < fShellProb[fIndexElement][i])
|
||||
break;
|
||||
}
|
||||
G4double gammaEnergy =
|
||||
electronEnergy + (*theElementVector)[fIndexElement]->GetAtomicShell(i);
|
||||
|
||||
// Sample cos theta
|
||||
// Copy of the G4PEEfectFluoModel cos theta sampling method
|
||||
// ElecCosThetaDistribution. This method cannot be used directly from
|
||||
// G4PEEffectFluoModel because it is a friend method.
|
||||
G4double cos_theta = 1.;
|
||||
G4double gamma = 1. + electronEnergy / electron_mass_c2;
|
||||
if(gamma <= 5.)
|
||||
{
|
||||
G4double beta = std::sqrt(gamma * gamma - 1.) / gamma;
|
||||
G4double b = 0.5 * gamma * (gamma - 1.) * (gamma - 2.);
|
||||
|
||||
G4double rndm, term, greject, grejsup;
|
||||
if(gamma < 2.)
|
||||
grejsup = gamma * gamma * (1. + b - beta * b);
|
||||
else
|
||||
grejsup = gamma * gamma * (1. + b + beta * b);
|
||||
|
||||
do
|
||||
{
|
||||
rndm = 1. - 2. * G4UniformRand();
|
||||
cos_theta = (rndm + beta) / (rndm * beta + 1.);
|
||||
term = 1. - beta * cos_theta;
|
||||
greject = (1. - cos_theta * cos_theta) * (1. + b * term) / (term * term);
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
} while(greject < G4UniformRand() * grejsup);
|
||||
}
|
||||
|
||||
// direction of the adjoint gamma electron
|
||||
G4double sin_theta = std::sqrt(1. - cos_theta * cos_theta);
|
||||
G4double phi = twopi * G4UniformRand();
|
||||
G4double dirx = sin_theta * std::cos(phi);
|
||||
G4double diry = sin_theta * std::sin(phi);
|
||||
G4double dirz = cos_theta;
|
||||
G4ThreeVector adjoint_gammaDirection(dirx, diry, dirz);
|
||||
adjoint_gammaDirection.rotateUz(electronDirection);
|
||||
|
||||
// Weight correction
|
||||
CorrectPostStepWeight(fParticleChange, aTrack.GetWeight(), electronEnergy,
|
||||
gammaEnergy, isScatProjToProj);
|
||||
|
||||
// Create secondary and modify fParticleChange
|
||||
G4DynamicParticle* anAdjointGamma = new G4DynamicParticle(
|
||||
G4AdjointGamma::AdjointGamma(), adjoint_gammaDirection, gammaEnergy);
|
||||
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(anAdjointGamma);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointPhotoElectricModel::CorrectPostStepWeight(
|
||||
G4ParticleChange* fParticleChange, G4double old_weight,
|
||||
G4double adjointPrimKinEnergy, G4double projectileKinEnergy, G4bool)
|
||||
{
|
||||
G4double new_weight = old_weight;
|
||||
|
||||
G4double G4AdjointPhotoElectricModel::AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
|
||||
G4double electronEnergy,
|
||||
G4bool IsScatProjToProjCase)
|
||||
{
|
||||
|
||||
G4double w_corr =
|
||||
G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection() /
|
||||
fFactorCSBiasing;
|
||||
w_corr *= fPostStepAdjointCS / fPreStepAdjointCS;
|
||||
|
||||
if (IsScatProjToProjCase) return 0.;
|
||||
new_weight *= w_corr * projectileKinEnergy / adjointPrimKinEnergy;
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
}
|
||||
|
||||
|
||||
if (aCouple !=currentCouple || current_eEnergy !=electronEnergy) {
|
||||
totAdjointCS = 0.;
|
||||
DefineCurrentMaterialAndElectronEnergy(aCouple, electronEnergy);
|
||||
const G4ElementVector* theElementVector = currentMaterial->GetElementVector();
|
||||
const double* theAtomNumDensityVector = currentMaterial->GetVecNbOfAtomsPerVolume();
|
||||
size_t nelm = currentMaterial->GetNumberOfElements();
|
||||
for (index_element=0;index_element<nelm;index_element++){
|
||||
|
||||
totAdjointCS +=AdjointCrossSectionPerAtom((*theElementVector)[index_element],electronEnergy)*theAtomNumDensityVector[index_element];
|
||||
xsec[index_element] = totAdjointCS;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4double G4AdjointPhotoElectricModel::AdjointCrossSection(
|
||||
const G4MaterialCutsCouple* aCouple, G4double electronEnergy,
|
||||
G4bool isScatProjToProj)
|
||||
{
|
||||
if(isScatProjToProj)
|
||||
return 0.;
|
||||
|
||||
totBiasedAdjointCS=std::min(totAdjointCS,0.01);
|
||||
// totBiasedAdjointCS=totAdjointCS;
|
||||
factorCSBiasing = totBiasedAdjointCS/totAdjointCS;
|
||||
lastCS=totBiasedAdjointCS;
|
||||
|
||||
|
||||
G4double totBiasedAdjointCS = 0.;
|
||||
if(aCouple != fCurrentCouple || fCurrenteEnergy != electronEnergy)
|
||||
{
|
||||
fTotAdjointCS = 0.;
|
||||
DefineCurrentMaterialAndElectronEnergy(aCouple, electronEnergy);
|
||||
const G4ElementVector* theElementVector =
|
||||
fCurrentMaterial->GetElementVector();
|
||||
const G4double* theAtomNumDensityVector =
|
||||
fCurrentMaterial->GetVecNbOfAtomsPerVolume();
|
||||
size_t nelm = fCurrentMaterial->GetNumberOfElements();
|
||||
for(fIndexElement = 0; fIndexElement < nelm; ++fIndexElement)
|
||||
{
|
||||
fTotAdjointCS += AdjointCrossSectionPerAtom(
|
||||
(*theElementVector)[fIndexElement], electronEnergy) *
|
||||
theAtomNumDensityVector[fIndexElement];
|
||||
fXsec[fIndexElement] = fTotAdjointCS;
|
||||
}
|
||||
|
||||
totBiasedAdjointCS = std::min(fTotAdjointCS, 0.01);
|
||||
fFactorCSBiasing = totBiasedAdjointCS / fTotAdjointCS;
|
||||
}
|
||||
return totBiasedAdjointCS;
|
||||
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
G4double G4AdjointPhotoElectricModel::GetAdjointCrossSection(const G4MaterialCutsCouple* aCouple,
|
||||
G4double electronEnergy,
|
||||
G4bool IsScatProjToProjCase)
|
||||
{ return AdjointCrossSection(aCouple,electronEnergy,IsScatProjToProjCase);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
G4double G4AdjointPhotoElectricModel::AdjointCrossSectionPerAtom(const G4Element* anElement,G4double electronEnergy)
|
||||
{
|
||||
G4int nShells = anElement->GetNbOfAtomicShells();
|
||||
G4double Z= anElement->GetZ();
|
||||
G4int i = 0;
|
||||
G4double B0=anElement->GetAtomicShell(0);
|
||||
G4double gammaEnergy = electronEnergy+B0;
|
||||
G4double CS= theDirectPEEffectModel->ComputeCrossSectionPerAtom(G4Gamma::Gamma(),gammaEnergy,Z,0.,0.,0.);
|
||||
G4double adjointCS =0.;
|
||||
if (CS >0) adjointCS += CS/gammaEnergy;
|
||||
shell_prob[index_element][0] = adjointCS;
|
||||
for (i=1;i<nShells;i++){
|
||||
//G4cout<<i<<G4endl;
|
||||
G4double Bi_= anElement->GetAtomicShell(i-1);
|
||||
G4double Bi = anElement->GetAtomicShell(i);
|
||||
//G4cout<<Bi_<<'\t'<<Bi<<G4endl;
|
||||
if (electronEnergy <Bi_-Bi) {
|
||||
gammaEnergy = electronEnergy+Bi;
|
||||
|
||||
CS=theDirectPEEffectModel->ComputeCrossSectionPerAtom(G4Gamma::Gamma(),gammaEnergy,Z,0.,0.,0.);
|
||||
if (CS>0) adjointCS +=CS/gammaEnergy;
|
||||
}
|
||||
shell_prob[index_element][i] = adjointCS;
|
||||
|
||||
G4double G4AdjointPhotoElectricModel::AdjointCrossSectionPerAtom(
|
||||
const G4Element* anElement, G4double electronEnergy)
|
||||
{
|
||||
G4int nShells = anElement->GetNbOfAtomicShells();
|
||||
G4double Z = anElement->GetZ();
|
||||
G4double gammaEnergy = electronEnergy + anElement->GetAtomicShell(0);
|
||||
G4double CS = fDirectModel->ComputeCrossSectionPerAtom(
|
||||
G4Gamma::Gamma(), gammaEnergy, Z, 0., 0., 0.);
|
||||
G4double adjointCS = 0.;
|
||||
if(CS > 0.)
|
||||
adjointCS += CS / gammaEnergy;
|
||||
fShellProb[fIndexElement][0] = adjointCS;
|
||||
for(G4int i = 1; i < nShells; ++i)
|
||||
{
|
||||
G4double Bi1 = anElement->GetAtomicShell(i - 1);
|
||||
G4double Bi = anElement->GetAtomicShell(i);
|
||||
if(electronEnergy < Bi1 - Bi)
|
||||
{
|
||||
gammaEnergy = electronEnergy + Bi;
|
||||
CS = fDirectModel->ComputeCrossSectionPerAtom(G4Gamma::Gamma(),
|
||||
gammaEnergy, Z, 0., 0., 0.);
|
||||
if(CS > 0.)
|
||||
adjointCS += CS / gammaEnergy;
|
||||
}
|
||||
fShellProb[fIndexElement][i] = adjointCS;
|
||||
}
|
||||
adjointCS*=electronEnergy;
|
||||
adjointCS *= electronEnergy;
|
||||
return adjointCS;
|
||||
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void G4AdjointPhotoElectricModel::DefineCurrentMaterialAndElectronEnergy(const G4MaterialCutsCouple* couple, G4double anEnergy)
|
||||
{ currentCouple = const_cast<G4MaterialCutsCouple*> (couple);
|
||||
currentMaterial = const_cast<G4Material*> (couple->GetMaterial());
|
||||
currentCoupleIndex = couple->GetIndex();
|
||||
currentMaterialIndex = currentMaterial->GetIndex();
|
||||
current_eEnergy = anEnergy;
|
||||
theDirectPEEffectModel->SetCurrentCouple(couple);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointPhotoElectricModel::DefineCurrentMaterialAndElectronEnergy(
|
||||
const G4MaterialCutsCouple* couple, G4double anEnergy)
|
||||
{
|
||||
fCurrentCouple = const_cast<G4MaterialCutsCouple*>(couple);
|
||||
fCurrentMaterial = const_cast<G4Material*>(couple->GetMaterial());
|
||||
fCurrenteEnergy = anEnergy;
|
||||
fDirectModel->SetCurrentCouple(couple);
|
||||
}
|
||||
|
||||
+170
-218
@@ -23,297 +23,249 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
// GEANT 4 class implementation file
|
||||
//
|
||||
// Class Description
|
||||
//
|
||||
// This class is for adjoint process equivalent to direct process
|
||||
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
// Created by L.Desorgher 25 Sept. 2009 Inspired from G4WrapperProcess
|
||||
// Created by L.Desorgher 25 Sept. 2009
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#include "G4AdjointProcessEquivalentToDirectProcess.hh"
|
||||
|
||||
#include "G4DynamicParticle.hh"
|
||||
G4AdjointProcessEquivalentToDirectProcess::G4AdjointProcessEquivalentToDirectProcess(const G4String& aName,
|
||||
G4VProcess* aProcess,
|
||||
G4ParticleDefinition* fwd_particle_def)
|
||||
:G4VProcess(aName)
|
||||
{
|
||||
theDirectProcess =aProcess;
|
||||
theProcessType = theDirectProcess->GetProcessType();
|
||||
theFwdParticleDef = fwd_particle_def;
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4VProcess.hh"
|
||||
|
||||
G4AdjointProcessEquivalentToDirectProcess::
|
||||
G4AdjointProcessEquivalentToDirectProcess(
|
||||
const G4String& aName, G4VProcess* aProcess,
|
||||
G4ParticleDefinition* fwd_particle_def)
|
||||
: G4VProcess(aName)
|
||||
{
|
||||
fDirectProcess = aProcess;
|
||||
theProcessType = fDirectProcess->GetProcessType();
|
||||
fFwdParticleDef = fwd_particle_def;
|
||||
}
|
||||
|
||||
|
||||
G4AdjointProcessEquivalentToDirectProcess::~G4AdjointProcessEquivalentToDirectProcess()
|
||||
G4AdjointProcessEquivalentToDirectProcess::
|
||||
~G4AdjointProcessEquivalentToDirectProcess()
|
||||
{
|
||||
if (theDirectProcess!=0) delete theDirectProcess;
|
||||
if(fDirectProcess != nullptr)
|
||||
delete fDirectProcess;
|
||||
}
|
||||
|
||||
void G4AdjointProcessEquivalentToDirectProcess::ResetNumberOfInteractionLengthLeft()
|
||||
void G4AdjointProcessEquivalentToDirectProcess::
|
||||
ResetNumberOfInteractionLengthLeft()
|
||||
{
|
||||
theDirectProcess->ResetNumberOfInteractionLengthLeft();
|
||||
fDirectProcess->ResetNumberOfInteractionLengthLeft();
|
||||
}
|
||||
|
||||
G4double G4AdjointProcessEquivalentToDirectProcess::
|
||||
AlongStepGetPhysicalInteractionLength( const G4Track& track,
|
||||
G4double previousStepSize,
|
||||
G4double currentMinimumStep,
|
||||
G4double& proposedSafety,
|
||||
G4GPILSelection* selection )
|
||||
{
|
||||
|
||||
|
||||
//Change the particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
G4DynamicParticle* theDynPart = const_cast<G4DynamicParticle*> (track.GetDynamicParticle());
|
||||
AlongStepGetPhysicalInteractionLength(const G4Track& track,
|
||||
G4double previousStepSize,
|
||||
G4double currentMinimumStep,
|
||||
G4double& proposedSafety,
|
||||
G4GPILSelection* selection)
|
||||
{
|
||||
// Change the particle definition to the direct one
|
||||
G4DynamicParticle* theDynPart =
|
||||
const_cast<G4DynamicParticle*>(track.GetDynamicParticle());
|
||||
G4ParticleDefinition* adjPartDef = theDynPart->GetDefinition();
|
||||
|
||||
G4DecayProducts* decayProducts = const_cast<G4DecayProducts*> (theDynPart->GetPreAssignedDecayProducts());
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*)(0));
|
||||
theDynPart->SetDefinition(theFwdParticleDef);
|
||||
|
||||
|
||||
//Call the direct process
|
||||
//----------------------
|
||||
G4double GPIL = theDirectProcess->
|
||||
AlongStepGetPhysicalInteractionLength( track,
|
||||
previousStepSize,
|
||||
currentMinimumStep,
|
||||
proposedSafety,
|
||||
selection );
|
||||
|
||||
|
||||
//Restore the adjoint particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
|
||||
G4DecayProducts* decayProducts =
|
||||
const_cast<G4DecayProducts*>(theDynPart->GetPreAssignedDecayProducts());
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*) (0));
|
||||
theDynPart->SetDefinition(fFwdParticleDef);
|
||||
|
||||
// Call the direct process
|
||||
G4double GPIL = fDirectProcess->AlongStepGetPhysicalInteractionLength(
|
||||
track, previousStepSize, currentMinimumStep, proposedSafety, selection);
|
||||
|
||||
// Restore the adjoint particle definition to the direct one
|
||||
theDynPart->SetDefinition(adjPartDef);
|
||||
theDynPart->SetPreAssignedDecayProducts(decayProducts);
|
||||
|
||||
|
||||
|
||||
return GPIL;
|
||||
|
||||
}
|
||||
|
||||
G4double G4AdjointProcessEquivalentToDirectProcess::
|
||||
AtRestGetPhysicalInteractionLength( const G4Track& track,
|
||||
G4ForceCondition* condition )
|
||||
{ //Change the particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
G4DynamicParticle* theDynPart = const_cast<G4DynamicParticle*> (track.GetDynamicParticle());
|
||||
G4double
|
||||
G4AdjointProcessEquivalentToDirectProcess::AtRestGetPhysicalInteractionLength(
|
||||
const G4Track& track, G4ForceCondition* condition)
|
||||
{
|
||||
// Change the particle definition to the direct one
|
||||
G4DynamicParticle* theDynPart =
|
||||
const_cast<G4DynamicParticle*>(track.GetDynamicParticle());
|
||||
G4ParticleDefinition* adjPartDef = theDynPart->GetDefinition();
|
||||
|
||||
G4DecayProducts* decayProducts = const_cast<G4DecayProducts*> (theDynPart->GetPreAssignedDecayProducts());
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*)(0));
|
||||
theDynPart->SetDefinition(theFwdParticleDef);
|
||||
|
||||
|
||||
//Call the direct process
|
||||
//----------------------
|
||||
|
||||
|
||||
G4double GPIL = theDirectProcess->AtRestGetPhysicalInteractionLength( track, condition );
|
||||
|
||||
//Restore the adjoint particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
G4DecayProducts* decayProducts =
|
||||
const_cast<G4DecayProducts*>(theDynPart->GetPreAssignedDecayProducts());
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*) (0));
|
||||
theDynPart->SetDefinition(fFwdParticleDef);
|
||||
|
||||
// Call the direct process
|
||||
G4double GPIL =
|
||||
fDirectProcess->AtRestGetPhysicalInteractionLength(track, condition);
|
||||
|
||||
// Restore the adjoint particle definition to the direct one
|
||||
theDynPart->SetDefinition(adjPartDef);
|
||||
theDynPart->SetPreAssignedDecayProducts(decayProducts);
|
||||
|
||||
|
||||
return GPIL;
|
||||
|
||||
|
||||
}
|
||||
|
||||
G4double G4AdjointProcessEquivalentToDirectProcess::
|
||||
PostStepGetPhysicalInteractionLength( const G4Track& track,
|
||||
G4double previousStepSize,
|
||||
G4ForceCondition* condition )
|
||||
G4double
|
||||
G4AdjointProcessEquivalentToDirectProcess::PostStepGetPhysicalInteractionLength(
|
||||
const G4Track& track, G4double previousStepSize, G4ForceCondition* condition)
|
||||
{
|
||||
//Change the particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
G4DynamicParticle* theDynPart = const_cast<G4DynamicParticle*> (track.GetDynamicParticle());
|
||||
// Change the particle definition to the direct one
|
||||
G4DynamicParticle* theDynPart =
|
||||
const_cast<G4DynamicParticle*>(track.GetDynamicParticle());
|
||||
G4ParticleDefinition* adjPartDef = theDynPart->GetDefinition();
|
||||
|
||||
G4DecayProducts* decayProducts = const_cast<G4DecayProducts*> (theDynPart->GetPreAssignedDecayProducts());
|
||||
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*)(0));
|
||||
theDynPart->SetDefinition(theFwdParticleDef);
|
||||
|
||||
|
||||
//Call the direct process
|
||||
//----------------------
|
||||
|
||||
|
||||
G4double GPIL = theDirectProcess->PostStepGetPhysicalInteractionLength( track,
|
||||
previousStepSize,
|
||||
condition );
|
||||
|
||||
//Restore the adjoint particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
G4DecayProducts* decayProducts =
|
||||
const_cast<G4DecayProducts*>(theDynPart->GetPreAssignedDecayProducts());
|
||||
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*) (0));
|
||||
theDynPart->SetDefinition(fFwdParticleDef);
|
||||
|
||||
// Call the direct process
|
||||
G4double GPIL = fDirectProcess->PostStepGetPhysicalInteractionLength(
|
||||
track, previousStepSize, condition);
|
||||
|
||||
// Restore the adjoint particle definition to the direct one
|
||||
theDynPart->SetDefinition(adjPartDef);
|
||||
theDynPart->SetPreAssignedDecayProducts(decayProducts);
|
||||
|
||||
return GPIL;
|
||||
|
||||
|
||||
}
|
||||
/*
|
||||
|
||||
void G4AdjointProcessEquivalentToDirectProcess::SetProcessManager(const G4ProcessManager* procMan)
|
||||
{
|
||||
theDirectProcess->SetProcessManager(procMan);
|
||||
|
||||
return GPIL;
|
||||
}
|
||||
|
||||
const G4ProcessManager* G4AdjointProcessEquivalentToDirectProcess::GetProcessManager()
|
||||
G4VParticleChange* G4AdjointProcessEquivalentToDirectProcess::PostStepDoIt(
|
||||
const G4Track& track, const G4Step& stepData)
|
||||
{
|
||||
return theDirectProcess->GetProcessManager();
|
||||
}
|
||||
*/
|
||||
G4VParticleChange* G4AdjointProcessEquivalentToDirectProcess::PostStepDoIt( const G4Track& track,
|
||||
const G4Step& stepData )
|
||||
{
|
||||
//Change the particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
G4DynamicParticle* theDynPart = const_cast<G4DynamicParticle*> (track.GetDynamicParticle());
|
||||
// Change the particle definition to the direct one
|
||||
G4DynamicParticle* theDynPart =
|
||||
const_cast<G4DynamicParticle*>(track.GetDynamicParticle());
|
||||
G4ParticleDefinition* adjPartDef = theDynPart->GetDefinition();
|
||||
|
||||
G4DecayProducts* decayProducts = const_cast<G4DecayProducts*> (theDynPart->GetPreAssignedDecayProducts());
|
||||
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*)(0));
|
||||
theDynPart->SetDefinition(theFwdParticleDef);
|
||||
|
||||
|
||||
//Call the direct process
|
||||
//----------------------
|
||||
|
||||
G4VParticleChange* partChange = theDirectProcess->PostStepDoIt( track, stepData );
|
||||
|
||||
|
||||
//Restore the adjoint particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
|
||||
G4DecayProducts* decayProducts =
|
||||
const_cast<G4DecayProducts*>(theDynPart->GetPreAssignedDecayProducts());
|
||||
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*) (0));
|
||||
theDynPart->SetDefinition(fFwdParticleDef);
|
||||
|
||||
// Call the direct process
|
||||
G4VParticleChange* partChange = fDirectProcess->PostStepDoIt(track, stepData);
|
||||
|
||||
// Restore the adjoint particle definition to the direct one
|
||||
theDynPart->SetDefinition(adjPartDef);
|
||||
theDynPart->SetPreAssignedDecayProducts(decayProducts);
|
||||
|
||||
|
||||
return partChange;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
G4VParticleChange* G4AdjointProcessEquivalentToDirectProcess::AlongStepDoIt( const G4Track& track,
|
||||
const G4Step& stepData )
|
||||
{
|
||||
//Change the particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
G4DynamicParticle* theDynPart = const_cast<G4DynamicParticle*> (track.GetDynamicParticle());
|
||||
G4VParticleChange* G4AdjointProcessEquivalentToDirectProcess::AlongStepDoIt(
|
||||
const G4Track& track, const G4Step& stepData)
|
||||
{
|
||||
// Change the particle definition to the direct one
|
||||
G4DynamicParticle* theDynPart =
|
||||
const_cast<G4DynamicParticle*>(track.GetDynamicParticle());
|
||||
G4ParticleDefinition* adjPartDef = theDynPart->GetDefinition();
|
||||
|
||||
G4DecayProducts* decayProducts = const_cast<G4DecayProducts*> (theDynPart->GetPreAssignedDecayProducts());
|
||||
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*)(0));
|
||||
theDynPart->SetDefinition(theFwdParticleDef);
|
||||
|
||||
|
||||
//Call the direct process
|
||||
//----------------------
|
||||
G4VParticleChange* partChange =theDirectProcess->AlongStepDoIt( track, stepData );
|
||||
|
||||
//Restore the adjoint particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
|
||||
G4DecayProducts* decayProducts =
|
||||
const_cast<G4DecayProducts*>(theDynPart->GetPreAssignedDecayProducts());
|
||||
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*) (0));
|
||||
theDynPart->SetDefinition(fFwdParticleDef);
|
||||
|
||||
// Call the direct process
|
||||
G4VParticleChange* partChange =
|
||||
fDirectProcess->AlongStepDoIt(track, stepData);
|
||||
|
||||
// Restore the adjoint particle definition to the direct one
|
||||
theDynPart->SetDefinition(adjPartDef);
|
||||
theDynPart->SetPreAssignedDecayProducts(decayProducts);
|
||||
|
||||
return partChange;
|
||||
|
||||
return partChange;
|
||||
}
|
||||
|
||||
G4VParticleChange* G4AdjointProcessEquivalentToDirectProcess::AtRestDoIt( const G4Track& track,
|
||||
const G4Step& stepData )
|
||||
|
||||
G4VParticleChange* G4AdjointProcessEquivalentToDirectProcess::AtRestDoIt(
|
||||
const G4Track& track, const G4Step& stepData)
|
||||
{
|
||||
//Change the particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
G4DynamicParticle* theDynPart = const_cast<G4DynamicParticle*> (track.GetDynamicParticle());
|
||||
// Change the particle definition to the direct one
|
||||
G4DynamicParticle* theDynPart =
|
||||
const_cast<G4DynamicParticle*>(track.GetDynamicParticle());
|
||||
G4ParticleDefinition* adjPartDef = theDynPart->GetDefinition();
|
||||
|
||||
G4DecayProducts* decayProducts = const_cast<G4DecayProducts*> (theDynPart->GetPreAssignedDecayProducts());
|
||||
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*)(0));
|
||||
theDynPart->SetDefinition(theFwdParticleDef);
|
||||
|
||||
|
||||
//Call the direct process
|
||||
//----------------------
|
||||
G4VParticleChange* partChange =theDirectProcess->AtRestDoIt( track, stepData );
|
||||
|
||||
//Restore the adjoint particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
|
||||
G4DecayProducts* decayProducts =
|
||||
const_cast<G4DecayProducts*>(theDynPart->GetPreAssignedDecayProducts());
|
||||
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*) (0));
|
||||
theDynPart->SetDefinition(fFwdParticleDef);
|
||||
|
||||
// Call the direct process
|
||||
G4VParticleChange* partChange = fDirectProcess->AtRestDoIt(track, stepData);
|
||||
|
||||
// Restore the adjoint particle definition to the direct one
|
||||
theDynPart->SetDefinition(adjPartDef);
|
||||
theDynPart->SetPreAssignedDecayProducts(decayProducts);
|
||||
|
||||
return partChange;
|
||||
|
||||
|
||||
|
||||
return partChange;
|
||||
}
|
||||
|
||||
G4bool G4AdjointProcessEquivalentToDirectProcess::IsApplicable(const G4ParticleDefinition&)
|
||||
G4bool G4AdjointProcessEquivalentToDirectProcess::IsApplicable(
|
||||
const G4ParticleDefinition&)
|
||||
{
|
||||
return theDirectProcess->IsApplicable(*theFwdParticleDef);
|
||||
return fDirectProcess->IsApplicable(*fFwdParticleDef);
|
||||
}
|
||||
|
||||
void G4AdjointProcessEquivalentToDirectProcess::BuildPhysicsTable(const G4ParticleDefinition& )
|
||||
void G4AdjointProcessEquivalentToDirectProcess::BuildPhysicsTable(
|
||||
const G4ParticleDefinition&)
|
||||
{
|
||||
return theDirectProcess->BuildPhysicsTable(*theFwdParticleDef);
|
||||
return fDirectProcess->BuildPhysicsTable(*fFwdParticleDef);
|
||||
}
|
||||
|
||||
void G4AdjointProcessEquivalentToDirectProcess::PreparePhysicsTable(const G4ParticleDefinition& )
|
||||
void G4AdjointProcessEquivalentToDirectProcess::PreparePhysicsTable(
|
||||
const G4ParticleDefinition&)
|
||||
{
|
||||
return theDirectProcess->PreparePhysicsTable(*theFwdParticleDef);
|
||||
return fDirectProcess->PreparePhysicsTable(*fFwdParticleDef);
|
||||
}
|
||||
|
||||
G4bool G4AdjointProcessEquivalentToDirectProcess::
|
||||
StorePhysicsTable(const G4ParticleDefinition* ,
|
||||
const G4String& directory,
|
||||
G4bool ascii)
|
||||
G4bool G4AdjointProcessEquivalentToDirectProcess::StorePhysicsTable(
|
||||
const G4ParticleDefinition*, const G4String& directory, G4bool ascii)
|
||||
{
|
||||
return theDirectProcess->StorePhysicsTable(theFwdParticleDef, directory, ascii);
|
||||
}
|
||||
|
||||
G4bool G4AdjointProcessEquivalentToDirectProcess::
|
||||
RetrievePhysicsTable( const G4ParticleDefinition* ,
|
||||
const G4String& directory,
|
||||
G4bool ascii)
|
||||
return fDirectProcess->StorePhysicsTable(fFwdParticleDef, directory, ascii);
|
||||
}
|
||||
|
||||
G4bool G4AdjointProcessEquivalentToDirectProcess::RetrievePhysicsTable(
|
||||
const G4ParticleDefinition*, const G4String& directory, G4bool ascii)
|
||||
{
|
||||
return theDirectProcess->RetrievePhysicsTable(theFwdParticleDef, directory, ascii);
|
||||
}
|
||||
return fDirectProcess->RetrievePhysicsTable(fFwdParticleDef, directory,
|
||||
ascii);
|
||||
}
|
||||
|
||||
void G4AdjointProcessEquivalentToDirectProcess::StartTracking(G4Track* track)
|
||||
{
|
||||
//Change the particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
G4DynamicParticle* theDynPart = const_cast<G4DynamicParticle*> (track->GetDynamicParticle());
|
||||
// Change the particle definition to the direct one
|
||||
G4DynamicParticle* theDynPart =
|
||||
const_cast<G4DynamicParticle*>(track->GetDynamicParticle());
|
||||
G4ParticleDefinition* adjPartDef = theDynPart->GetDefinition();
|
||||
|
||||
G4DecayProducts* decayProducts = const_cast<G4DecayProducts*> (theDynPart->GetPreAssignedDecayProducts());
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*)(0));
|
||||
theDynPart->SetDefinition(theFwdParticleDef);
|
||||
|
||||
theDirectProcess->StartTracking(track);
|
||||
|
||||
//Restore the adjoint particle definition to the direct one
|
||||
//------------------------------------------------
|
||||
|
||||
G4DecayProducts* decayProducts =
|
||||
const_cast<G4DecayProducts*>(theDynPart->GetPreAssignedDecayProducts());
|
||||
theDynPart->SetPreAssignedDecayProducts((G4DecayProducts*) (0));
|
||||
theDynPart->SetDefinition(fFwdParticleDef);
|
||||
|
||||
fDirectProcess->StartTracking(track);
|
||||
|
||||
// Restore the adjoint particle definition to the direct one
|
||||
theDynPart->SetDefinition(adjPartDef);
|
||||
theDynPart->SetPreAssignedDecayProducts(decayProducts);
|
||||
|
||||
|
||||
return;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void G4AdjointProcessEquivalentToDirectProcess::EndTracking()
|
||||
{
|
||||
theDirectProcess->EndTracking();
|
||||
fDirectProcess->EndTracking();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,193 +23,175 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4AdjointeIonisationModel.hh"
|
||||
#include "G4AdjointCSManager.hh"
|
||||
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4Integrator.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4AdjointElectron.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4AdjointGamma.hh"
|
||||
|
||||
#include "G4Electron.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointeIonisationModel::G4AdjointeIonisationModel():
|
||||
G4VEmAdjointModel("Inv_eIon_model")
|
||||
G4AdjointeIonisationModel::G4AdjointeIonisationModel()
|
||||
: G4VEmAdjointModel("Inv_eIon_model")
|
||||
|
||||
{
|
||||
|
||||
UseMatrix =true;
|
||||
UseMatrixPerElement = true;
|
||||
ApplyCutInRange = true;
|
||||
UseOnlyOneMatrixForAllElements = true;
|
||||
CS_biasing_factor =1.;
|
||||
WithRapidSampling = false;
|
||||
|
||||
theAdjEquivOfDirectPrimPartDef =G4AdjointElectron::AdjointElectron();
|
||||
theAdjEquivOfDirectSecondPartDef=G4AdjointElectron::AdjointElectron();
|
||||
theDirectPrimaryPartDef=G4Electron::Electron();
|
||||
second_part_of_same_type=true;
|
||||
fUseMatrix = true;
|
||||
fUseMatrixPerElement = true;
|
||||
fApplyCutInRange = true;
|
||||
fOneMatrixForAllElements = true;
|
||||
|
||||
fAdjEquivDirectPrimPart = G4AdjointElectron::AdjointElectron();
|
||||
fAdjEquivDirectSecondPart = G4AdjointElectron::AdjointElectron();
|
||||
fDirectPrimaryPart = G4Electron::Electron();
|
||||
fSecondPartSameType = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointeIonisationModel::~G4AdjointeIonisationModel()
|
||||
{;}
|
||||
G4AdjointeIonisationModel::~G4AdjointeIonisationModel() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointeIonisationModel::SampleSecondaries(const G4Track& aTrack,
|
||||
G4bool IsScatProjToProjCase,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
void G4AdjointeIonisationModel::SampleSecondaries(
|
||||
const G4Track& aTrack, G4bool IsScatProjToProj,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
const G4DynamicParticle* theAdjointPrimary = aTrack.GetDynamicParticle();
|
||||
|
||||
// Elastic inverse scattering
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimP = theAdjointPrimary->GetTotalMomentum();
|
||||
|
||||
const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
|
||||
|
||||
//Elastic inverse scattering
|
||||
//---------------------------------------------------------
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimP =theAdjointPrimary->GetTotalMomentum();
|
||||
if(adjointPrimKinEnergy > GetHighEnergyLimit() * 0.999)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
|
||||
return;
|
||||
}
|
||||
|
||||
//Sample secondary energy
|
||||
//-----------------------
|
||||
G4double projectileKinEnergy;
|
||||
if (!WithRapidSampling ) { //used by default
|
||||
projectileKinEnergy = SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy, IsScatProjToProjCase);
|
||||
|
||||
CorrectPostStepWeight(fParticleChange,
|
||||
aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy,
|
||||
projectileKinEnergy,
|
||||
IsScatProjToProjCase); //Caution !!!this weight correction should be always applied
|
||||
}
|
||||
else { //only for test at the moment
|
||||
|
||||
G4double Emin,Emax;
|
||||
if (IsScatProjToProjCase) {
|
||||
Emin=GetSecondAdjEnergyMinForScatProjToProjCase(adjointPrimKinEnergy,currentTcutForDirectSecond);
|
||||
Emax=GetSecondAdjEnergyMaxForScatProjToProjCase(adjointPrimKinEnergy);
|
||||
}
|
||||
else {
|
||||
Emin=GetSecondAdjEnergyMinForProdToProjCase(adjointPrimKinEnergy);
|
||||
Emax=GetSecondAdjEnergyMaxForProdToProjCase(adjointPrimKinEnergy);
|
||||
}
|
||||
projectileKinEnergy = Emin*std::pow(Emax/Emin,G4UniformRand());
|
||||
|
||||
|
||||
|
||||
lastCS=lastAdjointCSForScatProjToProjCase;
|
||||
if ( !IsScatProjToProjCase) lastCS=lastAdjointCSForProdToProjCase;
|
||||
|
||||
G4double new_weight=aTrack.GetWeight();
|
||||
G4double used_diffCS=lastCS*std::log(Emax/Emin)/projectileKinEnergy;
|
||||
G4double needed_diffCS=adjointPrimKinEnergy/projectileKinEnergy;
|
||||
if (!IsScatProjToProjCase) needed_diffCS *=DiffCrossSectionPerVolumePrimToSecond(currentMaterial,projectileKinEnergy,adjointPrimKinEnergy);
|
||||
else needed_diffCS *=DiffCrossSectionPerVolumePrimToScatPrim(currentMaterial,projectileKinEnergy,adjointPrimKinEnergy);
|
||||
new_weight*=needed_diffCS/used_diffCS;
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Kinematic:
|
||||
//we consider a two body elastic scattering for the forward processes where the projectile knock on an e- at rest and gives
|
||||
// him part of its energy
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
G4double projectileM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0+projectileKinEnergy;
|
||||
G4double projectileP2 = projectileTotalEnergy*projectileTotalEnergy - projectileM0*projectileM0;
|
||||
|
||||
|
||||
|
||||
//Companion
|
||||
//-----------
|
||||
G4double companionM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
if (IsScatProjToProjCase) {
|
||||
companionM0=theAdjEquivOfDirectSecondPartDef->GetPDGMass();
|
||||
}
|
||||
G4double companionTotalEnergy =companionM0+ projectileKinEnergy-adjointPrimKinEnergy;
|
||||
G4double companionP2 = companionTotalEnergy*companionTotalEnergy - companionM0*companionM0;
|
||||
|
||||
|
||||
//Projectile momentum
|
||||
//--------------------
|
||||
G4double P_parallel = (adjointPrimP*adjointPrimP + projectileP2 - companionP2)/(2.*adjointPrimP);
|
||||
G4double P_perp = std::sqrt( projectileP2 - P_parallel*P_parallel);
|
||||
G4ThreeVector dir_parallel=theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi =G4UniformRand()*2.*3.1415926;
|
||||
G4ThreeVector projectileMomentum = G4ThreeVector(P_perp*std::cos(phi),P_perp*std::sin(phi),P_parallel);
|
||||
projectileMomentum.rotateUz(dir_parallel);
|
||||
|
||||
|
||||
|
||||
if (!IsScatProjToProjCase ){ //kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,projectileMomentum));
|
||||
//G4cout<<"projectileMomentum "<<projectileMomentum<<G4endl;
|
||||
}
|
||||
else {
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
|
||||
// Sample secondary energy
|
||||
G4double projectileKinEnergy;
|
||||
if(!fWithRapidSampling)
|
||||
{ // used by default
|
||||
projectileKinEnergy =
|
||||
SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy, IsScatProjToProj);
|
||||
|
||||
|
||||
// Caution!!! this weight correction should be always applied
|
||||
CorrectPostStepWeight(fParticleChange, aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy, projectileKinEnergy,
|
||||
IsScatProjToProj);
|
||||
}
|
||||
else
|
||||
{ // only for testing
|
||||
G4double Emin, Emax;
|
||||
if(IsScatProjToProj)
|
||||
{
|
||||
Emin = GetSecondAdjEnergyMinForScatProjToProj(adjointPrimKinEnergy,
|
||||
fTcutSecond);
|
||||
Emax = GetSecondAdjEnergyMaxForScatProjToProj(adjointPrimKinEnergy);
|
||||
}
|
||||
else
|
||||
{
|
||||
Emin = GetSecondAdjEnergyMinForProdToProj(adjointPrimKinEnergy);
|
||||
Emax = GetSecondAdjEnergyMaxForProdToProj(adjointPrimKinEnergy);
|
||||
}
|
||||
projectileKinEnergy = Emin * std::pow(Emax / Emin, G4UniformRand());
|
||||
|
||||
fLastCS = fLastAdjointCSForScatProjToProj;
|
||||
if(!IsScatProjToProj)
|
||||
fLastCS = fLastAdjointCSForProdToProj;
|
||||
|
||||
G4double new_weight = aTrack.GetWeight();
|
||||
G4double used_diffCS =
|
||||
fLastCS * std::log(Emax / Emin) / projectileKinEnergy;
|
||||
G4double needed_diffCS = adjointPrimKinEnergy / projectileKinEnergy;
|
||||
if(!IsScatProjToProj)
|
||||
needed_diffCS *= DiffCrossSectionPerVolumePrimToSecond(
|
||||
fCurrentMaterial, projectileKinEnergy, adjointPrimKinEnergy);
|
||||
else
|
||||
needed_diffCS *= DiffCrossSectionPerVolumePrimToScatPrim(
|
||||
fCurrentMaterial, projectileKinEnergy, adjointPrimKinEnergy);
|
||||
new_weight *= needed_diffCS / used_diffCS;
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
}
|
||||
|
||||
// Kinematic:
|
||||
// we consider a two body elastic scattering for the forward processes where
|
||||
// the projectile knock on an e- at rest and gives it part of its energy
|
||||
G4double projectileM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0 + projectileKinEnergy;
|
||||
G4double projectileP2 =
|
||||
projectileTotalEnergy * projectileTotalEnergy - projectileM0 * projectileM0;
|
||||
|
||||
// Companion
|
||||
G4double companionM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
if(IsScatProjToProj)
|
||||
{
|
||||
companionM0 = fAdjEquivDirectSecondPart->GetPDGMass();
|
||||
}
|
||||
G4double companionTotalEnergy =
|
||||
companionM0 + projectileKinEnergy - adjointPrimKinEnergy;
|
||||
G4double companionP2 =
|
||||
companionTotalEnergy * companionTotalEnergy - companionM0 * companionM0;
|
||||
|
||||
// Projectile momentum
|
||||
G4double P_parallel =
|
||||
(adjointPrimP * adjointPrimP + projectileP2 - companionP2) /
|
||||
(2. * adjointPrimP);
|
||||
G4double P_perp = std::sqrt(projectileP2 - P_parallel * P_parallel);
|
||||
G4ThreeVector dir_parallel = theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi = G4UniformRand() * twopi;
|
||||
G4ThreeVector projectileMomentum =
|
||||
G4ThreeVector(P_perp * std::cos(phi), P_perp * std::sin(phi), P_parallel);
|
||||
projectileMomentum.rotateUz(dir_parallel);
|
||||
|
||||
if(!IsScatProjToProj)
|
||||
{ // kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(
|
||||
new G4DynamicParticle(fAdjEquivDirectPrimPart, projectileMomentum));
|
||||
}
|
||||
else
|
||||
{
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//The implementation here is correct for energy loss process, for the photoelectric and compton scattering the method should be redefine
|
||||
// The implementation here is correct for energy loss process, for the
|
||||
// photoelectric and compton scattering the method should be redefined
|
||||
G4double G4AdjointeIonisationModel::DiffCrossSectionPerAtomPrimToSecond(
|
||||
G4double kinEnergyProj,
|
||||
G4double kinEnergyProd,
|
||||
G4double Z,
|
||||
G4double )
|
||||
G4double kinEnergyProj, G4double kinEnergyProd, G4double Z, G4double)
|
||||
{
|
||||
G4double dSigmadEprod=0;
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProjCase(kinEnergyProd);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProjCase(kinEnergyProd);
|
||||
|
||||
|
||||
if (kinEnergyProj>Emin_proj && kinEnergyProj<=Emax_proj){ //the produced particle should have a kinetic energy smaller than the projectile
|
||||
dSigmadEprod=Z*DiffCrossSectionMoller(kinEnergyProj,kinEnergyProd);
|
||||
}
|
||||
return dSigmadEprod;
|
||||
|
||||
|
||||
|
||||
G4double dSigmadEprod = 0.;
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProj(kinEnergyProd);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProj(kinEnergyProd);
|
||||
|
||||
// the produced particle should have a kinetic energy smaller than the
|
||||
// projectile
|
||||
if(kinEnergyProj > Emin_proj && kinEnergyProj <= Emax_proj)
|
||||
{
|
||||
dSigmadEprod = Z * DiffCrossSectionMoller(kinEnergyProj, kinEnergyProd);
|
||||
}
|
||||
return dSigmadEprod;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointeIonisationModel::DiffCrossSectionMoller(G4double kinEnergyProj,G4double kinEnergyProd){
|
||||
|
||||
G4double energy = kinEnergyProj + electron_mass_c2;
|
||||
G4double x = kinEnergyProd/kinEnergyProj;
|
||||
G4double gam = energy/electron_mass_c2;
|
||||
G4double gamma2 = gam*gam;
|
||||
G4double beta2 = 1.0 - 1.0/gamma2;
|
||||
|
||||
G4double gg = (2.0*gam - 1.0)/gamma2;
|
||||
G4double y = 1.0 - x;
|
||||
G4double fac=twopi_mc2_rcl2/electron_mass_c2;
|
||||
G4double dCS = fac*( 1.-gg + ((1.0 - gg*x)/(x*x))
|
||||
+ ((1.0 - gg*y)/(y*y)))/(beta2*(gam-1));
|
||||
return dCS/kinEnergyProj;
|
||||
|
||||
|
||||
|
||||
}
|
||||
G4double G4AdjointeIonisationModel::DiffCrossSectionMoller(
|
||||
G4double kinEnergyProj, G4double kinEnergyProd)
|
||||
{
|
||||
// G4double energy = kinEnergyProj + electron_mass_c2;
|
||||
G4double x = kinEnergyProd / kinEnergyProj;
|
||||
G4double gam = (kinEnergyProj + electron_mass_c2) / electron_mass_c2;
|
||||
G4double gamma2 = gam * gam;
|
||||
G4double beta2 = 1.0 - 1.0 / gamma2;
|
||||
|
||||
G4double gg = (2.0 * gam - 1.0) / gamma2;
|
||||
G4double y = 1.0 - x;
|
||||
G4double fac = twopi_mc2_rcl2 / electron_mass_c2;
|
||||
G4double dCS =
|
||||
fac * (1. - gg + ((1.0 - gg * x) / (x * x)) + ((1.0 - gg * y) / (y * y))) /
|
||||
(beta2 * (gam - 1.));
|
||||
return dCS / kinEnergyProj;
|
||||
}
|
||||
|
||||
@@ -23,476 +23,444 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4AdjointhIonisationModel.hh"
|
||||
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4AdjointCSManager.hh"
|
||||
#include "G4Integrator.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4AdjointElectron.hh"
|
||||
#include "G4AdjointProton.hh"
|
||||
#include "G4AdjointInterpolator.hh"
|
||||
#include "G4BetheBlochModel.hh"
|
||||
#include "G4BraggModel.hh"
|
||||
#include "G4Proton.hh"
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4Proton.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4TrackStatus.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointhIonisationModel::G4AdjointhIonisationModel(G4ParticleDefinition* projectileDefinition):
|
||||
G4VEmAdjointModel("Adjoint_hIonisation")
|
||||
{
|
||||
G4AdjointhIonisationModel::G4AdjointhIonisationModel(G4ParticleDefinition* pDef)
|
||||
: G4VEmAdjointModel("Adjoint_hIonisation")
|
||||
{
|
||||
fUseMatrix = true;
|
||||
fUseMatrixPerElement = true;
|
||||
fApplyCutInRange = true;
|
||||
fOneMatrixForAllElements = true;
|
||||
fSecondPartSameType = false;
|
||||
|
||||
// The direct EM Model is taken as BetheBloch. It is only used for the
|
||||
// computation of the differential cross section.
|
||||
// The Bragg model could be used as an alternative as it offers the same
|
||||
// differential cross section
|
||||
|
||||
fDirectModel = new G4BetheBlochModel(pDef);
|
||||
fBraggDirectEMModel = new G4BraggModel(pDef);
|
||||
fAdjEquivDirectSecondPart = G4AdjointElectron::AdjointElectron();
|
||||
fDirectPrimaryPart = pDef;
|
||||
|
||||
UseMatrix =true;
|
||||
UseMatrixPerElement = true;
|
||||
ApplyCutInRange = true;
|
||||
UseOnlyOneMatrixForAllElements = true;
|
||||
CS_biasing_factor =1.;
|
||||
second_part_of_same_type =false;
|
||||
|
||||
//The direct EM Modfel is taken has BetheBloch it is only used for the computation
|
||||
// of the differential cross section.
|
||||
//The Bragg model could be used as an alternative as it offers the same differential cross section
|
||||
|
||||
theDirectEMModel = new G4BetheBlochModel(projectileDefinition);
|
||||
theBraggDirectEMModel = new G4BraggModel(projectileDefinition);
|
||||
theAdjEquivOfDirectSecondPartDef=G4AdjointElectron::AdjointElectron();
|
||||
|
||||
theDirectPrimaryPartDef = projectileDefinition;
|
||||
theAdjEquivOfDirectPrimPartDef = 0;
|
||||
if (projectileDefinition == G4Proton::Proton()) {
|
||||
theAdjEquivOfDirectPrimPartDef = G4AdjointProton::AdjointProton();
|
||||
|
||||
if(pDef == G4Proton::Proton())
|
||||
{
|
||||
fAdjEquivDirectPrimPart = G4AdjointProton::AdjointProton();
|
||||
}
|
||||
|
||||
|
||||
DefineProjectileProperty();
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4AdjointhIonisationModel::~G4AdjointhIonisationModel()
|
||||
{;}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointhIonisationModel::SampleSecondaries(const G4Track& aTrack,
|
||||
G4bool IsScatProjToProjCase,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
if (!UseMatrix) return RapidSampleSecondaries(aTrack,IsScatProjToProjCase,fParticleChange);
|
||||
|
||||
const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
|
||||
|
||||
//Elastic inverse scattering
|
||||
//---------------------------------------------------------
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimP =theAdjointPrimary->GetTotalMomentum();
|
||||
|
||||
if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
|
||||
return;
|
||||
}
|
||||
|
||||
//Sample secondary energy
|
||||
//-----------------------
|
||||
G4double projectileKinEnergy = SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy, IsScatProjToProjCase);
|
||||
CorrectPostStepWeight(fParticleChange,
|
||||
aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy,
|
||||
projectileKinEnergy,
|
||||
IsScatProjToProjCase); //Caution !!!this weight correction should be always applied
|
||||
|
||||
|
||||
//Kinematic:
|
||||
//we consider a two body elastic scattering for the forward processes where the projectile knock on an e- at rest and gives
|
||||
// him part of its energy
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
G4double projectileM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0+projectileKinEnergy;
|
||||
G4double projectileP2 = projectileTotalEnergy*projectileTotalEnergy - projectileM0*projectileM0;
|
||||
|
||||
|
||||
|
||||
//Companion
|
||||
//-----------
|
||||
G4double companionM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
if (IsScatProjToProjCase) {
|
||||
companionM0=theAdjEquivOfDirectSecondPartDef->GetPDGMass();
|
||||
}
|
||||
G4double companionTotalEnergy =companionM0+ projectileKinEnergy-adjointPrimKinEnergy;
|
||||
G4double companionP2 = companionTotalEnergy*companionTotalEnergy - companionM0*companionM0;
|
||||
|
||||
|
||||
//Projectile momentum
|
||||
//--------------------
|
||||
G4double P_parallel = (adjointPrimP*adjointPrimP + projectileP2 - companionP2)/(2.*adjointPrimP);
|
||||
G4double P_perp = std::sqrt( projectileP2 - P_parallel*P_parallel);
|
||||
G4ThreeVector dir_parallel=theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi =G4UniformRand()*2.*3.1415926;
|
||||
G4ThreeVector projectileMomentum = G4ThreeVector(P_perp*std::cos(phi),P_perp*std::sin(phi),P_parallel);
|
||||
projectileMomentum.rotateUz(dir_parallel);
|
||||
|
||||
|
||||
|
||||
if (!IsScatProjToProjCase ){ //kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,projectileMomentum));
|
||||
//G4cout<<"projectileMomentum "<<projectileMomentum<<G4endl;
|
||||
}
|
||||
else {
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
G4AdjointhIonisationModel::~G4AdjointhIonisationModel() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointhIonisationModel::RapidSampleSecondaries(const G4Track& aTrack,
|
||||
G4bool IsScatProjToProjCase,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
void G4AdjointhIonisationModel::SampleSecondaries(
|
||||
const G4Track& aTrack, G4bool isScatProjToProj,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
if(!fUseMatrix)
|
||||
return RapidSampleSecondaries(aTrack, isScatProjToProj, fParticleChange);
|
||||
|
||||
const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
|
||||
DefineCurrentMaterial(aTrack.GetMaterialCutsCouple());
|
||||
|
||||
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimP =theAdjointPrimary->GetTotalMomentum();
|
||||
|
||||
if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
|
||||
return;
|
||||
}
|
||||
|
||||
G4double projectileKinEnergy =0.;
|
||||
G4double eEnergy=0.;
|
||||
G4double newCS=currentMaterial->GetElectronDensity()*twopi_mc2_rcl2*mass;
|
||||
if (!IsScatProjToProjCase){//1/E^2 distribution
|
||||
|
||||
eEnergy=adjointPrimKinEnergy;
|
||||
G4double Emax = GetSecondAdjEnergyMaxForProdToProjCase(adjointPrimKinEnergy);
|
||||
G4double Emin= GetSecondAdjEnergyMinForProdToProjCase(adjointPrimKinEnergy);
|
||||
if (Emin>=Emax) return;
|
||||
G4double a=1./Emax;
|
||||
G4double b=1./Emin;
|
||||
newCS=newCS*(b-a)/eEnergy;
|
||||
|
||||
projectileKinEnergy =1./(b- (b-a)*G4UniformRand());
|
||||
|
||||
|
||||
}
|
||||
else { G4double Emax = GetSecondAdjEnergyMaxForScatProjToProjCase(adjointPrimKinEnergy);
|
||||
G4double Emin = GetSecondAdjEnergyMinForScatProjToProjCase(adjointPrimKinEnergy,currentTcutForDirectSecond);
|
||||
if (Emin>=Emax) return;
|
||||
G4double diff1=Emin-adjointPrimKinEnergy;
|
||||
G4double diff2=Emax-adjointPrimKinEnergy;
|
||||
|
||||
G4double t1=adjointPrimKinEnergy*(1./diff1-1./diff2);
|
||||
G4double t2=adjointPrimKinEnergy*(1./Emin-1./Emax);
|
||||
/*G4double f31=diff1/Emin;
|
||||
G4double f32=diff2/Emax/f31;*/
|
||||
G4double t3=2.*std::log(Emax/Emin);
|
||||
G4double sum_t=t1+t2+t3;
|
||||
newCS=newCS*sum_t/adjointPrimKinEnergy/adjointPrimKinEnergy;
|
||||
G4double t=G4UniformRand()*sum_t;
|
||||
if (t <=t1 ){
|
||||
G4double q= G4UniformRand()*t1/adjointPrimKinEnergy ;
|
||||
projectileKinEnergy =adjointPrimKinEnergy +1./(1./diff1-q);
|
||||
|
||||
}
|
||||
else if (t <=t2 ) {
|
||||
G4double q= G4UniformRand()*t2/adjointPrimKinEnergy;
|
||||
projectileKinEnergy =1./(1./Emin-q);
|
||||
}
|
||||
else {
|
||||
projectileKinEnergy=Emin*std::pow(Emax/Emin,G4UniformRand());
|
||||
|
||||
}
|
||||
eEnergy=projectileKinEnergy-adjointPrimKinEnergy;
|
||||
|
||||
|
||||
}
|
||||
const G4DynamicParticle* theAdjointPrimary = aTrack.GetDynamicParticle();
|
||||
|
||||
|
||||
// Elastic inverse scattering
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimP = theAdjointPrimary->GetTotalMomentum();
|
||||
|
||||
G4double diffCS_perAtom_Used=twopi_mc2_rcl2*mass*adjointPrimKinEnergy/projectileKinEnergy/projectileKinEnergy/eEnergy/eEnergy;
|
||||
|
||||
|
||||
|
||||
//Weight correction
|
||||
//-----------------------
|
||||
//First w_corr is set to the ratio between adjoint total CS and fwd total CS
|
||||
G4double w_corr=G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection();
|
||||
|
||||
//G4cout<<w_corr<<G4endl;
|
||||
w_corr*=newCS/lastCS;
|
||||
//G4cout<<w_corr<<G4endl;
|
||||
//Then another correction is needed due to the fact that a biaised differential CS has been used rather than the one consistent with the direct model
|
||||
//Here we consider the true diffCS as the one obtained by the numerical differentiation over Tcut of the direct CS
|
||||
|
||||
G4double diffCS = DiffCrossSectionPerAtomPrimToSecond(projectileKinEnergy, eEnergy,1,1);
|
||||
w_corr*=diffCS/diffCS_perAtom_Used;
|
||||
//G4cout<<w_corr<<G4endl;
|
||||
|
||||
G4double new_weight = aTrack.GetWeight()*w_corr;
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
|
||||
|
||||
|
||||
|
||||
//Kinematic:
|
||||
//we consider a two body elastic scattering for the forward processes where the projectile knock on an e- at rest and gives
|
||||
// him part of its energy
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
G4double projectileM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0+projectileKinEnergy;
|
||||
G4double projectileP2 = projectileTotalEnergy*projectileTotalEnergy - projectileM0*projectileM0;
|
||||
|
||||
|
||||
|
||||
//Companion
|
||||
//-----------
|
||||
G4double companionM0 = theAdjEquivOfDirectPrimPartDef->GetPDGMass();
|
||||
if (IsScatProjToProjCase) {
|
||||
companionM0=theAdjEquivOfDirectSecondPartDef->GetPDGMass();
|
||||
}
|
||||
G4double companionTotalEnergy =companionM0+ projectileKinEnergy-adjointPrimKinEnergy;
|
||||
G4double companionP2 = companionTotalEnergy*companionTotalEnergy - companionM0*companionM0;
|
||||
|
||||
|
||||
//Projectile momentum
|
||||
//--------------------
|
||||
G4double P_parallel = (adjointPrimP*adjointPrimP + projectileP2 - companionP2)/(2.*adjointPrimP);
|
||||
G4double P_perp = std::sqrt( projectileP2 - P_parallel*P_parallel);
|
||||
G4ThreeVector dir_parallel=theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi =G4UniformRand()*2.*3.1415926;
|
||||
G4ThreeVector projectileMomentum = G4ThreeVector(P_perp*std::cos(phi),P_perp*std::sin(phi),P_parallel);
|
||||
projectileMomentum.rotateUz(dir_parallel);
|
||||
|
||||
|
||||
|
||||
if (!IsScatProjToProjCase ){ //kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,projectileMomentum));
|
||||
//G4cout<<"projectileMomentum "<<projectileMomentum<<G4endl;
|
||||
}
|
||||
else {
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointhIonisationModel::DiffCrossSectionPerAtomPrimToSecond(
|
||||
G4double kinEnergyProj,
|
||||
G4double kinEnergyProd,
|
||||
G4double Z,
|
||||
G4double A)
|
||||
{//Probably that here the Bragg Model should be also used for kinEnergyProj/nuc<2MeV
|
||||
|
||||
|
||||
|
||||
G4double dSigmadEprod=0;
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProjCase(kinEnergyProd);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProjCase(kinEnergyProd);
|
||||
|
||||
|
||||
if (kinEnergyProj>Emin_proj && kinEnergyProj<=Emax_proj){ //the produced particle should have a kinetic energy smaller than the projectile
|
||||
G4double Tmax=kinEnergyProj;
|
||||
|
||||
G4double E1=kinEnergyProd;
|
||||
G4double E2=kinEnergyProd*1.000001;
|
||||
G4double dE=(E2-E1);
|
||||
G4double sigma1,sigma2;
|
||||
if (kinEnergyProj >2.*MeV){
|
||||
sigma1=theDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E1,1.e20);
|
||||
sigma2=theDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E2,1.e20);
|
||||
}
|
||||
else {
|
||||
sigma1=theBraggDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E1,1.e20);
|
||||
sigma2=theBraggDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E2,1.e20);
|
||||
}
|
||||
|
||||
|
||||
dSigmadEprod=(sigma1-sigma2)/dE;
|
||||
if (dSigmadEprod>1.) {
|
||||
G4cout<<"sigma1 "<<kinEnergyProj/MeV<<'\t'<<kinEnergyProd/MeV<<'\t'<<sigma1<<G4endl;
|
||||
G4cout<<"sigma2 "<<kinEnergyProj/MeV<<'\t'<<kinEnergyProd/MeV<<'\t'<<sigma2<<G4endl;
|
||||
G4cout<<"dsigma "<<kinEnergyProj/MeV<<'\t'<<kinEnergyProd/MeV<<'\t'<<dSigmadEprod<<G4endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//correction of differential cross section at high energy to correct for the suppression of particle at secondary at high
|
||||
//energy used in the Bethe Bloch Model. This correction consist to multiply by g the probability function used
|
||||
//to test the rejection of a secondary
|
||||
//-------------------------
|
||||
|
||||
//Source code taken from G4BetheBlochModel::SampleSecondaries
|
||||
|
||||
G4double deltaKinEnergy = kinEnergyProd;
|
||||
|
||||
//Part of the taken code
|
||||
//----------------------
|
||||
|
||||
|
||||
|
||||
// projectile formfactor - suppresion of high energy
|
||||
// delta-electron production at high energy
|
||||
G4double x = formfact*deltaKinEnergy;
|
||||
if(x > 1.e-6) {
|
||||
|
||||
|
||||
G4double totEnergy = kinEnergyProj + mass;
|
||||
G4double etot2 = totEnergy*totEnergy;
|
||||
G4double beta2 = kinEnergyProj*(kinEnergyProj + 2.0*mass)/etot2;
|
||||
G4double f;
|
||||
G4double f1 = 0.0;
|
||||
f = 1.0 - beta2*deltaKinEnergy/Tmax;
|
||||
if( 0.5 == spin ) {
|
||||
f1 = 0.5*deltaKinEnergy*deltaKinEnergy/etot2;
|
||||
f += f1;
|
||||
}
|
||||
G4double x1 = 1.0 + x;
|
||||
G4double gg = 1.0/(x1*x1);
|
||||
if( 0.5 == spin ) {
|
||||
G4double x2 = 0.5*electron_mass_c2*deltaKinEnergy/(mass*mass);
|
||||
gg *= (1.0 + magMoment2*(x2 - f1/f)/(1.0 + x2));
|
||||
}
|
||||
if(gg > 1.0) {
|
||||
G4cout << "### G4BetheBlochModel in Adjoint Sim WARNING: g= " << g
|
||||
<< G4endl;
|
||||
gg=1.;
|
||||
}
|
||||
//G4cout<<"gg"<<gg<<G4endl;
|
||||
dSigmadEprod*=gg;
|
||||
}
|
||||
|
||||
if(adjointPrimKinEnergy > GetHighEnergyLimit() * 0.999)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return dSigmadEprod;
|
||||
// Sample secondary energy
|
||||
G4double projectileKinEnergy =
|
||||
SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy, isScatProjToProj);
|
||||
CorrectPostStepWeight(fParticleChange, aTrack.GetWeight(),
|
||||
adjointPrimKinEnergy, projectileKinEnergy,
|
||||
isScatProjToProj);
|
||||
// Caution!!! this weight correction should be always applied
|
||||
|
||||
// Kinematic:
|
||||
// we consider a two body elastic scattering for the forward processes where
|
||||
// the projectile knock on an e- at rest and gives it part of its energy
|
||||
G4double projectileM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0 + projectileKinEnergy;
|
||||
G4double projectileP2 =
|
||||
projectileTotalEnergy * projectileTotalEnergy - projectileM0 * projectileM0;
|
||||
|
||||
// Companion
|
||||
G4double companionM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
if(isScatProjToProj)
|
||||
{
|
||||
companionM0 = fAdjEquivDirectSecondPart->GetPDGMass();
|
||||
}
|
||||
G4double companionTotalEnergy =
|
||||
companionM0 + projectileKinEnergy - adjointPrimKinEnergy;
|
||||
G4double companionP2 =
|
||||
companionTotalEnergy * companionTotalEnergy - companionM0 * companionM0;
|
||||
|
||||
// Projectile momentum
|
||||
G4double P_parallel =
|
||||
(adjointPrimP * adjointPrimP + projectileP2 - companionP2) /
|
||||
(2. * adjointPrimP);
|
||||
G4double P_perp = std::sqrt(projectileP2 - P_parallel * P_parallel);
|
||||
G4ThreeVector dir_parallel = theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi = G4UniformRand() * twopi;
|
||||
G4ThreeVector projectileMomentum =
|
||||
G4ThreeVector(P_perp * std::cos(phi), P_perp * std::sin(phi), P_parallel);
|
||||
projectileMomentum.rotateUz(dir_parallel);
|
||||
|
||||
if(!isScatProjToProj)
|
||||
{ // kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(
|
||||
new G4DynamicParticle(fAdjEquivDirectPrimPart, projectileMomentum));
|
||||
}
|
||||
else
|
||||
{
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointhIonisationModel::RapidSampleSecondaries(
|
||||
const G4Track& aTrack, G4bool isScatProjToProj,
|
||||
G4ParticleChange* fParticleChange)
|
||||
{
|
||||
const G4DynamicParticle* theAdjointPrimary = aTrack.GetDynamicParticle();
|
||||
DefineCurrentMaterial(aTrack.GetMaterialCutsCouple());
|
||||
|
||||
G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
|
||||
G4double adjointPrimP = theAdjointPrimary->GetTotalMomentum();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4AdjointhIonisationModel::DefineProjectileProperty()
|
||||
{
|
||||
//Slightly modified code taken from G4BetheBlochModel::SetParticle
|
||||
//------------------------------------------------
|
||||
G4String pname = theDirectPrimaryPartDef->GetParticleName();
|
||||
if (theDirectPrimaryPartDef->GetParticleType() == "nucleus" &&
|
||||
pname != "deuteron" && pname != "triton") {
|
||||
isIon = true;
|
||||
if(adjointPrimKinEnergy > GetHighEnergyLimit() * 0.999)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
G4double projectileKinEnergy = 0.;
|
||||
G4double eEnergy = 0.;
|
||||
G4double newCS =
|
||||
fCurrentMaterial->GetElectronDensity() * twopi_mc2_rcl2 * fMass;
|
||||
if(!isScatProjToProj)
|
||||
{ // 1/E^2 distribution
|
||||
|
||||
eEnergy = adjointPrimKinEnergy;
|
||||
G4double Emax = GetSecondAdjEnergyMaxForProdToProj(adjointPrimKinEnergy);
|
||||
G4double Emin = GetSecondAdjEnergyMinForProdToProj(adjointPrimKinEnergy);
|
||||
if(Emin >= Emax)
|
||||
return;
|
||||
G4double a = 1. / Emax;
|
||||
G4double b = 1. / Emin;
|
||||
newCS = newCS * (b - a) / eEnergy;
|
||||
|
||||
projectileKinEnergy = 1. / (b - (b - a) * G4UniformRand());
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double Emax =
|
||||
GetSecondAdjEnergyMaxForScatProjToProj(adjointPrimKinEnergy);
|
||||
G4double Emin =
|
||||
GetSecondAdjEnergyMinForScatProjToProj(adjointPrimKinEnergy, fTcutSecond);
|
||||
if(Emin >= Emax)
|
||||
return;
|
||||
G4double diff1 = Emin - adjointPrimKinEnergy;
|
||||
G4double diff2 = Emax - adjointPrimKinEnergy;
|
||||
|
||||
G4double t1 = adjointPrimKinEnergy * (1. / diff1 - 1. / diff2);
|
||||
G4double t2 = adjointPrimKinEnergy * (1. / Emin - 1. / Emax);
|
||||
G4double t3 = 2. * std::log(Emax / Emin);
|
||||
G4double sum_t = t1 + t2 + t3;
|
||||
newCS = newCS * sum_t / adjointPrimKinEnergy / adjointPrimKinEnergy;
|
||||
G4double t = G4UniformRand() * sum_t;
|
||||
if(t <= t1)
|
||||
{
|
||||
G4double q = G4UniformRand() * t1 / adjointPrimKinEnergy;
|
||||
projectileKinEnergy = adjointPrimKinEnergy + 1. / (1. / diff1 - q);
|
||||
}
|
||||
|
||||
mass = theDirectPrimaryPartDef->GetPDGMass();
|
||||
mass_ratio_projectile = proton_mass_c2/theDirectPrimaryPartDef->GetPDGMass();;
|
||||
spin = theDirectPrimaryPartDef->GetPDGSpin();
|
||||
G4double q = theDirectPrimaryPartDef->GetPDGCharge()/eplus;
|
||||
chargeSquare = q*q;
|
||||
ratio = electron_mass_c2/mass;
|
||||
ratio2 = ratio*ratio;
|
||||
one_plus_ratio_2=(1+ratio)*(1+ratio);
|
||||
one_minus_ratio_2=(1-ratio)*(1-ratio);
|
||||
G4double magmom = theDirectPrimaryPartDef->GetPDGMagneticMoment()
|
||||
*mass/(0.5*eplus*hbar_Planck*c_squared);
|
||||
magMoment2 = magmom*magmom - 1.0;
|
||||
formfact = 0.0;
|
||||
if(theDirectPrimaryPartDef->GetLeptonNumber() == 0) {
|
||||
G4double x = 0.8426*GeV;
|
||||
if(spin == 0.0 && mass < GeV) {x = 0.736*GeV;}
|
||||
else if(mass > GeV) {
|
||||
x /= G4NistManager::Instance()->GetZ13(mass/proton_mass_c2);
|
||||
// tlimit = 51.2*GeV*A13[iz]*A13[iz];
|
||||
}
|
||||
formfact = 2.0*electron_mass_c2/(x*x);
|
||||
tlimit = 2.0/formfact;
|
||||
}
|
||||
else if(t <= t2)
|
||||
{
|
||||
G4double q = G4UniformRand() * t2 / adjointPrimKinEnergy;
|
||||
projectileKinEnergy = 1. / (1. / Emin - q);
|
||||
}
|
||||
else
|
||||
{
|
||||
projectileKinEnergy = Emin * std::pow(Emax / Emin, G4UniformRand());
|
||||
}
|
||||
eEnergy = projectileKinEnergy - adjointPrimKinEnergy;
|
||||
}
|
||||
|
||||
G4double diffCS_perAtom_Used = twopi_mc2_rcl2 * fMass * adjointPrimKinEnergy /
|
||||
projectileKinEnergy / projectileKinEnergy /
|
||||
eEnergy / eEnergy;
|
||||
|
||||
// Weight correction
|
||||
// First w_corr is set to the ratio between adjoint total CS and fwd total CS
|
||||
G4double w_corr =
|
||||
G4AdjointCSManager::GetAdjointCSManager()->GetPostStepWeightCorrection();
|
||||
|
||||
w_corr *= newCS / fLastCS;
|
||||
// Then another correction is needed due to the fact that a biaised
|
||||
// differential CS has been used rather than the one consistent with the
|
||||
// direct model. Here we consider the true diffCS as the one obtained by the
|
||||
// numerical differentiation over Tcut of the direct CS
|
||||
|
||||
G4double diffCS =
|
||||
DiffCrossSectionPerAtomPrimToSecond(projectileKinEnergy, eEnergy, 1, 1);
|
||||
w_corr *= diffCS / diffCS_perAtom_Used;
|
||||
|
||||
G4double new_weight = aTrack.GetWeight() * w_corr;
|
||||
fParticleChange->SetParentWeightByProcess(false);
|
||||
fParticleChange->SetSecondaryWeightByProcess(false);
|
||||
fParticleChange->ProposeParentWeight(new_weight);
|
||||
|
||||
// Kinematic:
|
||||
// we consider a two body elastic scattering for the forward processes where
|
||||
// the projectile knocks on an e- at rest and gives it part of its energy
|
||||
G4double projectileM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
G4double projectileTotalEnergy = projectileM0 + projectileKinEnergy;
|
||||
G4double projectileP2 =
|
||||
projectileTotalEnergy * projectileTotalEnergy - projectileM0 * projectileM0;
|
||||
|
||||
// Companion
|
||||
G4double companionM0 = fAdjEquivDirectPrimPart->GetPDGMass();
|
||||
if(isScatProjToProj)
|
||||
{
|
||||
companionM0 = fAdjEquivDirectSecondPart->GetPDGMass();
|
||||
}
|
||||
G4double companionTotalEnergy =
|
||||
companionM0 + projectileKinEnergy - adjointPrimKinEnergy;
|
||||
G4double companionP2 =
|
||||
companionTotalEnergy * companionTotalEnergy - companionM0 * companionM0;
|
||||
|
||||
// Projectile momentum
|
||||
G4double P_parallel =
|
||||
(adjointPrimP * adjointPrimP + projectileP2 - companionP2) /
|
||||
(2. * adjointPrimP);
|
||||
G4double P_perp = std::sqrt(projectileP2 - P_parallel * P_parallel);
|
||||
G4ThreeVector dir_parallel = theAdjointPrimary->GetMomentumDirection();
|
||||
G4double phi = G4UniformRand() * twopi;
|
||||
G4ThreeVector projectileMomentum =
|
||||
G4ThreeVector(P_perp * std::cos(phi), P_perp * std::sin(phi), P_parallel);
|
||||
projectileMomentum.rotateUz(dir_parallel);
|
||||
|
||||
if(!isScatProjToProj)
|
||||
{ // kill the primary and add a secondary
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->AddSecondary(
|
||||
new G4DynamicParticle(fAdjEquivDirectPrimPart, projectileMomentum));
|
||||
}
|
||||
else
|
||||
{
|
||||
fParticleChange->ProposeEnergy(projectileKinEnergy);
|
||||
fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointhIonisationModel::AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
|
||||
G4double primEnergy,
|
||||
G4bool IsScatProjToProjCase)
|
||||
{
|
||||
if (UseMatrix) return G4VEmAdjointModel::AdjointCrossSection(aCouple,primEnergy,IsScatProjToProjCase);
|
||||
DefineCurrentMaterial(aCouple);
|
||||
|
||||
|
||||
G4double Cross=currentMaterial->GetElectronDensity()*twopi_mc2_rcl2*mass;
|
||||
|
||||
if (!IsScatProjToProjCase ){
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProjCase(primEnergy);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProjCase(primEnergy);
|
||||
if (Emax_proj>Emin_proj && primEnergy > currentTcutForDirectSecond) {
|
||||
Cross*=(1./Emin_proj -1./Emax_proj)/primEnergy;
|
||||
}
|
||||
else Cross=0.;
|
||||
|
||||
|
||||
G4double G4AdjointhIonisationModel::DiffCrossSectionPerAtomPrimToSecond(
|
||||
G4double kinEnergyProj, G4double kinEnergyProd, G4double Z, G4double A)
|
||||
{ // Probably here the Bragg Model should be also used for
|
||||
// kinEnergyProj/nuc < 2 MeV
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForScatProjToProjCase(primEnergy);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForScatProjToProjCase(primEnergy,currentTcutForDirectSecond);
|
||||
G4double diff1=Emin_proj-primEnergy;
|
||||
G4double diff2=Emax_proj-primEnergy;
|
||||
G4double t1=(1./diff1+1./Emin_proj-1./diff2-1./Emax_proj)/primEnergy;
|
||||
//G4double t2=2.*std::log(diff2*Emin_proj/Emax_proj/diff1)/primEnergy/primEnergy;
|
||||
G4double t2=2.*std::log(Emax_proj/Emin_proj)/primEnergy/primEnergy;
|
||||
Cross*=(t1+t2);
|
||||
G4double dSigmadEprod = 0.;
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProj(kinEnergyProd);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProj(kinEnergyProd);
|
||||
|
||||
|
||||
// the produced particle should have a kinetic energy smaller than the
|
||||
// projectile
|
||||
if(kinEnergyProj > Emin_proj && kinEnergyProj <= Emax_proj)
|
||||
{
|
||||
G4double Tmax = kinEnergyProj;
|
||||
G4double E1 = kinEnergyProd;
|
||||
G4double E2 = kinEnergyProd * 1.000001;
|
||||
G4double sigma1, sigma2;
|
||||
if(kinEnergyProj > 2. * MeV)
|
||||
{
|
||||
sigma1 = fDirectModel->ComputeCrossSectionPerAtom(
|
||||
fDirectPrimaryPart, kinEnergyProj, Z, A, E1, 1.e20);
|
||||
sigma2 = fDirectModel->ComputeCrossSectionPerAtom(
|
||||
fDirectPrimaryPart, kinEnergyProj, Z, A, E2, 1.e20);
|
||||
}
|
||||
else
|
||||
{
|
||||
sigma1 = fBraggDirectEMModel->ComputeCrossSectionPerAtom(
|
||||
fDirectPrimaryPart, kinEnergyProj, Z, A, E1, 1.e20);
|
||||
sigma2 = fBraggDirectEMModel->ComputeCrossSectionPerAtom(
|
||||
fDirectPrimaryPart, kinEnergyProj, Z, A, E2, 1.e20);
|
||||
}
|
||||
|
||||
dSigmadEprod = (sigma1 - sigma2) / (E2 - E1);
|
||||
if(dSigmadEprod > 1.)
|
||||
{
|
||||
G4cout << "sigma1 " << kinEnergyProj / MeV << '\t' << kinEnergyProd / MeV
|
||||
<< '\t' << sigma1 << G4endl;
|
||||
G4cout << "sigma2 " << kinEnergyProj / MeV << '\t' << kinEnergyProd / MeV
|
||||
<< '\t' << sigma2 << G4endl;
|
||||
G4cout << "dsigma " << kinEnergyProj / MeV << '\t' << kinEnergyProd / MeV
|
||||
<< '\t' << dSigmadEprod << G4endl;
|
||||
}
|
||||
|
||||
// correction of differential cross section at high energy to correct for
|
||||
// the suppression of particle at secondary at high energy used in the Bethe
|
||||
// Bloch Model. This correction consists of multiplying by g the probability
|
||||
// function used to test the rejection of a secondary. Source code taken
|
||||
// from G4BetheBlochModel::SampleSecondaries
|
||||
G4double deltaKinEnergy = kinEnergyProd;
|
||||
|
||||
// projectile formfactor - suppression of high energy
|
||||
// delta-electron production at high energy
|
||||
G4double x = fFormFact * deltaKinEnergy;
|
||||
if(x > 1.e-6)
|
||||
{
|
||||
G4double totEnergy = kinEnergyProj + fMass;
|
||||
G4double etot2 = totEnergy * totEnergy;
|
||||
G4double beta2 = kinEnergyProj * (kinEnergyProj + 2.0 * fMass) / etot2;
|
||||
G4double f = 1.0 - beta2 * deltaKinEnergy / Tmax;
|
||||
G4double f1 = 0.0;
|
||||
if(0.5 == fSpin)
|
||||
{
|
||||
f1 = 0.5 * deltaKinEnergy * deltaKinEnergy / etot2;
|
||||
f += f1;
|
||||
}
|
||||
G4double x1 = 1.0 + x;
|
||||
G4double gg = 1.0 / (x1 * x1);
|
||||
if(0.5 == fSpin)
|
||||
{
|
||||
G4double x2 = 0.5 * electron_mass_c2 * deltaKinEnergy / (fMass * fMass);
|
||||
gg *= (1.0 + fMagMoment2 * (x2 - f1 / f) / (1.0 + x2));
|
||||
}
|
||||
if(gg > 1.0)
|
||||
{
|
||||
G4cout << "### G4BetheBlochModel in Adjoint Sim WARNING: g= " << g
|
||||
<< G4endl;
|
||||
gg = 1.;
|
||||
}
|
||||
dSigmadEprod *= gg;
|
||||
}
|
||||
}
|
||||
lastCS =Cross;
|
||||
return Cross;
|
||||
|
||||
return dSigmadEprod;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4AdjointhIonisationModel::DefineProjectileProperty()
|
||||
{
|
||||
// Slightly modified code taken from G4BetheBlochModel::SetParticle
|
||||
G4String pname = fDirectPrimaryPart->GetParticleName();
|
||||
|
||||
fMass = fDirectPrimaryPart->GetPDGMass();
|
||||
fSpin = fDirectPrimaryPart->GetPDGSpin();
|
||||
fMassRatio = electron_mass_c2 / fMass;
|
||||
fOnePlusRatio2 = (1. + fMassRatio) * (1. + fMassRatio);
|
||||
fOneMinusRatio2 = (1. - fMassRatio) * (1. - fMassRatio);
|
||||
G4double magmom = fDirectPrimaryPart->GetPDGMagneticMoment() * fMass /
|
||||
(0.5 * eplus * hbar_Planck * c_squared);
|
||||
fMagMoment2 = magmom * magmom - 1.0;
|
||||
fFormFact = 0.0;
|
||||
if(fDirectPrimaryPart->GetLeptonNumber() == 0)
|
||||
{
|
||||
G4double x = 0.8426 * GeV;
|
||||
if(fSpin == 0.0 && fMass < GeV)
|
||||
{
|
||||
x = 0.736 * GeV;
|
||||
}
|
||||
else if(fMass > GeV)
|
||||
{
|
||||
x /= G4NistManager::Instance()->GetZ13(fMass / proton_mass_c2);
|
||||
}
|
||||
fFormFact = 2.0 * electron_mass_c2 / (x * x);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4double G4AdjointhIonisationModel::AdjointCrossSection(
|
||||
const G4MaterialCutsCouple* aCouple, G4double primEnergy,
|
||||
G4bool isScatProjToProj)
|
||||
{
|
||||
if(fUseMatrix)
|
||||
return G4VEmAdjointModel::AdjointCrossSection(aCouple, primEnergy,
|
||||
isScatProjToProj);
|
||||
DefineCurrentMaterial(aCouple);
|
||||
|
||||
G4double Cross =
|
||||
fCurrentMaterial->GetElectronDensity() * twopi_mc2_rcl2 * fMass;
|
||||
|
||||
if(!isScatProjToProj)
|
||||
{
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProj(primEnergy);
|
||||
G4double Emin_proj = GetSecondAdjEnergyMinForProdToProj(primEnergy);
|
||||
if(Emax_proj > Emin_proj && primEnergy > fTcutSecond)
|
||||
{
|
||||
Cross *= (1. / Emin_proj - 1. / Emax_proj) / primEnergy;
|
||||
}
|
||||
else
|
||||
Cross = 0.;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double Emax_proj = GetSecondAdjEnergyMaxForScatProjToProj(primEnergy);
|
||||
G4double Emin_proj =
|
||||
GetSecondAdjEnergyMinForScatProjToProj(primEnergy, fTcutSecond);
|
||||
G4double diff1 = Emin_proj - primEnergy;
|
||||
G4double diff2 = Emax_proj - primEnergy;
|
||||
G4double t1 =
|
||||
(1. / diff1 + 1. / Emin_proj - 1. / diff2 - 1. / Emax_proj) / primEnergy;
|
||||
G4double t2 =
|
||||
2. * std::log(Emax_proj / Emin_proj) / primEnergy / primEnergy;
|
||||
Cross *= (t1 + t2);
|
||||
}
|
||||
fLastCS = Cross;
|
||||
return Cross;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointhIonisationModel::GetSecondAdjEnergyMaxForScatProjToProjCase(G4double PrimAdjEnergy)
|
||||
{
|
||||
G4double Tmax=PrimAdjEnergy*one_plus_ratio_2/(one_minus_ratio_2-2.*ratio*PrimAdjEnergy/mass);
|
||||
G4double G4AdjointhIonisationModel::GetSecondAdjEnergyMaxForScatProjToProj(
|
||||
G4double primAdjEnergy)
|
||||
{
|
||||
G4double Tmax = primAdjEnergy * fOnePlusRatio2 /
|
||||
(fOneMinusRatio2 - 2. * fMassRatio * primAdjEnergy / fMass);
|
||||
return Tmax;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointhIonisationModel::GetSecondAdjEnergyMinForScatProjToProjCase(G4double PrimAdjEnergy,G4double Tcut)
|
||||
{ return PrimAdjEnergy+Tcut;
|
||||
G4double G4AdjointhIonisationModel::GetSecondAdjEnergyMinForScatProjToProj(
|
||||
G4double primAdjEnergy, G4double tcut)
|
||||
{
|
||||
return primAdjEnergy + tcut;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointhIonisationModel::GetSecondAdjEnergyMaxForProdToProjCase(G4double )
|
||||
{ return HighEnergyLimit;
|
||||
G4double G4AdjointhIonisationModel::GetSecondAdjEnergyMaxForProdToProj(G4double)
|
||||
{
|
||||
return GetHighEnergyLimit();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4AdjointhIonisationModel::GetSecondAdjEnergyMinForProdToProjCase(G4double PrimAdjEnergy)
|
||||
{ G4double Tmin= (2*PrimAdjEnergy-4*mass + std::sqrt(4.*PrimAdjEnergy*PrimAdjEnergy +16.*mass*mass + 8.*PrimAdjEnergy*mass*(1/ratio +ratio)))/4.;
|
||||
return Tmin;
|
||||
G4double G4AdjointhIonisationModel::GetSecondAdjEnergyMinForProdToProj(
|
||||
G4double primAdjEnergy)
|
||||
{
|
||||
G4double Tmin =
|
||||
(2. * primAdjEnergy - 4. * fMass +
|
||||
std::sqrt(4. * primAdjEnergy * primAdjEnergy + 16. * fMass * fMass +
|
||||
8. * primAdjEnergy * fMass * (1. / fMassRatio + fMassRatio))) /
|
||||
4.;
|
||||
return Tmin;
|
||||
}
|
||||
|
||||
@@ -23,92 +23,61 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// GEANT4 Class file
|
||||
// Geant4 class file
|
||||
//
|
||||
// File name: G4AdjointhMultipleScattering
|
||||
//
|
||||
// Author: Desorgher Laurent
|
||||
//
|
||||
// Creation date: 03.06.2009 cloned from G4hMultipleScattering by U.Laszlo with slight modification for adjoint_ion.
|
||||
// Creation date: 03.06.2009 cloned from G4hMultipleScattering by U.Laszlo with
|
||||
// slight modification for adjoint_ion.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "G4AdjointhMultipleScattering.hh"
|
||||
|
||||
#include "G4MscStepLimitType.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4UrbanMscModel.hh"
|
||||
#include "G4MscStepLimitType.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4AdjointhMultipleScattering::G4AdjointhMultipleScattering(const G4String& processName)
|
||||
G4AdjointhMultipleScattering::G4AdjointhMultipleScattering(
|
||||
const G4String& processName)
|
||||
: G4VMultipleScattering(processName)
|
||||
{
|
||||
isInitialized = false;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4AdjointhMultipleScattering::~G4AdjointhMultipleScattering()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4AdjointhMultipleScattering::~G4AdjointhMultipleScattering() {}
|
||||
|
||||
G4bool G4AdjointhMultipleScattering::IsApplicable (const G4ParticleDefinition& p)
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4AdjointhMultipleScattering::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "Inverse multiple scattering process for hadrons.\n";
|
||||
StreamProcessInfo(out);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4AdjointhMultipleScattering::StreamProcessInfo(std::ostream& out) const
|
||||
{
|
||||
out << " RangeFactor= " << RangeFactor()
|
||||
<< ", step limit type: " << StepLimitType()
|
||||
<< ", lateralDisplacement: " << LateralDisplasmentFlag()
|
||||
<< ", skin= " << Skin() << G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool G4AdjointhMultipleScattering::IsApplicable(const G4ParticleDefinition& p)
|
||||
{
|
||||
return (p.GetPDGCharge() != 0.0 && !p.IsShortLived());
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4AdjointhMultipleScattering::InitialiseProcess(const G4ParticleDefinition*)
|
||||
void G4AdjointhMultipleScattering::InitialiseProcess(
|
||||
const G4ParticleDefinition*)
|
||||
{
|
||||
if(isInitialized) { return; }
|
||||
if(fIsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
AddEmModel(1, new G4UrbanMscModel());
|
||||
isInitialized = true;
|
||||
fIsInitialized = true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4AdjointhMultipleScattering::PrintInfo()
|
||||
{
|
||||
G4cout << " RangeFactor= " << RangeFactor()
|
||||
<< ", step limit type: " << StepLimitType()
|
||||
<< ", lateralDisplacement: " << LateralDisplasmentFlag()
|
||||
<< ", skin= " << Skin()
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
/*G4double G4AdjointhMultipleScattering::AlongStepGetPhysicalInteractionLength(
|
||||
const G4Track& track,
|
||||
double,
|
||||
G4double currentMinimalStep,
|
||||
G4double& currentSafety,
|
||||
G4GPILSelection* selection)
|
||||
{
|
||||
// get Step limit proposed by the process
|
||||
valueGPILSelectionMSC = NotCandidateForSelection;
|
||||
|
||||
G4double escaled = track.GetKineticEnergy();
|
||||
if(isIon) escaled *= track.GetDynamicParticle()->GetMass()/proton_mass_c2;
|
||||
|
||||
G4double steplength = GetMscContinuousStepLimit(track,
|
||||
escaled,
|
||||
currentMinimalStep,
|
||||
currentSafety);
|
||||
// G4cout << "StepLimit= " << steplength << G4endl;
|
||||
// set return value for G4GPILSelection
|
||||
*selection = valueGPILSelectionMSC;
|
||||
return steplength;
|
||||
}
|
||||
*/
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
@@ -27,299 +27,232 @@
|
||||
|
||||
#include "G4ContinuousGainOfEnergy.hh"
|
||||
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4VEmModel.hh"
|
||||
#include "G4VEmFluctuationModel.hh"
|
||||
#include "G4VParticleChange.hh"
|
||||
#include "G4AdjointCSManager.hh"
|
||||
#include "G4EmCorrections.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4VEmFluctuationModel.hh"
|
||||
#include "G4VEmModel.hh"
|
||||
#include "G4VEnergyLossProcess.hh"
|
||||
#include "G4VParticleChange.hh"
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4ContinuousGainOfEnergy::G4ContinuousGainOfEnergy(const G4String& name,
|
||||
G4ProcessType type): G4VContinuousProcess(name, type)
|
||||
G4ContinuousGainOfEnergy::G4ContinuousGainOfEnergy(const G4String& name,
|
||||
G4ProcessType type)
|
||||
: G4VContinuousProcess(name, type)
|
||||
{}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
G4ContinuousGainOfEnergy::~G4ContinuousGainOfEnergy() {}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
void G4ContinuousGainOfEnergy::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
|
||||
|
||||
linLossLimit=0.05;
|
||||
lossFluctuationArePossible =true;
|
||||
lossFluctuationFlag=true;
|
||||
is_integral = false;
|
||||
|
||||
//Will be properly set in SetDirectParticle()
|
||||
IsIon=false;
|
||||
massRatio =1.;
|
||||
chargeSqRatio=1.;
|
||||
preStepChargeSqRatio=1.;
|
||||
|
||||
//Some initialization
|
||||
currentCoupleIndex=9999999;
|
||||
currentCutInRange=0.;
|
||||
currentMaterialIndex=9999999;
|
||||
currentTcut=0.;
|
||||
preStepKinEnergy=0.;
|
||||
preStepRange=0.;
|
||||
preStepScaledKinEnergy=0.;
|
||||
|
||||
currentCouple=0;
|
||||
out << "Continuous process acting on adjoint particles to compute the "
|
||||
"continuous gain of energy of charged particles when they are "
|
||||
"tracked back.\n";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
G4ContinuousGainOfEnergy::~G4ContinuousGainOfEnergy()
|
||||
void G4ContinuousGainOfEnergy::SetDirectParticle(G4ParticleDefinition* p)
|
||||
{
|
||||
|
||||
}
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void G4ContinuousGainOfEnergy::PreparePhysicsTable(
|
||||
const G4ParticleDefinition& )
|
||||
{//theDirectEnergyLossProcess->PreparePhysicsTable(part);
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void G4ContinuousGainOfEnergy::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
{//theDirectEnergyLossProcess->BuildPhysicsTable(part);
|
||||
;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
void G4ContinuousGainOfEnergy::SetDirectParticle(G4ParticleDefinition* p)
|
||||
{theDirectPartDef=p;
|
||||
if (theDirectPartDef->GetParticleType()== "nucleus") {
|
||||
IsIon=true;
|
||||
massRatio = proton_mass_c2/theDirectPartDef->GetPDGMass();
|
||||
G4double q=theDirectPartDef->GetPDGCharge();
|
||||
chargeSqRatio=q*q;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
G4VParticleChange* G4ContinuousGainOfEnergy::AlongStepDoIt(const G4Track& track,
|
||||
const G4Step& step)
|
||||
{
|
||||
|
||||
//Caution in this method the step length should be the true step length
|
||||
// A problem is that this is compute by the multiple scattering that does not know the energy at the end of the adjoint step. This energy is used during the
|
||||
//Forward sim. Nothing we can really do against that at this time. This is inherent to the MS method
|
||||
//
|
||||
|
||||
|
||||
|
||||
aParticleChange.Initialize(track);
|
||||
|
||||
// Get the actual (true) Step length
|
||||
//----------------------------------
|
||||
G4double length = step.GetStepLength();
|
||||
G4double degain = 0.0;
|
||||
|
||||
|
||||
|
||||
// Compute this for weight change after continuous energy loss
|
||||
//-------------------------------------------------------------
|
||||
G4double DEDX_before = theDirectEnergyLossProcess->GetDEDX(preStepKinEnergy, currentCouple);
|
||||
|
||||
|
||||
|
||||
// For the fluctuation we generate a new dynamic particle with energy =preEnergy+egain
|
||||
// and then compute the fluctuation given in the direct case.
|
||||
//-----------------------------------------------------------------------
|
||||
G4DynamicParticle* dynParticle = new G4DynamicParticle();
|
||||
*dynParticle = *(track.GetDynamicParticle());
|
||||
dynParticle->SetDefinition(theDirectPartDef);
|
||||
G4double Tkin = dynParticle->GetKineticEnergy();
|
||||
|
||||
|
||||
size_t n=1;
|
||||
if (is_integral ) n=10;
|
||||
n=1;
|
||||
G4double dlength= length/n;
|
||||
for (size_t i=0;i<n;i++) {
|
||||
if (Tkin != preStepKinEnergy && IsIon) {
|
||||
chargeSqRatio = currentModel->GetChargeSquareRatio(theDirectPartDef,currentMaterial,Tkin);
|
||||
theDirectEnergyLossProcess->SetDynamicMassCharge(massRatio,chargeSqRatio);
|
||||
|
||||
}
|
||||
|
||||
G4double r = theDirectEnergyLossProcess->GetRange(Tkin, currentCouple);
|
||||
if( dlength <= linLossLimit * r ) {
|
||||
degain = DEDX_before*dlength;
|
||||
}
|
||||
else {
|
||||
G4double x = r + dlength;
|
||||
//degain = theDirectEnergyLossProcess->GetKineticEnergy(x,currentCouple) - theDirectEnergyLossProcess->GetKineticEnergy(r,currentCouple);
|
||||
G4double E = theDirectEnergyLossProcess->GetKineticEnergy(x,currentCouple);
|
||||
if (IsIon){
|
||||
chargeSqRatio = currentModel->GetChargeSquareRatio(theDirectPartDef,currentMaterial,E);
|
||||
theDirectEnergyLossProcess->SetDynamicMassCharge(massRatio,chargeSqRatio);
|
||||
G4double x1= theDirectEnergyLossProcess->GetRange(E, currentCouple);
|
||||
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
G4int ii=0;
|
||||
const G4int iimax = 100;
|
||||
while (std::abs(x-x1)>0.01*x) {
|
||||
E = theDirectEnergyLossProcess->GetKineticEnergy(x,currentCouple);
|
||||
chargeSqRatio = currentModel->GetChargeSquareRatio(theDirectPartDef,currentMaterial,E);
|
||||
theDirectEnergyLossProcess->SetDynamicMassCharge(massRatio,chargeSqRatio);
|
||||
x1= theDirectEnergyLossProcess->GetRange(E, currentCouple);
|
||||
++ii;
|
||||
if(ii >= iimax) { break; }
|
||||
}
|
||||
}
|
||||
|
||||
degain=E-Tkin;
|
||||
|
||||
|
||||
|
||||
}
|
||||
//G4cout<<degain<<G4endl;
|
||||
G4double tmax = currentModel->MaxSecondaryKinEnergy(dynParticle);
|
||||
tmax = std::min(tmax,currentTcut);
|
||||
|
||||
|
||||
dynParticle->SetKineticEnergy(Tkin+degain);
|
||||
|
||||
// Corrections, which cannot be tabulated for ions
|
||||
//----------------------------------------
|
||||
G4double esecdep=0;//not used in most models
|
||||
currentModel->CorrectionsAlongStep(currentCouple, dynParticle, degain,esecdep, dlength);
|
||||
|
||||
// Sample fluctuations
|
||||
//-------------------
|
||||
|
||||
|
||||
G4double deltaE =0.;
|
||||
if (lossFluctuationFlag ) {
|
||||
deltaE = currentModel->GetModelOfFluctuations()->
|
||||
SampleFluctuations(currentCouple,dynParticle,tmax,dlength,degain)-degain;
|
||||
}
|
||||
|
||||
G4double egain=degain+deltaE;
|
||||
if (egain <=0) egain=degain;
|
||||
Tkin+=egain;
|
||||
dynParticle->SetKineticEnergy(Tkin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
delete dynParticle;
|
||||
|
||||
if (IsIon){
|
||||
chargeSqRatio = currentModel->GetChargeSquareRatio(theDirectPartDef,currentMaterial,Tkin);
|
||||
theDirectEnergyLossProcess->SetDynamicMassCharge(massRatio,chargeSqRatio);
|
||||
|
||||
fDirectPartDef = p;
|
||||
if(fDirectPartDef->GetParticleType() == "nucleus")
|
||||
{
|
||||
fIsIon = true;
|
||||
fMassRatio = proton_mass_c2 / fDirectPartDef->GetPDGMass();
|
||||
}
|
||||
|
||||
G4double DEDX_after = theDirectEnergyLossProcess->GetDEDX(Tkin, currentCouple);
|
||||
|
||||
|
||||
G4double weight_correction=DEDX_after/DEDX_before;
|
||||
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
G4VParticleChange* G4ContinuousGainOfEnergy::AlongStepDoIt(const G4Track& track,
|
||||
const G4Step& step)
|
||||
{
|
||||
// Caution in this method the step length should be the true step length
|
||||
// A problem is that this is computed by the multiple scattering that does
|
||||
// not know the energy at the end of the adjoint step. This energy is used
|
||||
// during the forward sim. Nothing we can really do against that at this
|
||||
// time. This is inherent to the MS method
|
||||
|
||||
aParticleChange.Initialize(track);
|
||||
|
||||
// Get the actual (true) Step length
|
||||
G4double length = step.GetStepLength();
|
||||
G4double degain = 0.0;
|
||||
|
||||
// Compute this for weight change after continuous energy loss
|
||||
G4double DEDX_before =
|
||||
fDirectEnergyLossProcess->GetDEDX(fPreStepKinEnergy, fCurrentCouple);
|
||||
|
||||
// For the fluctuation we generate a new dynamic particle with energy
|
||||
// = preEnergy+egain and then compute the fluctuation given in the direct
|
||||
// case.
|
||||
G4DynamicParticle* dynParticle = new G4DynamicParticle();
|
||||
*dynParticle = *(track.GetDynamicParticle());
|
||||
dynParticle->SetDefinition(fDirectPartDef);
|
||||
G4double Tkin = dynParticle->GetKineticEnergy();
|
||||
|
||||
G4double dlength = length;
|
||||
if(Tkin != fPreStepKinEnergy && fIsIon)
|
||||
{
|
||||
G4double chargeSqRatio = fCurrentModel->GetChargeSquareRatio(
|
||||
fDirectPartDef, fCurrentMaterial, Tkin);
|
||||
fDirectEnergyLossProcess->SetDynamicMassCharge(fMassRatio, chargeSqRatio);
|
||||
}
|
||||
|
||||
G4double r = fDirectEnergyLossProcess->GetRange(Tkin, fCurrentCouple);
|
||||
if(dlength <= fLinLossLimit * r)
|
||||
{
|
||||
degain = DEDX_before * dlength;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double x = r + dlength;
|
||||
G4double E = fDirectEnergyLossProcess->GetKineticEnergy(x, fCurrentCouple);
|
||||
if(fIsIon)
|
||||
{
|
||||
G4double chargeSqRatio = fCurrentModel->GetChargeSquareRatio(
|
||||
fDirectPartDef, fCurrentMaterial, E);
|
||||
fDirectEnergyLossProcess->SetDynamicMassCharge(fMassRatio, chargeSqRatio);
|
||||
G4double x1 = fDirectEnergyLossProcess->GetRange(E, fCurrentCouple);
|
||||
|
||||
G4int ii = 0;
|
||||
constexpr G4int iimax = 100;
|
||||
while(std::abs(x - x1) > 0.01 * x)
|
||||
{
|
||||
E = fDirectEnergyLossProcess->GetKineticEnergy(x, fCurrentCouple);
|
||||
chargeSqRatio = fCurrentModel->GetChargeSquareRatio(
|
||||
fDirectPartDef, fCurrentMaterial, E);
|
||||
fDirectEnergyLossProcess->SetDynamicMassCharge(fMassRatio,
|
||||
chargeSqRatio);
|
||||
x1 = fDirectEnergyLossProcess->GetRange(E, fCurrentCouple);
|
||||
++ii;
|
||||
if(ii >= iimax)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
degain = E - Tkin;
|
||||
}
|
||||
G4double tmax = fCurrentModel->MaxSecondaryKinEnergy(dynParticle);
|
||||
tmax = std::min(tmax, fCurrentTcut);
|
||||
|
||||
dynParticle->SetKineticEnergy(Tkin + degain);
|
||||
|
||||
// Corrections, which cannot be tabulated for ions
|
||||
fCurrentModel->CorrectionsAlongStep(fCurrentCouple, dynParticle, dlength, degain);
|
||||
|
||||
// Sample fluctuations
|
||||
G4double deltaE = 0.;
|
||||
if(fLossFluctuationFlag)
|
||||
{
|
||||
deltaE = fCurrentModel->GetModelOfFluctuations()->SampleFluctuations(
|
||||
fCurrentCouple, dynParticle, tmax, dlength, degain) -
|
||||
degain;
|
||||
}
|
||||
|
||||
G4double egain = degain + deltaE;
|
||||
if(egain <= 0.)
|
||||
egain = degain;
|
||||
Tkin += egain;
|
||||
dynParticle->SetKineticEnergy(Tkin);
|
||||
|
||||
delete dynParticle;
|
||||
|
||||
if(fIsIon)
|
||||
{
|
||||
G4double chargeSqRatio = fCurrentModel->GetChargeSquareRatio(
|
||||
fDirectPartDef, fCurrentMaterial, Tkin);
|
||||
fDirectEnergyLossProcess->SetDynamicMassCharge(fMassRatio, chargeSqRatio);
|
||||
}
|
||||
|
||||
G4double DEDX_after = fDirectEnergyLossProcess->GetDEDX(Tkin, fCurrentCouple);
|
||||
G4double weight_correction = DEDX_after / DEDX_before;
|
||||
|
||||
aParticleChange.ProposeEnergy(Tkin);
|
||||
|
||||
// Caution!!! It is important to select the weight of the post_step_point
|
||||
// as the current weight and not the weight of the track, as the weight of
|
||||
// the track is changed after having applied all the along_step_do_it.
|
||||
|
||||
//Caution!!!
|
||||
// It is important to select the weight of the post_step_point
|
||||
// as the current weight and not the weight of the track, as t
|
||||
// the weight of the track is changed after having applied all
|
||||
// the along_step_do_it.
|
||||
|
||||
// G4double new_weight=weight_correction*track.GetWeight(); //old
|
||||
G4double new_weight=weight_correction*step.GetPostStepPoint()->GetWeight();
|
||||
G4double new_weight =
|
||||
weight_correction * step.GetPostStepPoint()->GetWeight();
|
||||
aParticleChange.SetParentWeightByProcess(false);
|
||||
aParticleChange.ProposeParentWeight(new_weight);
|
||||
|
||||
|
||||
return &aParticleChange;
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
void G4ContinuousGainOfEnergy::SetLossFluctuations(G4bool val)
|
||||
{
|
||||
if(val && !lossFluctuationArePossible) return;
|
||||
lossFluctuationFlag = val;
|
||||
if(val && !fLossFluctuationArePossible)
|
||||
return;
|
||||
fLossFluctuationFlag = val;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
|
||||
|
||||
G4double G4ContinuousGainOfEnergy::GetContinuousStepLimit(const G4Track& track,
|
||||
G4double , G4double , G4double& )
|
||||
{
|
||||
G4double x = DBL_MAX;
|
||||
x=.1*mm;
|
||||
|
||||
|
||||
G4double, G4double,
|
||||
G4double&)
|
||||
{
|
||||
DefineMaterial(track.GetMaterialCutsCouple());
|
||||
|
||||
preStepKinEnergy = track.GetKineticEnergy();
|
||||
preStepScaledKinEnergy = track.GetKineticEnergy()*massRatio;
|
||||
currentModel = theDirectEnergyLossProcess->SelectModelForMaterial(preStepScaledKinEnergy,currentCoupleIndex);
|
||||
G4double emax_model=currentModel->HighEnergyLimit();
|
||||
if (IsIon) {
|
||||
chargeSqRatio = currentModel->GetChargeSquareRatio(theDirectPartDef,currentMaterial,preStepKinEnergy);
|
||||
preStepChargeSqRatio = chargeSqRatio;
|
||||
theDirectEnergyLossProcess->SetDynamicMassCharge(massRatio,preStepChargeSqRatio);
|
||||
}
|
||||
|
||||
|
||||
G4double maxE =1.1*preStepKinEnergy;
|
||||
/*if (preStepKinEnergy< 0.05*MeV) maxE =2.*preStepKinEnergy;
|
||||
else if (preStepKinEnergy< 0.1*MeV) maxE =1.5*preStepKinEnergy;
|
||||
else if (preStepKinEnergy< 0.5*MeV) maxE =1.25*preStepKinEnergy;*/
|
||||
|
||||
if (preStepKinEnergy < currentTcut) maxE = std::min(currentTcut,maxE);
|
||||
|
||||
maxE=std::min(emax_model*1.001,maxE);
|
||||
|
||||
preStepRange = theDirectEnergyLossProcess->GetRange(preStepKinEnergy, currentCouple);
|
||||
|
||||
if (IsIon) {
|
||||
G4double chargeSqRatioAtEmax = currentModel->GetChargeSquareRatio(theDirectPartDef,currentMaterial,maxE);
|
||||
theDirectEnergyLossProcess->SetDynamicMassCharge(massRatio,chargeSqRatioAtEmax);
|
||||
}
|
||||
|
||||
G4double r1 = theDirectEnergyLossProcess->GetRange(maxE, currentCouple);
|
||||
|
||||
if (IsIon) theDirectEnergyLossProcess->SetDynamicMassCharge(massRatio,preStepChargeSqRatio);
|
||||
|
||||
|
||||
|
||||
x=r1-preStepRange;
|
||||
x=std::max(r1-preStepRange,0.001*mm);
|
||||
|
||||
return x;
|
||||
|
||||
|
||||
fPreStepKinEnergy = track.GetKineticEnergy();
|
||||
fCurrentModel = fDirectEnergyLossProcess->SelectModelForMaterial(
|
||||
track.GetKineticEnergy() * fMassRatio, fCurrentCoupleIndex);
|
||||
G4double emax_model = fCurrentModel->HighEnergyLimit();
|
||||
G4double preStepChargeSqRatio = 0.;
|
||||
if(fIsIon)
|
||||
{
|
||||
G4double chargeSqRatio = fCurrentModel->GetChargeSquareRatio(
|
||||
fDirectPartDef, fCurrentMaterial, fPreStepKinEnergy);
|
||||
preStepChargeSqRatio = chargeSqRatio;
|
||||
fDirectEnergyLossProcess->SetDynamicMassCharge(fMassRatio,
|
||||
preStepChargeSqRatio);
|
||||
}
|
||||
|
||||
G4double maxE = 1.1 * fPreStepKinEnergy;
|
||||
|
||||
if(fPreStepKinEnergy < fCurrentTcut)
|
||||
maxE = std::min(fCurrentTcut, maxE);
|
||||
|
||||
maxE = std::min(emax_model * 1.001, maxE);
|
||||
|
||||
G4double preStepRange =
|
||||
fDirectEnergyLossProcess->GetRange(fPreStepKinEnergy, fCurrentCouple);
|
||||
|
||||
if(fIsIon)
|
||||
{
|
||||
G4double chargeSqRatioAtEmax = fCurrentModel->GetChargeSquareRatio(
|
||||
fDirectPartDef, fCurrentMaterial, maxE);
|
||||
fDirectEnergyLossProcess->SetDynamicMassCharge(fMassRatio,
|
||||
chargeSqRatioAtEmax);
|
||||
}
|
||||
|
||||
G4double r1 = fDirectEnergyLossProcess->GetRange(maxE, fCurrentCouple);
|
||||
|
||||
if(fIsIon)
|
||||
fDirectEnergyLossProcess->SetDynamicMassCharge(fMassRatio,
|
||||
preStepChargeSqRatio);
|
||||
|
||||
return std::max(r1 - preStepRange, 0.001 * mm);
|
||||
}
|
||||
#include "G4EmCorrections.hh"
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void G4ContinuousGainOfEnergy::SetDynamicMassCharge(const G4Track& ,G4double energy)
|
||||
{
|
||||
|
||||
G4double ChargeSqRatio= G4LossTableManager::Instance()->EmCorrections()->EffectiveChargeSquareRatio(theDirectPartDef,currentMaterial,energy);
|
||||
if (theDirectEnergyLossProcess) theDirectEnergyLossProcess->SetDynamicMassCharge(massRatio,ChargeSqRatio);
|
||||
void G4ContinuousGainOfEnergy::SetDynamicMassCharge(const G4Track&,
|
||||
G4double energy)
|
||||
{
|
||||
G4double ChargeSqRatio =
|
||||
G4LossTableManager::Instance()->EmCorrections()->EffectiveChargeSquareRatio(
|
||||
fDirectPartDef, fCurrentMaterial, energy);
|
||||
if(fDirectEnergyLossProcess)
|
||||
fDirectEnergyLossProcess->SetDynamicMassCharge(fMassRatio, ChargeSqRatio);
|
||||
}
|
||||
|
||||
@@ -23,22 +23,26 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
#include "G4InversePEEffect.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
#include "G4AdjointPhotoElectricModel.hh"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4InversePEEffect::G4InversePEEffect(G4String process_name,G4AdjointPhotoElectricModel* aModel):
|
||||
G4VAdjointReverseReaction(process_name,false)
|
||||
{theAdjointEMModel = aModel;
|
||||
theAdjointEMModel->SetSecondPartOfSameType(false);
|
||||
SetIntegralMode(false);
|
||||
|
||||
|
||||
#include "G4InversePEEffect.hh"
|
||||
|
||||
#include "G4AdjointPhotoElectricModel.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4InversePEEffect::G4InversePEEffect(G4String process_name,
|
||||
G4AdjointPhotoElectricModel* aModel)
|
||||
: G4VAdjointReverseReaction(process_name, false)
|
||||
{
|
||||
fAdjointModel = aModel;
|
||||
fAdjointModel->SetSecondPartOfSameType(false);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4InversePEEffect::~G4InversePEEffect(){
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4InversePEEffect::~G4InversePEEffect() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4InversePEEffect::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "Inverse photoelectric effect process.\n";
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
// File name: G4IonInverseIonisation
|
||||
//
|
||||
@@ -32,18 +31,26 @@
|
||||
// Creation date: 25.08.2009
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
#include "G4IonInverseIonisation.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4IonInverseIonisation::G4IonInverseIonisation(G4bool whichScatCase,G4String process_name,G4AdjointIonIonisationModel* aEmAdjointModel):
|
||||
G4VAdjointReverseReaction(process_name,whichScatCase)
|
||||
{theAdjointEMModel = aEmAdjointModel;
|
||||
theAdjointEMModel->SetSecondPartOfSameType(false);
|
||||
SetIntegralMode(true);
|
||||
#include "G4IonInverseIonisation.hh"
|
||||
|
||||
#include "G4AdjointIonIonisationModel.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4IonInverseIonisation::G4IonInverseIonisation(
|
||||
G4bool whichScatCase, G4String process_name,
|
||||
G4AdjointIonIonisationModel* aEmAdjointModel)
|
||||
: G4VAdjointReverseReaction(process_name, whichScatCase)
|
||||
{
|
||||
fAdjointModel = aEmAdjointModel;
|
||||
fAdjointModel->SetSecondPartOfSameType(false);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4IonInverseIonisation::~G4IonInverseIonisation(){
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4IonInverseIonisation::~G4IonInverseIonisation() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4IonInverseIonisation::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "Inversion ionisation process for ions.\n";
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,145 +23,78 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4VAdjointReverseReaction.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4AdjointCSManager.hh"
|
||||
#include "G4AdjointCSMatrix.hh"
|
||||
#include "G4AdjointInterpolator.hh"
|
||||
#include "G4AdjointCSMatrix.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
#include "G4ElementTable.hh"
|
||||
#include "G4Element.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
|
||||
#include "G4AdjointCSManager.hh"
|
||||
#include "G4ParticleChange.hh"
|
||||
#include "G4AdjointElectron.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
|
||||
G4VAdjointReverseReaction::G4VAdjointReverseReaction(G4String process_name,
|
||||
G4bool whichScatCase)
|
||||
: G4VDiscreteProcess(process_name)
|
||||
{
|
||||
fCSManager = G4AdjointCSManager::GetAdjointCSManager();
|
||||
fIsScatProjToProj = whichScatCase;
|
||||
fParticleChange = new G4ParticleChange();
|
||||
}
|
||||
|
||||
G4VAdjointReverseReaction::
|
||||
G4VAdjointReverseReaction(G4String process_name, G4bool whichScatCase):
|
||||
G4VDiscreteProcess(process_name)
|
||||
{theAdjointCSManager = G4AdjointCSManager::GetAdjointCSManager();
|
||||
IsScatProjToProjCase=whichScatCase;
|
||||
fParticleChange=new G4ParticleChange();
|
||||
IsFwdCSUsed=false;
|
||||
IsIntegralModeUsed=false;
|
||||
lastCS=0.;
|
||||
trackid = nstep = 0;
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
G4VAdjointReverseReaction::~G4VAdjointReverseReaction()
|
||||
{
|
||||
if(fParticleChange)
|
||||
delete fParticleChange;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4VAdjointReverseReaction::
|
||||
~G4VAdjointReverseReaction()
|
||||
{ if (fParticleChange) delete fParticleChange;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4VAdjointReverseReaction::PreparePhysicsTable(const G4ParticleDefinition&)
|
||||
{;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void G4VAdjointReverseReaction::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
{
|
||||
|
||||
theAdjointCSManager->BuildCrossSectionMatrices(); //do not worry it will be done just once
|
||||
theAdjointCSManager->BuildTotalSigmaTables();
|
||||
|
||||
fCSManager->BuildCrossSectionMatrices(); // it will be done just once
|
||||
fCSManager->BuildTotalSigmaTables();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4VParticleChange* G4VAdjointReverseReaction::PostStepDoIt(const G4Track& track, const G4Step& )
|
||||
{
|
||||
|
||||
G4VParticleChange* G4VAdjointReverseReaction::PostStepDoIt(const G4Track& track,
|
||||
const G4Step&)
|
||||
{
|
||||
fParticleChange->Initialize(track);
|
||||
|
||||
/* if (IsFwdCSUsed && IsIntegralModeUsed){ //INtegral mode still unstable
|
||||
G4double Tkin = step.GetPostStepPoint()->GetKineticEnergy();
|
||||
G4double fwdCS = theAdjointCSManager->GetTotalForwardCS(track.GetDefinition(), Tkin, track.GetMaterialCutsCouple());
|
||||
//G4cout<<"lastCS "<<lastCS<<G4endl;
|
||||
if (fwdCS<lastCS*G4UniformRand()) { // the reaction does not take place, same integral method as the one used for forward ionisation in G4
|
||||
ClearNumberOfInteractionLengthLeft();
|
||||
return fParticleChange;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
theAdjointEMModel->SampleSecondaries(track,
|
||||
IsScatProjToProjCase,
|
||||
fParticleChange);
|
||||
|
||||
fAdjointModel->SampleSecondaries(track, fIsScatProjToProj, fParticleChange);
|
||||
|
||||
ClearNumberOfInteractionLengthLeft();
|
||||
return fParticleChange;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4double G4VAdjointReverseReaction::GetMeanFreePath(const G4Track& track,
|
||||
G4double ,
|
||||
G4ForceCondition* condition)
|
||||
{ *condition = NotForced;
|
||||
G4double,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
*condition = NotForced;
|
||||
G4double preStepKinEnergy = track.GetKineticEnergy();
|
||||
|
||||
if(track.GetTrackID() != trackid) {
|
||||
trackid = track.GetTrackID();
|
||||
nstep = 0;
|
||||
if(track.GetTrackID() != fTrackId)
|
||||
{
|
||||
fTrackId = track.GetTrackID();
|
||||
}
|
||||
++nstep;
|
||||
G4double sigma = fAdjointModel->AdjointCrossSection(
|
||||
track.GetMaterialCutsCouple(), preStepKinEnergy, fIsScatProjToProj);
|
||||
|
||||
G4double corr = fCSManager->GetCrossSectionCorrection(
|
||||
track.GetDefinition(), preStepKinEnergy, track.GetMaterialCutsCouple(),
|
||||
fIsFwdCSUsed);
|
||||
|
||||
|
||||
/*G4double Sigma =
|
||||
theAdjointEMModel->AdjointCrossSection(track.GetMaterialCutsCouple(),preStepKinEnergy,IsScatProjToProjCase);*/
|
||||
|
||||
G4double Sigma =
|
||||
theAdjointEMModel->GetAdjointCrossSection(track.GetMaterialCutsCouple(),preStepKinEnergy,IsScatProjToProjCase);
|
||||
|
||||
//G4double sig = Sigma;
|
||||
|
||||
G4double fwd_TotCS;
|
||||
G4double corr = theAdjointCSManager->GetCrossSectionCorrection(track.GetDefinition(),preStepKinEnergy,track.GetMaterialCutsCouple(),IsFwdCSUsed, fwd_TotCS);
|
||||
|
||||
if(std::fabs(corr) > 100.) { Sigma = 0.0; }
|
||||
else { Sigma *= corr; }
|
||||
|
||||
//G4cout<<fwd_TotCS<<G4endl;
|
||||
/*if (IsFwdCSUsed && IsIntegralModeUsed){ //take the maximum cross section only for charged particle
|
||||
G4double e_sigma_max, sigma_max;
|
||||
theAdjointCSManager->GetMaxFwdTotalCS(track.GetDefinition(),
|
||||
track.GetMaterialCutsCouple(), e_sigma_max, sigma_max);
|
||||
if (e_sigma_max > preStepKinEnergy){
|
||||
Sigma*=sigma_max/fwd_TotCS;
|
||||
}
|
||||
if(std::fabs(corr) > 100.)
|
||||
{
|
||||
sigma = 0.0;
|
||||
}
|
||||
*/
|
||||
|
||||
G4double mean_free_path = 1.e60 *mm;
|
||||
if (Sigma>0) mean_free_path = 1./Sigma;
|
||||
lastCS=Sigma;
|
||||
/*
|
||||
if(nstep > 100) {
|
||||
|
||||
G4cout << "#* " << track.GetDefinition()->GetParticleName()
|
||||
<< " " << GetProcessName()
|
||||
<< " Nstep " << nstep
|
||||
<< " E(MeV)= " << preStepKinEnergy << " Sig0= " << sig
|
||||
<< " sig1= " << Sigma << " mfp= " << mean_free_path << G4endl;
|
||||
|
||||
}
|
||||
if (nstep > 20000) {
|
||||
exit(1);
|
||||
else
|
||||
{
|
||||
sigma *= corr;
|
||||
}
|
||||
*/
|
||||
/*G4cout<<"Sigma "<<Sigma<<G4endl;
|
||||
G4cout<<"mean_free_path [mm] "<<mean_free_path/mm<<G4endl;
|
||||
*/
|
||||
|
||||
|
||||
G4double mean_free_path = 1.e60;
|
||||
if(sigma > 0.)
|
||||
mean_free_path = 1. / sigma;
|
||||
|
||||
return mean_free_path;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,81 +23,81 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
// File name: G4eAdjointMultipleScattering
|
||||
//
|
||||
// Author: Vladimir Ivanchenko
|
||||
//
|
||||
// Creation date: 10 March 2008
|
||||
//
|
||||
// Modifications:
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "G4eAdjointMultipleScattering.hh"
|
||||
#include "G4UrbanAdjointMscModel.hh"
|
||||
#include "G4MscStepLimitType.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Positron.hh"
|
||||
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4MscStepLimitType.hh"
|
||||
#include "G4UrbanAdjointMscModel.hh"
|
||||
#include "G4VMultipleScattering.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4eAdjointMultipleScattering::G4eAdjointMultipleScattering(const G4String& processName)
|
||||
G4eAdjointMultipleScattering::G4eAdjointMultipleScattering(
|
||||
const G4String& processName)
|
||||
: G4VMultipleScattering(processName)
|
||||
{
|
||||
isInitialized = false;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4eAdjointMultipleScattering::~G4eAdjointMultipleScattering()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4eAdjointMultipleScattering::~G4eAdjointMultipleScattering() {}
|
||||
|
||||
G4bool G4eAdjointMultipleScattering::IsApplicable (const G4ParticleDefinition& p)
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4eAdjointMultipleScattering::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "Inverse multiple scattering for e-.\n";
|
||||
StreamProcessInfo(out);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool G4eAdjointMultipleScattering::IsApplicable(const G4ParticleDefinition& p)
|
||||
{
|
||||
return (p.GetPDGCharge() != 0.0 && !p.IsShortLived());
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4eAdjointMultipleScattering::InitialiseProcess(const G4ParticleDefinition*)
|
||||
void G4eAdjointMultipleScattering::InitialiseProcess(
|
||||
const G4ParticleDefinition*)
|
||||
{
|
||||
if(isInitialized) { return; }
|
||||
if(!EmModel(0)) { SetEmModel(new G4UrbanAdjointMscModel(), 0); }
|
||||
if(fIsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(EmModel(0) == nullptr)
|
||||
{
|
||||
SetEmModel(new G4UrbanAdjointMscModel());
|
||||
}
|
||||
AddEmModel(1, EmModel(0));
|
||||
isInitialized = true;
|
||||
fIsInitialized = true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4eAdjointMultipleScattering::PrintInfo()
|
||||
void G4eAdjointMultipleScattering::StreamProcessInfo(std::ostream& out) const
|
||||
{
|
||||
G4cout << " RangeFactor= " << RangeFactor()
|
||||
<< ", stepLimitType: " << StepLimitType()
|
||||
<< ", latDisplacement: " << LateralDisplasmentFlag();
|
||||
if(StepLimitType() == fUseDistanceToBoundary) {
|
||||
G4cout << ", skin= " << Skin() << ", geomFactor= " << GeomFactor();
|
||||
}
|
||||
G4cout << G4endl;
|
||||
out << " RangeFactor= " << RangeFactor()
|
||||
<< ", stepLimType: " << StepLimitType()
|
||||
<< ", latDisp: " << LateralDisplasmentFlag();
|
||||
if(StepLimitType() == fUseDistanceToBoundary)
|
||||
{
|
||||
out << ", skin= " << Skin() << ", geomFactor= " << GeomFactor();
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4eAdjointMultipleScattering::StartTracking(G4Track* )
|
||||
{ G4DynamicParticle* aDynPart = new G4DynamicParticle(G4Electron::Electron(), G4ThreeVector(0.,0.,1.),1.);
|
||||
G4Track* tempTrack = new G4Track(aDynPart,0.,G4ThreeVector(0.,0.,0.));
|
||||
G4VMultipleScattering::StartTracking( tempTrack);
|
||||
delete tempTrack;
|
||||
void G4eAdjointMultipleScattering::StartTracking(G4Track*)
|
||||
{
|
||||
G4DynamicParticle* aDynPart = new G4DynamicParticle(
|
||||
G4Electron::Electron(), G4ThreeVector(0., 0., 1.), 1.);
|
||||
G4Track* tempTrack = new G4Track(aDynPart, 0., G4ThreeVector(0., 0., 0.));
|
||||
G4VMultipleScattering::StartTracking(tempTrack);
|
||||
delete tempTrack;
|
||||
}
|
||||
|
||||
@@ -22,23 +22,26 @@
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
#include "G4eInverseBremsstrahlung.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
#include "G4AdjointBremsstrahlungModel.hh"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4eInverseBremsstrahlung::G4eInverseBremsstrahlung(G4bool whichScatCase,G4String process_name,
|
||||
G4VEmAdjointModel* aBremAdjointModel):
|
||||
G4VAdjointReverseReaction(process_name,whichScatCase)
|
||||
{theAdjointEMModel = aBremAdjointModel;
|
||||
theAdjointEMModel->SetSecondPartOfSameType(false);
|
||||
if (IsScatProjToProjCase) SetIntegralMode(true);
|
||||
else SetIntegralMode(false);
|
||||
#include "G4eInverseBremsstrahlung.hh"
|
||||
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4eInverseBremsstrahlung::G4eInverseBremsstrahlung(
|
||||
G4bool whichScatCase, G4String process_name,
|
||||
G4VEmAdjointModel* aBremAdjointModel)
|
||||
: G4VAdjointReverseReaction(process_name, whichScatCase)
|
||||
{
|
||||
fAdjointModel = aBremAdjointModel;
|
||||
fAdjointModel->SetSecondPartOfSameType(false);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4eInverseBremsstrahlung::~G4eInverseBremsstrahlung(){
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4eInverseBremsstrahlung::~G4eInverseBremsstrahlung() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4eInverseBremsstrahlung::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "Inverse bremsstrahlung process.\n";
|
||||
}
|
||||
|
||||
@@ -23,30 +23,34 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
// File name: G4eInverseCompton
|
||||
//
|
||||
// Author: Laurent Desorgher
|
||||
//
|
||||
// Creation date: 20.11.2006
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
#include "G4eInverseCompton.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
#include "G4AdjointComptonModel.hh"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4eInverseCompton::G4eInverseCompton(G4bool whichScatCase,G4String process_name,G4AdjointComptonModel* aComptonAdjointModel):
|
||||
G4VAdjointReverseReaction(process_name,whichScatCase)
|
||||
{theAdjointEMModel = aComptonAdjointModel;
|
||||
theAdjointEMModel->SetSecondPartOfSameType(false);
|
||||
SetIntegralMode(false);
|
||||
/*if (IsScatProjToProjCase) SetIntegralMode(false);
|
||||
else SetIntegralMode(true); */
|
||||
#include "G4eInverseCompton.hh"
|
||||
|
||||
#include "G4AdjointComptonModel.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4eInverseCompton::G4eInverseCompton(
|
||||
G4bool whichScatCase, G4String process_name,
|
||||
G4AdjointComptonModel* aComptonAdjointModel)
|
||||
: G4VAdjointReverseReaction(process_name, whichScatCase)
|
||||
{
|
||||
fAdjointModel = aComptonAdjointModel;
|
||||
fAdjointModel->SetSecondPartOfSameType(false);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4eInverseCompton::~G4eInverseCompton(){
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4eInverseCompton::~G4eInverseCompton() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4eInverseCompton::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "Inverse Compton effect.\n";
|
||||
}
|
||||
|
||||
@@ -30,21 +30,27 @@
|
||||
// Author: Laurent Desorgher
|
||||
//
|
||||
// Creation date: 20.11.2006
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
#include "G4eInverseIonisation.hh"
|
||||
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4eInverseIonisation::G4eInverseIonisation(G4bool whichScatCase,G4String process_name,G4VEmAdjointModel* aEmAdjointModel):
|
||||
G4VAdjointReverseReaction(process_name,whichScatCase)
|
||||
{theAdjointEMModel = aEmAdjointModel;
|
||||
theAdjointEMModel->SetSecondPartOfSameType(true);
|
||||
SetIntegralMode(true);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4eInverseIonisation::G4eInverseIonisation(G4bool whichScatCase,
|
||||
G4String process_name,
|
||||
G4VEmAdjointModel* aEmAdjointModel)
|
||||
: G4VAdjointReverseReaction(process_name, whichScatCase)
|
||||
{
|
||||
fAdjointModel = aEmAdjointModel;
|
||||
fAdjointModel->SetSecondPartOfSameType(true);
|
||||
}
|
||||
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4eInverseIonisation::~G4eInverseIonisation(){
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
G4eInverseIonisation::~G4eInverseIonisation() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void G4eInverseIonisation::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "Inverse ionisation process for electrons.\n";
|
||||
}
|
||||
|
||||
@@ -32,18 +32,20 @@
|
||||
// Creation date: 15.02.2009
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
#include "G4hInverseIonisation.hh"
|
||||
#include "G4VEmAdjointModel.hh"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4hInverseIonisation::G4hInverseIonisation(G4bool whichScatCase,G4String process_name,G4AdjointhIonisationModel* aEmAdjointModel):
|
||||
G4VAdjointReverseReaction(process_name,whichScatCase)
|
||||
{theAdjointEMModel = aEmAdjointModel;
|
||||
theAdjointEMModel->SetSecondPartOfSameType(false);
|
||||
SetIntegralMode(true);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
G4hInverseIonisation::~G4hInverseIonisation(){
|
||||
#include "G4hInverseIonisation.hh"
|
||||
|
||||
#include "G4AdjointhIonisationModel.hh"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
G4hInverseIonisation::G4hInverseIonisation(
|
||||
G4bool whichScatCase, G4String process_name,
|
||||
G4AdjointhIonisationModel* aEmAdjointModel)
|
||||
: G4VAdjointReverseReaction(process_name, whichScatCase)
|
||||
{
|
||||
fAdjointModel = aEmAdjointModel;
|
||||
fAdjointModel->SetSecondPartOfSameType(false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
G4hInverseIonisation::~G4hInverseIonisation() {}
|
||||
|
||||
Reference in New Issue
Block a user