Import Geant4 11.0.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2021-06-25 16:12:29 +02:00
parent c968e26a39
commit 6399a014b6
4200 changed files with 207479 additions and 237366 deletions
@@ -1,17 +0,0 @@
#------------------------------------------------------------------------------
# CMakeLists.txt
# Module : G4emadjoint
# Package: Geant4.src.G4processes.G4electromagnetic.G4emadjoint
#
# CMakeLists.txt for building a single granular library.
#
# Generated on : 24/9/2010
#
#
#------------------------------------------------------------------------------
if(GEANT4_BUILD_GRANULAR_LIBS)
include(Geant4MacroLibraryTargets)
GEANT4_GRANULAR_LIBRARY_TARGET(COMPONENT sources.cmake)
endif()
@@ -16,39 +16,76 @@ committal in the CVS repository !
* Reverse chronological order (last date on top), please *
---------------------------------------------------------
16 Apr 2021: B. Morgan (emadjoint-V10-07-05)
- Migrate build to modular CMake API
28 Mar 2021: V. Ivanchenko (emadjoint-V10-07-04)
- G4ContinuousGainOfEnergy - used updated signature for ion ionisation
22 Mar 2021: V. Ivanchenko (emadjoint-V10-07-03)
- G4VEmAdjointModel - minor clean-up
12 Mar 2021: D. Sawkey (emadjoint-V10-07-02)
- free resources in destructors
- fix uninitialized variables
8 Mar 2021: D. Sawkey (emadjoint-V10-07-01)
- Second large round of cleaning for v11 release
- use 'virtual' and 'override' methods consistently
- member variables start with f; shorten long names
- remove unused variables; make class variables local where appropriate
- order declarations of class variables
- define class variables
- removed unused functions
- mark copy/assignment operators as 'delete'
- add ProcessDescriptions
- remove ChangeHistory from top of code
- replace 2.*3.14... with CLHEP::twopi
- remove more unused headers
20 Feb 2021: D. Sawkey (emadjoint-V10-07-00)
- First pass on large cleaning for v11 release
- apply clang-format style guidelines
- apply C++11 codewords to method declarations: virtual, override, explicit
- delete unused variables and methods
- start naming class member variables with f
- use nullptr instead of 0
- remove unused headers
- use constexpr for numbers
11 Mar 2019: G. Cosmo (emadjoint-V10-05-00)
-Fixed typos in printouts and comments.
06 Nov 2017: V. Ivanchenko (emadjoint-V10-03-01)
-Extended correction of occurrence of FPE in G4AdjointForcedInteractionForGamma.
-G4eAdjointMultipleScattering - change index of the default accourding to recent
-G4eAdjointMultipleScattering - change index of the default accourding to recent
modifications in emutils
27 Jan 2017: L. Desorgher (emadjoint-V10-03-00)
-Correction of occurrence of FPE in G4AdjointForcedInteractionForGamma.
27 Octb 2016: L. Desorgher (emadjoint-V10-02-03)
-Correction in G4AdjointForcedInteractionForGamma to avoid high weight of forced gamma
when only the brem is used.
-Modification in G4AdjointBremsstrahlungModel to use the direcet angular model to compute the direction of the
-Modification in G4AdjointBremsstrahlungModel to use the direcet angular model to compute the direction of the
adjoint secondary
-Add G4UrbanAdjointMscModel.cc and G4eAdjointMultipleScattering.cc
18 Octb 2016: L. Desorgher (emadjoint-V10-02-02)
-Correct use of logical or in G4AdjointForcedInteractionForGamma for compilation
error under windows.
error under windows.
17 Octb 2016: L. Desorgher (emadjoint-V10-02-01)
-Correct G4AdjointForcedInteractionForGamma for compilation error under windows.
-Correct G4AdjointForcedInteractionForGamma for compilation error under windows.
26 Sept 2016: L. Desorgher (emadjoint-V10-02-00)
-Add new adjoint process G4AdjointForcedInteractionForGamma to force the
-Add new adjoint process G4AdjointForcedInteractionForGamma to force the
reverse interaction of adjoint gamma.
-Slight modifications of G4VEmAdjointModel for new forced interaction
-Some corrections in G4AdjointBremsstrahlungModel
24 Oct 2015: V.Ivanchenko (emadjoint-V10-01-03)
- G4AdjointCSManager - use G4ThreadLocalSingleton pattern,
- G4AdjointCSManager - use G4ThreadLocalSingleton pattern,
fixed computation of A of an element, added initialisation
of all class members in the constructor
@@ -61,12 +98,12 @@ committal in the CVS repository !
G4AdjointCSManager - add checks for while loops
21 May 2015: V.Ivanchenko (emadjoint-V10-01-00)
- G4AdjointhMultipleScattering - make it coherent with the forward
- G4AdjointhMultipleScattering - make it coherent with the forward
msc processes
10 Apr 2014: V.Ivanchenko (emadjoint-V10-00-00)
- G4VAdjointReverseReaction - added protection against infinite
loop in ReverseMC01 example: if cross section correction
- G4VAdjointReverseReaction - added protection against infinite
loop in ReverseMC01 example: if cross section correction
exceed 100 the total cross section is set to zero
31 Oct 2013: L.Desorgher (emadjoint-V09-06-09)
@@ -90,9 +127,9 @@ committal in the CVS repository !
24 Jan 2013: V.Ivanchenko (emadjoint-V09-06-04)
- G4AdjointPhotoElectricModel - define current G4MaterialCutsCouple
for the direct model
22 Feb 2013: L.Desorgher (emadjoint-V09-06-03)
-Remove of unused variables detected by compilation warnings.
-Remove of unused variables detected by compilation warnings.
23 Jan 2013: V.Ivanchenko (emadjoint-V09-06-02)
11 Jan 2013: V.Ivanchenko (emadjoint-V09-06-01)
@@ -109,9 +146,9 @@ committal in the CVS repository !
26 Oct 2012: L.Desorgher (emadjoint-V09-05-03)
-G4AdjointBremsstrahlungModel changed to use G4SeltzerBergerModel as forward model by default
-Correct differential CS expression in G4VEmAdjointModel
-Get the weight from PostStepPoint instead of from Track when correcting the step in along stepping actions of
G4ContinuousGainOfEnergy and G4AdjointAlongStepWeightCorrection. THis is needed for a correct propagation
of weight correction in different along step actions.
-Get the weight from PostStepPoint instead of from Track when correcting the step in along stepping actions of
G4ContinuousGainOfEnergy and G4AdjointAlongStepWeightCorrection. THis is needed for a correct propagation
of weight correction in different along step actions.
10 Jul 2012: G.Cosmo (emadjoint-V09-05-02)
- Explicitly use inclusion of headers for system of units and physical
@@ -125,7 +162,7 @@ committal in the CVS repository !
24 Jun 2011: V.Ivanchenko (emadjoint-V09-04-03)
- G4AdjointAlongStepWeightCorrection,G4ContinuousGainOfEnergy,
G4VEmAdjointModel - fixed initialisation of currentCouple
G4VEmAdjointModel - fixed initialisation of currentCouple
class member in constructor (Valgrind report)
10 Jun 2011: G.Cosmo (emadjoint-V09-04-02)
@@ -165,24 +202,24 @@ Coverity fixes
-G4VEmAdjointModel
-Comment dead code in GetAdjointCrossSection (defect 23168)
-Neglect at the moment coverity bug 20612-20618.
27 May 2011: L. Desorgher (emadjoint-V09-04-00)
-Remove few unused variables to avoid compilation warning with gcc-4.6.0.
11 Nov 2010: L. Desorgher (emadjoint-V09-03-02)
-G4AdjointBremsstrahlungModel: add a G4EmModelManager to initialise properly,
the G4eBremsstrahlungModel used as forward model. This allows to fix the
the G4eBremsstrahlungModel used as forward model. This allows to fix the
floating point exception detected when compiling with G4FPE_DEBUG=1.
-G4AdjointhIonisation:
Remove a negative term in the expression of the adjoint
Remove a negative term in the expression of the adjoint
cross section (AdjointCrossSection method) and adapt the RapidSampleSecondaries method.
-G4VEmAdjointModel:
-G4VEmAdjointModel:
Add a check on null cross section to avoid FPE.
3 Sep 2010: G.Cosmo (emadjoint-V09-03-01)
- G4AdjointAlongStepWeightCorrection: get rid of call to non-Standard isnan(),
replaced by explicit validity test.
replaced by explicit validity test.
12 Apr 2010: V.Ivanchenko (emadjoint-V09-03-00)
- G4AdjointhMultipleScattering: removed obsolete unused header.
@@ -196,8 +233,8 @@ Coverity fixes
10 Nov 2009: L.Desorgher (emadjoint-V09-02-00)
- Commit of the electromagnetic adjoint processes for the release of the all adjoint machinery into Geant4.
Compared to the first commit, all e- processes have been improved and adjoint proton and ion ionisation have been added.
The use of adjoint cross section matrices can be now limited only to e- Ionisation and Ion ionisation.
The GNUmakefile has been modified by adding -I$(G4BASE)/geometry/navigation/include in CPPFLAGS.
The use of adjoint cross section matrices can be now limited only to e- Ionisation and Ion ionisation.
The GNUmakefile has been modified by adding -I$(G4BASE)/geometry/navigation/include in CPPFLAGS.
14 Nov 2008: G.Cosmo (emadjoint-V09-01-00)
- First commit.
@@ -23,114 +23,81 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointAlongStepWeightCorrection
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
// Class: G4AdjointAlongStepWeightCorrection
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 10 May 2007 creation by L. Desorgher
// October 2009 implementation of the mode where the total adjoint and forward cross sections are equivalent. L. Desorgher
// Documentation:
//
// 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)
//
//-------------------------------------------------------------
// Documentation:
// Continuous processes acting on adjoint particles to correct continuously their weight during the adjoint reverse tracking.
// Thi process is needed whene the adjoint cross section are not scaled such that the total adjoint cross section match 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 an therefore this along step weight
// correction factor is 1.
// However in some cases (some energy ranges) the total forward cross section or the total adjoint cross section can be null, in this case the along step
// weight correction is neede and is given by exp(-(Sigma_tot_adj-Sigma_tot_fwd).dx)
//
//
//
#ifndef G4AdjointAlongStepWeightCorrection_h
#define G4AdjointAlongStepWeightCorrection_h 1
#include "G4VContinuousProcess.hh"
#include "globals.hh"
#include "G4Material.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Track.hh"
#include "G4ParticleChange.hh"
#include "G4VContinuousProcess.hh"
class G4Step;
class G4AdjointCSManager;
class G4MaterialCutsCouple;
class G4ParticleDefinition;
class G4ParticleChange;
class G4Step;
class G4Track;
class G4AdjointAlongStepWeightCorrection : public G4VContinuousProcess
{
public:
public:
explicit G4AdjointAlongStepWeightCorrection(
const G4String& name = "ContinuousWeightCorrection",
G4ProcessType type = fElectromagnetic);
G4AdjointAlongStepWeightCorrection(const G4String& name = "ContinuousWeightCorrection",
G4ProcessType type = fElectromagnetic);
~G4AdjointAlongStepWeightCorrection() override;
virtual ~G4AdjointAlongStepWeightCorrection();
G4VParticleChange* AlongStepDoIt(const G4Track&, const G4Step&) override;
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
protected:
virtual G4double GetContinuousStepLimit(const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety);
G4AdjointAlongStepWeightCorrection(G4AdjointAlongStepWeightCorrection&) =
delete;
G4AdjointAlongStepWeightCorrection& operator=(
const G4AdjointAlongStepWeightCorrection& right) = delete;
//------------------------------------------------------------------------
// Generic methods common to all processes
//------------------------------------------------------------------------
public:
void PreparePhysicsTable(const G4ParticleDefinition&);
void BuildPhysicsTable(const G4ParticleDefinition&);
G4VParticleChange* AlongStepDoIt(const G4Track&, const G4Step&);
private:
protected:
G4double GetContinuousStepLimit(const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety) override;
private:
void DefineMaterial(const G4MaterialCutsCouple* couple);
G4AdjointAlongStepWeightCorrection(G4AdjointAlongStepWeightCorrection &);
G4AdjointAlongStepWeightCorrection & operator=(const G4AdjointAlongStepWeightCorrection &right);
protected:
const G4MaterialCutsCouple* fCurrentCouple = nullptr;
G4AdjointCSManager* fCSManager = nullptr;
G4ParticleChange* fParticleChange;
private:
const G4Material* currentMaterial;
const G4MaterialCutsCouple* currentCouple;
size_t currentMaterialIndex;
G4double preStepKinEnergy;
G4double fPreStepKinEnergy = 1.;
};
inline void G4AdjointAlongStepWeightCorrection::DefineMaterial(
const G4MaterialCutsCouple* couple)
const G4MaterialCutsCouple* couple)
{
if(couple != currentCouple) {
currentCouple = couple;
currentMaterial = couple->GetMaterial();
currentMaterialIndex = couple->GetIndex();
if(couple != fCurrentCouple)
{
fCurrentCouple = couple;
}
}
#endif
@@ -23,93 +23,73 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointBremsstrahlungModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointBremsstrahlungModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 15 June 2007 creation by L. Desorgher. Adapted from G4eBremsstrahlungModel
// 20-10-2009 Remove all the screening effect that are not considered in the direct models blow 10 GeV. L.Desorgher
// 4-11-2009 Implement the use of a simple biased differential cross section (C(Z)/Egamma) allowing a rapid computation of adjoint CS
// and rapid sampling of adjoint secondaries. By this way cross section matrices are not used anymore, avoiding a rather
// time consuming computation of adjoint brem cross section matrices for each material at initialisation. This mode is switch on/off
// by selecting SetUseMatrix(false)/ SetUseMatrix(true) in the constructor. L.Desorgher
//
// Adjoint Model for e- Bremsstrahlung.Adapted from G4eBremsstrahlungModel
// Use of a simple biased differential cross section (C(Z)/Egamma) allowing a
// rapid computation of adjoint CS and rapid sampling of adjoint secondaries.
// In this way cross section matrices are not used anymore, avoiding a long
// computation of adjoint brem cross section matrices for each material
// at initialisation. This mode can be switched on/off by selecting
// SetUseMatrix(false)/ SetUseMatrix(true) in the constructor.
//
//-------------------------------------------------------------
// Documentation:
// Adjoint Model for e- Bremsstrahlung
//
#ifndef G4AdjointBremsstrahlungModel_h
#define G4AdjointBremsstrahlungModel_h 1
#include "globals.hh"
#include "G4VEmAdjointModel.hh"
#include "G4VEmAngularDistribution.hh"
#include "G4PhysicsTable.hh"
#include "G4EmModelManager.hh"
class G4Timer;
class G4AdjointBremsstrahlungModel: public G4VEmAdjointModel
class G4AdjointCSManager;
class G4EmModelManager;
class G4ParticleDefinition;
class G4AdjointBremsstrahlungModel : public G4VEmAdjointModel
{
public:
public:
explicit G4AdjointBremsstrahlungModel(G4VEmModel* aModel);
G4AdjointBremsstrahlungModel(G4VEmModel* aModel);
G4AdjointBremsstrahlungModel();
~G4AdjointBremsstrahlungModel();
virtual void SampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange);
void RapidSampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange);
virtual G4double DiffCrossSectionPerVolumePrimToSecond(
const G4Material* aMaterial,
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyProd // kinetic energy of the secondary particle
);
G4double DiffCrossSectionPerVolumePrimToSecondApproximated1(
const G4Material* aMaterial,
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyProd // kinetic energy of the secondary particle
);
G4double DiffCrossSectionPerVolumePrimToSecondApproximated2(
const G4Material* aMaterial,
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyProd // kinetic energy of the secondary particle
);
virtual G4double AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool IsScatProjToProjCase);
virtual G4double GetAdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool IsScatProjToProjCase);
// private void InitialiseFwdModels();
~G4AdjointBremsstrahlungModel() override;
private:
G4VEmModel* theDirectStdBremModel;
G4EmModelManager* theEmModelManagerForFwdModels;
G4bool isDirectModelInitialised ;
void SampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange) override;
G4double highKinEnergy;
G4double lowKinEnergy, lastCZ;
std::vector<G4DataVector*> partialSumSigma;
std::vector<float> SigmaPerAtom;
void RapidSampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange);
G4double DiffCrossSectionPerVolumePrimToSecond(
const G4Material* aMaterial,
G4double kinEnergyProj, // kinetic energy of the primary particle before
// the interaction
G4double kinEnergyProd // kinetic energy of the secondary particle
) override;
G4double AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool isScatProjToProj) override;
G4AdjointBremsstrahlungModel(G4AdjointBremsstrahlungModel&) = delete;
G4AdjointBremsstrahlungModel& operator=(
const G4AdjointBremsstrahlungModel& right) = delete;
private:
void Initialize();
G4EmModelManager* fEmModelManagerForFwdModels;
G4AdjointCSManager* fCSManager;
G4ParticleDefinition* fElectron;
G4ParticleDefinition* fGamma;
G4double fLastCZ = 0.;
G4bool fIsDirectModelInitialised = false;
};
#endif
@@ -23,245 +23,220 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointCSManager
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointCSManager
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 1st April 2007 creation by L. Desorgher
//
// September-October 2009. Implementation of the mode where the adjoint cross sections are scaled such that the total used adjoint cross sections is in
// most of the cases equal to the total forward cross section. L.Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Is responsible for the management of all adjoint cross sections matrices, and for the computation of the total forward and adjoint cross sections.
// Total adjoint and forward cross sections are needed to correct the weight of a particle after a tracking step or after the occurrence of a reverse reaction.
// It is also used to sample an adjoint secondary from a given adjoint cross section matrix.
// Class is responsible for the management of all adjoint cross section
// matrices, and for the computation of the total forward and adjoint cross
// sections. Total adjoint and forward cross sections are needed to correct the
// weight of a particle after a tracking step or after the occurrence of a
// reverse reaction. It is also used to sample an adjoint secondary from a
// given adjoint cross section matrix.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef G4AdjointCSManager_h
#define G4AdjointCSManager_h 1
#include"globals.hh"
#include<vector>
#include"G4AdjointCSMatrix.hh"
#include "globals.hh"
#include "G4AdjointCSMatrix.hh"
#include "G4ThreadLocalSingleton.hh"
class G4VEmAdjointModel;
class G4MaterialCutsCouple;
class G4Material;
class G4ParticleDefinition;
class G4Element;
class G4VEmProcess;
class G4VEnergyLossProcess;
class G4PhysicsTable;
#include <vector>
class G4Element;
class G4Material;
class G4MaterialCutsCouple;
class G4ParticleDefinition;
class G4PhysicsTable;
class G4VEmProcess;
class G4VEmAdjointModel;
class G4VEnergyLossProcess;
////////////////////////////////////////////////////////////////////////////////
//
class G4AdjointCSManager
{
friend class G4ThreadLocalSingleton<G4AdjointCSManager>;
public:
~G4AdjointCSManager();
static G4AdjointCSManager* GetAdjointCSManager();
public:
G4int GetNbProcesses();
//Registration of the different models and processes
size_t RegisterEmAdjointModel(G4VEmAdjointModel*);
void RegisterEmProcess(G4VEmProcess* aProcess, G4ParticleDefinition* aPartDef);
void RegisterEnergyLossProcess(G4VEnergyLossProcess* aProcess, G4ParticleDefinition* aPartDef);
void RegisterAdjointParticle(G4ParticleDefinition* aPartDef);
//Building of the CS Matrices and Total Forward and Adjoint LambdaTables
//----------------------------------------------------------------------
void BuildCrossSectionMatrices();
void BuildTotalSigmaTables();
//Get TotalCrossSections form Total Lambda Tables, Needed for Weight correction and scaling of the
//-------------------------------------------------
G4double GetTotalAdjointCS(G4ParticleDefinition* aPartDef, G4double Ekin,
const G4MaterialCutsCouple* aCouple);
G4double GetTotalForwardCS(G4ParticleDefinition* aPartDef, G4double Ekin,
const G4MaterialCutsCouple* aCouple);
G4double GetAdjointSigma(G4double Ekin_nuc, size_t index_model,G4bool is_scat_proj_to_proj,
const G4MaterialCutsCouple* aCouple);
void GetEminForTotalCS(G4ParticleDefinition* aPartDef,
const G4MaterialCutsCouple* aCouple, G4double& emin_adj, G4double& emin_fwd);
void GetMaxFwdTotalCS(G4ParticleDefinition* aPartDef,
const G4MaterialCutsCouple* aCouple, G4double& e_sigma_max, G4double& sigma_max);
void GetMaxAdjTotalCS(G4ParticleDefinition* aPartDef,
const G4MaterialCutsCouple* aCouple, G4double& e_sigma_max, G4double& sigma_max);
//CrossSection Correction 1 or FwdCS/AdjCS following the G4boolean value of forward_CS_is_used and forward_CS_mode
//-------------------------------------------------
G4double GetCrossSectionCorrection(G4ParticleDefinition* aPartDef,G4double PreStepEkin,const G4MaterialCutsCouple* aCouple, G4bool& fwd_is_used, G4double& fwd_TotCS);
//Cross section mode
//------------------
inline void SetFwdCrossSectionMode(G4bool aBool){forward_CS_mode=aBool;}
//Weight correction
//------------------
G4double GetContinuousWeightCorrection(G4ParticleDefinition* aPartDef, G4double PreStepEkin,G4double AfterStepEkin,
const G4MaterialCutsCouple* aCouple, G4double step_length);
G4double GetPostStepWeightCorrection();
//Method Called by the adjoint model to get there CS, if not precised otherwise
//-------------------------------
G4double ComputeAdjointCS(G4Material* aMaterial,
G4VEmAdjointModel* aModel,
G4double PrimEnergy,
G4double Tcut,
G4bool IsScatProjToProjCase,
std::vector<G4double>&
AdjointCS_for_each_element);
//Method Called by the adjoint model to sample the secondary energy form the CS matrix
//--------------------------------------------------------------------------------
G4Element* SampleElementFromCSMatrices(G4Material* aMaterial,
G4VEmAdjointModel* aModel,
G4double PrimEnergy,
G4double Tcut,
G4bool IsScatProjToProjCase);
//Total Adjoint CS is computed at initialisation phase
//-----------------------------------------------------
G4double ComputeTotalAdjointCS(const G4MaterialCutsCouple* aMatCutCouple,G4ParticleDefinition* aPart,G4double PrimEnergy);
G4ParticleDefinition* GetAdjointParticleEquivalent(G4ParticleDefinition* theFwdPartDef);
G4ParticleDefinition* GetForwardParticleEquivalent(G4ParticleDefinition* theAdjPartDef);
//inline
inline void SetTmin(G4double aVal){Tmin=aVal;}
inline void SetTmax(G4double aVal){Tmax=aVal;}
inline void SetNbins(G4int aInt){nbins=aInt;}
inline void SetIon(G4ParticleDefinition* adjIon,
G4ParticleDefinition* fwdIon) {theAdjIon=adjIon; theFwdIon =fwdIon;}
private:
static G4ThreadLocal G4AdjointCSManager* theInstance;
std::vector< std::vector<G4AdjointCSMatrix*> > theAdjointCSMatricesForScatProjToProj; //x dim is for G4VAdjointEM*, y dim is for elements
std::vector< std::vector<G4AdjointCSMatrix*> > theAdjointCSMatricesForProdToProj;
std::vector< G4VEmAdjointModel*> listOfAdjointEMModel;
std::vector<G4AdjointCSMatrix*>
BuildCrossSectionsMatricesForAGivenModelAndElement(G4VEmAdjointModel* aModel,
G4int Z,
G4int A,
G4int nbin_pro_decade);
std::vector<G4AdjointCSMatrix*>
BuildCrossSectionsMatricesForAGivenModelAndMaterial(G4VEmAdjointModel* aModel,
G4Material* aMaterial,
G4int nbin_pro_decade);
G4Material* lastMaterial;
G4double lastPrimaryEnergy;
G4double lastTcut;
std::vector< size_t> listOfIndexOfAdjointEMModelInAction;
std::vector< G4bool> listOfIsScatProjToProjCase;
std::vector< std::vector<G4double> > lastAdjointCSVsModelsAndElements;
G4bool CrossSectionMatrixesAreBuilt;
size_t currentParticleIndex;
G4ParticleDefinition* currentParticleDef;
//total adjoint and total forward cross section table in function of material and in function of adjoint particle type
//--------------------------------------------------------------------------------------------------------------------
std::vector<G4PhysicsTable*> theTotalForwardSigmaTableVector;
std::vector<G4PhysicsTable*> theTotalAdjointSigmaTableVector;
std::vector< std::vector<G4double> > EminForFwdSigmaTables;
std::vector< std::vector<G4double> > EminForAdjSigmaTables;
std::vector< std::vector<G4double> > EkinofFwdSigmaMax;
std::vector< std::vector<G4double> > EkinofAdjSigmaMax;
G4bool TotalSigmaTableAreBuilt;
//Sigma tavle for each G4VAdjointEMModel
std::vector<G4PhysicsTable*> listSigmaTableForAdjointModelScatProjToProj;
std::vector<G4PhysicsTable*> listSigmaTableForAdjointModelProdToProj;
//list of forward G4VEMLossProcess and of G4VEMProcess for the different adjoint particle
//--------------------------------------------------------------
std::vector< std::vector<G4VEmProcess*>* > listOfForwardEmProcess;
std::vector< std::vector<G4VEnergyLossProcess*>* > listOfForwardEnergyLossProcess;
//list of adjoint particles considered
//--------------------------------------------------------------
std::vector< G4ParticleDefinition*> theListOfAdjointParticlesInAction;
G4double Tmin,Tmax;
G4int nbins;
//Current material
//----------------
G4MaterialCutsCouple* currentCouple;
G4Material* currentMaterial;
size_t currentMatIndex;
G4int verbose;
//Two CS mode are possible :forward_CS_mode = false the Adjoint CS are used as it is implying a AlongStep Weight Correction.
// :forward_CS_mode = true the Adjoint CS are scaled to have the total adjoint CS eual to the fwd one implying a PostStep Weight Correction.
// For energy range where the total FwdCS or the total adjoint CS are null, the scaling is not possble and
// forward_CS_is_used is set to false
//--------------------------------------------
G4bool forward_CS_is_used;
G4bool forward_CS_mode;
//Adj and Fwd CS values for re-use
//------------------------
G4double PreadjCS,PostadjCS;
G4double PrefwdCS,PostfwdCS;
G4double LastEkinForCS;
G4double LastCSCorrectionFactor;
G4ParticleDefinition* lastPartDefForCS;
//Ion
//----------------
G4ParticleDefinition* theAdjIon; //at the moment Only one ion can be considered by simulation
G4ParticleDefinition* theFwdIon;
G4double massRatio;
private:
G4AdjointCSManager();
void DefineCurrentMaterial(const G4MaterialCutsCouple* couple);
void DefineCurrentParticle(const G4ParticleDefinition* aPartDef);
G4double ComputeAdjointCS(G4double aPrimEnergy, G4AdjointCSMatrix* anAdjointCSMatrix, G4double Tcut);
size_t eindex;
public:
~G4AdjointCSManager();
static G4AdjointCSManager* GetAdjointCSManager();
G4int GetNbProcesses();
// Registration of the different models and processes
size_t RegisterEmAdjointModel(G4VEmAdjointModel*);
void RegisterEmProcess(G4VEmProcess* aProcess,
G4ParticleDefinition* aPartDef);
void RegisterEnergyLossProcess(G4VEnergyLossProcess* aProcess,
G4ParticleDefinition* aPartDef);
void RegisterAdjointParticle(G4ParticleDefinition* aPartDef);
// Building of the CS Matrices and Total Forward and Adjoint LambdaTables
void BuildCrossSectionMatrices();
void BuildTotalSigmaTables();
// Get TotalCrossSections form Total Lambda Tables, Needed for Weight
// correction and scaling of the
G4double GetTotalAdjointCS(G4ParticleDefinition* aPartDef, G4double Ekin,
const G4MaterialCutsCouple* aCouple);
G4double GetTotalForwardCS(G4ParticleDefinition* aPartDef, G4double Ekin,
const G4MaterialCutsCouple* aCouple);
G4double GetAdjointSigma(G4double Ekin_nuc, size_t index_model,
G4bool is_scat_proj_to_proj,
const G4MaterialCutsCouple* aCouple);
void GetEminForTotalCS(G4ParticleDefinition* aPartDef,
const G4MaterialCutsCouple* aCouple,
G4double& emin_adj, G4double& emin_fwd);
void GetMaxFwdTotalCS(G4ParticleDefinition* aPartDef,
const G4MaterialCutsCouple* aCouple,
G4double& e_sigma_max, G4double& sigma_max);
void GetMaxAdjTotalCS(G4ParticleDefinition* aPartDef,
const G4MaterialCutsCouple* aCouple,
G4double& e_sigma_max, G4double& sigma_max);
// CrossSection Correction 1 or FwdCS/AdjCS following the G4boolean value of
// forward_CS_is_used and forward_CS_mode
G4double GetCrossSectionCorrection(G4ParticleDefinition* aPartDef,
G4double PreStepEkin,
const G4MaterialCutsCouple* aCouple,
G4bool& fwd_is_used);
// Cross section mode
inline void SetFwdCrossSectionMode(G4bool aBool) { fForwardCSMode = aBool; }
// Weight correction
G4double GetContinuousWeightCorrection(G4ParticleDefinition* aPartDef,
G4double PreStepEkin,
G4double AfterStepEkin,
const G4MaterialCutsCouple* aCouple,
G4double step_length);
G4double GetPostStepWeightCorrection();
// called by the adjoint model to get the CS, if not otherwise specified
G4double ComputeAdjointCS(G4Material* aMaterial, G4VEmAdjointModel* aModel,
G4double PrimEnergy, G4double Tcut,
G4bool isScatProjToProj,
std::vector<G4double>& AdjointCS_for_each_element);
// called by the adjoint model to sample secondary energy from the CS matrix
G4Element* SampleElementFromCSMatrices(G4Material* aMaterial,
G4VEmAdjointModel* aModel,
G4double PrimEnergy, G4double Tcut,
G4bool isScatProjToProj);
// Total Adjoint CS is computed at initialisation phase
G4double ComputeTotalAdjointCS(const G4MaterialCutsCouple* aMatCutCouple,
G4ParticleDefinition* aPart,
G4double PrimEnergy);
G4ParticleDefinition* GetAdjointParticleEquivalent(
G4ParticleDefinition* theFwdPartDef);
G4ParticleDefinition* GetForwardParticleEquivalent(
G4ParticleDefinition* theAdjPartDef);
// inline
inline void SetIon(G4ParticleDefinition* adjIon, G4ParticleDefinition* fwdIon)
{
fAdjIon = adjIon;
fFwdIon = fwdIon;
}
private:
G4AdjointCSManager();
void DefineCurrentMaterial(const G4MaterialCutsCouple* couple);
void DefineCurrentParticle(const G4ParticleDefinition* aPartDef);
G4double ComputeAdjointCS(G4double aPrimEnergy,
G4AdjointCSMatrix* anAdjointCSMatrix,
G4double Tcut);
std::vector<G4AdjointCSMatrix*> BuildCrossSectionsModelAndElement(
G4VEmAdjointModel* aModel, G4int Z, G4int A, G4int nbin_pro_decade);
std::vector<G4AdjointCSMatrix*> BuildCrossSectionsModelAndMaterial(
G4VEmAdjointModel* aModel, G4Material* aMaterial, G4int nbin_pro_decade);
static constexpr G4double fTmin = 0.1 * CLHEP::keV;
static constexpr G4double fTmax = 100. * CLHEP::TeV;
// fNbins chosen to avoid error
// in the CS value close to CS jump. (For example at Tcut)
static constexpr G4int fNbins = 320;
static G4ThreadLocal G4AdjointCSManager* fInstance;
// only one ion can be considered by simulation
G4ParticleDefinition* fAdjIon = nullptr;
G4ParticleDefinition* fFwdIon = nullptr;
G4MaterialCutsCouple* fCurrentCouple = nullptr;
G4Material* fCurrentMaterial = nullptr;
// x dim is for G4VAdjointEM*, y dim is for elements
std::vector<std::vector<G4AdjointCSMatrix*>>
fAdjointCSMatricesForScatProjToProj;
std::vector<std::vector<G4AdjointCSMatrix*>> fAdjointCSMatricesForProdToProj;
std::vector<G4VEmAdjointModel*> fAdjointModels;
std::vector<size_t> fIndexOfAdjointEMModelInAction;
std::vector<G4bool> fIsScatProjToProj;
std::vector<std::vector<G4double>> fLastAdjointCSVsModelsAndElements;
// total adjoint and total forward cross section table in function of material
// and in function of adjoint particle type
std::vector<G4PhysicsTable*> fTotalFwdSigmaTable;
std::vector<G4PhysicsTable*> fTotalAdjSigmaTable;
// Sigma table for each G4VAdjointEMModel
std::vector<G4PhysicsTable*> fSigmaTableForAdjointModelScatProjToProj;
std::vector<G4PhysicsTable*> fSigmaTableForAdjointModelProdToProj;
std::vector<std::vector<G4double>> fEminForFwdSigmaTables;
std::vector<std::vector<G4double>> fEminForAdjSigmaTables;
std::vector<std::vector<G4double>> fEkinofFwdSigmaMax;
std::vector<std::vector<G4double>> fEkinofAdjSigmaMax;
// list of forward G4VEmProcess and of G4VEnergyLossProcess for the different
// adjoint particle
std::vector<std::vector<G4VEmProcess*>*> fForwardProcesses;
std::vector<std::vector<G4VEnergyLossProcess*>*> fForwardLossProcesses;
// list of adjoint particles considered
std::vector<G4ParticleDefinition*> fAdjointParticlesInAction;
G4double fMassRatio = 1.; // ion
G4double fLastCSCorrectionFactor = 1.;
size_t fCurrentParticleIndex = 0;
size_t fCurrentMatIndex = 0;
G4bool fCSMatricesBuilt = false;
G4bool fSigmaTableBuilt = false;
G4bool fForwardCSUsed = true;
G4bool fForwardCSMode = true;
// Two CS mode are possible:
// 1) fForwardCSMode = false, the Adjoint CS are used as it is implying
// an AlongStep Weight Correction.
// 2) fForwardCSMode = true, the Adjoint CS are scaled to have the total
// adjoint CS equal to the fwd one implying a PostStep Weight Correction.
// For energies where the total Fwd CS or the total adjoint CS are zero,
// the scaling is not possible and fForwardCSUsed is set to false
};
#endif
@@ -23,82 +23,78 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointCSMatrix
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointCSMatrix.hh
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 1st April 2007 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// An adjoint CS matrix is used by the model of a reverse process to sample an adjoint secondary (being equivalent to a forward primary).
// It represents the integration over the energy of the adjoint secondary (therefore the forward primary) of the differential cross section
// of the equiavlent forward discrete process (Ionisation, Brem, PE effect, Compton,..) . Each reverse model has its own cross section matrix for a given cut,
// material couple. It is therefore recompute after a modification of the cuts by the user.
//
//
// An adjoint CS matrix is used by the model of a reverse process to sample
// an adjoint secondary (being equivalent to a forward primary). It represents
// the integration over the energy of the adjoint secondary (therefore the
// forward primary) of the differential cross section of the equivalent forward
// discrete process (Ionisation, Brem, PE effect, Compton,..). Each reverse
// model has its own cross section matrix for a given cut, material couple. It
// is therefore recomputed after a modification of the cuts by the user.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef G4AdjointCSMatrix_h
#define G4AdjointCSMatrix_h 1
#include"globals.hh"
#include<vector>
#include"G4ParticleDefinition.hh"
#include "globals.hh"
#include "G4ParticleDefinition.hh"
#include <vector>
////////////////////////////////////////////////////////////////////////////////
//
class G4AdjointCSMatrix
{
////////////////////////////////
// Constructors and Destructor
////////////////////////////////
public:
G4AdjointCSMatrix(G4bool aBool);
~G4AdjointCSMatrix();
public:
G4AdjointCSMatrix(G4bool aBool);
~G4AdjointCSMatrix();
//////////////
// Methods //
//////////////
void Clear();
void AddData(G4double aPrimEnergy,G4double aCS, std::vector< double>* aLogSecondEnergyVector,
std::vector< double>* aLogProbVector,size_t n_pro_decade=0);
G4bool GetData(unsigned int i, G4double& aPrimEnergy,G4double& aCS,G4double& log0, std::vector< double>*& aLogSecondEnergyVector,
std::vector< double>*& aLogProbVector,
std::vector< size_t>*& aLogProbVectorIndex);
inline std::vector< double>* GetLogPrimEnergyVector(){return &theLogPrimEnergyVector;}
inline std::vector< double>* GetLogCrossSectionvector(){return &theLogCrossSectionVector;}
inline G4double GetDlog(){return dlog;}
inline G4bool IsScatProjToProjCase(){return is_scat_proj_to_proj_case;}
void Write(G4String file_name);
void Read(G4String file_name);
void Clear();
private:
// we did first try to use G4PhysicsOrderedVector but they are not general enough for our purpose
std::vector< double> theLogPrimEnergyVector;
std::vector< double> theLogCrossSectionVector; //Adjoint Cross sections in function of primary energy
std::vector< std::vector< double>* > theLogSecondEnergyMatrix;
std::vector< std::vector< double>* > theLogProbMatrix; //Each column represents the integrated probability of getting a secondary
// in function of their energy
std::vector< std::vector< size_t >* > theLogProbMatrixIndex; //index of equidistant LogProb
std::vector< double> log0Vector;
unsigned int nb_of_PrimEnergy;
G4bool is_scat_proj_to_proj_case;
G4double dlog;
void AddData(G4double aPrimEnergy, G4double aCS,
std::vector<double>* aLogSecondEnergyVector,
std::vector<double>* aLogProbVector, size_t n_pro_decade = 0);
G4bool GetData(unsigned int i, G4double& aPrimEnergy, G4double& aCS,
G4double& log0, std::vector<double>*& aLogSecondEnergyVector,
std::vector<double>*& aLogProbVector,
std::vector<size_t>*& aLogProbVectorIndex);
inline std::vector<double>* GetLogPrimEnergyVector()
{
return &fLogPrimEnergyVector;
}
inline std::vector<double>* GetLogCrossSectionvector()
{
return &fLogCrossSectionVector;
}
inline G4bool IsScatProjToProj() { return fScatProjToProj; }
void Write(G4String file_name);
void Read(G4String file_name);
private:
std::vector<double> fLogPrimEnergyVector;
// Adjoint Cross sections as functions of primary energy
std::vector<double> fLogCrossSectionVector;
std::vector<std::vector<double>*> fLogSecondEnergyMatrix;
std::vector<std::vector<double>*> fLogProbMatrix;
// Each column represents the integrated probability of
// getting a secondary
// index of equidistant LogProb
std::vector<std::vector<size_t>*> fLogProbMatrixIndex;
std::vector<double> fLog0Vector;
size_t fNbPrimEnergy = 0;
G4bool fScatProjToProj;
};
#endif
@@ -23,81 +23,64 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointComptonModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointComptonModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 1 September 2007 creation by L. Desorgher
// 11 November 2009 Implement the use of approximated diffCS as an alternative of CSMatrix.
//
//-------------------------------------------------------------
// Documentation:
// Model for the adjoint compton scattering.
//
// Model for the adjoint compton scattering.
////////////////////////////////////////////////////////////////////////////////
#ifndef G4AdjointComptonModel_h
#define G4AdjointComptonModel_h 1
#include "globals.hh"
#include "G4VEmAdjointModel.hh"
#include "G4VEmProcess.hh"
class G4AdjointComptonModel: public G4VEmAdjointModel
class G4VEmProcess;
class G4AdjointComptonModel : public G4VEmAdjointModel
{
public:
public:
G4AdjointComptonModel();
~G4AdjointComptonModel();
virtual void SampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange);
void RapidSampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange);
virtual G4double DiffCrossSectionPerAtomPrimToScatPrim(
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyScatProj, // kinetic energy of the primary particle after the interaction
G4double Z,
G4double A = 0.);
virtual G4double DiffCrossSectionPerAtomPrimToSecond(
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyProd, // kinetic energy of the secondary particle
G4double Z,
G4double A = 0.);
virtual G4double GetSecondAdjEnergyMaxForScatProjToProjCase(G4double PrimAdjEnergy);
virtual G4double GetSecondAdjEnergyMinForProdToProjCase(G4double PrimAdjEnergy);
virtual G4double AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool IsScatProjToProjCase);
virtual G4double GetAdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool IsScatProjToProjCase);
~G4AdjointComptonModel() override;
inline void SetDirectProcess(G4VEmProcess* aProcess){theDirectEMProcess = aProcess;};
private:
G4VEmProcess* theDirectEMProcess;
G4double G4direct_CS;
void SampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange) override;
void RapidSampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange);
G4double DiffCrossSectionPerAtomPrimToScatPrim(
G4double kinEnergyProj, // kin energy of primary before interaction
G4double kinEnergyScatProj, // kin energy of primary after interaction
G4double Z, G4double A = 0.) override;
G4double DiffCrossSectionPerAtomPrimToSecond(
G4double kinEnergyProj, // kin energy of primary before interaction
G4double kinEnergyProd, // kin energy of secondary particle
G4double Z, G4double A = 0.) override;
G4double GetSecondAdjEnergyMaxForScatProjToProj(
G4double primAdjEnergy) override;
G4double GetSecondAdjEnergyMinForProdToProj(G4double primAdjEnergy) override;
G4double AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool isScatProjToProj) override;
inline void SetDirectProcess(G4VEmProcess* aProcess)
{
fDirectProcess = aProcess;
};
G4AdjointComptonModel(G4AdjointComptonModel&) = delete;
G4AdjointComptonModel& operator=(const G4AdjointComptonModel& right) = delete;
private:
G4VEmProcess* fDirectProcess = nullptr;
G4double fDirectCS = 0.;
};
#endif
@@ -23,109 +23,89 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4AdjointForcedInteractionForGamma
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
// Class: G4AdjointForcedInteractionForGamma
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
// Class for the forced interaction of reverse gamma
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 12 September 2016 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Class for the forced interaction of reverse gamma
//
#ifndef G4AdjointForcedInteractionForGamma_h
#define G4AdjointForcedInteractionForGamma_h 1
#include "globals.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4ElementVector.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "G4VContinuousDiscreteProcess.hh"
#include"G4PhysicsOrderedFreeVector.hh"
class G4PhysicsTable;
class G4Region;
class G4VParticleChange;
class G4ParticleChange;
class G4ParticleDefinition;
class G4Track;
class G4VEmAdjointModel;
class G4AdjointCSMatrix;
class G4AdjointCSManager;
class G4Material;
class G4MaterialCutsCouple;
class G4Navigator;
class G4AdjointForcedInteractionForGamma : public G4VContinuousDiscreteProcess
{
public:
explicit G4AdjointForcedInteractionForGamma(G4String process_name);
public:
~G4AdjointForcedInteractionForGamma() override;
G4AdjointForcedInteractionForGamma(G4String process_name);
void BuildPhysicsTable(const G4ParticleDefinition&) override;
virtual ~G4AdjointForcedInteractionForGamma();
public:
void PreparePhysicsTable(const G4ParticleDefinition&);
void BuildPhysicsTable(const G4ParticleDefinition&);
virtual G4double PostStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition);
virtual G4VParticleChange* PostStepDoIt(const G4Track&, const G4Step&);
virtual G4VParticleChange* AlongStepDoIt(const G4Track& track,const G4Step& step);
inline void RegisterAdjointComptonModel(G4VEmAdjointModel* aAdjointComptonModel){theAdjointComptonModel = aAdjointComptonModel;}
inline void RegisterAdjointBremModel(G4VEmAdjointModel* aAdjointBremModel){theAdjointBremModel = aAdjointBremModel;}
protected :// with description
G4double PostStepGetPhysicalInteractionLength(
const G4Track& track, G4double previousStepSize,
G4ForceCondition* condition) override;
virtual G4double GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition);
virtual G4double GetContinuousStepLimit(const G4Track& aTrack,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety
);
G4VParticleChange* PostStepDoIt(const G4Track&, const G4Step&) override;
private:
G4VEmAdjointModel* theAdjointComptonModel;
G4VEmAdjointModel* theAdjointBremModel;
G4VParticleChange* AlongStepDoIt(const G4Track& track,
const G4Step& step) override;
G4ParticleChange* fParticleChange;
G4AdjointCSManager* theAdjointCSManager;
private:
G4double lastAdjCS,lastFwdCS;
inline void RegisterAdjointComptonModel(G4VEmAdjointModel* adjModel)
{
fAdjointComptonModel = adjModel;
}
G4int trackid;
G4int nstep;
G4bool is_free_flight_gamma;
G4bool copy_gamma_for_forced_interaction;
G4int last_free_flight_trackid;
inline void RegisterAdjointBremModel(G4VEmAdjointModel* adjModel)
{
fAdjointBremModel = adjModel;
}
G4double acc_track_length;
G4double total_acc_nb_adj_interaction_length;
G4double total_acc_nb_fwd_interaction_length;
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
G4AdjointForcedInteractionForGamma(G4AdjointForcedInteractionForGamma&) =
delete;
G4AdjointForcedInteractionForGamma& operator=(
const G4AdjointForcedInteractionForGamma& right) = delete;
G4double acc_nb_adj_interaction_length;
G4double acc_nb_fwd_interaction_length;
G4bool continue_gamma_as_new_free_flight;
};
protected:
G4double GetMeanFreePath(const G4Track& track, G4double previousStepSize,
G4ForceCondition* condition) override;
G4double GetContinuousStepLimit(const G4Track& aTrack,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety) override;
private:
G4VEmAdjointModel* fAdjointComptonModel;
G4VEmAdjointModel* fAdjointBremModel;
G4ParticleChange* fParticleChange;
G4AdjointCSManager* fCSManager;
G4double fLastAdjCS = 0.;
G4double fAccTrackLength = 0.;
G4double fTotNbAdjIntLength = 0.;
G4double fNbAdjIntLength = 0.;
G4bool fContinueGammaAsNewFreeFlight = false;
G4bool fFreeFlightGamma = false;
G4bool fCopyGammaForForced = false;
};
#endif
@@ -23,77 +23,67 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointInterpolator
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4AdjointInterpolator
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 1st April 2007 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Used by G4AdjointCSManager for interpolation purpose.
//
// Used by G4AdjointCSManager for interpolation purpose.
////////////////////////////////////////////////////////////////////////////////
#ifndef G4AdjointInterpolator_h
#define G4AdjointInterpolator_h 1
#include"globals.hh"
#include<vector>
#include "globals.hh"
#include <vector>
////////////////////////////////////////////////////////////////////////////////
//
class G4AdjointInterpolator
{
public:
static G4AdjointInterpolator* GetAdjointInterpolator();
static G4AdjointInterpolator* GetInstance();
public:
////////////////////////////////
// Constructors and Destructor
////////////////////////////////
~G4AdjointInterpolator();
public:
static G4AdjointInterpolator* GetAdjointInterpolator();
static G4AdjointInterpolator* GetInstance();
////////////
// Methods
////////////
//Caution everywher it is considere thta x_vec increase monotically
G4double LinearInterpolation(G4double& x,G4double& x1,G4double& x2,G4double& y1,G4double& y2);
G4double LogarithmicInterpolation(G4double& x,G4double& x1,G4double& x2,G4double& y1,G4double& y2);
G4double ExponentialInterpolation(G4double& x,G4double& x1,G4double& x2,G4double& y1,G4double& y2);
G4double Interpolation(G4double& x,G4double& x1,G4double& x2,G4double& y1,G4double &y2,G4String InterPolMethod="Log");
size_t FindPosition(G4double& x,std::vector<G4double>& x_vec,size_t ind_min=0, size_t ind_max=0);
size_t FindPositionForLogVector(G4double& x,std::vector<G4double>& x_vec);
G4double Interpolate(G4double& x,std::vector<G4double>& x_vec,std::vector<G4double>& y_vec,G4String InterPolMethod="Log"); //xvec should monotically increase
G4double InterpolateWithIndexVector(G4double& x,std::vector<G4double>& x_vec,std::vector<G4double>& y_vec,
std::vector<size_t>& index_vec, G4double x0,G4double dx); //xvec should monotically increase
G4double InterpolateForLogVector(G4double& x,std::vector<G4double>& x_vec,std::vector<G4double>& y_vec);
private:
static G4ThreadLocal G4AdjointInterpolator* theInstance;
private:
G4AdjointInterpolator();
~G4AdjointInterpolator();
// Caution: everywhere it is considered that x_vec increases monotically
G4double LinearInterpolation(G4double& x, G4double& x1, G4double& x2,
G4double& y1, G4double& y2);
G4double LogarithmicInterpolation(G4double& x, G4double& x1, G4double& x2,
G4double& y1, G4double& y2);
G4double ExponentialInterpolation(G4double& x, G4double& x1, G4double& x2,
G4double& y1, G4double& y2);
G4double Interpolation(G4double& x, G4double& x1, G4double& x2, G4double& y1,
G4double& y2, G4String InterPolMethod = "Log");
size_t FindPosition(G4double& x, std::vector<G4double>& x_vec,
size_t ind_min = 0, size_t ind_max = 0);
size_t FindPositionForLogVector(G4double& x, std::vector<G4double>& x_vec);
// xvec should monotically increase
G4double Interpolate(G4double& x, std::vector<G4double>& x_vec,
std::vector<G4double>& y_vec,
G4String InterPolMethod = "Log");
G4double InterpolateWithIndexVector(
G4double& x, std::vector<G4double>& x_vec, std::vector<G4double>& y_vec,
std::vector<size_t>& index_vec, G4double x0,
G4double dx); // xvec should monotically increase
G4double InterpolateForLogVector(G4double& x, std::vector<G4double>& x_vec,
std::vector<G4double>& y_vec);
G4AdjointInterpolator(G4AdjointInterpolator&) = delete;
G4AdjointInterpolator& operator=(const G4AdjointInterpolator& right) = delete;
private:
G4AdjointInterpolator();
static G4ThreadLocal G4AdjointInterpolator* fInstance;
};
#endif
@@ -23,124 +23,82 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4IonIonisationModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
// Class: G4IonIonisationModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
// Adjoint EM model for discrete reverse ion ionisation
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 26th August 2009 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Adjoint EM model for discrete reverse ion ionisation
//
#ifndef G4AdjointIonIonisationModel_h
#define G4AdjointIonIonisationModel_h 1
#include "globals.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4ElementVector.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4Electron.hh"
#include "G4Gamma.hh"
#include "G4ProductionCutsTable.hh"
#include "G4VEmAdjointModel.hh"
class G4PhysicsTable;
class G4Region;
class G4VParticleChange;
class G4ParticleChange;
class G4Track;
class G4AdjointCSMatrix;
class G4ParticleChange;
class G4ParticleDefinition;
class G4VEmModel;
class G4VParticleChange;
class G4AdjointIonIonisationModel: public G4VEmAdjointModel
class G4AdjointIonIonisationModel : public G4VEmAdjointModel
{
public:
public:
G4AdjointIonIonisationModel();
virtual ~G4AdjointIonIonisationModel();
virtual void SampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange);
~G4AdjointIonIonisationModel() override;
void SampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange) override;
G4double DiffCrossSectionPerAtomPrimToSecond(
G4double kinEnergyProj, // kin energy of primary before interaction
G4double kinEnergyProd, // kinetic energy of the secondary particle
G4double Z, G4double A = 0.) override;
void CorrectPostStepWeight(G4ParticleChange* fParticleChange,
G4double old_weight, G4double adjointPrimKinEnergy,
G4double projectileKinEnergy,
G4bool isScatProjToProj) override;
G4double GetSecondAdjEnergyMaxForScatProjToProj(
G4double primAdjEnergy) override;
G4double GetSecondAdjEnergyMinForScatProjToProj(G4double primAdjEnergy,
G4double tcut = 0.) override;
G4double GetSecondAdjEnergyMaxForProdToProj(G4double primAdjEnergy) override;
G4double GetSecondAdjEnergyMinForProdToProj(G4double primAdjEnergy) override;
inline void SetUseOnlyBragg(G4bool aBool) { fUseOnlyBragg = aBool; }
virtual G4double DiffCrossSectionPerAtomPrimToSecond(
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyProd, // kinetic energy of the secondary particle
G4double Z,
G4double A = 0.);
virtual void CorrectPostStepWeight(G4ParticleChange* fParticleChange,
G4double old_weight,
G4double adjointPrimKinEnergy,
G4double projectileKinEnergy,
G4bool IsScatProjToProjCase);
//Set/Get methods
//------------------
virtual G4double GetSecondAdjEnergyMaxForScatProjToProjCase(G4double PrimAdjEnergy);
virtual G4double GetSecondAdjEnergyMinForScatProjToProjCase(G4double PrimAdjEnergy,G4double Tcut=0);
virtual G4double GetSecondAdjEnergyMaxForProdToProjCase(G4double PrimAdjEnergy);
virtual G4double GetSecondAdjEnergyMinForProdToProjCase(G4double PrimAdjEnergy);
inline void SetUseOnlyBragg(G4bool aBool){use_only_bragg =aBool;}
void SetIon(G4ParticleDefinition* adj_ion, G4ParticleDefinition* fwd_ion);
private: //Methods
G4AdjointIonIonisationModel(G4AdjointIonIonisationModel&) = delete;
G4AdjointIonIonisationModel& operator=(
const G4AdjointIonIonisationModel& right) = delete;
private:
void DefineProjectileProperty();
//projectile property
G4double mass;
G4double tlimit;
G4double spin;
G4double magMoment2;
G4double chargeSquare;
G4double massRatio;
G4double ratio, ratio2;
G4double one_plus_ratio_2;
G4double formfact;
G4bool isIon;
G4double one_minus_ratio_2;
G4bool use_only_bragg;
G4VEmModel* theBraggIonDirectEMModel;
G4VEmModel* theBetheBlochDirectEMModel;
G4VEmModel* fBraggIonDirectEMModel;
G4VEmModel* fBetheBlochDirectEMModel;
// projectile properties
G4double fMass = 0.;
G4double fSpin = 0.;
G4double fMagMoment2 = 0.;
G4double fChargeSquare = 0.;
G4double fMassRatio = 0.;
G4double fRatio = 0.;
G4double fOnePlusRatio2 = 0.;
G4double fOneMinusRatio2 = 0.;
G4double fFormFact = 0.;
G4bool fUseOnlyBragg = false;
};
#endif
@@ -23,96 +23,72 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointPhotoElectricModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4AdjointPhotoElectricModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// -1 September 2007 creation by L. Desorgher
//
// -January 2009. L. Desorgher
// Put a higher limit on the CS to avoid a high rate of Inverse Photo e- effect at low energy. The very high adjoint CS of the reverse
// photo electric reaction produce a high rate of reverse photo electric reaction in the inner side of a shielding for eaxmple, the correction of this occurrence
// by weight correction in the StepDoIt method is not statistically sufficient at small energy. The problem is partially solved by setting an higher CS limit
// and compensating it by an extra weight correction factor. However when coupling it with other reverse processes the reverse photo-electric is still
// the source of very occasional high weight that decrease the efficiency of the computation. A way to solve this problemn is still needed but is difficult
// to find as it happens in rarea case but does give a weighrt that is outside the noemal distribution. (Very Tricky!)
//
// -October 2009 Correction of Element sampling. L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Model for the adjoint photo electric process
// Model for the adjoint photo electric process.
// Put a higher limit on the CS to avoid a high rate of Inverse Photo e-effect
// at low energy. The very high adjoint CS of the reverse photo electric
// reaction produce a high rate of reverse photo electric reaction in the inner
// side of a shielding for eaxmple, the correction of this occurrence by weight
// correction in the StepDoIt method is not statistically sufficient at small
// energy. The problem is partially solved by setting a higher CS limit and
// compensating it by an extra weight correction factor. However when coupling
// it with other reverse processes the reverse photo-electric is still the
// source of very occasional high weights that decrease the efficiency of the
// computation. A way to solve this problemn is still needed but is difficult
// to find as it happens in rare cases but does give a weight that is outside
// the normal distribution. (Very Tricky!)
//
////////////////////////////////////////////////////////////////////////////////
#ifndef G4AdjointPhotoElectricModel_h
#define G4AdjointPhotoElectricModel_h 1
#include "globals.hh"
#include "G4VEmAdjointModel.hh"
#include "G4PEEffectFluoModel.hh"
class G4AdjointPhotoElectricModel: public G4VEmAdjointModel
class G4AdjointPhotoElectricModel : public G4VEmAdjointModel
{
public:
public:
G4AdjointPhotoElectricModel();
~G4AdjointPhotoElectricModel();
virtual void SampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange);
virtual G4double AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool IsScatProjToProjCase);
virtual G4double GetAdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool IsScatProjToProjCase);
G4double AdjointCrossSectionPerAtom(const G4Element* anElement,G4double electronEnergy);
inline void SetTheDirectPEEffectModel(G4PEEffectFluoModel* aModel){theDirectPEEffectModel = aModel;
DefineDirectEMModel(aModel);}
virtual void CorrectPostStepWeight(G4ParticleChange* fParticleChange,
G4double old_weight,
G4double adjointPrimKinEnergy,
G4double projectileKinEnergy,
G4bool IsScatProjToProjCase);
private:
G4double xsec[40];
G4double totAdjointCS;
G4double totBiasedAdjointCS;
G4double factorCSBiasing;
G4double pre_step_AdjointCS;
G4double post_step_AdjointCS;
G4double shell_prob[40][40];
G4PEEffectFluoModel* theDirectPEEffectModel;
size_t index_element;
G4double current_eEnergy;
private:
void DefineCurrentMaterialAndElectronEnergy(const G4MaterialCutsCouple* aCouple,
G4double eEnergy);
~G4AdjointPhotoElectricModel() override;
void SampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange) override;
G4double AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool isScatProjToProj) override;
G4double AdjointCrossSectionPerAtom(const G4Element* anElement,
G4double electronEnergy);
G4AdjointPhotoElectricModel(G4AdjointPhotoElectricModel&) = delete;
G4AdjointPhotoElectricModel& operator=(
const G4AdjointPhotoElectricModel& right) = delete;
protected:
void CorrectPostStepWeight(G4ParticleChange* fParticleChange,
G4double old_weight, G4double adjointPrimKinEnergy,
G4double projectileKinEnergy,
G4bool isScatProjToProj) override;
private:
void DefineCurrentMaterialAndElectronEnergy(
const G4MaterialCutsCouple* aCouple, G4double eEnergy);
G4double fShellProb[40][40];
G4double fXsec[40];
G4double fTotAdjointCS = 0.;
G4double fFactorCSBiasing = 1.;
G4double fPreStepAdjointCS = 0.;
G4double fPostStepAdjointCS = 0.;
G4double fCurrenteEnergy = 0.;
size_t fIndexElement = 0;
};
#endif
@@ -23,149 +23,77 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointProcessEquivalentToDirectProcess
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
// Class: G4AdjointProcessEquivalentToDirectProcess
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
// Adjoint process equivalent to direct process, used for some multiple
// scattering.
// A virtual class for wrapper process objects.
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 25 Sept. 2009 Created by L.Desorgher. Inspired from G4WrapperProcess
//
//-------------------------------------------------------------
// Documentation:
// Adjoint process equivalent to direct process, used for some multiple scattering
//
//
#ifndef G4AdjointProcessEquivalentToDirectProcess_h
#ifndef G4AdjointProcessEquivalentToDirectProcess_h
#define G4AdjointProcessEquivalentToDirectProcess_h 1
#include "globals.hh"
#include "G4ios.hh"
#include "G4VProcess.hh"
class G4AdjointProcessEquivalentToDirectProcess : public G4VProcess
{
// A virtual class for wrapper process objects.
public:
explicit G4AdjointProcessEquivalentToDirectProcess(
const G4String& aName, G4VProcess* aProcess,
G4ParticleDefinition* fwd_particle_def);
public: // with description
// constructor requires the process name and type
G4AdjointProcessEquivalentToDirectProcess(const G4String& aName, G4VProcess* aProcess,G4ParticleDefinition* fwd_particle_def);
~G4AdjointProcessEquivalentToDirectProcess() override;
G4VParticleChange* PostStepDoIt(const G4Track& track,
const G4Step& stepData) override;
public:
// destructor
virtual ~G4AdjointProcessEquivalentToDirectProcess();
G4VParticleChange* AlongStepDoIt(const G4Track& track,
const G4Step& stepData) override;
G4VParticleChange* AtRestDoIt(const G4Track& track,
const G4Step& stepData) override;
public: // with description
////////////////////////////
// DoIt /////////////////
///////////////////////////
virtual G4VParticleChange* PostStepDoIt(
const G4Track& track,
const G4Step& stepData
);
G4double AlongStepGetPhysicalInteractionLength(
const G4Track& track, G4double previousStepSize,
G4double currentMinimumStep, G4double& proposedSafety,
G4GPILSelection* selection) override;
virtual G4VParticleChange* AlongStepDoIt(
const G4Track& track,
const G4Step& stepData
);
virtual G4VParticleChange* AtRestDoIt(
const G4Track& track,
const G4Step& stepData
);
//////////////////////////
// GPIL //////////////
/////////////////////////
virtual G4double AlongStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& proposedSafety,
G4GPILSelection* selection);
G4double AtRestGetPhysicalInteractionLength(
const G4Track& track, G4ForceCondition* condition) override;
virtual G4double AtRestGetPhysicalInteractionLength(
const G4Track& track,
G4ForceCondition* condition
);
G4double PostStepGetPhysicalInteractionLength(
const G4Track& track, G4double previousStepSize,
G4ForceCondition* condition) override;
virtual G4double PostStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition
) ;
//////////////////////
virtual G4bool IsApplicable(const G4ParticleDefinition&);
// Returns true if this process object is applicable to
// the particle type
// Process will not be registered to a particle if IsApplicable is false
G4bool IsApplicable(const G4ParticleDefinition&) override;
virtual void BuildPhysicsTable(const G4ParticleDefinition&);
// Messaged by the Particle definition (via the Process manager)
// whenever cross section tables have to be rebuilt (i.e. if new
// materials have been defined).
// It is overloaded by individual processes when they need physics
// tables.
void BuildPhysicsTable(const G4ParticleDefinition&) override;
// Processes which Build (for example in their
// constructors) physics tables independent of cuts
// should preferably use a
// private void BuildThePhysicsTable()
// function. Not another BuildPhysicsTable, please.
virtual void PreparePhysicsTable(const G4ParticleDefinition&);
// Messaged by the Particle definition (via the Process manager)
// whenever cross section tables have to be prepare for rebuilt
// (i.e. if new materials have been defined).
// It is overloaded by individual processes when they need physics
// tables.
void PreparePhysicsTable(const G4ParticleDefinition&) override;
// Processes which Build physics tables independent of cuts
// (for example in their constructors)
// should preferably use private
// void BuildThePhysicsTable() and void PreparePhysicsTable().
// Not another BuildPhysicsTable, please.
G4bool StorePhysicsTable(const G4ParticleDefinition*,
const G4String& directory,
G4bool ascii = false) override;
G4bool RetrievePhysicsTable(const G4ParticleDefinition*,
const G4String& directory,
G4bool ascii = false) override;
virtual G4bool StorePhysicsTable(const G4ParticleDefinition* ,
const G4String& directory,
G4bool ascii = false);
// Store PhysicsTable in a file.
// (return false in case of failure at I/O )
virtual G4bool RetrievePhysicsTable( const G4ParticleDefinition* ,
const G4String& directory,
G4bool ascii = false);
// Retrieve Physics from a file.
// (return true if the Physics Table can be build by using file)
// (return false if the process has no functionality or in case of failure)
// File name should be defined by each process
// and the file should be placed under the directory specified by the argument.
////////////////////////////
virtual void StartTracking(G4Track*);
virtual void EndTracking();
// inform Start/End of tracking for each track to the physics process
public:
virtual void ResetNumberOfInteractionLengthLeft();
// reset (determine the value of)NumberOfInteractionLengthLeft
private:
G4ParticleDefinition* theFwdParticleDef;
G4VProcess* theDirectProcess;
void StartTracking(G4Track*) override;
void EndTracking() override;
void ResetNumberOfInteractionLengthLeft() override;
G4AdjointProcessEquivalentToDirectProcess(G4AdjointProcessEquivalentToDirectProcess&) =
delete;
G4AdjointProcessEquivalentToDirectProcess& operator=(
const G4AdjointProcessEquivalentToDirectProcess& right) = delete;
private:
G4ParticleDefinition* fFwdParticleDef;
G4VProcess* fDirectProcess;
};
#endif
@@ -23,24 +23,14 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointeIonisationModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
// Adjoint EM model for discrete reverse e- ionisation
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4AdjointeIonisationModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// September 2009 creation by L. Desorgher. Separate the concrete ionisation stuff from G4VEMAdjointModel
//
//-------------------------------------------------------------
// Documentation:
// Adjoint EM model for discrete reverse e- ionisation
//
#ifndef G4AdjointeIonisationModel_h
#define G4AdjointeIonisationModel_h 1
@@ -48,35 +38,29 @@
#include "globals.hh"
#include "G4VEmAdjointModel.hh"
class G4AdjointeIonisationModel: public G4VEmAdjointModel
class G4AdjointeIonisationModel : public G4VEmAdjointModel
{
public: //methods
//Constructor, destructor
public:
G4AdjointeIonisationModel();
virtual ~G4AdjointeIonisationModel();
~G4AdjointeIonisationModel() override;
//Concrete implementation or virtual methods
virtual void SampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange);
virtual G4double DiffCrossSectionPerAtomPrimToSecond(
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyProd, // kinetic energy of the secondary particle
G4double Z,
G4double A = 0.);
void SampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange) override;
private:
G4double DiffCrossSectionMoller(G4double kinEnergyProj,G4double kinEnergyProd);
private: //attributes
G4bool WithRapidSampling;
G4double DiffCrossSectionPerAtomPrimToSecond(
G4double kinEnergyProj, // kin energy of particle before interaction
G4double kinEnergyProd, // kinetic energy of the secondary particle
G4double Z, G4double A = 0.) override;
G4AdjointeIonisationModel(G4AdjointeIonisationModel&) = delete;
G4AdjointeIonisationModel& operator=(const G4AdjointeIonisationModel& right) =
delete;
private:
G4double DiffCrossSectionMoller(G4double kinEnergyProj,
G4double kinEnergyProd);
G4bool fWithRapidSampling = false;
};
#endif
@@ -23,115 +23,76 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointhIonisationModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4AdjointhIonisationModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 13th February 2009 creation by L. Desorgher
// 10 November 2009 Implementation of the rapid sampling.
//
//-------------------------------------------------------------
// Documentation:
// Adjoint EM model for discrete reverse hadron ionisation. Tested at the moment only for protons.
//
// Adjoint EM model for discrete reverse hadron ionisation.
// Tested only for protons.
////////////////////////////////////////////////////////////////////////////////
#ifndef G4AdjointhIonisationModel_h
#define G4AdjointhIonisationModel_h 1
#include "globals.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4ElementVector.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4Electron.hh"
#include "G4Gamma.hh"
#include "G4ProductionCutsTable.hh"
#include "G4VEmAdjointModel.hh"
class G4PhysicsTable;
class G4Region;
class G4VParticleChange;
class G4MaterialCutsCouple;
class G4ParticleChange;
class G4ParticleDefinition;
class G4Track;
class G4AdjointCSMatrix;
class G4VEmModel;
class G4AdjointhIonisationModel: public G4VEmAdjointModel
class G4AdjointhIonisationModel : public G4VEmAdjointModel
{
public:
explicit G4AdjointhIonisationModel(G4ParticleDefinition* pDef);
public:
~G4AdjointhIonisationModel() override;
G4AdjointhIonisationModel(G4ParticleDefinition* projectileDefinition);
void SampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange) override;
virtual ~G4AdjointhIonisationModel();
void RapidSampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange);
virtual void SampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange);
void RapidSampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange);
virtual G4double DiffCrossSectionPerAtomPrimToSecond(
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyProd, // kinetic energy of the secondary particle
G4double Z,
G4double A = 0.);
virtual G4double AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool IsScatProjToProjCase);
//Set/Get methods
//------------------
virtual G4double GetSecondAdjEnergyMaxForScatProjToProjCase(G4double PrimAdjEnergy);
virtual G4double GetSecondAdjEnergyMinForScatProjToProjCase(G4double PrimAdjEnergy,G4double Tcut=0);
virtual G4double GetSecondAdjEnergyMaxForProdToProjCase(G4double PrimAdjEnergy);
virtual G4double GetSecondAdjEnergyMinForProdToProjCase(G4double PrimAdjEnergy);
G4double DiffCrossSectionPerAtomPrimToSecond(
G4double kinEnergyProj, // kin energy of primary before interaction
G4double kinEnergyProd, // kinetic energy of the secondary particle
G4double Z, G4double A = 0.) override;
private: //Methods
G4double AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool isScatProjToProj) override;
G4double GetSecondAdjEnergyMaxForScatProjToProj(
G4double primAdjEnergy) override;
G4double GetSecondAdjEnergyMinForScatProjToProj(G4double primAdjEnergy,
G4double tcut = 0.) override;
G4double GetSecondAdjEnergyMaxForProdToProj(G4double primAdjEnergy) override;
G4double GetSecondAdjEnergyMinForProdToProj(G4double primAdjEnergy) override;
G4AdjointhIonisationModel(G4AdjointhIonisationModel&) = delete;
G4AdjointhIonisationModel& operator=(const G4AdjointhIonisationModel& right) =
delete;
private:
void DefineProjectileProperty();
//projectile property
G4double mass;
G4double tlimit;
G4double spin;
G4double magMoment2;
G4double chargeSquare;
G4double ratio, ratio2;
G4double one_plus_ratio_2;
G4double formfact;
G4bool isIon;
G4double one_minus_ratio_2;
G4VEmModel* theBraggDirectEMModel;
//G4double term_Cross1, term_Cross2;
G4VEmModel* fBraggDirectEMModel;
// projectile properties
G4double fMass = 0.;
G4double fSpin = 0.;
G4double fMagMoment2 = 0.;
G4double fMassRatio = 0.;
G4double fFormFact = 0.;
G4double fOnePlusRatio2 = 0.;
G4double fOneMinusRatio2 = 0.;
};
#endif
@@ -23,78 +23,48 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointhMultipleScattering
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4AdjointhMultipleScattering
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// GEANT4 Class header file
//
// File name: G4AdjointhMultipleScattering
//
// Author: Desorgher Laurent
//
// Creation date: 03.06.2009 cloned from G4hMultipleScattering by U.Laszlo with slight modification for adjoint_ion.
//
//
//------------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 03.06.2009 Creation by L. Desorgher. Cloned from G4hMultipleScattering by U.Laszlo with slight modifications.
// 09.11.2009 Remove AlongStepGetPhysicalInteractionLength, to call the one of the base class.
//-------------------------------------------------------------
// Documentation:
// The class simulates the multiple scattering for adjoint proton of charged particle. In this approximate implementation the reverse multiple scattering
// is the same than the foward one. This should be changed in the future to have the MultipleScaterring computed for the energy at the end of the step
// and not before the step.
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// The class simulates the multiple scattering for adjoint proton of charged
// particle. In this approximate implementation the reverse multiple scattering
// is the same as the forward one. This should be changed in the future to
// have the MultipleScattering computed for the energy at the end of the step
// and not before the step.
////////////////////////////////////////////////////////////////////////////////
#ifndef G4AdjointhMultipleScattering_h
#define G4AdjointhMultipleScattering_h 1
#include "G4VMultipleScattering.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class G4VMscModel;
class G4AdjointhMultipleScattering : public G4VMultipleScattering
{
public: // with description
public:
explicit G4AdjointhMultipleScattering(const G4String& processName = "msc");
G4AdjointhMultipleScattering(const G4String& processName="msc");
virtual ~G4AdjointhMultipleScattering();
~G4AdjointhMultipleScattering() override;
// returns true for charged particles, false otherwise
G4bool IsApplicable (const G4ParticleDefinition& p);
G4bool IsApplicable(const G4ParticleDefinition& p) override;
// PrG4int few lines of informations about the process: validity range,
void PrintInfo();
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
void StreamProcessInfo(std::ostream& out) const override;
protected:
G4AdjointhMultipleScattering(G4AdjointhMultipleScattering&) = delete;
G4AdjointhMultipleScattering& operator=(
const G4AdjointhMultipleScattering& right) = delete;
// This function initialise models
void InitialiseProcess(const G4ParticleDefinition*);
protected:
void InitialiseProcess(const G4ParticleDefinition*) override;
private: // data members
G4bool isInitialized;
private:
G4bool fIsInitialized = false;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif
@@ -23,167 +23,99 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4ContinuousGainOfEnergy
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Class: G4ContinuousGainOfEnergy
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// -10 May 2007 creation by L. Desorgher
// -February-March 2009 Update for protons by L.Desorgher
// -July August 2009 Update for ion by L.Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Continuous process acting on adjoint particles to compute the continuous gain of energy of charged particles when they are tracked back!
//
//
// Continuous process acting on adjoint particles to compute the continuous
// gain of energy of charged particles when they are tracked back.
////////////////////////////////////////////////////////////////////////////////
#ifndef G4ContinuousGainOfEnergy_h
#define G4ContinuousGainOfEnergy_h 1
#include "G4VContinuousProcess.hh"
#include "globals.hh"
#include "G4Material.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Track.hh"
#include "G4UnitsTable.hh"
#include "G4ParticleChange.hh"
#include "G4VEnergyLossProcess.hh"
#include "G4ProductionCutsTable.hh"
#include "G4VContinuousProcess.hh"
class G4Step;
class G4Material;
class G4MaterialCutsCouple;
class G4ParticleChange;
class G4ParticleDefinition;
class G4Step;
class G4Track;
class G4VEmModel;
class G4VEmFluctuationModel;
class G4VEnergyLossProcess;
class G4ContinuousGainOfEnergy : public G4VContinuousProcess
{
public:
public:
explicit G4ContinuousGainOfEnergy(const G4String& name = "EnergyGain",
G4ProcessType type = fElectromagnetic);
G4ContinuousGainOfEnergy(const G4String& name = "EnergyGain",
G4ProcessType type = fElectromagnetic);
virtual ~G4ContinuousGainOfEnergy();
protected:
//------------------------------------------------------------------------
// Methods with standard implementation; may be overwritten if needed
//------------------------------------------------------------------------
protected:
virtual G4double GetContinuousStepLimit(const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety);
//------------------------------------------------------------------------
// Generic methods common to all processes
//------------------------------------------------------------------------
public:
void PreparePhysicsTable(const G4ParticleDefinition&);
void BuildPhysicsTable(const G4ParticleDefinition&);
G4VParticleChange* AlongStepDoIt(const G4Track&, const G4Step&);
~G4ContinuousGainOfEnergy() override;
G4VParticleChange* AlongStepDoIt(const G4Track&, const G4Step&) override;
void SetLossFluctuations(G4bool val);
inline void SetIsIntegral(G4bool val){is_integral= val;}
inline void SetDirectEnergyLossProcess(G4VEnergyLossProcess* aProcess){theDirectEnergyLossProcess=aProcess;};
inline void SetDirectEnergyLossProcess(G4VEnergyLossProcess* aProcess)
{
fDirectEnergyLossProcess = aProcess;
};
void SetDirectParticle(G4ParticleDefinition* p);
protected:
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
G4ContinuousGainOfEnergy(G4ContinuousGainOfEnergy&) = delete;
G4ContinuousGainOfEnergy& operator=(const G4ContinuousGainOfEnergy& right) =
delete;
private:
protected:
G4double GetContinuousStepLimit(const G4Track& track,
G4double previousStepSize,
G4double currentMinimumStep,
G4double& currentSafety) override;
private:
void DefineMaterial(const G4MaterialCutsCouple* couple);
void SetDynamicMassCharge(const G4Track& track, G4double energy);
// hide assignment operator
G4ContinuousGainOfEnergy(G4ContinuousGainOfEnergy &);
G4ContinuousGainOfEnergy & operator=(const G4ContinuousGainOfEnergy &right);
const G4Material* fCurrentMaterial = nullptr;
const G4MaterialCutsCouple* fCurrentCouple = nullptr;
private:
const G4Material* currentMaterial;
const G4MaterialCutsCouple* currentCouple;
size_t currentMaterialIndex;
size_t currentCoupleIndex;
G4double currentTcut;
G4double currentCutInRange;
G4double preStepKinEnergy;
G4double linLossLimit;
G4bool lossFluctuationFlag;
G4bool lossFluctuationArePossible;
G4VEnergyLossProcess* theDirectEnergyLossProcess;
G4ParticleDefinition* theDirectPartDef;
G4bool is_integral;
//adding for Ions
//----------------
G4bool IsIon;
G4double massRatio;
G4double chargeSqRatio;
G4VEmModel* currentModel;
G4double preStepChargeSqRatio;
G4double preStepScaledKinEnergy;
G4double preStepRange;
G4VEmModel* fCurrentModel = nullptr;
G4VEnergyLossProcess* fDirectEnergyLossProcess = nullptr;
G4ParticleDefinition* fDirectPartDef = nullptr;
G4double fCurrentTcut = 0.;
G4double fPreStepKinEnergy = 1.;
G4double fLinLossLimit = 0.05;
G4double fMassRatio = 1.;
size_t fCurrentCoupleIndex = 9999999;
G4bool fIsIon = false;
G4bool fLossFluctuationFlag = true;
G4bool fLossFluctuationArePossible = true;
};
///////////////////////////////////////////////////////
//
inline void G4ContinuousGainOfEnergy::DefineMaterial(
const G4MaterialCutsCouple* couple)
const G4MaterialCutsCouple* couple)
{
if(couple != currentCouple) {
currentCouple = couple;
currentMaterial = couple->GetMaterial();
currentCoupleIndex = couple->GetIndex();
currentMaterialIndex = currentMaterial->GetIndex();
size_t idx=1;
const std::vector<G4double>* aVec = G4ProductionCutsTable::GetProductionCutsTable()->GetEnergyCutsVector(idx);
currentTcut=(*aVec)[currentCoupleIndex];
currentCutInRange = couple->GetProductionCuts()->GetProductionCut(theDirectPartDef->GetParticleName());
//G4cout<<"Define Material"<<G4endl;
//if(!meanFreePath) ResetNumberOfInteractionLengthLeft();
if(couple != fCurrentCouple)
{
fCurrentCouple = couple;
fCurrentMaterial = couple->GetMaterial();
fCurrentCoupleIndex = couple->GetIndex();
const std::vector<G4double>* aVec =
G4ProductionCutsTable::GetProductionCutsTable()->GetEnergyCutsVector(1);
fCurrentTcut = (*aVec)[fCurrentCoupleIndex];
}
}
@@ -23,41 +23,34 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4InversePEEffect
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4InversePEEffect.hh
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 25 October 2007 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Adjoint/reverse photo electric process
//
// Adjoint/reverse photo electric process
////////////////////////////////////////////////////////////////////////////////
#ifndef G4InversePEEffect_h
#define G4InversePEEffect_h 1
#include "G4VAdjointReverseReaction.hh"
#include "globals.hh"
#include "G4VAdjointReverseReaction.hh"
class G4AdjointPhotoElectricModel;
class G4InversePEEffect: public G4VAdjointReverseReaction
class G4InversePEEffect : public G4VAdjointReverseReaction
{
public:
public:
explicit G4InversePEEffect(G4String process_name,
G4AdjointPhotoElectricModel* aModel);
~G4InversePEEffect() override;
G4InversePEEffect(G4String process_name, G4AdjointPhotoElectricModel* aModel);
~G4InversePEEffect();
private:
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
G4InversePEEffect(G4InversePEEffect&) = delete;
G4InversePEEffect& operator=(const G4InversePEEffect& right) = delete;
};
#endif
@@ -23,42 +23,35 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4IonInverseIonisation
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4IonInverseIonisation
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 25 August 2009 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Adjoint/reverse discrete ionisation for ions
//
// Adjoint/reverse discrete ionisation for ions
////////////////////////////////////////////////////////////////////////////////
#ifndef G4IonInverseIonisation_h
#define G4IonInverseIonisation_h 1
#include "G4VAdjointReverseReaction.hh"
#include "globals.hh"
#include "G4eIonisation.hh"
#include "G4AdjointIonIonisationModel.hh"
class G4IonInverseIonisation: public G4VAdjointReverseReaction
#include "G4VAdjointReverseReaction.hh"
class G4AdjointIonIonisationModel;
class G4IonInverseIonisation : public G4VAdjointReverseReaction
{
public:
public:
explicit G4IonInverseIonisation(G4bool whichScatCase, G4String process_name,
G4AdjointIonIonisationModel* aEmAdjointModel);
~G4IonInverseIonisation() override;
G4IonInverseIonisation(G4bool whichScatCase, G4String process_name, G4AdjointIonIonisationModel* aEmAdjointModel);
~G4IonInverseIonisation();
private:
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
G4IonInverseIonisation(G4IonInverseIonisation&) = delete;
G4IonInverseIonisation& operator=(const G4IonInverseIonisation& right) =
delete;
};
#endif
@@ -23,91 +23,69 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
//
// GEANT4 Class header file
//
//
// File name: G4UrbanAdjointMscModel
//
// Author: Laszlo Urban
//
// Creation date: 19.02.2013
//
// Created from G4UrbanAdjointMscModel96
//
// New parametrization for theta0
// Correction for very small step length
//
// Class Description:
//
// Implementation of the model of multiple scattering based on
// H.W.Lewis Phys Rev 78 (1950) 526 and L.Urban model
// Implementation of the model of multiple scattering based on
// H.W.Lewis Phys Rev 78 (1950) 526 and L.Urban model
// -------------------------------------------------------------------
//
#ifndef G4UrbanAdjointMscModel_h
#define G4UrbanAdjointMscModel_h 1
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include <CLHEP/Units/SystemOfUnits.h>
#include "G4VMscModel.hh"
#include "G4MscStepLimitType.hh"
#include "G4Log.hh"
#include "G4Exp.hh"
#include "G4Electron.hh"
#include "G4Exp.hh"
#include "G4Log.hh"
#include "G4MscStepLimitType.hh"
#include "G4VMscModel.hh"
class G4ParticleChangeForMSC;
class G4SafetyHelper;
class G4LossTableManager;
class G4MaterialCutsCouple;
class G4ParticleChangeForMSC;
class G4ParticleDefinition;
class G4SafetyHelper;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class G4UrbanAdjointMscModel : public G4VMscModel
{
public:
public:
explicit G4UrbanAdjointMscModel(const G4String& nam = "UrbanMsc");
virtual ~G4UrbanAdjointMscModel();
~G4UrbanAdjointMscModel() override;
virtual void Initialise(const G4ParticleDefinition*,
const G4DataVector&) override;
void Initialise(const G4ParticleDefinition*, const G4DataVector&) override;
virtual void StartTracking(G4Track*) override;
void StartTracking(G4Track*) override;
virtual G4double
ComputeCrossSectionPerAtom(const G4ParticleDefinition* particle,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicWeight=0.,
G4double cut =0.,
G4double emax=DBL_MAX) override;
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition* particle,
G4double KineticEnergy,
G4double AtomicNumber,
G4double AtomicWeight = 0.,
G4double cut = 0.,
G4double emax = DBL_MAX) override;
virtual G4ThreeVector& SampleScattering(const G4ThreeVector&,
G4double safety) override;
G4ThreeVector& SampleScattering(const G4ThreeVector&,
G4double safety) override;
virtual G4double
ComputeTruePathLengthLimit(const G4Track& track,
G4double& currentMinimalStep) override;
G4double ComputeTruePathLengthLimit(const G4Track& track,
G4double& currentMinimalStep) override;
virtual G4double ComputeGeomPathLength(G4double truePathLength) override;
G4double ComputeGeomPathLength(G4double truePathLength) override;
virtual G4double ComputeTrueStepLength(G4double geomStepLength) override;
G4double ComputeTrueStepLength(G4double geomStepLength) override;
G4double ComputeTheta0(G4double truePathLength, G4double KineticEnergy);
inline void SetNewDisplacementFlag(G4bool);
private:
G4UrbanAdjointMscModel& operator=(const G4UrbanAdjointMscModel& right) =
delete;
G4UrbanAdjointMscModel(const G4UrbanAdjointMscModel&) = delete;
private:
G4double SampleCosineTheta(G4double trueStepLength, G4double KineticEnergy);
void SampleDisplacement(G4double sinTheta, G4double phi);
@@ -119,25 +97,21 @@ private:
inline void UpdateCache();
inline G4double Randomizetlimit();
inline G4double SimpleScattering(G4double xmeanth, G4double x2meanth);
// hide assignment operator
G4UrbanAdjointMscModel & operator=(const G4UrbanAdjointMscModel &right) = delete;
G4UrbanAdjointMscModel(const G4UrbanAdjointMscModel&) = delete;
CLHEP::HepRandomEngine* rndmEngineMod;
CLHEP::HepRandomEngine* rndmEngineMod;
const G4ParticleDefinition* particle;
const G4ParticleDefinition* positron;
G4ParticleChangeForMSC* fParticleChange;
G4ParticleChangeForMSC* fParticleChange;
const G4MaterialCutsCouple* couple;
G4LossTableManager* theManager;
G4LossTableManager* theManager;
G4double mass;
G4double charge,ChargeSquare;
G4double masslimite,lambdalimit,fr;
G4double charge, ChargeSquare;
G4double masslimite, lambdalimit, fr;
G4double taubig;
G4double tausmall;
@@ -145,7 +119,7 @@ private:
G4double currentTau;
G4double tlimit;
G4double tlimitmin;
G4double tlimitminfix,tlimitminfix2;
G4double tlimitminfix, tlimitminfix2;
G4double tgeom;
G4double geombig;
@@ -160,122 +134,119 @@ private:
G4double lambdaeff;
G4double tPathLength;
G4double zPathLength;
G4double par1,par2,par3;
G4double par1, par2, par3;
G4double stepmin;
G4double currentKinEnergy;
G4double currentRange;
G4double currentRange;
G4double rangeinit;
G4double currentRadLength;
G4int currentMaterialIndex;
G4double Zold;
G4double Zeff,Z2,Z23,lnZ;
G4double coeffth1,coeffth2;
G4double coeffc1,coeffc2,coeffc3,coeffc4;
G4bool firstStep;
G4bool insideskin;
G4bool latDisplasmentbackup ;
G4bool displacementFlag;
G4double Zeff, Z2, Z23, lnZ;
G4double coeffth1, coeffth2;
G4double coeffc1, coeffc2, coeffc3, coeffc4;
G4double rangecut;
G4double drr,finalr;
G4double drr, finalr;
G4int currentMaterialIndex;
G4bool firstStep;
G4bool insideskin;
G4bool latDisplasmentbackup;
G4bool displacementFlag;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline void G4UrbanAdjointMscModel::SetNewDisplacementFlag(G4bool val)
{
displacementFlag = val;
}
inline
void G4UrbanAdjointMscModel::SetParticle(const G4ParticleDefinition* p)
{ const G4ParticleDefinition* p1 =p;
inline void G4UrbanAdjointMscModel::SetParticle(const G4ParticleDefinition* p)
{
const G4ParticleDefinition* p1 = p;
if (p->GetParticleName() =="adj_e-") p1= G4Electron::Electron();
if(p->GetParticleName() == "adj_e-")
p1 = G4Electron::Electron();
if (p1 != particle) {
particle = p1;
mass = p1->GetPDGMass();
charge = p1->GetPDGCharge()/CLHEP::eplus;
ChargeSquare = charge*charge;
if(p1 != particle)
{
particle = p1;
mass = p1->GetPDGMass();
charge = p1->GetPDGCharge() / CLHEP::eplus;
ChargeSquare = charge * charge;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline G4double G4UrbanAdjointMscModel::Randomizetlimit()
{
G4double temptlimit = tlimit;
if(tlimit > tlimitmin)
{
G4double delta = tlimit-tlimitmin;
do {
temptlimit = G4RandGauss::shoot(rndmEngineMod,tlimit,0.1*delta);
// Loop checking, 10-Apr-2016, Laszlo Urban
} while ((temptlimit < tlimit-delta) ||
(temptlimit > tlimit+delta));
G4double delta = tlimit - tlimitmin;
do
{
temptlimit = G4RandGauss::shoot(rndmEngineMod, tlimit, 0.1 * delta);
// Loop checking, 10-Apr-2016, Laszlo Urban
} while((temptlimit < tlimit - delta) || (temptlimit > tlimit + delta));
}
else
{
temptlimit = tlimitmin;
}
else { temptlimit = tlimitmin; }
return temptlimit;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline void G4UrbanAdjointMscModel::UpdateCache()
{
lnZ = G4Log(Zeff);
// correction in theta0 formula
G4double w = G4Exp(lnZ/6.);
G4double facz = 0.990395+w*(-0.168386+w*0.093286) ;
coeffth1 = facz*(1. - 8.7780e-2/Zeff);
coeffth2 = facz*(4.0780e-2 + 1.7315e-4*Zeff);
G4double w = G4Exp(lnZ / 6.);
G4double facz = 0.990395 + w * (-0.168386 + w * 0.093286);
coeffth1 = facz * (1. - 8.7780e-2 / Zeff);
coeffth2 = facz * (4.0780e-2 + 1.7315e-4 * Zeff);
// tail parameters
G4double Z13 = w*w;
coeffc1 = 2.3785 - Z13*(4.1981e-1 - Z13*6.3100e-2);
coeffc2 = 4.7526e-1 + Z13*(1.7694 - Z13*3.3885e-1);
coeffc3 = 2.3683e-1 - Z13*(1.8111 - Z13*3.2774e-1);
coeffc4 = 1.7888e-2 + Z13*(1.9659e-2 - Z13*2.6664e-3);
G4double Z13 = w * w;
coeffc1 = 2.3785 - Z13 * (4.1981e-1 - Z13 * 6.3100e-2);
coeffc2 = 4.7526e-1 + Z13 * (1.7694 - Z13 * 3.3885e-1);
coeffc3 = 2.3683e-1 - Z13 * (1.8111 - Z13 * 3.2774e-1);
coeffc4 = 1.7888e-2 + Z13 * (1.9659e-2 - Z13 * 2.6664e-3);
Z2 = Zeff * Zeff;
Z23 = Z13 * Z13;
Z2 = Zeff*Zeff;
Z23 = Z13*Z13;
Zold = Zeff;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline
G4double G4UrbanAdjointMscModel::SimpleScattering(G4double xmeanth, G4double x2meanth)
inline G4double G4UrbanAdjointMscModel::SimpleScattering(G4double xmeanth,
G4double x2meanth)
{
// 'large angle scattering'
// 2 model functions with correct xmean and x2mean
G4double a = (2.*xmeanth+9.*x2meanth-3.)/(2.*xmeanth-3.*x2meanth+1.);
G4double prob = (a+2.)*xmeanth/a;
G4double a =
(2. * xmeanth + 9. * x2meanth - 3.) / (2. * xmeanth - 3. * x2meanth + 1.);
G4double prob = (a + 2.) * xmeanth / a;
// sampling
G4double cth = 1.;
if(rndmEngineMod->flat() < prob) {
cth = -1.+2.*G4Exp(G4Log(rndmEngineMod->flat())/(a+1.));
} else {
cth = -1.+2.*rndmEngineMod->flat();
if(rndmEngineMod->flat() < prob)
{
cth = -1. + 2. * G4Exp(G4Log(rndmEngineMod->flat()) / (a + 1.));
}
else
{
cth = -1. + 2. * rndmEngineMod->flat();
}
return cth;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif
@@ -23,100 +23,60 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4VAdjointReverseReaction
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4VAdjointReverseReaction
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 1st April 2007 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Abstract class for adjoint/reverse discrete scattering
//
// Abstract class for adjoint/reverse discrete scattering
////////////////////////////////////////////////////////////////////////////////
#ifndef G4VAdjointReverseReaction_h
#define G4VAdjointReverseReaction_h 1
#include "globals.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4ElementVector.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "G4VDiscreteProcess.hh"
class G4PhysicsTable;
class G4Region;
class G4VParticleChange;
class G4AdjointCSManager;
class G4ParticleChange;
class G4ParticleDefinition;
class G4Track;
class G4VEmAdjointModel;
class G4AdjointCSMatrix;
class G4AdjointCSManager;
class G4Material;
class G4MaterialCutsCouple;
class G4VParticleChange;
class G4VAdjointReverseReaction : public G4VDiscreteProcess
{
public:
explicit G4VAdjointReverseReaction(G4String process_name,
G4bool whichScatCase);
public:
~G4VAdjointReverseReaction() override;
G4VAdjointReverseReaction(G4String process_name,G4bool whichScatCase);
void BuildPhysicsTable(const G4ParticleDefinition&) override;
virtual ~G4VAdjointReverseReaction();
public:
void PreparePhysicsTable(const G4ParticleDefinition&);
void BuildPhysicsTable(const G4ParticleDefinition&);
virtual G4VParticleChange* PostStepDoIt(const G4Track&, const G4Step&);
inline void SetIntegralMode(G4bool aBool){IsIntegralModeUsed = aBool;}
protected :// with description
virtual G4double GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition);
G4VParticleChange* PostStepDoIt(const G4Track&,
const G4Step&) override;
protected:
G4VEmAdjointModel* theAdjointEMModel;
G4ParticleChange* fParticleChange;
G4AdjointCSManager* theAdjointCSManager;
G4bool IsScatProjToProjCase;
G4VAdjointReverseReaction(G4VAdjointReverseReaction&) = delete;
G4VAdjointReverseReaction& operator=(
const G4VAdjointReverseReaction& right) = delete;
private:
G4double lastCS;
std::vector<G4double> CS_Vs_Element;
G4bool IsFwdCSUsed;
//For integral mode
//------------------
G4bool IsIntegralModeUsed;
G4int trackid;
G4int nstep;
protected:
G4double GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition) override;
G4VEmAdjointModel* fAdjointModel = nullptr;
G4bool fIsScatProjToProj;
};
private:
G4ParticleChange* fParticleChange;
G4AdjointCSManager* fCSManager;
G4int fTrackId = 0;
G4bool fIsFwdCSUsed = false;
};
#endif
@@ -23,328 +23,290 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4VEMAdjointModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4VEMAdjointModel
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 10 September 2009 Move to a virtual class. L. Desorgher
// 1st April 2007 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Base class for Adjoint EM model. It is based on the use of direct G4VEmModel.
//
// Base class for Adjoint EM model. It is based on the use of direct
// G4VEmModel.
////////////////////////////////////////////////////////////////////////////////
#ifndef G4VEmAdjointModel_h
#define G4VEmAdjointModel_h 1
#include "globals.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4ElementVector.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4Electron.hh"
#include "G4Gamma.hh"
#include "G4ProductionCutsTable.hh"
class G4PhysicsTable;
class G4Region;
class G4VParticleChange;
class G4ParticleChange;
class G4Track;
class G4AdjointCSMatrix;
class G4AdjointCSManager;
class G4Material;
class G4MaterialCutsCouple;
class G4ParticleChange;
class G4Region;
class G4Track;
class G4VEmAdjointModel
{
public: // public methods
G4VEmAdjointModel(const G4String& nam);
public:
explicit G4VEmAdjointModel(const G4String& nam);
virtual ~G4VEmAdjointModel();
//------------------------------------------------------------------------
// Virtual methods to be implemented for the sample secondaries concrete model
//------------------------------------------------------------------------
//virtual void Initialise()=0;
virtual void SampleSecondaries(const G4Track& aTrack,
G4bool IsScatProjToProjCase,
G4ParticleChange* fParticleChange)=0;
virtual void SampleSecondaries(const G4Track& aTrack, G4bool isScatProjToProj,
G4ParticleChange* fParticleChange) = 0;
//------------------------------------------------------------------------
// Methods for adjoint processes; may be overwritten if needed;
// Methods for adjoint processes
//------------------------------------------------------------------------
virtual G4double AdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool IsScatProjToProjCase);
virtual G4double GetAdjointCrossSection(const G4MaterialCutsCouple* aCouple,
G4double primEnergy,
G4bool IsScatProjToProjCase);
G4double primEnergy,
G4bool isScatProjToProj);
// The implementation of the DiffCrossSection... here are correct for
// energy loss process. For the photoelectric and Compton scattering
// the method should be redefined
virtual G4double DiffCrossSectionPerAtomPrimToSecond(
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyProd, // kinetic energy of the secondary particle
G4double Z,
G4double A = 0.);
virtual G4double DiffCrossSectionPerAtomPrimToScatPrim(
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyScatProj, // kinetic energy of the primary particle after the interaction
G4double Z,
G4double A = 0.);
G4double kinEnergyProj, // kin energy of primary before interaction
G4double kinEnergyProd, // kinetic energy of the secondary particle
G4double Z, G4double A = 0.);
virtual G4double DiffCrossSectionPerAtomPrimToScatPrim(
G4double kinEnergyProj, // kin energy of primary before interaction
G4double kinEnergyScatProj, // kin energy of primary after interaction
G4double Z, G4double A = 0.);
virtual G4double DiffCrossSectionPerVolumePrimToSecond(
const G4Material* aMaterial,
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyProd // kinetic energy of the secondary particle
);
const G4Material* aMaterial,
G4double kinEnergyProj, // kin energy of primary before interaction
G4double kinEnergyProd // kinetic energy of secondary particle
);
virtual G4double DiffCrossSectionPerVolumePrimToScatPrim(
const G4Material* aMaterial,
G4double kinEnergyProj, // kinetic energy of the primary particle before the interaction
G4double kinEnergyScatProj // kinetic energy of the primary particle after the interaction
);
//Energy limits of adjoint secondary
const G4Material* aMaterial,
G4double kinEnergyProj, // kin energy of primary before interaction
G4double kinEnergyScatProj // kinetic energy of primary after interaction
);
// Energy limits of adjoint secondary
//------------------
virtual G4double GetSecondAdjEnergyMaxForScatProjToProjCase(G4double PrimAdjEnergy);
virtual G4double GetSecondAdjEnergyMinForScatProjToProjCase(G4double PrimAdjEnergy,G4double Tcut=0);
virtual G4double GetSecondAdjEnergyMaxForProdToProjCase(G4double PrimAdjEnergy);
virtual G4double GetSecondAdjEnergyMinForProdToProjCase(G4double PrimAdjEnergy);
//Other Methods
virtual G4double GetSecondAdjEnergyMaxForScatProjToProj(
G4double primAdjEnergy);
virtual G4double GetSecondAdjEnergyMinForScatProjToProj(
G4double primAdjEnergy, G4double tcut = 0.);
virtual G4double GetSecondAdjEnergyMaxForProdToProj(G4double primAdjEnergy);
virtual G4double GetSecondAdjEnergyMinForProdToProj(G4double primAdjEnergy);
// Other Methods
//---------------
void DefineCurrentMaterial(const G4MaterialCutsCouple* couple);
std::vector< std::vector< double>* > ComputeAdjointCrossSectionVectorPerAtomForSecond(
G4double kinEnergyProd,
G4double Z,
G4double A = 0.,
G4int nbin_pro_decade=10
);
std::vector< std::vector< double>* > ComputeAdjointCrossSectionVectorPerAtomForScatProj(
G4double kinEnergyProd,
G4double Z,
G4double A = 0.,
G4int nbin_pro_decade=10
);
std::vector< std::vector< double>* > ComputeAdjointCrossSectionVectorPerVolumeForSecond(
G4Material* aMaterial,
G4double kinEnergyProd,
G4int nbin_pro_decade=10
);
std::vector< std::vector< double>* > ComputeAdjointCrossSectionVectorPerVolumeForScatProj(
G4Material* aMaterial,
G4double kinEnergyProd,
G4int nbin_pro_decade=10
);
inline void SetCSMatrices(std::vector< G4AdjointCSMatrix* >* Vec1CSMatrix, std::vector< G4AdjointCSMatrix* >* Vec2CSMatrix){
pOnCSMatrixForProdToProjBackwardScattering = Vec1CSMatrix;
pOnCSMatrixForScatProjToProjBackwardScattering = Vec2CSMatrix;
void DefineCurrentMaterial(const G4MaterialCutsCouple* couple);
std::vector<std::vector<double>*>
ComputeAdjointCrossSectionVectorPerAtomForSecond(G4double kinEnergyProd,
G4double Z, G4double A = 0.,
G4int nbin_pro_decade = 10);
std::vector<std::vector<double>*>
ComputeAdjointCrossSectionVectorPerAtomForScatProj(
G4double kinEnergyProd, G4double Z, G4double A = 0.,
G4int nbin_pro_decade = 10);
std::vector<std::vector<double>*>
ComputeAdjointCrossSectionVectorPerVolumeForSecond(
G4Material* aMaterial, G4double kinEnergyProd, G4int nbin_pro_decade = 10);
std::vector<std::vector<double>*>
ComputeAdjointCrossSectionVectorPerVolumeForScatProj(
G4Material* aMaterial, G4double kinEnergyProd, G4int nbin_pro_decade = 10);
inline void SetCSMatrices(std::vector<G4AdjointCSMatrix*>* Vec1CSMatrix,
std::vector<G4AdjointCSMatrix*>* Vec2CSMatrix)
{
fCSMatrixProdToProjBackScat = Vec1CSMatrix;
fCSMatrixProjToProjBackScat = Vec2CSMatrix;
};
inline G4ParticleDefinition* GetAdjointEquivalentOfDirectPrimaryParticleDefinition(){return theAdjEquivOfDirectPrimPartDef;}
inline G4ParticleDefinition* GetAdjointEquivalentOfDirectSecondaryParticleDefinition(){return theAdjEquivOfDirectSecondPartDef;}
inline G4double GetHighEnergyLimit(){return HighEnergyLimit;}
inline G4double GetLowEnergyLimit(){return LowEnergyLimit;}
void SetHighEnergyLimit(G4double aVal);
void SetLowEnergyLimit(G4double aVal);
inline void DefineDirectEMModel(G4VEmModel* aModel){theDirectEMModel = aModel;}
void SetAdjointEquivalentOfDirectPrimaryParticleDefinition(G4ParticleDefinition* aPart);
inline void SetAdjointEquivalentOfDirectSecondaryParticleDefinition(G4ParticleDefinition* aPart){
theAdjEquivOfDirectSecondPartDef =aPart;
inline G4ParticleDefinition*
GetAdjointEquivalentOfDirectPrimaryParticleDefinition()
{
return fAdjEquivDirectPrimPart;
}
inline void SetSecondPartOfSameType(G4bool aBool){second_part_of_same_type =aBool;}
inline G4bool GetSecondPartOfSameType(){return second_part_of_same_type;}
inline void SetUseMatrix(G4bool aBool) { UseMatrix = aBool;}
inline void SetUseMatrixPerElement(G4bool aBool){ UseMatrixPerElement = aBool;}
inline void SetUseOnlyOneMatrixForAllElements(G4bool aBool){ UseOnlyOneMatrixForAllElements = aBool;}
inline void SetApplyCutInRange(G4bool aBool){ ApplyCutInRange = aBool;}
inline G4bool GetUseMatrix() {return UseMatrix;}
inline G4bool GetUseMatrixPerElement(){ return UseMatrixPerElement;}
inline G4bool GetUseOnlyOneMatrixForAllElements(){ return UseOnlyOneMatrixForAllElements;}
inline G4bool GetApplyCutInRange(){ return ApplyCutInRange;}
inline G4String GetName(){ return name;}
inline virtual void SetCSBiasingFactor(G4double aVal) {CS_biasing_factor = aVal;}
inline void SetCorrectWeightForPostStepInModel(G4bool aBool) {correct_weight_for_post_step_in_model = aBool;}
inline void SetAdditionalWeightCorrectionFactorForPostStepOutsideModel(G4double factor) {additional_weight_correction_factor_for_post_step_outside_model = factor;}
inline G4ParticleDefinition*
GetAdjointEquivalentOfDirectSecondaryParticleDefinition()
{
return fAdjEquivDirectSecondPart;
}
protected:
inline G4double GetHighEnergyLimit() { return fHighEnergyLimit; }
//Some of them can be overriden by daughter classes
inline G4double GetLowEnergyLimit() { return fLowEnergyLimit; }
void SetHighEnergyLimit(G4double aVal);
void SetLowEnergyLimit(G4double aVal);
inline void DefineDirectEMModel(G4VEmModel* aModel) { fDirectModel = aModel; }
void SetAdjointEquivalentOfDirectPrimaryParticleDefinition(
G4ParticleDefinition* aPart);
inline void SetAdjointEquivalentOfDirectSecondaryParticleDefinition(
G4ParticleDefinition* aPart)
{
fAdjEquivDirectSecondPart = aPart;
}
inline void SetSecondPartOfSameType(G4bool aBool)
{
fSecondPartSameType = aBool;
}
inline G4bool GetSecondPartOfSameType() { return fSecondPartSameType; }
inline void SetUseMatrix(G4bool aBool) { fUseMatrix = aBool; }
inline void SetUseMatrixPerElement(G4bool aBool)
{
fUseMatrixPerElement = aBool;
}
inline void SetUseOnlyOneMatrixForAllElements(G4bool aBool)
{
fOneMatrixForAllElements = aBool;
}
inline void SetApplyCutInRange(G4bool aBool) { fApplyCutInRange = aBool; }
inline G4bool GetUseMatrix() { return fUseMatrix; }
inline G4bool GetUseMatrixPerElement() { return fUseMatrixPerElement; }
inline G4bool GetUseOnlyOneMatrixForAllElements()
{
return fOneMatrixForAllElements;
}
inline G4bool GetApplyCutInRange() { return fApplyCutInRange; }
inline G4String GetName() { return fName; }
inline virtual void SetCSBiasingFactor(G4double aVal)
{
fCsBiasingFactor = aVal;
}
inline void SetCorrectWeightForPostStepInModel(G4bool aBool)
{
fInModelWeightCorr = aBool;
}
inline void SetAdditionalWeightCorrectionFactorForPostStepOutsideModel(
G4double factor)
{
fOutsideWeightFactor = factor;
}
G4VEmAdjointModel(G4VEmAdjointModel&) = delete;
G4VEmAdjointModel& operator=(const G4VEmAdjointModel& right) = delete;
protected:
G4double DiffCrossSectionFunction1(G4double kinEnergyProj);
G4double DiffCrossSectionFunction2(G4double kinEnergyProj);
G4double DiffCrossSectionPerVolumeFunctionForIntegrationOverEkinProj(G4double EkinProd);
//General methods to sample secondary energy
//--------------------------------------
G4double SampleAdjSecEnergyFromCSMatrix(size_t MatrixIndex,G4double prim_energy,G4bool IsScatProjToProjCase);
G4double SampleAdjSecEnergyFromCSMatrix(G4double prim_energy,G4bool IsScatProjToProjCase);
void SelectCSMatrix(G4bool IsScatProjToProjCase);
virtual G4double SampleAdjSecEnergyFromDiffCrossSectionPerAtom(G4double prim_energy,G4bool IsScatProjToProjCase);
//Post Step weight correction
//----------------------------
virtual void CorrectPostStepWeight(G4ParticleChange* fParticleChange,
G4double old_weight,
G4double adjointPrimKinEnergy,
G4double projectileKinEnergy,
G4bool IsScatProjToProjCase);
protected: //attributes
G4VEmModel* theDirectEMModel;
G4VParticleChange* pParticleChange;
// General methods to sample secondary energy
G4double SampleAdjSecEnergyFromCSMatrix(size_t MatrixIndex,
G4double prim_energy,
G4bool isScatProjToProj);
//Name
//-----
const G4String name;
//Needed for CS integration at the initialisation phase
//-----------------------------------------------------
G4int ASelectedNucleus;
G4int ZSelectedNucleus;
G4Material* SelectedMaterial;
G4double kinEnergyProdForIntegration;
G4double kinEnergyScatProjForIntegration;
G4double kinEnergyProjForIntegration;
G4double SampleAdjSecEnergyFromCSMatrix(G4double prim_energy,
G4bool isScatProjToProj);
//for the adjoint simulation we need for each element or material:
//an adjoint CS Matrix
//-----------------------------
std::vector< G4AdjointCSMatrix* >* pOnCSMatrixForProdToProjBackwardScattering;
std::vector< G4AdjointCSMatrix* >* pOnCSMatrixForScatProjToProjBackwardScattering;
std::vector<G4double> CS_Vs_ElementForScatProjToProjCase;
std::vector<G4double> CS_Vs_ElementForProdToProjCase;
G4double lastCS;
G4double lastAdjointCSForScatProjToProjCase;
G4double lastAdjointCSForProdToProjCase;
//particle definition
//------------------
G4ParticleDefinition* theAdjEquivOfDirectPrimPartDef;
G4ParticleDefinition* theAdjEquivOfDirectSecondPartDef;
G4ParticleDefinition* theDirectPrimaryPartDef;
G4bool second_part_of_same_type;
//Prestep energy
//-------------
G4double preStepEnergy;
//Current couple material
//----------------------
G4Material* currentMaterial;
G4MaterialCutsCouple* currentCouple;
size_t currentMaterialIndex;
size_t currentCoupleIndex;
G4double currentTcutForDirectPrim;
G4double currentTcutForDirectSecond;
G4bool ApplyCutInRange;
//For ions
//---------
G4double mass_ratio_product;
G4double mass_ratio_projectile;
void SelectCSMatrix(G4bool isScatProjToProj);
//Energy limits
//-------------
G4double HighEnergyLimit;
G4double LowEnergyLimit;
virtual G4double SampleAdjSecEnergyFromDiffCrossSectionPerAtom(
G4double prim_energy, G4bool isScatProjToProj);
//Cross Section biasing factor
//---------------------------
G4double CS_biasing_factor;
//Type of Model with Matrix or not
//--------------------------------
G4bool UseMatrix;
G4bool UseMatrixPerElement; //other possibility is per Material
G4bool UseOnlyOneMatrixForAllElements;
//Index of Cross section matrices to be used
//------------
size_t indexOfUsedCrossSectionMatrix;
size_t model_index;
//This is needed for the forced interaction where part of the weight correction
// is given outside the model while the secondary are created in the model
//The weight should be fixed before adding the secondary
G4bool correct_weight_for_post_step_in_model;
G4double additional_weight_correction_factor_for_post_step_outside_model;
// Post Step weight correction
virtual void CorrectPostStepWeight(G4ParticleChange* fParticleChange,
G4double old_weight,
G4double adjointPrimKinEnergy,
G4double projectileKinEnergy,
G4bool isScatProjToProj);
G4AdjointCSManager* fCSManager;
G4VEmModel* fDirectModel = nullptr;
const G4String fName;
G4Material* fSelectedMaterial = nullptr;
G4Material* fCurrentMaterial = nullptr;
G4MaterialCutsCouple* fCurrentCouple = nullptr;
// particle definition
G4ParticleDefinition* fAdjEquivDirectPrimPart = nullptr;
G4ParticleDefinition* fAdjEquivDirectSecondPart = nullptr;
G4ParticleDefinition* fDirectPrimaryPart = nullptr;
// adjoint CS matrix for each element or material
std::vector<G4AdjointCSMatrix*>* fCSMatrixProdToProjBackScat = nullptr;
std::vector<G4AdjointCSMatrix*>* fCSMatrixProjToProjBackScat = nullptr;
std::vector<G4double> fElementCSScatProjToProj;
std::vector<G4double> fElementCSProdToProj;
G4double fKinEnergyProdForIntegration = 0.;
G4double fKinEnergyScatProjForIntegration = 0.;
G4double fLastCS = 0.;
G4double fLastAdjointCSForScatProjToProj = 0.;
G4double fLastAdjointCSForProdToProj = 0.;
G4double fPreStepEnergy = 0.;
G4double fTcutPrim = 0.;
G4double fTcutSecond = 0.;
// Energy limits
G4double fHighEnergyLimit = 0.;
G4double fLowEnergyLimit = 0.;
// Cross Section biasing factor
G4double fCsBiasingFactor = 1.;
// [1] This is needed for the forced interaction where part of the weight
// correction is given outside the model while the secondary are created in
// the model. The weight should be fixed before adding the secondary
G4double fOutsideWeightFactor = 1.;
// Needed for CS integration at the initialisation phase
G4int fASelectedNucleus = 0;
G4int fZSelectedNucleus = 0;
size_t fCSMatrixUsed = 0; // Index of crosssection matrices used
G4bool fSecondPartSameType = false;
G4bool fInModelWeightCorr =
false; // correct_weight_for_post_step_in_model, see [1]
G4bool fApplyCutInRange = true;
// Type of Model with Matrix or not
G4bool fUseMatrix = false;
G4bool fUseMatrixPerElement = false; // other possibility is per Material
G4bool fOneMatrixForAllElements = false;
};
#endif
@@ -23,68 +23,47 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -----------------------------------------------------------------------------
//
// GEANT4 Class header file
//
// File name: G4eAdjointMultipleScattering
//
// Author: Vladimir Ivanchenko
//
// Creation date: 10 March 2001
//
// Modifications:
//
// The class simulates the multiple scattering for e+ and e-
//
//------------------------------------------------------------------------------
//
// class description
//
// The class simulates the multiple scattering for e+ and e-
//
// class description - end
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef G4eAdjointMultipleScattering_h
#define G4eAdjointMultipleScattering_h 1
#include "G4VMultipleScattering.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class G4eAdjointMultipleScattering : public G4VMultipleScattering
{
public: // with description
public:
explicit G4eAdjointMultipleScattering(const G4String& processName = "msc");
virtual ~G4eAdjointMultipleScattering();
~G4eAdjointMultipleScattering() override;
// This is called in the beginning of tracking for a new track
void StartTracking(G4Track*) override;
// returns true for charged particles, false otherwise
G4bool IsApplicable (const G4ParticleDefinition& p) final;
G4bool IsApplicable(const G4ParticleDefinition& p) override;
// Print few lines of informations about the process: validity range,
void PrintInfo() override;
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
void StreamProcessInfo(std::ostream& outFile) const override;
protected:
G4eAdjointMultipleScattering(G4eAdjointMultipleScattering&) = delete;
G4eAdjointMultipleScattering& operator =(
const G4eAdjointMultipleScattering& right) = delete;
// This function initialise models
protected:
void InitialiseProcess(const G4ParticleDefinition*) override;
private: // data members
G4bool isInitialized;
private:
G4bool fIsInitialized = false;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif
@@ -23,44 +23,35 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4eInverseBremstrahlung.hh
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4eInverseBremstrahlung.hh
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 25 October 2007 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Adjoint/reverse bremstrahlung
//
// Adjoint/reverse bremsstrahlung
////////////////////////////////////////////////////////////////////////////////
#ifndef G4eInverseBremsstrahlung_h
#define G4eInverseBremsstrahlung_h 1
#include "G4VAdjointReverseReaction.hh"
#include "globals.hh"
#include "G4eIonisation.hh"
#include "G4VAdjointReverseReaction.hh"
class G4VEmAdjointModel;
class G4eInverseBremsstrahlung: public G4VAdjointReverseReaction
class G4eInverseBremsstrahlung : public G4VAdjointReverseReaction
{
public:
public:
explicit G4eInverseBremsstrahlung(G4bool whichScatCase, G4String process_name,
G4VEmAdjointModel* aEmAdjointModel);
~G4eInverseBremsstrahlung() override;
G4eInverseBremsstrahlung(G4bool whichScatCase, G4String process_name,
G4VEmAdjointModel* aEmAdjointModel);
~G4eInverseBremsstrahlung();
private:
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
G4eInverseBremsstrahlung(G4eInverseBremsstrahlung&) = delete;
G4eInverseBremsstrahlung& operator=(const G4eInverseBremsstrahlung& right) =
delete;
};
#endif
@@ -23,43 +23,34 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4eInverseCompton.hh
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4eInverseCompton.hh
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 25 October 2007 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Adjoint/reverse Compton
//
// Adjoint/reverse Compton
////////////////////////////////////////////////////////////////////////////////
#ifndef G4eInverseCompton_h
#define G4eInverseCompton_h 1
#include "G4VAdjointReverseReaction.hh"
#include "globals.hh"
#include "G4eIonisation.hh"
#include "G4VAdjointReverseReaction.hh"
class G4AdjointComptonModel;
class G4eInverseCompton: public G4VAdjointReverseReaction
class G4eInverseCompton : public G4VAdjointReverseReaction
{
public:
public:
explicit G4eInverseCompton(G4bool whichScatCase, G4String process_name,
G4AdjointComptonModel* aEmAdjointModel);
~G4eInverseCompton() override;
G4eInverseCompton(G4bool whichScatCase, G4String process_name, G4AdjointComptonModel* aEmAdjointModel);
~G4eInverseCompton();
private:
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
G4eInverseCompton(G4eInverseCompton&) = delete;
G4eInverseCompton& operator=(const G4eInverseCompton& right) = delete;
};
#endif
@@ -23,42 +23,34 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4eInverseIonisation.hh
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4eInverseIonisation.hh
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 15 April 2007 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Adjoint/reverse discrete ionisation
// Adjoint/reverse discrete ionisation
//
////////////////////////////////////////////////////////////////////////////////
#ifndef G4eInverseIonisation_h
#define G4eInverseIonisation_h 1
#include "G4VAdjointReverseReaction.hh"
#include "globals.hh"
#include "G4eIonisation.hh"
#include "G4VEmAdjointModel.hh"
class G4eInverseIonisation: public G4VAdjointReverseReaction
class G4VEmAdjointModel;
class G4eInverseIonisation : public G4VAdjointReverseReaction
{
public:
G4eInverseIonisation(G4bool whichScatCase, G4String process_name, G4VEmAdjointModel* aEmAdjointModel);
public:
G4eInverseIonisation(G4bool whichScatCase, G4String process_name,
G4VEmAdjointModel* aEmAdjointModel);
~G4eInverseIonisation();
private:
void ProcessDescription(std::ostream&) const override;
void DumpInfo() const override { ProcessDescription(G4cout); };
G4eInverseIonisation(G4eInverseIonisation&) = delete;
G4eInverseIonisation& operator=(const G4eInverseIonisation& right) = delete;
};
#endif
@@ -23,42 +23,31 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// Class: G4hInverseIonisation
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
//
/////////////////////////////////////////////////////////////////////////////////
// Module: G4hInverseIonisation.hh
// Author: L. Desorgher
// Organisation: SpaceIT GmbH
// Contract: ESA contract 21435/08/NL/AT
// Customer: ESA/ESTEC
/////////////////////////////////////////////////////////////////////////////////
//
// CHANGE HISTORY
// --------------
// ChangeHistory:
// 15 February 2009 creation by L. Desorgher
//
//-------------------------------------------------------------
// Documentation:
// Adjoint/reverse discrete ionisation for proton
//
// Adjoint/reverse discrete ionisation for proton
////////////////////////////////////////////////////////////////////////////////
#ifndef G4hInverseIonisation_h
#define G4hInverseIonisation_h 1
#include "G4VAdjointReverseReaction.hh"
#include "globals.hh"
#include "G4eIonisation.hh"
#include "G4AdjointhIonisationModel.hh"
class G4hInverseIonisation: public G4VAdjointReverseReaction
#include "G4VAdjointReverseReaction.hh"
class G4AdjointhIonisationModel;
class G4hInverseIonisation : public G4VAdjointReverseReaction
{
public:
public:
explicit G4hInverseIonisation(G4bool whichScatCase, G4String process_name,
G4AdjointhIonisationModel* aEmAdjointModel);
~G4hInverseIonisation() override;
G4hInverseIonisation(G4bool whichScatCase, G4String process_name, G4AdjointhIonisationModel* aEmAdjointModel);
~G4hInverseIonisation();
private:
G4hInverseIonisation(G4hInverseIonisation&) = delete;
G4hInverseIonisation& operator=(const G4hInverseIonisation& right) = delete;
};
#endif
@@ -1,102 +1,73 @@
#------------------------------------------------------------------------------
# sources.cmake
# Module : G4emadjoint
# Package: Geant4.src.G4processes.G4electromagnetic.G4emadjoint
#
# Sources description for a library.
# Lists the sources and headers of the code explicitly.
# Lists include paths needed.
# Lists the internal granular and global dependencies of the library.
# Source specific properties should be added at the end.
#
# Generated on : 24/9/2010
#
#
#------------------------------------------------------------------------------
# - G4emadjoint module build definition
#
# Define the Geant4 Module.
#
GEANT4_DEFINE_MODULE(NAME G4emadjoint
HEADERS
G4AdjointAlongStepWeightCorrection.hh
G4AdjointBremsstrahlungModel.hh
G4AdjointCSManager.hh
G4AdjointCSMatrix.hh
G4AdjointComptonModel.hh
G4AdjointInterpolator.hh
G4AdjointIonIonisationModel.hh
G4AdjointPhotoElectricModel.hh
G4AdjointProcessEquivalentToDirectProcess.hh
G4AdjointeIonisationModel.hh
G4AdjointhIonisationModel.hh
G4AdjointhMultipleScattering.hh
G4ContinuousGainOfEnergy.hh
G4InversePEEffect.hh
G4IonInverseIonisation.hh
G4VAdjointReverseReaction.hh
G4AdjointForcedInteractionForGamma.hh
G4VEmAdjointModel.hh
G4eInverseBremsstrahlung.hh
G4eInverseCompton.hh
G4eInverseIonisation.hh
G4hInverseIonisation.hh
G4UrbanAdjointMscModel.hh
G4eAdjointMultipleScattering.hh
SOURCES
G4AdjointAlongStepWeightCorrection.cc
G4AdjointBremsstrahlungModel.cc
G4AdjointCSManager.cc
G4AdjointCSMatrix.cc
G4AdjointComptonModel.cc
G4AdjointInterpolator.cc
G4AdjointIonIonisationModel.cc
G4AdjointPhotoElectricModel.cc
G4AdjointProcessEquivalentToDirectProcess.cc
G4AdjointeIonisationModel.cc
G4AdjointhIonisationModel.cc
G4AdjointhMultipleScattering.cc
G4ContinuousGainOfEnergy.cc
G4InversePEEffect.cc
G4IonInverseIonisation.cc
G4VAdjointReverseReaction.cc
G4AdjointForcedInteractionForGamma.cc
G4VEmAdjointModel.cc
G4eInverseBremsstrahlung.cc
G4eInverseCompton.cc
G4eInverseIonisation.cc
G4hInverseIonisation.cc
G4UrbanAdjointMscModel.cc
G4eAdjointMultipleScattering.cc
GRANULAR_DEPENDENCIES
G4baryons
G4bosons
G4cuts
G4emstandard
G4emutils
G4geometrymng
G4globman
G4hepnumerics
G4intercoms
G4ions
G4leptons
G4materials
G4mesons
G4navigation
G4partadj
G4partman
G4procman
G4track
G4volumes
GLOBAL_DEPENDENCIES
G4geometry
G4global
G4intercoms
G4materials
G4particles
G4track
LINK_LIBRARIES
)
# List any source specific properties here
geant4_add_module(G4emadjoint
PUBLIC_HEADERS
G4AdjointAlongStepWeightCorrection.hh
G4AdjointBremsstrahlungModel.hh
G4AdjointCSManager.hh
G4AdjointCSMatrix.hh
G4AdjointComptonModel.hh
G4AdjointInterpolator.hh
G4AdjointIonIonisationModel.hh
G4AdjointPhotoElectricModel.hh
G4AdjointProcessEquivalentToDirectProcess.hh
G4AdjointeIonisationModel.hh
G4AdjointhIonisationModel.hh
G4AdjointhMultipleScattering.hh
G4ContinuousGainOfEnergy.hh
G4InversePEEffect.hh
G4IonInverseIonisation.hh
G4VAdjointReverseReaction.hh
G4AdjointForcedInteractionForGamma.hh
G4VEmAdjointModel.hh
G4eInverseBremsstrahlung.hh
G4eInverseCompton.hh
G4eInverseIonisation.hh
G4hInverseIonisation.hh
G4UrbanAdjointMscModel.hh
G4eAdjointMultipleScattering.hh
SOURCES
G4AdjointAlongStepWeightCorrection.cc
G4AdjointBremsstrahlungModel.cc
G4AdjointCSManager.cc
G4AdjointCSMatrix.cc
G4AdjointComptonModel.cc
G4AdjointInterpolator.cc
G4AdjointIonIonisationModel.cc
G4AdjointPhotoElectricModel.cc
G4AdjointProcessEquivalentToDirectProcess.cc
G4AdjointeIonisationModel.cc
G4AdjointhIonisationModel.cc
G4AdjointhMultipleScattering.cc
G4ContinuousGainOfEnergy.cc
G4InversePEEffect.cc
G4IonInverseIonisation.cc
G4VAdjointReverseReaction.cc
G4AdjointForcedInteractionForGamma.cc
G4VEmAdjointModel.cc
G4eInverseBremsstrahlung.cc
G4eInverseCompton.cc
G4eInverseIonisation.cc
G4hInverseIonisation.cc
G4UrbanAdjointMscModel.cc
G4eAdjointMultipleScattering.cc)
geant4_module_link_libraries(G4emadjoint
PUBLIC
G4cuts
G4emutils
G4globman
G4leptons
G4partman
G4procman
PRIVATE
G4baryons
G4bosons
G4emstandard
G4hepnumerics
G4heprandom
G4ions
G4materials
G4partadj
G4track)
@@ -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);
}
@@ -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);
}
@@ -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() {}